Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c816627
feat(dgw): route JMUX channels through agents
irvingoujAtDevolution Sep 7, 2026
8995646
fix(dgw,agent): preserve routed target addresses
irvingoujAtDevolution Sep 7, 2026
54c106c
fix(dgw,jetsocat): release failed JMUX channel IDs
irvingoujAtDevolution Sep 7, 2026
d954814
docs(dgw): document routed target address
irvingoujAtDevolution Sep 7, 2026
c10d66a
docs(dgw): clarify agent routing result
irvingoujAtDevolution Sep 7, 2026
6572260
fix(dgw,agent,jetsocat): simplify JMUX routing
irvingoujAtDevolution Sep 8, 2026
201f03c
fix(agent): preserve tunneled TCP half-close
irvingoujAtDevolution Sep 8, 2026
9bfef41
fix(dgw,agent,jetsocat): harden JMUX routing
CBenoit Sep 10, 2026
69f4f7c
test(dgw,agent): cover routed JMUX boundaries
CBenoit Sep 10, 2026
a2a58b4
test(jmux): cover connector half-close
CBenoit Sep 10, 2026
8a30605
test(jmux): make EOF probes explicit
CBenoit Sep 10, 2026
70bbb44
fix(dgw,agent): preserve Agent route liveness
CBenoit Sep 10, 2026
83d6fb7
fix(dgw,agent): enforce route refresh margin
CBenoit Sep 10, 2026
c28ac7a
ci: update PSTools checksum
CBenoit Sep 10, 2026
6815f77
Merge branch 'master' into feat/jmux-agent-routing
CBenoit Sep 10, 2026
64c9f68
ci: align Agent policy PSTools checksum
CBenoit Sep 10, 2026
1df771d
test(jmux): cover connector audit exclusion
CBenoit Sep 10, 2026
065dcff
chore: drop unrelated PSTools checksum update
CBenoit Sep 10, 2026
e96b0d8
Merge branch 'master' into feat/jmux-agent-routing
CBenoit Sep 10, 2026
08a6f5b
refactor(agent): model tunnel state explicitly
CBenoit Sep 11, 2026
e62ae60
refactor(agent): expose validated gateway endpoint
CBenoit Sep 15, 2026
918af3d
docs(agent): explain tunnel half-close relay
CBenoit Sep 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions crates/agent-tunnel-proto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ pub use session::{ConnectRequest, ConnectResponse, MAX_SESSION_MESSAGE_SIZE};
pub use stream::{ControlStream, FramedRecv, FramedSend, SessionStream};
pub use version::{ALPN_PROTOCOL, CURRENT_PROTOCOL_VERSION, MIN_SUPPORTED_VERSION, validate_protocol_version};

/// Maximum time the Gateway keeps an Agent route online without a liveness message.
pub const AGENT_OFFLINE_TIMEOUT_SECS: u64 = 90;

/// Current wall-clock time in milliseconds since UNIX epoch.
pub fn current_time_millis() -> u64 {
u64::try_from(
Expand Down
4 changes: 2 additions & 2 deletions crates/agent-tunnel/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::{Duration, SystemTime};

use agent_tunnel_proto::{DomainAdvertisement, current_time_millis};
use agent_tunnel_proto::{AGENT_OFFLINE_TIMEOUT_SECS, DomainAdvertisement, current_time_millis};
use ipnetwork::Ipv4Network;
use parking_lot::RwLock;
use serde::Serialize;
Expand All @@ -13,7 +13,7 @@ use uuid::Uuid;
use crate::routing::RouteTarget;

/// Duration after which an agent is considered offline if no heartbeat has been received.
pub const AGENT_OFFLINE_TIMEOUT: Duration = Duration::from_secs(90);
pub const AGENT_OFFLINE_TIMEOUT: Duration = Duration::from_secs(AGENT_OFFLINE_TIMEOUT_SECS);

/// Tracks route advertisements received from an agent.
///
Expand Down
16 changes: 8 additions & 8 deletions crates/jmux-proxy/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ pub enum EventOutcome {

/// Complete audit information for one traffic item's lifecycle.
///
/// A single `TrafficEvent` is emitted exactly once per JMUX traffic item when
/// it ends (successfully or with error).
/// A single `TrafficEvent` is emitted exactly once when an eligible JMUX traffic item ends.
/// An item is eligible only when direct target resolution provides a concrete IP address.
///
/// # Timestamp semantics
///
Expand All @@ -94,7 +94,7 @@ pub enum EventOutcome {
/// - connect failure: the last IP that was attempted
/// - `target_port`: the destination port.
///
/// DNS failures do **not** produce an event because `target_ip` is unknown.
/// DNS failures and connection attempts handled by connector overrides do **not** produce an event because `target_ip` is unknown.
#[derive(Clone, Debug)]
pub struct TrafficEvent {
/// How the traffic item's lifecycle ended.
Expand Down Expand Up @@ -142,13 +142,13 @@ pub struct TrafficEvent {

/// Type-erased traffic audit callback.
///
/// Invoked exactly once per JMUX traffic item at end-of-lifecycle. The callback
/// itself is **synchronous**; perform any asynchronous work by spawning within
/// the callback (e.g., `tokio::spawn`) or by sending to an internal channel.
/// Invoked exactly once at the end of each eligible JMUX traffic item.
/// An item is eligible only when direct target resolution provides a concrete IP address.
/// The callback itself is **synchronous**; perform asynchronous work by spawning within the callback (e.g., `tokio::spawn`) or by sending to an internal channel.
///
/// # Exactly-once
///
/// - Each traffic item yields exactly one event.
/// - Each eligible traffic item yields exactly one event.
/// - Emitted at cleanup time, not during operation.
/// - Guarded to prevent duplicate emission.
/// - No aggregation—each event stands alone.
Expand All @@ -162,7 +162,7 @@ pub struct TrafficEvent {
///
/// ```rust,ignore
/// let proxy = JmuxProxy::new(reader, writer)
/// .with_traffic_event_callback(|event| {
/// .with_outgoing_traffic_event_callback(|event| {
/// // Log quickly...
/// tracing::info!(
/// outcome = ?event.outcome,
Expand Down
Loading
Loading