consumer: the BIND reply#2 re-entry guard + session hygiene (review-002 C-1, D-1, N-6, S-2)
- C-1: BindSession::await_inbound is take-guarded — the first read takes the session's stream; the returned BindDataPlane owns it (the TakenInner pairing posture; the session stays the teardown owner), so a second call returns the family's spent shape Ok(None) and can never re-read the live data plane. A failed read restores the inner (the phase is only consumed on success; the producer ends the session on every post-reply#1 failure exit, so a re-call EOFs — never a live data-plane re-read either way). Pinned by the double-await_inbound integration test (the spent shape + the data-plane bytes asserted untouched) and the spent-BIND unit test. - D-1: one normative reply#2 reader (option a) — the session's await_inbound; BindReply1::await_inbound is cut and reply1() is documented as a view (bind_addr + raw_mut), matching its actual usage; the reply1()-twice re-entry path is closed (pinned by the view test). - N-6: the three session constructors' prologues collapsed into one private open_and_negotiate helper (teardown-at-birth in one place); zero behavior change. - S-2: the EOF-propagation doc line on all three reap sites (the dropped teardown_channel handle is deliberate — the graceful shape; clear_all aborts instead). - BindDataPlane is un-lifetimed (owns the stream); into_inner returns the owned Socks5Stream<BiStream>; docs synced (module + session docs, consumer.md §The BIND client). Verification: cargo test 352 green (all-features too), clippy -D warnings clean, fmt clean, cargo doc clean, both wasm checks clean.
This commit is contained in:
1 parent
6d14d35a54
commit
53739b20cb
4 files changed
+459
-139
No files matched your search
@@ -1,8 +1,8 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-09-24 (the landed session signatures reconciled —
|
||||
`&ChannelClient` constructors, `impl ToTargetAddr` datagrams, the
|
||||
`Option`-shaped `recv_datagram`; Phase 1 initial draft 2026-09-20)
|
||||
last_updated: 2026-09-24 (the BIND spent posture reconciled — the
|
||||
take-guarded reply#2 reader, review 002 C-1/D-1; the landed session
|
||||
signatures reconciled 2026-09-24; Phase 1 initial draft 2026-09-20)
|
||||
---
|
||||
|
||||
# alksocks — The Consumer Half
|
||||
@@ -69,8 +69,18 @@ The BIND reply#2 reader (POC #5's `read_reply2` sketch): the forked
|
||||
client `request()` reads reply#1; reply#2 is hand-read with the
|
||||
forked public `read_address` codec (reply#1's codec applied again;
|
||||
no second codec). The session then rides the pass-through data
|
||||
plane. The BIND client is a wrapper-aware-consumer convenience —
|
||||
vanilla clients reach BIND through the front door instead.
|
||||
plane. The reply#2 phase is take-guarded: the one normative reader
|
||||
is `await_inbound` — the first read consumes the session's stream
|
||||
(the returned plane owns it; the session stays the teardown owner),
|
||||
so a second call returns the family's spent shape (`Ok(None)`, the
|
||||
same posture the sibling sessions pin) and cannot re-read the live
|
||||
data plane; a failed read restores the inner (the producer ends the
|
||||
session on every post-reply#1 failure exit, so a re-call EOFs —
|
||||
never a live data-plane re-read either way). The
|
||||
`reply1()` handle is a view (the advertised BND.ADDR + the raw
|
||||
pre-reply#2 stream), not a reader. The BIND client is a
|
||||
wrapper-aware-consumer convenience — vanilla clients reach BIND
|
||||
through the front door instead.
|
||||
|
||||
### Error surface
|
||||
|
||||
|
||||
Reference in new issue
Block a user