docs: codec direction set — raw pass-through (TCP) + u16 length prefix (UDP)
Structural rationale: alktty's 5-byte header is a sub-demux key for five logical streams sharing one BiStream; a tunnel has exactly one data stream per direction, so no type byte. TCP needs no length prefix (channels already length-prefixes every chunk). UDP needs boundary re-framing only, and u16 suffices (UDP max payload 65507). Wire overhead table: tunnel TCP = 8 B/chunk total (channels header only), tunnel UDP = 10 B/datagram, vs alktty's 13 B. udpgw calibration: 5 B + per-datagram address. Trade-offs accepted: no in-band control path for TCP channels ever (post-ADR-049 this is clean; escape hatch = new ALPN, not a wire change); sentinel collision does not exist (UDP len=0 = empty datagram, legal; EOF is the channels-level sentinel on the BiStream at a different layer); future multi-endpoint UDP gateway framing lives inside datagram payloads (udpgw precedent). Residual for the Phase 1 codec ADR: empty-datagram semantics; u16 BE over varint (leaned, MTU-bounded anyway).
This commit is contained in:
@@ -233,11 +233,54 @@ Implications:
|
||||
split/pump plumbing is tokio-async, no substrate types in the
|
||||
protocol layer. Same as alktty.
|
||||
|
||||
Open: whether the tunnel codec is *literally* alktty's 5-byte format
|
||||
with different stream-type constants (reuse), a stripped 5-byte
|
||||
variant (1 stream type + ctrl), or raw pass-through with framing only
|
||||
for UDP (the OQ-TN-01 reframe suggests TCP needs nothing beyond the
|
||||
channels chunk stream). Phase 1 ADR, before the first consumer.
|
||||
**Codec direction set 2026-09-06 (discussion): raw pass-through for
|
||||
stream substrates, `u16` length-prefix for UDP — no 5-byte header.**
|
||||
Phase 1 ADR, before the first consumer.
|
||||
|
||||
Rationale (structural, not stylistic): alktty's 5-byte
|
||||
`[stream_type:u8][len:u32]` exists because five logical streams share
|
||||
one `BiStream` — the type byte is a sub-demux key. A tunnel has
|
||||
exactly one data stream per direction (the channel's own read/write
|
||||
halves), so there is nothing to demux and no per-chunk type byte. TCP
|
||||
needs no length prefix either: the channels layer already
|
||||
length-prefixes every chunk (8-byte header), so the codec is pure
|
||||
pass-through. Only UDP needs boundary re-framing (datagram boundaries
|
||||
do not survive the chunk stream), and `u16` suffices — UDP's max
|
||||
payload is 65507 < 65535.
|
||||
|
||||
Per-chunk wire overhead (data chunks, both directions):
|
||||
|
||||
| | channels header | tunnel codec | total |
|
||||
|---|---|---|---|
|
||||
| alktty in channels | 8 B | 5 B (type + len) | 13 B |
|
||||
| tunnel TCP | 8 B | **0 B** | 8 B |
|
||||
| tunnel UDP | 8 B | **2 B** (len:u16) | 10 B |
|
||||
|
||||
Calibration: udpgw's packet header is 5 bytes + a per-datagram SOCKS5
|
||||
address (its CONN_ID/FLAGS vocabulary is dropped per OQ-TN-02); a
|
||||
DNS-sized datagram (~100 B) pays ~3% for boundary framing.
|
||||
|
||||
Trade-offs accepted:
|
||||
- **No in-band control path for TCP channels, ever** (any future
|
||||
mid-stream signaling is a wire break). Post-ADR-049 this is clean —
|
||||
establishment is call-level (`channel:open_failed`), the survey
|
||||
found no mid-stream control need, and the escape hatch is
|
||||
protocol-level (a new ALPN is cheap; a wire change is not). The
|
||||
udpgw KEEPALIVE/ERR vocabulary is dropped per OQ-TN-02.
|
||||
- **Sentinel collision does not exist** across layers: the UDP codec's
|
||||
`len=0` means *empty datagram* (legal in UDP; DNS uses it, e.g. TCP
|
||||
length-prefix `0`), while EOF is the channels-level sentinel on the
|
||||
`BiStream` (`length=0` in the channels 8-byte header). They live at
|
||||
different layers and do not interact.
|
||||
- UDP-specific framing lives only in the UDP path; a hypothetical
|
||||
future multi-endpoint UDP gateway resource would carry its own
|
||||
self-describing framing *inside* the datagram payloads (udpgw
|
||||
precedent, OQ-TN-02) — invisible to this base codec.
|
||||
|
||||
Remaining for the Phase 1 codec ADR: confirm `len=0` empty-datagram
|
||||
semantics (send allowed? receive maps to a zero-payload datagram),
|
||||
and whether the UDP length prefix rides `u16 BE` (leaned) or a varint
|
||||
(rejected for v1 simplicity — datagrams are MTU-bounded anyway).
|
||||
|
||||
## Open Questions
|
||||
|
||||
@@ -754,9 +797,14 @@ Candidate reading for the research specialist (to be expanded):
|
||||
unknown_resource / resource_shortage / handler_error / timeout),
|
||||
never a phantom channel. Residual for Phase 1: half-open
|
||||
semantics only; v1 needs no mid-stream control frame
|
||||
- [ ] Codec decision (from the alktty pattern prior art) — reuse
|
||||
5-byte format vs stripped variant vs raw pass-through + UDP
|
||||
framing; feeds OQ-TN-07 (ALPN) and the OQ-TN-05 trait shape
|
||||
- [x] Codec direction set (from the alktty pattern prior art) — raw
|
||||
pass-through for stream substrates (0 B tunnel overhead),
|
||||
`[len:u16 BE]` per datagram for UDP (2 B); no 5-byte header (a
|
||||
tunnel has one data stream per direction — no sub-demux key
|
||||
needed). Residual for the Phase 1 ADR: empty-datagram
|
||||
(`len=0`) semantics. Feeds OQ-TN-07 (option A strengthened:
|
||||
substrate discriminator in params selects the framing) and the
|
||||
OQ-TN-05 trait shape
|
||||
- [ ] Decision input: backend trait vs no-trait (OQ-TN-05), now
|
||||
including the hub re-produce composition question
|
||||
- [ ] Targeted POC(s) run + summary (OQ-TN-10) — UDP first, reverse
|
||||
|
||||
Reference in New Issue
Block a user