Files
rustunnel/droid-wiki/features/stream-multiplexing.md
T
rootandfactory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> 0166fb6511
CI / cargo fmt (push) Has been cancelled
CI / cargo clippy (macos-latest) (push) Has been cancelled
CI / cargo clippy (ubuntu-latest) (push) Has been cancelled
CI / cargo clippy (windows-latest) (push) Has been cancelled
CI / cargo test (macos-latest) (push) Has been cancelled
CI / cargo test (ubuntu-latest) (push) Has been cancelled
CI / cargo test (windows-latest) (push) Has been cancelled
CI / cargo build (macos-latest) (push) Has been cancelled
CI / cargo build (ubuntu-latest) (push) Has been cancelled
CI / cargo build (windows-latest) (push) Has been cancelled
CI / cargo build --release (macos-latest) (push) Has been cancelled
CI / cargo build --release (ubuntu-latest) (push) Has been cancelled
CI / cargo build --release (windows-latest) (push) Has been cancelled
CI / CLI smoke (macos-latest) (push) Has been cancelled
CI / CLI smoke (ubuntu-latest) (push) Has been cancelled
CI / CLI smoke (windows-latest) (push) Has been cancelled
CI / Minimal E2E (macos-latest) (push) Has been cancelled
CI / Minimal E2E (ubuntu-latest) (push) Has been cancelled
CI / Minimal E2E (windows-latest) (push) Has been cancelled
docs: add comprehensive project wiki for v1.0
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-06-04 14:07:55 -06:00

2.1 KiB

Stream multiplexing

rustunnel carries multiple SOCKS5 connections over a single persistent TLS tunnel using stream IDs.

Purpose

Avoid the overhead of establishing a new HTTPS connection for every SOCKS5 request. A single mTLS+auth session stays open, and multiple logical streams are interleaved via the binary framing protocol.

How it works

Connector side

  1. A local SOCKS5 client connects to the connector's SOCKS5 proxy.
  2. The connector's StreamMux::open_stream allocates the next odd stream ID.
  3. It sends a CONNECT frame with the target address encoded in the payload.
  4. It waits for a CONNECT_REPLY frame (status 0x00 = OK).
  5. On success, it returns a mpsc::Receiver<Bytes> for tunnel-to-SOCKS5 data.
  6. The connector spawns a task to read from the SOCKS5 client and send DATA frames to the tunnel.
  7. Another path reads from the data_rx channel and writes raw bytes back to the SOCKS5 client.

Listener side

  1. The listener receives a CONNECT frame with a stream ID and target address.
  2. It resolves the target address and opens a TCP connection.
  3. It spawns a task to read from the target and send DATA frames back to the tunnel.
  4. It sends a CONNECT_REPLY frame to acknowledge the stream.
  5. Incoming DATA frames for that stream ID are written to the target connection.
  6. CLOSE frames trigger shutdown of the target connection.

Stream isolation

Each stream has its own ID. Data from one stream never mixes with another. The E2E test e2e_concurrent_streams_isolation verifies this by sending unique payloads through two concurrent streams and asserting each echo response matches its original payload.

Key abstractions

Type File Description
StreamMux src/tunnel.rs Connector-side multiplexer
ServerStreamEntry src/tunnel.rs Listener-side per-stream target write half
ConnectorStreamEntry src/tunnel.rs Connector-side per-stream data channel and reply channel

Key source files

File Purpose
src/tunnel.rs StreamMux, open_stream, dispatch_frame, framing loops
src/framing.rs Frame types, CONNECT/DATA/CLOSE/ERROR encoding