Skip to main content

Module wire

Module wire 

Source
Expand description

The ASSOCIATE datagram frame codec (ADR-003): the crate’s one framed stage — [len: u16 BE][addr + data] per datagram, both directions of the channel BiStream. CONNECT/BIND are raw pass-through (no framing). Normative WHAT: wire.md §The Data Plane; the binary contract: bast.md (AssociateFrame). The length codec is first-party code shaped on alktunnels’ frame_datagram/DatagramReader (same F-2 behavior; no dependency on it).

The inner bytes are the RFC 1928 address encoding — exactly TargetAddr::to_be_bytes() (ATYP + addr + port; the RFC UDP header minus RSV/FRAG, which ride only vanilla front doors, ADR-003) — followed by the datagram payload.

Framing is applied exactly once, by this layer. The egress seam speaks inner bytes (addr + data, no length prefix — Egress::next_reply returns inner bytes); the producer’s frame writer adds the single length prefix, and the consumer’s send path frames via frame exactly once. The double-framing bug class POC #2 caught (an egress framing its replies, the producer prefixing again — the client parsed the length field as ATYP 0x00) is an API-design invariant: the wire layer owns the length prefix; nothing else adds one.

The joint bound (the load-bearing constraint). The u16 length field covers addr + data, not the payload alone: a frame is rejected (WireError::Oversize, at frame time) whenever len(addr) + len(payload) > 65535. The UDP payload bound alone (65507) does NOT fit u16 unconditionally — a 65507-byte datagram to a 255-character domain is 65507 + 259 = 65766 frame bytes. Max payload per address form: 65276 (domain, 255 chars), 65516 (IPv6), 65528 (IPv4). addr_encoding_len exposes the per-address encoding size so callers can compute the joint bound; no unchecked u16 arithmetic is used on the payload bound.

The F-2 invariant, at payload level. A zero-length payload is a legal empty datagram — a real datagram, never an EOF signal: frame encodes it and DatagramReader decodes it as (addr, empty). (len == 0 — zero inner bytes — is unreachable from a compliant peer, since addr is always ≥ 7 bytes; a wire len of 0 is protocol garbage and surfaces as WireError::EmptyFrame.)

EOF layering. EOF is the channels-level sentinel on the BiStream, outside this codec: the codec never emits zero-length reads, so the sentinel and the datagram stream never collide (an empty datagram and a zero-byte read are different shapes — the reason boundary-preserving framing is mandatory for the datagram stage at all). A stream end mid-frame is the session’s fail-loud truncated-datagram condition (DatagramReader::is_mid_frame is the teardown diagnostic); the codec itself only buffers — it never errors on truncation and never yields a partial frame.

Structs§

DatagramReader
Incremental datagram decoder over the framed stage’s read direction. Feed it whatever read() yields; it reassembles [len: u16 BE][addr + data] frames across chunk boundaries — a frame may be split across chunks, several frames may share one chunk, and partial headers wait for more bytes. Each completed frame is decoded into (TargetAddr, Bytes) — the addr sub-layout (ATYP determines the address length) is split off, the remainder is the datagram payload.

Enums§

WireError
Codec errors. Two families:

Constants§

MAX_INNER_LEN
The u16 length-field bound on a frame’s inner bytes (addr + data): frames whose address encoding plus payload exceed this are rejected at frame time (ADR-003 — never a wire overflow). The joint bound, not a payload bound: see the module docs.

Functions§

addr_encoding_len
The RFC 1928 address encoding’s length for addr (ATYP + addr + port — exactly TargetAddr::to_be_bytes()’s size): 7 bytes for IPv4, 19 for IPv6, 4 + domain.len() for domain form (259 max). Callers compute the joint bound with it: a payload is framable for addr iff addr_encoding_len(addr) + payload.len() <= MAX_INNER_LEN.
frame
Frame one datagram: [len: u16 BE][addr + data] where addr + data is TargetAddr::to_be_bytes() (ATYP + addr + port) followed by payload. One frame per datagram; the single length prefix on this wire (framing-once — see the module docs). A zero-length payload is a legal empty datagram (the F-2 invariant, at payload level). Rejects WireError::Oversize at frame time when len(addr) + len(payload) > 65535 — the joint bound; the payload bound alone (65507) does not fit u16 unconditionally.
frame_inner
Frame pre-encoded inner bytes (addr + data — exactly what crate::egress::Egress::next_reply returns) as one [len: u16 BE][inner] frame. The reply-direction half of the framing-once invariant: the egress speaks inner bytes (no length prefix), and this adds the single prefix at the wire layer. Rejects WireError::Oversize when the inner bytes exceed MAX_INNER_LEN (the u16 length field would wrap).