pub struct SessionManager { /* private fields */ }Expand description
Manages authenticated peer sessions with dual-index tracking.
Sessions are indexed by:
- Session nonce (primary key, unique per session)
- Identity key (secondary index, one-to-many)
This allows lookup by either nonce or identity key, with the identity key lookup returning the “best” session (preferring authenticated ones).
Implementations§
Source§impl SessionManager
impl SessionManager
Sourcepub fn with_config(idle_ttl_ms: u64, seen_nonce_cap: usize) -> Self
pub fn with_config(idle_ttl_ms: u64, seen_nonce_cap: usize) -> Self
Create a new empty SessionManager with an explicit idle TTL and per-session replay seen-set cap. Used by tests and by callers that want a tighter reaping policy.
Sourcepub fn idle_ttl_ms(&self) -> u64
pub fn idle_ttl_ms(&self) -> u64
The configured idle TTL in milliseconds.
Sourcepub fn add_session(&mut self, session: PeerSession)
pub fn add_session(&mut self, session: PeerSession)
Add a session to the manager.
Indexes by session_nonce (primary) and peer_identity_key (secondary). Does NOT overwrite existing sessions for the same identity key, allowing multiple concurrent sessions per peer.
Sourcepub fn get_session(&self, nonce: &str) -> Option<&PeerSession>
pub fn get_session(&self, nonce: &str) -> Option<&PeerSession>
Get a session by nonce (immutable reference).
Sourcepub fn get_session_mut(&mut self, nonce: &str) -> Option<&mut PeerSession>
pub fn get_session_mut(&mut self, nonce: &str) -> Option<&mut PeerSession>
Get a session by nonce (mutable reference).
Sourcepub fn get_sessions_for_identity(&self, identity_key: &str) -> Vec<&PeerSession>
pub fn get_sessions_for_identity(&self, identity_key: &str) -> Vec<&PeerSession>
Get all sessions for a given identity key.
Sourcepub fn get_session_by_identifier(
&self,
identifier: &str,
) -> Option<&PeerSession>
pub fn get_session_by_identifier( &self, identifier: &str, ) -> Option<&PeerSession>
Get the “best” session for an identity key (prefers authenticated).
Matches TS SDK SessionManager.getSession() behavior: if the identifier is a session nonce, returns that exact session. If it is an identity key, returns the best (authenticated preferred) session.
Sourcepub fn has_session(&self, nonce: &str) -> bool
pub fn has_session(&self, nonce: &str) -> bool
Check if a session exists for a given nonce.
Sourcepub fn has_session_by_identifier(&self, identifier: &str) -> bool
pub fn has_session_by_identifier(&self, identifier: &str) -> bool
Check if any session exists for a given identifier (nonce or identity key).
Sourcepub fn update_session(&mut self, nonce: &str, session: PeerSession)
pub fn update_session(&mut self, nonce: &str, session: PeerSession)
Replace a session at the given nonce.
Sourcepub fn remove_session(&mut self, nonce: &str) -> Option<PeerSession>
pub fn remove_session(&mut self, nonce: &str) -> Option<PeerSession>
Remove a session by nonce. Returns the removed session if found.
Also drops the session’s replay/activity metadata, freeing its seen-set.
Sourcepub fn touch(&mut self, session_nonce: &str, now_ms: u64)
pub fn touch(&mut self, session_nonce: &str, now_ms: u64)
Record activity on an existing session, creating its metadata if absent
and advancing last_used_ms to now_ms. No-op if the session is unknown.
Call this right after a handshake adds/promotes a session so that idle reaping has a baseline, and on every accepted message thereafter.
Sourcepub fn is_expired(&self, session_nonce: &str, now_ms: u64) -> bool
pub fn is_expired(&self, session_nonce: &str, now_ms: u64) -> bool
True if the session has recorded activity AND has been idle longer than the configured TTL. A session with no recorded activity yet (freshly added, not touched) is treated as fresh (not expired).
Sourcepub fn get_active_session(
&self,
identifier: &str,
now_ms: u64,
) -> Option<&PeerSession>
pub fn get_active_session( &self, identifier: &str, now_ms: u64, ) -> Option<&PeerSession>
Look up a session by identifier (nonce or identity key) honoring the
idle TTL: returns None if the session is missing OR has gone idle past
the TTL. The hot verify path uses this so a stale/captured yourNonce
stops resolving a live session once the TTL lapses.
Sourcepub fn mark_message_seen(
&mut self,
session_nonce: &str,
message_nonce: &str,
now_ms: u64,
) -> MarkSeen
pub fn mark_message_seen( &mut self, session_nonce: &str, message_nonce: &str, now_ms: u64, ) -> MarkSeen
Anti-replay check-and-insert for a single per-message nonce, scoped to a
session. Atomic under &mut self (the caller’s brief write lock), so
concurrent verifies of the SAME captured message resolve to exactly one
MarkSeen::Fresh and the rest MarkSeen::Replay.
The effective replay key is (peer_identity_key, session_nonce, message_nonce): session_nonce selects the per-session set (which is
itself bound to one peer identity via the handshake), and message_nonce
is the fresh 32-byte random nonce an honest sender mints per outbound
message — so a legit sender never collides and only a byte-replay repeats.
Advances last_used_ms and enforces the per-session FIFO cap. Only call
AFTER the message signature has verified, so the set is never poisoned by
unauthenticated input.
Sourcepub fn reap_idle(&mut self, now_ms: u64) -> usize
pub fn reap_idle(&mut self, now_ms: u64) -> usize
Evict every session idle longer than the configured TTL, freeing each one’s replay seen-set. Returns the number reaped.
Intended to be called on the low-frequency handshake path (not the hot verify path), which bounds memory without serializing message verifies.