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

3.4 KiB
Raw Blame History

id, name, status, depends_on, scope, risk, impact, level, tags
id name status depends_on scope risk impact level tags
tunnels/fix-udp-framed-adapter U-1 remediation — make UdpHalf the FRAMED adapter (ADR-003 at the local boundary) pending
tunnels/review-impl
moderate medium component implementation
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)