local: the producer-side local backend — the producer's front door
- ProducerDoor (feature local, src/local/producer_door.rs): a real TcpListener accept loop handing each accepted connection to the landed Socks5Producer::serve_socks5_over — the NoAuth in-stream RFC conversation with the local seam providers dialing/egressing/accepting; no new protocol-layer code. - The accept path owns ADR-014's two knobs: the idle-first-byte peek (non-consuming) and the max-concurrent-sessions cap (try_acquire — an accept beyond the bound is refused door-side). - ProducerDoorGuard: the listener's lifetime is the caller's — graceful close() awaits the loop's end; Drop aborts best-effort (the alktunnels TunnelListener teardown posture). In-flight sessions are never force-closed. - Per-connection failures are logged + isolated (the loop continues). - The BIND gate on this path is the builder's bind_policy (no open-op identity here; the pump handler's identity-derived gate does not apply) — pinned by the 0x02-refusal test. - tests/local-backend-producer.rs (9): vanilla CONNECT round-trip on real sockets, faithful-RFC BIND (real reply#1/reply#2 addresses), UDP ASSOCIATE through the real egress, domain resolution at the seam, idle timeout, session cap, failure isolation, bind_policy(false). Verification: cargo test + --all-features green; clippy clean (default, all-features, wasm32 targets); cargo fmt --check clean; wasm checks green (backend is local-gated).
This commit is contained in:
1 parent
2413646b6a
commit
29569d9afd
5 files changed
+854
-3
No files matched your search
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: implementation/local-backend-producer
|
||||
name: Producer-side local backend — the producer's front door (vanilla clients → a locally-served SOCKS5 resource)
|
||||
status: pending
|
||||
status: completed
|
||||
depends_on: [implementation/local-providers]
|
||||
scope: narrow
|
||||
risk: low
|
||||
@@ -86,8 +86,47 @@ Deliverables:
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
- **Symbol choice**: the constructor is `ProducerDoor` (+ `ProducerDoorBuilder`/
|
||||
`ProducerDoorGuard`) in `src/local/producer_door.rs` — the consumer door's
|
||||
sibling name (`FrontDoor`/`UdpFrontDoor`), not `serve_local`: the surface is a
|
||||
builder + accept-loop object (`serve()` binds, `serve_on(listener)` is the
|
||||
test/assembly seam over an existing listener), matching the consumer door's
|
||||
shape rather than a free function.
|
||||
- **Door surface decision**: the NoAuth shape landed; the cred-bearing
|
||||
producer-side door is a documented follow-up (no test drives it). On this
|
||||
path the producer IS the RFC conversation (`serve_socks5_over` runs
|
||||
`accept_no_auth` in-stream) — there is no door-side protocol half to
|
||||
re-originate; a cred-bearing variant would wrap `accept_password_auth`
|
||||
before handing the stream to `serve_socks5_over`.
|
||||
- **Guard shape** (the alktunnels `TunnelListener` teardown posture):
|
||||
`serve`/`serve_on` return a `ProducerDoorGuard`; `close()` ends the accept
|
||||
loop gracefully and awaits the loop task; a Drop aborts it best-effort
|
||||
(sync, never awaits). In-flight sessions are never force-closed by the
|
||||
guard — they own their sockets (per-connection isolation cuts both ways).
|
||||
- **BIND gate documentation**: the per-caller gate (the pump handler's
|
||||
identity-derived one) does not apply here — this path has no open-op
|
||||
identity; the builder's `bind_policy` is the whole gate, pinned by the
|
||||
`bind_policy(false)` test (0x02 refusal, CONNECT still serves).
|
||||
- **No protocol-layer code**: the accept loop rides
|
||||
`Socks5Producer::serve_socks5_over` directly; the only additions are
|
||||
accept-loop assembly (`peek` idle gate, `Semaphore` session cap,
|
||||
`try_acquire_owned` door-side refusal) and the `watch`-signaled guard.
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
Landed the producer-side local backend (feature `local`): `ProducerDoor`
|
||||
(`src/local/producer_door.rs`, exported from the crate root) — a real
|
||||
`TcpListener` front door handing every accepted connection to the landed
|
||||
`Socks5Producer::serve_socks5_over` (NoAuth in-stream RFC conversation;
|
||||
`local::tcp_dial()` / `udp_egress()` / `bind_accept()` dial locally). The
|
||||
accept path owns ADR-014's two knobs (idle-first-byte peek + session-cap
|
||||
semaphore, door-side refusals); per-connection failures are logged +
|
||||
isolated; the `ProducerDoorGuard` carries the listener's lifetime
|
||||
(graceful `close()` / best-effort abort Drop). Pinned by
|
||||
`tests/local-backend-producer.rs` (9 tests): vanilla CONNECT round-trip on
|
||||
real sockets, faithful-RFC BIND (real reply#1/reply#2 addresses), UDP
|
||||
ASSOCIATE through the real egress, domain-target resolution at the seam,
|
||||
the idle timeout, the session cap (refusal while live sessions serve),
|
||||
failure isolation, and the `bind_policy(false)` gate. Verified: `cargo
|
||||
test` + `--all-features` green, clippy clean (default/all/wasm targets),
|
||||
`cargo fmt --check` clean, wasm checks stay green.
|
||||
Reference in new issue
Block a user