tokio-yamux

Tokio-native implementation of the Yamux stream-multiplexing protocol for running many logical streams over one connection.

Library
Cargo
v0.3.20
62stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
69/100Good
Development Activity80
Maintenance76
Community48
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
76/100Good
Architecture80
Code Quality78
Innovation74
Learning Curve72

tokio-yamux is a Rust implementation of HashiCorp’s Yamux specification, built on Tokio’s async I/O primitives. It multiplexes a single underlying connection — a TCP socket, a WebSocket, or anything implementing AsyncRead/AsyncWrite — into many independent, flow-controlled substreams, so applications don’t need to open a new connection per logical channel.

It began life as the transport-multiplexing layer inside the Nervos Network’s Tentacle p2p framework and now ships as its own crate within that workspace. A Session drives frame encoding/decoding and stream bookkeeping over a tokio_util::codec::Framed transport, while each StreamHandle exposes a standard AsyncRead/AsyncWrite interface with its own send/receive window, so callers can treat substreams like ordinary sockets while yamux handles keepalive pings, GoAway shutdown, and per-stream backpressure underneath.

What You Get

  • A Session type wrapping any AsyncRead + AsyncWrite transport, with distinct client/server session modes
  • StreamHandle substreams that implement standard Tokio AsyncRead/AsyncWrite
  • Per-stream flow control with configurable initial and maximum window sizes
  • Built-in keepalive pings, GoAway graceful shutdown, and configurable connection write timeouts
  • An async Control handle for opening new outbound streams and closing the session from user code
  • Optional metrics feature exposing ping latency and keepalive-timeout counters
  • A generic-timer/wasm feature for running under non-Tokio runtimes, including WASM

Common Use Cases

  • Multiplexing a p2p network framework’s protocol substreams over one TCP or WebSocket connection per peer, its original use inside Tentacle
  • Running many logical RPC channels over a single persistent connection without per-channel connection overhead
  • Adding stream multiplexing to a custom transport that only exposes one duplex byte stream, such as a tunneled or serial connection
  • Building peer-to-peer or overlay network protocols that need several independently flow-controlled channels between two nodes

Under The Hood

Architecture The crate centers on Session<T> (session.rs, ~1,455 lines), which wraps a tokio_util::codec::Framed<T, FrameCodec> and drives a Stream/Sink event loop: it polls the underlying framed transport for incoming Frames, dispatches Data/WindowUpdate/Ping/GoAway frames to per-stream mpsc::Sender<Frame> channels held in a HashMap<StreamId, Sender<Frame>>, tracks streams awaiting acceptance in a pending-streams queue, and multiplexes outbound writes back through a shared write buffer. StreamHandle (stream.rs) is a decoupled object that only sees its own inbound frame receiver and an unbounded event sender back to the session for open/window-update/close/reset notifications, while exposing AsyncRead/AsyncWrite by copying to and from internal buffers — giving a clean single-writer/many-reader structure without a central lock. A separate Control type layers an async API (open_stream, close) over the poll-based Session driver via a command channel with oneshot replies, decoupling synchronous session polling from user code awaiting stream operations; changing that command contract would ripple into both stream lifecycle and graceful shutdown, since they share the same queue.

Tech Stack Rust 2024 edition (rust-version 1.85.0), built on tokio (AsyncRead/AsyncWrite, plus an optional timer feature), tokio-util for the Framed/Decoder/Encoder codec abstraction, futures 0.3 (Stream/Sink traits, mpsc/oneshot/unbounded channels), bytes/BytesMut for frame buffers, and log for tracing. An optional metrics feature gates a dependency on the metrics crate; a wasm target substitutes web-time for std::time::Instant, and a generic-timer feature swaps in futures-timer so the crate can run on non-Tokio async runtimes, including WASM. It ships purely as a library crate, versioned alongside its parent Tentacle workspace with GitHub Actions CI and a dedicated release workflow.

Code Quality Extensive #[cfg(test)] unit test modules cover frame encode/decode round-trips (frame.rs), session lifecycle including keepalive and GoAway (session.rs, ~8 tests), and stream state transitions and backpressure (stream.rs, ~12 tests) — substantial per-module coverage for a protocol implementation, though there’s no separate integration-test directory. Errors are modeled as a single explicit Error enum implementing std::error::Error and Display rather than being swallowed or stringly-typed, and I/O boundaries return io::Result. Naming follows idiomatic Rust conventions, and the crate root sets #![deny(missing_docs)], forcing every public item to carry documentation. CI runs across the whole Tentacle workspace via GitHub Actions.

API Design The public surface is intentionally small: Session::new_client/new_server wrap any AsyncRead + AsyncWrite transport and expose the session itself as a Stream of accepted StreamHandles, Control::open_stream opens outbound streams, and each StreamHandle implements plain AsyncRead/AsyncWrite — so anyone already comfortable with Tokio’s I/O traits needs almost no new vocabulary. Getting started takes minimal boilerplate, as shown in the bundled yamux_simple.rs and throughput_test.rs examples: a transport, a Config::default(), and a Session::new_client/new_server call. Naming mirrors the reference HashiCorp Go implementation’s concepts (GoAway, keepalive, window update), which helps anyone porting from or comparing against other Yamux implementations, though the crate’s own README is minimal — most usage guidance lives one level up, in the parent Tentacle repository’s README and docs.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search