From 20672be48c16c52c7ddca4df08bf1bfa77edfe6c Mon Sep 17 00:00:00 2001 From: "glm-5.3-flash" Date: Mon, 7 Sep 2026 07:21:25 +0000 Subject: [PATCH] =?UTF-8?q?docs:=20codec=20direction=20set=20=E2=80=94=20r?= =?UTF-8?q?aw=20pass-through=20(TCP)=20+=20u16=20length=20prefix=20(UDP)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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). --- docs/research/phase-0-findings.md | 64 +++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/docs/research/phase-0-findings.md b/docs/research/phase-0-findings.md index c3467e7..33718d3 100644 --- a/docs/research/phase-0-findings.md +++ b/docs/research/phase-0-findings.md @@ -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