Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Architecture

The main path has four layers: transport, pipeline runtime, stage traits, and channel/context.

Crate Layout

  • src/lib.rs: public modules and common re-exports.
  • src/traits.rs: Inbound, Business, Handler, DatagramHandler, Outbound, and Flow.
  • src/pipeline/stream: TCP typed builder and runtime pipeline.
  • src/pipeline/datagram: UDP typed builder and runtime pipeline.
  • src/pipeline/core: shared Identity, Then, stage pipe traits, and builder state markers.
  • src/codec: stream/datagram codec traits and built-in codecs.
  • src/context: stage contexts, handler contexts, stats, and identity types.
  • src/channel: external write handles and internal command enums.
  • src/tls.rs: optional TLS context builders and server/client contexts behind the tls feature.
  • src/transport/tcp: TCP server, client, connection runtime, and config.
  • src/transport/udp: UDP server, client, socket runtime, and config.
  • src/life.rs: lifecycle hook trait and close reasons.
  • rs-netty-macros: the #[handler] attribute macro.

TCP Runtime Flow

A TCP server calls the pipeline factory once for each accepted connection. A client can use either a reusable factory or pipeline_instance, which consumes one single-use pipeline.

The runtime flow is roughly:

TcpListener / TcpStream
  -> optional TLS accept/connect
  -> read_buf
  -> Decoder::decode
  -> InboundPipe
  -> BusinessPipe
  -> Handler::read(Context<W>, msg)
  -> Context outbox or Channel command queue
  -> OutboundPipe
  -> Encoder::encode
  -> write_buf
  -> flush/write_all

StreamConnectionRuntime selects over socket reads, external channel commands, and shutdown signals. Without an idle timeout it uses a no-timeout loop. With idle_timeout, it adds a read-idle timer. The timer is reset only by socket reads; outbound writes do not reset it.

UDP Runtime Flow

UDP servers and clients run around one socket task. The pipeline is socket-level:

UdpSocket::recv_from
  -> DatagramDecoder::decode_datagram
  -> InboundPipe
  -> BusinessPipe
  -> DatagramHandler::read(DatagramContext<W>, msg)
  -> DatagramContext outbox or DatagramChannel command queue
  -> OutboundPipe
  -> DatagramEncoder::encode_datagram
  -> pending_datagrams
  -> flush/send_to

A UDP server does not currently create per-peer child pipelines. If you need per-peer state, store it in the handler explicitly, for example with HashMap<SocketAddr, State>.

Static Stage Composition

The builder composes stages at the type level as Then<A, B>. Identity means that a direction has no user stages. Runtime InboundPipe, BusinessPipe, and OutboundPipe process Then recursively:

  • Flow::Next(value) forwards the value to the next stage.
  • Flow::Stop stops processing the current message direction without treating it as an error.
  • Err is mapped by the connection/socket runtime into decode, encode, handler, or runtime errors.

The main path does not use dynamic Box<dyn Handler> pipeline dispatch. Pipeline types are built from generic static stage composition.

Channel And Context

Context<W> and DatagramContext<W> are the write entry points inside final handlers. They hold a handler-local outbox, which is useful for multiple writes and explicit flush boundaries during one read.

Channel<W> and DatagramChannel<W> are cloneable external handles. They send commands to the connection/socket task through a bounded Tokio mpsc queue. TCP channels expose stats(), capacity(), max_capacity(), and is_closed(); UDP channels expose socket identity and queue state.