pub struct Session { /* private fields */ }Expand description
Session - virtual association between two endpoints
Implementations§
Source§impl Session
impl Session
Sourcepub fn new(
session_id: SessionId,
shared_secret: &[u8; 32],
peer_side: bool,
) -> Result<Self, CoreError>
pub fn new( session_id: SessionId, shared_secret: &[u8; 32], peer_side: bool, ) -> Result<Self, CoreError>
Create a new session with given shared secret
Sourcepub fn from_derived(
session_id: SessionId,
crypto: CryptoState,
scheduler_mode: SchedulerMode,
traffic_secret: [u8; 32],
is_server: bool,
) -> Self
pub fn from_derived( session_id: SessionId, crypto: CryptoState, scheduler_mode: SchedulerMode, traffic_secret: [u8; 32], is_server: bool, ) -> Self
Create session from a pre-derived crypto state (e.g., after handshake).
traffic_secret is the master from which the supplied crypto was
derived — it seeds the rekey HKDF chain. is_server
records which side of the handshake we are; rekey re-derives keys
with the same side so per-direction layout is preserved.
Sourcepub fn resume(
session_id: SessionId,
resumption_secret: &[u8; 32],
peer_side: bool,
) -> Result<Self, CoreError>
pub fn resume( session_id: SessionId, resumption_secret: &[u8; 32], peer_side: bool, ) -> Result<Self, CoreError>
Resume a session using resumption secret (0-RTT)
Sourcepub fn state(&self) -> SessionState
pub fn state(&self) -> SessionState
Get current state
Sourcepub fn set_state(&self, new_state: SessionState)
pub fn set_state(&self, new_state: SessionState)
Transition to a new state
Sourcepub fn open_stream(&self) -> Arc<Stream>
pub fn open_stream(&self) -> Arc<Stream>
Open a new stream
Sourcepub fn close_stream(&self, stream_id: StreamId) -> bool
pub fn close_stream(&self, stream_id: StreamId) -> bool
Close a stream
Sourcepub fn stream_count(&self) -> u32
pub fn stream_count(&self) -> u32
Get number of active streams
Sourcepub fn replay_rejected_total(&self) -> u64
pub fn replay_rejected_total(&self) -> u64
Total number of replayed packets rejected by the sliding-window check
across all streams in this session. Intended for the
replay_rejected_total metric.
Sourcepub fn current_epoch(&self) -> u8
pub fn current_epoch(&self) -> u8
Current rekey generation (Phase 1.5). Starts at 0; each successful
rekey increments by one. Carried on the wire in
PacketHeader.epoch so the peer can match the right derived key.
Sourcepub fn is_server(&self) -> bool
pub fn is_server(&self) -> bool
Whether this session is acting as the server side. Determined at construction; required for re-deriving per-direction keys on rekey.
Sourcepub fn rekey(&self) -> Result<u8, CoreError>
pub fn rekey(&self) -> Result<u8, CoreError>
Mid-session key rotation (Phase 1.5).
Derives the next traffic secret from the current one via
HKDF-Expand(current, "phantom-rekey-v1", 32) and builds a fresh
CryptoState under that secret. The new state is installed via
an atomic ArcSwap::store, so concurrent encrypt/decrypt calls
observe either the old or the new state — never a partially-written
in-between. The previous traffic secret is explicitly zeroed before
being overwritten.
Returns the new epoch (1, 2, 3, …). Wraps an error if the epoch
counter has saturated u8::MAX (after 255 successful rekeys —
equivalent to ~5 days at the default 30-minute cadence; long-lived
sessions are expected to reconnect rather than wrap).
Wire signalling: callers that want the peer to follow this rekey
emit a V2 packet whose header carries the new epoch (and optionally
the PacketFlags::REKEY flag). Receivers respond by calling
rekey() themselves once they see the bump — keeping both ends in
lockstep.
Sourcepub fn send_invocations(&self) -> u64
pub fn send_invocations(&self) -> u64
Send-side AEAD invocation count for the current epoch (resets to 0 on
each rekey). Drives send_needs_rekey.
Sourcepub fn rekey_threshold(&self) -> u64
pub fn rekey_threshold(&self) -> u64
The send-invocation high-watermark at which the pump auto-rekeys.
Sourcepub fn set_rekey_threshold(&self, n: u64)
pub fn set_rekey_threshold(&self, n: u64)
Override the auto-rekey high-watermark (default REKEY_SOFT_LIMIT).
Clamped to >= 1. Rust-only — primarily for tests/soak harnesses that
need to exercise mid-session rekey without sending 2^47 packets.
Sourcepub fn set_seq_rekey_watermark(&self, n: u32)
pub fn set_seq_rekey_watermark(&self, n: u32)
Override the per-stream sequence rekey watermark (default
SEQ_REKEY_WATERMARK, 2^31). Clamped to >= 1. Rust-only — primarily
for tests/soak harnesses that need to exercise the per-stream forced rekey
(C1) without driving a single stream through 2^31 sequence numbers.
Sourcepub fn stream_seq_needs_rekey(&self, stream_id: StreamId, seq: u32) -> bool
pub fn stream_seq_needs_rekey(&self, stream_id: StreamId, seq: u32) -> bool
True once stream_id’s sequence has advanced past the per-stream
watermark within the current epoch (C1). The send path checks this before
stamping each packet and, when set, forces a rekey so a
per-stream u32 sequence can never wrap within one epoch — which would
otherwise repeat the AEAD nonce (epoch, stream_id, sequence, path_id)
under a fixed key (Invariant 8).
The per-stream (epoch, base) checkpoint is rebased lazily on the first
call after an epoch change, so the measured span is always relative to
where the stream entered the current epoch.
Sourcepub fn send_needs_rekey(&self) -> bool
pub fn send_needs_rekey(&self) -> bool
True once the send direction has crossed the rekey high-watermark and the
epoch has room to advance. The data pump checks this before each
application send and, when set, rekeys + flags the packet REKEY so the
peer follows via the authenticated epoch bump.
Sourcepub fn decrypt_packet_accepting_rekey(
&self,
header: &PacketHeader,
ciphertext: &[u8],
) -> Result<Vec<u8>, CoreError>
pub fn decrypt_packet_accepting_rekey( &self, header: &PacketHeader, ciphertext: &[u8], ) -> Result<Vec<u8>, CoreError>
Decrypt a packet, transparently following an authenticated forward
rekey of up to MAX_REKEY_CATCHUP epochs (C1).
header.epoch == current: ordinarydecrypt_packet.current < header.epoch <= current + MAX_REKEY_CATCHUP: derive the candidate key that many epochs ahead and trial-decrypt. Only on AEAD success — i.e. once the epoch bump is proven authentic — is the rekey committed and the replay window consulted (Invariant 4 ordering preserved). A forgedheader.epochfails the AEAD open, nothing is committed, and the session does not desync. The bound caps an attacker to at mostMAX_REKEY_CATCHUPHKDF steps per spoofed packet.- anything else (behind current, more than
MAX_REKEY_CATCHUPahead, or epoch saturated): rejected. Over a reliable transport the sender retransmits at the then-current epoch, so no data is lost.
Sourcepub fn ratchet_to_epoch(&self, target: u8) -> Result<(), CoreError>
pub fn ratchet_to_epoch(&self, target: u8) -> Result<(), CoreError>
Advance to a specific target epoch by repeatedly applying the rekey HKDF chain. Used by the receive path to “catch up” when it sees a packet from a higher epoch than the locally known one. Refuses to go backwards (a lower target than current returns Ok without changes).
Sourcepub fn validated_paths(&self) -> Vec<u8> ⓘ
pub fn validated_paths(&self) -> Vec<u8> ⓘ
Snapshot of currently Validated path ids. Useful for the
scheduler when picking an outbound path.
Sourcepub fn path_state(&self, path_id: u8) -> Option<PathStateKind>
pub fn path_state(&self, path_id: u8) -> Option<PathStateKind>
State of a specific path within this session. Returns None for
path ids the session has never observed.
Sourcepub fn begin_path_validation(&self, path_id: u8) -> Option<[u8; 32]>
pub fn begin_path_validation(&self, path_id: u8) -> Option<[u8; 32]>
Register a new path id and immediately issue a 32-byte
PATH_CHALLENGE for it. Returns the challenge bytes; the caller
must transmit them in a V2 packet with PacketFlags::PATH_VALIDATION
set on the new path. Subsequent calls on an already-Validating
path re-issue a fresh challenge.
Returns None if the path is in a terminal state (Validated
or Failed).
Sourcepub fn complete_path_validation(&self, path_id: u8, response: &[u8]) -> bool
pub fn complete_path_validation(&self, path_id: u8, response: &[u8]) -> bool
Verify a peer’s PATH_VALIDATION response. Returns true if
the response matches the in-flight challenge (path is now
Validated). Returns false otherwise — the path may have
transitioned to Failed.
Sourcepub fn mark_path_seen(&self, path_id: u8)
pub fn mark_path_seen(&self, path_id: u8)
Record that a packet was observed on the path. Cheap to call
per-packet — used by the data pump to keep last_packet_seen
fresh for the timeout sweep.
Sourcepub fn pacer(&self) -> Arc<Pacer>
pub fn pacer(&self) -> Arc<Pacer>
Shared handle to this session’s outbound rate-limiter. Cheap to
clone (Arc). The data pump consults this before every outbound
packet; idle by default (Pacer::unlimited).
Sourcepub fn on_packet_sent(&self, bytes: u64)
pub fn on_packet_sent(&self, bytes: u64)
Record that a packet of bytes length is going on the wire.
Feeds the BBR-style bandwidth estimator. Cheap (one mutex lock
- a counter increment).
Sourcepub fn on_packet_acked(&self, sample: DeliverySample) -> u64
pub fn on_packet_acked(&self, sample: DeliverySample) -> u64
Record that an ACK arrived with delivery sample sample. The
returned u64 is the updated bottleneck bandwidth estimate; we
reflect it into the pacer so the outbound rate tracks the
peer’s actual receive throughput.
Sourcepub fn on_packet_lost(&self, bytes: u64)
pub fn on_packet_lost(&self, bytes: u64)
Record that a packet of bytes length was lost (no ACK before
retransmit timer fired). Drives BBR’s loss-based feedback.
Sourcepub fn bbr_state(&self) -> BbrState
pub fn bbr_state(&self) -> BbrState
Current BBR congestion-control state. Observability / test hook — lets
callers confirm a loss drove the estimator into FastRecovery.
Sourcepub fn bandwidth_snapshot(&self) -> BandwidthSnapshot
pub fn bandwidth_snapshot(&self) -> BandwidthSnapshot
Read a snapshot of the bandwidth / pacing estimator. Cheap; held over a single mutex lock.
Sourcepub fn send_notifier(&self) -> Arc<Notify>
pub fn send_notifier(&self) -> Arc<Notify>
Shared handle to the outbound-ready notify. The API-layer data
pump awaits this via Notify::notified(); any task with the
handle can wake it instantly via Self::notify_outbound_ready.
Sourcepub fn notify_outbound_ready(&self)
pub fn notify_outbound_ready(&self)
Wake the data pump’s send loop immediately so it can drain newly-
queued packets instead of waiting for the next 10 ms tick. Cheap
(a single notify_one()); duplicate calls collapse to one wake.
Sourcepub fn encrypt_packet(
&self,
header: &PacketHeader,
plaintext: &[u8],
) -> Result<Vec<u8>, CoreError>
pub fn encrypt_packet( &self, header: &PacketHeader, plaintext: &[u8], ) -> Result<Vec<u8>, CoreError>
Encrypt a packet payload.
The AEAD nonce is derived from the authenticated (epoch, stream_id, sequence, path_id) fields of the packet header rather than from an
internal monotonic counter, so a failed peer decrypt never desyncs the
receiver. The AAD is the 45-byte wire image of the header
(PacketHeader::to_wire), so any wire-level mutation invalidates the tag.
Sourcepub fn decrypt_packet(
&self,
header: &PacketHeader,
ciphertext: &[u8],
) -> Result<Vec<u8>, CoreError>
pub fn decrypt_packet( &self, header: &PacketHeader, ciphertext: &[u8], ) -> Result<Vec<u8>, CoreError>
Decrypt a packet payload. Performs AEAD verify + per-stream sliding-window replay rejection (the window check runs after a successful AEAD open — Invariant 4 — so we never key off un-authenticated sequence numbers).
A failed decrypt does NOT desync future decrypts: the AEAD nonce is derived from this packet’s authenticated header fields, so the receiver stays in lock-step with the sender regardless of intervening bad packets.
Sourcepub fn create_control_packet(
&self,
_message: ControlMessage,
payload: Vec<u8>,
) -> PhantomPacket
pub fn create_control_packet( &self, _message: ControlMessage, payload: Vec<u8>, ) -> PhantomPacket
Create a control packet
Sourcepub fn set_resumption_secret(&self, secret: [u8; 32])
pub fn set_resumption_secret(&self, secret: [u8; 32])
Set resumption secret for 0-RTT.
If a secret was already set, the previous bytes are explicitly zeroed
before being replaced — defense in depth in case set_resumption_secret
is called multiple times within a session.
Sourcepub fn resumption_secret(&self) -> Option<[u8; 32]>
pub fn resumption_secret(&self) -> Option<[u8; 32]>
The resumption secret for 0-RTT, if one has been installed. Rust-only —
the FFI surface exposes this via PhantomSession::resumption_hint().
Sourcepub fn can_resume(&self) -> bool
pub fn can_resume(&self) -> bool
Check if session can be resumed (has resumption secret)
Sourcepub fn resumption_hint(&self) -> Option<([u8; 32], [u8; 32])>
pub fn resumption_hint(&self) -> Option<([u8; 32], [u8; 32])>
Extract the resumption hint needed to attempt 0-RTT resume on
a future connect (Phase 4.1). Returns Some((session_id_bytes, resumption_secret)) only after a successful handshake — the
resumption_secret is set by process_client_hello /
process_server_hello once shared key material is in place.
The caller is responsible for storing the tuple alongside the
pinned HybridVerifyingKey of the server it was negotiated
with. Mixing tickets across servers is a configuration bug —
the resumption_secret is server-pinned.
Sourcepub fn update_activity(&self)
pub fn update_activity(&self)
Update last activity timestamp
Sourcepub fn is_expired(&self, timeout: Duration) -> bool
pub fn is_expired(&self, timeout: Duration) -> bool
Check if session is expired