Skip to main content

NetSession

Struct NetSession 

Source
pub struct NetSession { /* private fields */ }
Expand description

Session state after handshake completion.

Implementations§

Source§

impl NetSession

Source

pub fn new( keys: SessionKeys, peer_addr: SocketAddr, pool_size: usize, default_reliable: bool, ) -> Self

Create a new session from handshake results

Source

pub fn cached_node_id(&self) -> Option<u64>

Read the cached peer NodeId resolution. Returns None until the dispatcher’s first resolution call publishes a value via Self::cache_node_id. See the field doc for the perf rationale.

Source

pub fn cache_node_id(&self, node_id: u64)

Publish the resolved peer NodeId for subsequent calls. Idempotent — concurrent first-resolution callers all write the same value (the resolver is deterministic for a given session_id), so a store over an existing identical value is correct. Callers should pass non-zero node_id; 0 is the reserved “unresolved” sentinel and is a no-op.

Source

pub fn next_control_tx_seq(&self) -> u64

Allocate the next sequence number for a subprotocol control packet. Uses a session-level counter separate from any user stream’s sequence space — see CONTROL_STREAM_ID.

Source

pub fn session_id(&self) -> u64

Get the session ID

Source

pub fn peer_addr(&self) -> SocketAddr

Get the peer address

Source

pub fn rx_cipher(&self) -> &PacketCipher

Get the RX cipher

Source

pub fn get_or_create_stream( &self, stream_id: u64, ) -> RefMut<'_, u64, StreamState>

Get or create stream state

Source

pub fn get_or_create_stream_for_packet( &self, stream_id: u64, reliable: bool, ) -> RefMut<'_, u64, StreamState>

Like Self::get_or_create_stream, but the receiver-side stream is created reliable when the arriving packet is RELIABLE-flagged — the sender’s reliability is a property of the traffic, not of the receiver’s default_reliable. Without this the auto-created receive stream is FireAndForget and never builds a NACK, so a reliable sender’s lost packets are unrecoverable. Only affects the reliability mode at first-touch (creation); an existing stream keeps its mode.

Source

pub fn collect_timed_out_retransmits(&self) -> Vec<Arc<RetransmitDescriptor>>

Collect retransmit descriptors for every reliable stream whose oldest unacked packet has exceeded its RTO. Drives the timeout backstop (STREAM_RETRANSMIT D-4) that recovers tail loss — the last packets dropped, with no later arrival to trigger a receiver NACK. Each call advances the per-packet retry clock, so a descriptor isn’t re-emitted until another RTO elapses, and a packet past max_retries is dropped from the window.

Source

pub fn collect_gap_nacks(&self) -> Vec<(u64, NackPayload)>

Collect a NACK for every stream that currently has a gap (H-4): (stream_id, NackPayload). Driven on a timer so a persistent gap with no further arrivals is re-requested promptly, rather than waiting for the sender’s RTO (the grant-piggybacked NACK only fires when a packet is accepted, i.e. when there IS new activity).

Source

pub fn take_failed_stream_ids(&self) -> Vec<u64>

Take-and-clear the “given up” flag across all streams, returning the ids of streams whose reliable layer exhausted retransmits on some packet (H-3). The caller signals a reset to the peer so the receiver fails fast instead of stalling to a timeout.

Source

pub fn try_stream(&self, stream_id: u64) -> Option<Ref<'_, u64, StreamState>>

Look up stream state without creating it. Returns None if the stream was never opened or has been closed.

Source

pub fn try_acquire_tx_credit_guard( self: &Arc<Self>, stream_id: u64, bytes: u32, ) -> TxAdmit

Try to acquire bytes of send credit on stream_id with RAII refund semantics.

Returns:

  • TxAdmit::Acquired with a TxSlotGuard that refunds bytes back to tx_credit_remaining when dropped — including on async cancellation, panic, and early return — unless the caller invokes TxSlotGuard::commit to suppress the refund after a successful socket send. This is the cure for the credit-leak that a plain “decrement / await / maybe-refund” shape would hit when the sending future is dropped mid-.await (e.g., tokio::select! cancel).
  • TxAdmit::WindowFull if tx_credit_remaining is below bytes. backpressure_events has already been bumped.
  • TxAdmit::StreamClosed if the stream isn’t registered (never opened, closed, or idle-evicted).
Source

pub fn try_acquire_tx_credit_matching_epoch( self: &Arc<Self>, stream_id: u64, expected_epoch: u64, bytes: u32, ) -> TxAdmit

Like Self::try_acquire_tx_credit_guard, but additionally rejects the admission if the live StreamState’s epoch differs from expected_epoch.

Use from the typed-handle send_on_stream path so a handle held across a close+reopen cycle doesn’t admit against the new stream’s state.

Source

pub fn try_rollback_tx_seq( self: &Arc<Self>, stream_id: u64, epoch: u64, seq: u64, ) -> bool

Roll back a TX sequence allocated by Self::try_acquire_tx_credit_matching_epoch when the packet it was minted for never reached the wire (scheduler/socket backpressure after the seq was consumed). Guarded by epoch so a close+reopen race can’t roll back a sequence on a fresh stream state that never issued it — the exact discipline TxSlotGuard::drop uses for the byte-credit refund.

Returns true if the sequence was reclaimed (it was the most- recently-issued seq and no concurrent send raced ahead), leaving no receiver-visible gap; false otherwise.

Source§

impl NetSession

Source

pub fn open_stream_with( &self, stream_id: u64, reliable: bool, fairness_weight: u8, ) -> u64

Open a stream with an explicit reliability mode and fair-scheduler weight.

Idempotent: if the stream already exists, this is a no-op and the caller’s config is ignored with a warning log — the first open wins. Callers that want to change a stream’s config must close + re-open it.

Source

pub fn open_stream_full( &self, stream_id: u64, reliable: bool, fairness_weight: u8, tx_window: u32, ) -> u64

Extended open that also sets the per-stream TX window for backpressure. tx_window == 0 keeps the pre-backpressure behavior (unbounded local queue).

Returns the epoch of the live StreamState for stream_id — either the fresh one created for a new stream, or the existing one if the stream is already open (first-open-wins). Callers embed this in their Stream handle so later sends can reject stale handles after close+reopen.

Source

pub fn close_stream(&self, stream_id: u64)

Close a stream: mark it inactive and remove its state.

Idempotent — closing a non-existent stream is a no-op. After close, a subsequent open_stream_with creates a fresh stream.

Also records stream_id in the grant-quarantine set so that any StreamWindow grant still in flight from a peer who was communicating with the just-closed lifetime is dropped rather than spuriously crediting a later reopen — see GRANT_QUARANTINE_WINDOW and Self::is_grant_quarantined.

Source

pub fn is_grant_quarantined(&self, stream_id: u64) -> bool

Whether a StreamWindow grant for stream_id should be dropped because the stream was closed within GRANT_QUARANTINE_WINDOW. Lazily garbage-collects expired entries on call.

Source

pub fn evict_idle_streams( &self, max_idle: Duration, max_streams: usize, reason_tag: &'static str, ) -> usize

Remove streams whose last_activity is older than max_idle, keeping the active count at or below max_streams by LRU-evicting the oldest if still over cap. Returns the number of streams evicted. Called from the session owner’s heartbeat loop.

Source

pub fn get_stream(&self, stream_id: u64) -> Option<Ref<'_, u64, StreamState>>

Get stream state (read-only)

Source

pub fn thread_local_pool(&self) -> &SharedLocalPool

Get the thread-local pool for zero-contention packet building

Source

pub fn build_heartbeat(&self) -> Bytes

Build an AEAD-authenticated heartbeat packet for this session.

Routes through thread_local_pool so the heartbeat shares its TX counter with data-path packets — heartbeats and data interleave cleanly on the wire, and the receiver’s replay window admits them in either order.

Wrapping heartbeat construction in this method removes the surface that would otherwise let callers build heartbeats with a fresh PacketBuilder::new(&[0u8; 32], session_id), which (a) would use the wrong key so the receiver’s AEAD verify would reject every heartbeat, and (b) would reuse counter=0 across successive heartbeats so the replay window would reject every heartbeat after the first.

Source

pub fn verify_and_touch_heartbeat(&self, parsed: &ParsedPacket) -> bool

Verify an inbound heartbeat’s AEAD tag against this session’s RX cipher, commit the counter into the replay window, and refresh last_activity. Returns true if the packet was accepted; the session is mutated only on success.

Verify and touch are fused into a single call so callers cannot get the order wrong (verify-then-touch, never the reverse) or forget to touch (which would defeat session idle-timeout for legitimate heartbeats).

Source-address validation (legacy adapter: 1:1 source per session) and any post-accept observation (mesh: failure_detector.heartbeat) remain the caller’s responsibility — those policies vary by adapter and don’t belong inside the helper.

Heartbeats MUST decrypt the AEAD tag rather than be fast- pathed through to failure_detector.heartbeat and session.touch() based on is_heartbeat() alone — without the decrypt step, an off-path attacker who observed the cleartext session_id and source UDP address could spoof heartbeats indefinitely.

Source

pub fn touch(&self)

Update last activity timestamp

Source

pub fn last_activity_ns(&self) -> u64

Nanoseconds since epoch of the last activity. Useful for tests / diagnostics that need to observe whether touch has been called.

Source

pub fn is_timed_out(&self, timeout: Duration) -> bool

Check if session has timed out

Source

pub fn is_active(&self) -> bool

Check if session is active

Source

pub fn deactivate(&self)

Deactivate the session

Source

pub fn stream_ids(&self) -> Vec<u64>

Get all stream IDs

Source

pub fn stream_count(&self) -> usize

Get the number of streams

Trait Implementations§

Source§

impl Debug for NetSession

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more