pub struct PacketBuilder { /* private fields */ }Expand description
Pre-allocated packet builder using counter-based nonces for zero-allocation packet construction.
Implementations§
Source§impl PacketBuilder
impl PacketBuilder
Sourcepub fn with_origin(key: &[u8; 32], session_id: u64, origin_hash: u64) -> Self
pub fn with_origin(key: &[u8; 32], session_id: u64, origin_hash: u64) -> Self
Create a new packet builder with origin identity
Create a packet builder that shares a TX counter with other builders.
All builders sharing the same counter atomically increment it,
preventing nonce reuse when multiple builders encrypt with the
same key (e.g., in a PacketPool or ThreadLocalPool).
Sourcepub fn set_key(&mut self, key: &[u8; 32], session_id: u64)
pub fn set_key(&mut self, key: &[u8; 32], session_id: u64)
Update the encryption key and session ID
Update the encryption key, session ID, and shared counter
Sourcepub fn set_origin_hash(&mut self, origin_hash: u64)
pub fn set_origin_hash(&mut self, origin_hash: u64)
Set the origin hash
Sourcepub fn set_channel_hash(&mut self, channel_hash: u16)
pub fn set_channel_hash(&mut self, channel_hash: u16)
Set the channel hash for outgoing packets
Sourcepub fn build(
&mut self,
stream_id: u64,
sequence: u64,
events: &[Bytes],
flags: PacketFlags,
) -> Bytes
pub fn build( &mut self, stream_id: u64, sequence: u64, events: &[Bytes], flags: PacketFlags, ) -> Bytes
Build a packet from events using counter-based encryption.
This method:
- Writes events to the payload buffer with length prefixes
- Serializes the header once, derives AAD from the serialized bytes
- Encrypts the payload in-place using counter-based nonce
- Patches nonce and payload_len into the serialized header
- Assembles the final packet
Returns the complete packet as Bytes.
§Panics
Panics if events.len() > NetHeader::MAX_EVENTS_PER_PACKET.
Pre-fix this performed events.len() as u16 and
silently wrapped on overflow. A caller passing >65 535
events stored len % 65 536 in the wire event_count
field; the receiver mis-parsed the payload because the
stored count no longer matched the encoded frames. Worse,
a wrapped value below the receiver’s MAX_EVENTS_PER_PACKET
cap (e.g. caller passed 67 562 → wrapped 32 026, which is
> 2027 → noisy reject; but caller passed 65 537 → wrapped
1, which is <= 2027 → silent corruption). The batching
layer above must already enforce the cap; this is a
defense-in-depth panic! so a missed cap surfaces
immediately instead of silently corrupting frames.
Sourcepub fn build_subprotocol(
&mut self,
stream_id: u64,
sequence: u64,
events: &[Bytes],
flags: PacketFlags,
subprotocol_id: u16,
) -> Bytes
pub fn build_subprotocol( &mut self, stream_id: u64, sequence: u64, events: &[Bytes], flags: PacketFlags, subprotocol_id: u16, ) -> Bytes
Build a packet with a subprotocol identifier.
Same as build() but sets subprotocol_id in the Net header,
which is included in the AEAD authenticated data.
§Panics
Panics on events.len() > NetHeader::MAX_EVENTS_PER_PACKET —
see Self::build for the rationale.
Sourcepub fn build_handshake(&mut self, payload: &[u8]) -> Bytes
pub fn build_handshake(&mut self, payload: &[u8]) -> Bytes
Build a handshake packet (unencrypted)
Sourcepub fn build_heartbeat(&mut self) -> Bytes
pub fn build_heartbeat(&mut self) -> Bytes
Build an AEAD-authenticated heartbeat packet.
Heartbeats used to be cleartext (header only, no auth tag) —
the receiver only checked source == peer_addr (UDP source,
spoofable) and session_id match (64-bit, observable in
flight). An off-path attacker who guessed or observed the
session_id could call session.touch() indefinitely,
defeating both the idle timeout and the failure detector.
Now: encrypt an empty payload with the session’s TX cipher so the heartbeat carries a 16-byte Poly1305 tag over the header’s AAD. An off-path attacker without the session key cannot forge a tag that decrypts.
Sourcepub fn max_events_for_size(&self, avg_event_size: usize) -> usize
pub fn max_events_for_size(&self, avg_event_size: usize) -> usize
Get the maximum number of events that can fit in a single packet
Sourcepub fn session_id(&self) -> u64
pub fn session_id(&self) -> u64
Get the session ID