Files
alktunnels/tasks/tunnels/fix-udp-framed-adapter.md
T
glm-5.3-flash a0f939c6df review: phase-gate review 001 — spec conformance of the v1 implementation
Findings + review doc: docs/reviews/001-implementation-review.md (the
alkcall house pattern). Closes tunnels/review-core-crates and
tunnels/review-impl.

Findings:
- U-1 [major, NOT fixed] — the local UDP adapter is not the framed
  adapter ADR-003 mandates: codec-framed bytes reach real targets,
  empty datagrams are EOF-shaped at the adapter (tunnel teardown),
  >8 KiB datagrams split, unframed target-initiated datagrams are
  dropped. Executable-pinned by real-socket probes (temporary test,
  deleted after the run). Remediation task: tunnels/fix-udp-framed-adapter.
- C-1 [major, fixed] — AcceptQueue::pop lost wakeup in the
  check→register window (open op hangs to the establishment bound);
  fixed via the tokio notify_waiters contract (Notified created before
  the check each iteration) + multi-thread regression test.
- N-4/N-5/N-7/N-8/N-9/N-10/N-11 [minor, fixed] — serialize TunnelParams
  in open_reverse_channel; stale doc ref; broken doc link; root
  re-exports (TunnelParams/Substrate/tunnel_open_spec/OP_TUNNEL_OPEN);
  README (publish dry-run was failing on the missing readme); harness
  comment; pump_against UDP framing doc note.
- N-2 retracted by executable falsification (codec buffering is
  bounded by construction); N-6 non-finding with rationale.

Verified: 63 tests default / 70 with --features local, 3x repeat-run
clean both configs; clippy -D warnings (all-targets + wasm32); fmt;
doc warning-free; wasm32 check; cargo publish --dry-run passes.
2026-09-08 10:58:11 +00:00

82 lines
3.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: tunnels/fix-udp-framed-adapter
name: "U-1 remediation — make UdpHalf the FRAMED adapter (ADR-003 at the local boundary)"
status: pending
depends_on: [tunnels/review-impl]
scope: moderate
risk: medium
impact: component
level: implementation
tags: [local, udp, codec, adr-003, review-remediation]
---
## Description
Review 001 finding U-1 (`docs/reviews/001-implementation-review.md`):
the `local` feature's `UdpHalf` (`src/local/mod.rs`) is NOT the framed
adapter ADR-003 mandates at the substrate boundary — it is
boundary-preserving (one datagram per poll_read/poll_write) but raw.
The `[len: u16 BE]` codec exists only on the session side, so
UDP-over-`local` tunnels:
1. deliver codec-framed bytes to real targets (the target sees
`[len]payload`, not payload — executable-pinned in the review
probes);
2. tear the tunnel down on an empty datagram (a raw zero-length
datagram is `Ok(())` with 0 bytes filled = EOF-shaped to
`tokio::io::copy` — the F-2 violation end-to-end; the session-side
codec exists precisely to prevent this);
3. split datagrams > ~8 KiB at the target (`tokio::io::copy`'s
`DEFAULT_BUF_SIZE` bounds each read; the raw adapter sends each
chunk as its own datagram);
4. silently drop unframed target-initiated datagrams (the session
codec parses a raw datagram's first two bytes as a length header).
The session-side tests pass because the harness's
`framed_udp_echo_dial` frames symmetrically at the test boundary — a
correct-shape stand-in for what `connect_udp` itself must do.
### The fix
Apply ADR-003's placement: `UdpHalf::poll_write` frames the caller's
buffer (`frame_datagram`) and sends one datagram per framed frame;
`poll_read` de-frames (feed `DatagramReader`, emit the next payload).
Both halves of the association then speak the same framing; `len=0`
becomes a 2-byte frame (unambiguous with EOF — the F-2 fix
end-to-end).
### Verification gates (from the review)
1. A recording UDP echo server asserts the datagrams it receives are
**payload bytes only** and an **empty datagram round-trips**
(session `recv_datagram` yields `Some(b"")`, channel alive).
2. A >8 KiB datagram round-trips as ONE datagram at the target.
3. An unframed target-initiated datagram resolves at the session.
4. The existing `local_halves` suite stays green unchanged (its
session-level round-trips are framing-symmetric today).
5. `cargo test` + `--features local` + wasm checks as usual; 3×
repeat-run stable.
### Riders (from the same review, same file)
- U-2: `connect_udp` binds `("0.0.0.0", 0)` — resolve the target
family first (or document the v4-only posture).
- U-3: size the recv scratch to the codec's MTU discipline instead of
a per-tunnel 65535-byte allocation (or justify the bound).
## Acceptance Criteria
- [ ] `UdpHalf` frames on write and de-frames on read (ADR-003's
placement; the pump stays raw)
- [ ] The 5 verification gates pass; suites green 3× in both configs
- [ ] U-2/U-3 riders resolved or explicitly deferred with rationale
- [ ] Review 001's U-1/U-2/U-3/N-1 sections get resolution notes
## References
- `docs/reviews/001-implementation-review.md` §U-1 (executable-pinned
probe evidence), §U-2, §U-3, §N-1
- `docs/architecture/decisions/003-codec-and-udp-framing.md` (the
framed-adapter mandate + F-2), `docs/architecture/wire.md`
§Datagram substrate
- `src/local/mod.rs` (`UdpHalf`), `src/wire.rs` (the codec to compose)