pub struct BindSession { /* private fields */ }Expand description
The BIND consumer session (the bind() entry namespace — the POC
#5 shape): opens the channel, negotiates, sends BIND, reads
reply#1 (bind), then awaits reply#2 + the data plane
(await_inbound). The session owns the adopted channel: on Drop
it reaps the entry (the CONNECT session’s teardown posture). It
does not implement Clone:
use alksocks::consumer::BindSession;
fn assert_clone<T: Clone>() {}
assert_clone::<BindSession>();Error surface: a refused BIND (the command gate’s 0x02) or a
factory failure’s reply#1 code surfaces from bind as
SocksSessionError::Rfc (the adopted channel is torn down
before the error returns — teardown-at-birth, the phantom-channel
property); accept-stage failures surface at await_inbound as
reply#2’s mapped code (SocksSessionError::Rfc) — the channel
is still open there (the listener existed; the session lives until
the app closes it; the inner is restored, see the take-guard
below).
The reply#2 phase is take-guarded (review 002
C-1): the first await_inbound takes the inner stream — the
returned plane owns it (the TakenInner pairing posture; the
session stays the teardown owner) — so a second call hits the
None arm and returns Ok(None): the session family’s spent
shape, with no re-read of the live data plane possible. 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).
Implementations§
Source§impl BindSession
impl BindSession
Sourcepub async fn bind(
client: &ChannelClient,
target: impl ToTargetAddr,
) -> Result<Self, SocksSessionError>
pub async fn bind( client: &ChannelClient, target: impl ToTargetAddr, ) -> Result<Self, SocksSessionError>
BIND through a produced SOCKS5 resource: opens the channel
(open_channel(OP_SOCKS5_OPEN, {}, SOCKS5_ALPN) — the trivial
params, ADR-001), drives the no-auth handshake and the BIND
request in-stream over the channel’s BiStream, and reads
reply#1 (carrying BND.ADDR — the forked client request()’s
normal path). The returned session owns the channel; the
advertised address is BindReply1::bind_addr.
Error surface: an open failure is SocksSessionError::Open
(the typed ADR-049 reasons; no channel was ever returned); a
refused BIND — the command gate’s ConnectionNotAllowed 0x02
or a factory failure’s mapped reply#1 code — surfaces the RFC
reply code through SocksSessionError::Rfc, and the adopted
channel is torn down before the error returns (no phantom
channel).
Sourcepub async fn bind_with_token(
client: &TokenClient,
target: impl ToTargetAddr,
token: Vec<u8>,
) -> Result<Self, SocksSessionError>
pub async fn bind_with_token( client: &TokenClient, target: impl ToTargetAddr, token: Vec<u8>, ) -> Result<Self, SocksSessionError>
The cred-bearing front door’s BIND re-origination (the
token-carrying twin of Self::bind): the open rides the
payload auth_token (CF-005 precedence (1) — the producer’s
identity provider resolves the door’s mapped identity; the
BIND command gate reads socks5:bind from it, ADR-006), then
the same in-stream BIND phase model over the channel’s
BiStream. Error surface identical.
Sourcepub fn channel_id(&self) -> u32
pub fn channel_id(&self) -> u32
The adopted channel’s id (observability + correlation; one session = one channel).
Sourcepub fn reply1(&mut self) -> Option<BindReply1<'_>>
pub fn reply1(&mut self) -> Option<BindReply1<'_>>
Reply#1’s view: the advertised BND.ADDR (the app server dials
it out-of-band — the RFC’s original role for the address) and
the raw pre-reply#2 stream (BindReply1::raw_mut, the
front-door bridge seam). A view, not a reader (review 002
D-1’s one-reader decision): the one normative reply#2 reader
is Self::await_inbound; the handle can be re-borrowed
freely — it carries no read phase.
Sourcepub async fn await_inbound(
&mut self,
) -> Result<Option<BindDataPlane>, SocksSessionError>
pub async fn await_inbound( &mut self, ) -> Result<Option<BindDataPlane>, SocksSessionError>
Await the inbound accept (reply#2) and take the pass-through
data plane. The one normative reply#2 reader (review 002 C-1 +
D-1): the phase is take-guarded — the read consumes the
session’s inner stream (the plane owns it; the session stays
the teardown owner) — so a second call cannot re-read the
live data plane. Reply#2 is hand-read with the forked
read_address codec — reply#1’s codec applied again, no
second codec (POC #5’s read_reply2 sketch; ADR-011’s
rationale).
Ok(None) after the plane was taken (the spent-session
posture — the doc claim this guard makes true). A failed read
restores the inner (the phase is not consumed on failure): the
channel stays owned (reply#1 succeeded — the listener existed;
reap via close/Drop), the pipe stays reachable
(split), and a re-call re-reads against the already-ended
session (the producer ends it on every post-reply#1 failure
exit — the read EOFs; never a live data-plane re-read).
Sourcepub fn split(&mut self) -> Option<SplitPipe<'_>>
pub fn split(&mut self) -> Option<SplitPipe<'_>>
The pass-through pipe as split read/write halves (0 B framing
— raw bytes to/from the accepted peer). Valid in the reply#1
phase (pre-reply#2 bytes ride the same channel — the
front-door bridge seam); post-Self::await_inbound the
plane owns the stream (the take-guard), so the data plane’s
halves ride BindDataPlane/its into_inner instead. None
after a graceful close (the pipe is dropped with the reap).