feat: local-socket-halves — the local feature (TCP/UDP/unix halves functions)
- src/local/mod.rs (feature = "local" -> tokio/net): dial_tcp (5s timeout), connect_udp (ephemeral bind + connect + the FRAMED UdpHalf adapter), dial_unix (OQ-TN-14 in v1), bind_tcp + TcpListenerHalves::accept_loop (the listen shape's assembly half), local_dial() (one DialFn covering all three substrates). - UdpHalf truncation fails loud (OQ-TN-13): poll_read recvs into a scratch buffer first and size-checks against the caller's buffer — an over-size datagram is io::ErrorKind::InvalidData, never a silent truncation (tokio's poll_recv-into-ReadBuf would truncate). - No socket type appears outside src/local/ (convention 16); the default crate stays wasm-clean; stdio bridging is NOT here (alktty owns process stdio). - Tests (tests/local_halves.rs, 7, feature-gated): TCP/UDP/unix dial round-trips through the real establisher path, the 1400-byte MTU datagram, the truncation fail-loud probe, dial-refusal -> dial_failed, listen producer over a real TCP listener end-to-end. Verified: cargo test green (default + --all-features, 44 + 7), clippy -D warnings (default + all-features + wasm32), fmt clean, cargo check --target wasm32-unknown-unknown passes.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: tunnels/local-socket-halves
|
||||
name: "local feature — real socket halves functions (TCP dial, UDP connect, unix)"
|
||||
status: pending
|
||||
status: completed
|
||||
depends_on: [tunnels/producer-open-op, tunnels/wire-codec]
|
||||
scope: moderate
|
||||
risk: medium
|
||||
@@ -104,6 +104,51 @@ POC's sizing test).
|
||||
|
||||
> Agent fills during implementation.
|
||||
|
||||
- **`bind_tcp` + `TcpListenerHalves::accept_loop(queue)`** complete the
|
||||
listen side (the task surface sketched `bind`/`accept_fn`): the
|
||||
accept loop is a spawned task feeding an [`AcceptQueue`] — the
|
||||
protocol-side queue contract from producer-listen. The assembly
|
||||
layer aborts the task on teardown; accept errors end the loop.
|
||||
- **`UdpHalf` truncation probe** (OQ-TN-13): `poll_read` recvs into a
|
||||
64KiB scratch buffer first, then size-checks against the caller's
|
||||
buffer — a >buffer datagram is `io::ErrorKind::InvalidData`, never
|
||||
a silent truncation. (`tokio`'s `poll_recv`-into-ReadBuf truncates
|
||||
silently, which is exactly the invariant F-2/OQ-TN-13 forbids.)
|
||||
WouldBlock polls `poll_recv_ready` for waker registration.
|
||||
- **The task sketch's `TcpListenerHalves::accept_fn(&self, queue)`
|
||||
became `accept_loop(&self, queue)`** (an owned async loop to spawn)
|
||||
— the `accept_fn` borrow-shape fought the spawn model; the loop
|
||||
returning on listener failure is the assembly-abort contract.
|
||||
- **Test plumbing note** (tests): the listen-over-real-socket test
|
||||
drives the client socket via std `try_clone` BEFORE `from_std`
|
||||
(O_NONBLOCK is shared across dup — both ends go async); the session
|
||||
uses borrowed halves (the producer's wrapper-managed pump already
|
||||
pumps channel <-> accepted handle; `pump_against` there would loop
|
||||
the same socket back into itself).
|
||||
|
||||
## Summary
|
||||
|
||||
> Agent fills this on completion.
|
||||
> Agent fills this on completion.
|
||||
|
||||
Implemented the `local` feature (src/local/mod.rs, feature =
|
||||
`["tokio/net"]`): `dial_tcp` (5s timeout), `connect_udp` (ephemeral
|
||||
bind + connect + the FRAMED `UdpHalf` adapter — truncation fails
|
||||
loud), `dial_unix` (OQ-TN-14 in v1), `bind_tcp`/`TcpListenerHalves::
|
||||
accept_loop` (the listen shape's assembly half), and `local_dial()`
|
||||
(the one `DialFn` covering all three substrates). No socket type
|
||||
appears outside `src/local/` (convention 16: the module is never
|
||||
imported from producer/consumer/shared; `TargetHandle` re-used from
|
||||
producer.rs). Stdio bridging is NOT here (alktty's pipe mode owns
|
||||
process stdio).
|
||||
|
||||
Tests: `tests/local_halves.rs` (7, `#![cfg(feature = "local")]`) —
|
||||
TCP dial round-trip through the real establisher path, UDP framed
|
||||
round-trip, the 1400-byte MTU datagram, unix dial round-trip, the
|
||||
OQ-TN-13 truncation fail-loud probe (60k datagram vs 16KiB read →
|
||||
InvalidData), dial-refusal → `dial_failed`, and the listen producer
|
||||
over a real TCP listener end-to-end.
|
||||
|
||||
Verified: `cargo test` (default) and `cargo test --all-features`
|
||||
green (44 + 7), clippy `-D warnings` clean (default + all-features +
|
||||
wasm32), fmt clean, wasm32 check passes (default crate stays
|
||||
wasm-clean; `local` is non-wasm by design).
|
||||
Reference in New Issue
Block a user