The inline vendor (vendor.md, ADR-011 §Amendment) is the root of the crate's dependency graph; this decomposes it before any downstream group (params/wire/producer/consumer/doors). - vendor-crate-scaffolding: Cargo.toml (wasm-clean tokio subset, no alkcall yet), lib.rs, vendor/ skeleton, bundled MIT notice - vendor-wire-vocabulary: consts, codecs, errors, macros — with the extraction-boundary pins (error-variant pruning, pub command codecs, macro de-exporting) - vendor-server-typestate: Socks5ServerProtocol + the new_reply publication (carried change #2); BIND's driving is producer-group work, the vendor carries only the surface - vendor-client-session: Socks5Stream::use_stream path + the AsyncRead/AsyncWrite impls; Config pruned (connect_timeout cut); tests against a raw-byte mock server so it runs parallel with the typestate task - vendor-differential-tests: RFC edge-case suite over duplex streams, pinning upstream behavior per vendor.md's differential posture - review-vendor-extraction: the gate before downstream groups — file-by-file diff vs /workspace/fast-socks5 must contain only cut/carried-change/adjustment hunks Graph validated: all dependency ids resolve, no cycles; topological order scaffolding → wire → (typestate ∥ client) → tests → review.
5.6 KiB
5.6 KiB
id, name, status, depends_on, scope, risk, impact, level
| id | name | status | depends_on | scope | risk | impact | level | |
|---|---|---|---|---|---|---|---|---|
| implementation/vendor-client-session | Vendor — the client session (Socks5Stream::use_stream path) | pending |
|
narrow | low | component | implementation |
Description
Extract the client session — the consumer half's stream-session base
(ADR-002; POC #1's fit) — into src/vendor/client.rs: the
Socks5Stream<S>::use_stream path plus its AsyncRead/AsyncWrite
impls, generic over the backing stream. The consumer layer (a later
task group) opens a channels BiStream and feeds it here; the
first-party associate session in consumer.rs was informed by this
shape (vendor.md's extraction table).
What is extracted (upstream src/client.rs → src/vendor/client.rs):
Socks5Stream<S>struct + the generic impl block, verbatim:use_stream,request,send_version_and_methods,which_method_accepted,use_password_auth,request_header,read_request_reply,get_socket/get_socket_ref/get_socket_mut.- The
AsyncRead/AsyncWriteimpls forSocks5Stream<S>(upstreamclient.rs:641–681) verbatim — the consumer's session rides these (aSocks5Streamis itself a stream, sopump_bidi-shaped consumers and the front doors can pipe through it). - The client
Configstruct — pruned: upstream carriesconnect_timeout(only consumed by the cutconnect_raw) andskip_auth(consumed byuse_stream). Keepskip_auth; dropconnect_timeoutand its setter (its only consumer is cut). If dropping it leavesConfiga single-field struct, keep it anyway (fidelity: the field is load-bearing inuse_stream's handshake branch) or inline the flag — implementer's choice, but theuse_streambehavior must stay byte-identical.
What is NOT extracted (vendor.md's cut table row 2):
Socks5Datagram(struct + impl — the kernelUdpSocketassociate client; the crate's associate session is first-party inconsumer.rsper ADR-003's handle swap).- The
Socks5Stream<TcpStream>convenience impl (connect/connect_with_password/connect_raw— thetokio::net::TcpStreamdialers; the consumer's transport is a channelsBiStream, not a TCP dial).
Extraction-time adjustments (mechanical):
- Drop
anyhow::Context— upstream wraps nearly every client error in.context(...). The error surface isSocksError(thiserror): replace.context("...")?with plain?where the error variant already carries the meaning, and with the typed variants (SocksError::Io,AuthMethodUnacceptable, ...) where upstream usedanyhow::Error::msg(...).into()(upstreamclient.rs:285— the missing-target-addr case) orSocksError::Other(anyhow!(...))(upstreamclient.rs:528— but that site is inside the cutSocks5Datagram, so it goes with the cut). No behavior change to the wire: the same bytes are read/written; only the error typing changes. - Drop
logcalls (debug!in the extracted region). use_password_auth'sunreachable!()(upstreamclient.rs:207—methods.get(1)beingSome(AuthenticationMethod::None)): convention 2 forbids panics in library code. Replace with a typed error path (SocksError::AuthenticationRejected(...)or anAuthMethodUnacceptable) — the state is reachable only by misuse of the public API, but the faithful translation is an error return, not a panic.client_src-style"[::]:0".parse().unwrap()sites are all inside the cutSocks5Datagramregion — verify none remain.
Acceptance Criteria
src/vendor/client.rsexists with the inventory above;cargo testcompilescargo check --target wasm32-unknown-unknownclean- No
Socks5Datagram, noSocks5Stream<TcpStream>convenience impl (connect/connect_with_password/connect_raw) anywhere undersrc/vendor/ - No
anyhow,log,tokio::net,UdpSocketanywhere undersrc/vendor/ - No
unwrap/expect/unreachable!/panic paths in the extracted client code (convention 2) Socks5Stream::use_streamover an in-memory duplex completes: no-auth handshake, password handshake (both accept and reject paths), CONNECT request + reply read (success and each mapped failure code), domain-target and IP-target request encoding — against a raw-byte mock server (pinned byte sequences written directly, not the vendored server typestate — keeping this task parallel with the typestate extraction and the client's wire expectations uncorrelated from the server implementation; tokio duplex streams, no sockets)Socks5Stream<S>implementsAsyncRead+AsyncWrite(the impls extracted) and the impls are exercised by at least one test (e.g.tokio::io::copythrough the session)cargo clippy --all-targets -- -D warningsandcargo fmt --checkclean
References
- docs/architecture/vendor.md (the extraction table row 5, the cut table row 2)
- docs/architecture/decisions/002-protocol-base.md (the client side:
Socks5Stream<S>::use_stream) - docs/architecture/decisions/003-udp-handle-swap.md (why
Socks5Datagramis cut — the associate session is first-party) - docs/research/poc-connect-wasm-findings.md §Wire/API notes
(
Socks5Stream::requesttarget construction; theAuthenticationRejectedunit-variant note) - Upstream:
/workspace/fast-socks5/src/client.rs - POC #4 gate map: docs/research/poc-connect-wasm-findings.md (client.rs row)
Notes
To be filled by implementation agent
Summary
To be filled on completion