net-io 0.3.0

Network IO substrate for Rust: TCP, UDP and local-socket listeners, connection lifecycle, limits, graceful drain, PROXY protocol, and a TLS seam. Protocol-free and dependency-free.
Documentation

What it does

Area In 0.3.0 Later
Transports TCP listeners and connections UDP, Unix domain sockets (0.4.0), Windows named pipes (0.5.0)
Drivers a bounded blocking worker pool: 2 system calls per keep-alive round trip on Linux (3 on macOS and Windows), no allocation after warm-up its own reactor on epoll, kqueue, and IOCP (0.5.0)
Limits global, per-listener, and per-source caps; idle, read, write, exchange, and park deadlines; a minimum transfer rate against slowloris and slow readers; bounded buffers adaptive deadlines and lane reservations (0.6.0)
Lifecycle the door, graceful drain with a deadline, kill from any thread, one CloseReason and one closed event per connection, a control line (shed, lockdown, drain, stop) listener hand-off, systemd activation (0.4.0)
Seams the gate (admission before any byte is read, a check before every write), sans-IO sessions, an event sink, a completion queue for offloaded work PROXY protocol, the TLS seam wired to listeners (0.4.0)

The full plan:

Area Planned
Transports TCP, UDP, Unix domain sockets (Unix and Windows), Windows named pipes
Socket options TCP_NODELAY, keepalive tuning, linger, buffer sizes, SO_REUSEADDR / SO_EXCLUSIVEADDRUSE, SO_REUSEPORT, IPV6_V6ONLY, and the server options std does not expose
Connections a never-reused ConnectionId, ConnectionInfo (endpoints, real client behind a trusted proxy, transport, TLS facts), one CloseReason on every close
Limits global, per-listener, and per-source caps; handshake, idle, read, write, and total deadlines; a minimum transfer rate against slowloris and slow-read; bounded buffers and queues
Drivers a bounded blocking worker pool (0.3.0); its own reactor on epoll, kqueue, and IOCP (0.5.0); one completion-shaped interface
Sessions sans-IO protocol engines driven the same way on every driver, with zero-copy input and an O(1) buffer hand-off
Behind a proxy PROXY protocol v1 and v2, honoured only from configured trusted proxies
Restarts a door that opens last and closes first, graceful drain, systemd socket activation, FastCGI descriptor 0, listener hand-off between processes
Seams a gate (admission before any byte is read, a check before every write, kill from any thread), a sans-IO TLS seam, an event sink, a control line, a completion queue for offloaded work

Use

[dependencies]
net-io = "0.3"

The simplest server (the full API is in docs/API.md; examples/ has a sans-IO session, kill and drain, and a gate):

fn main() -> Result<(), net_io::NetError> {
    // Echo server on a bounded worker pool with every default limit applied.
    let server = net_io::serve("127.0.0.1:7000", |conn| {
        let mut buf = [0u8; 4096];
        loop {
            let n = conn.recv(&mut buf)?;
            if n == 0 {
                return Ok(());
            }
            conn.send_all(&buf[..n])?;
        }
    })?;
    server.wait_for_stop(); // runs until server.handle().request_stop(), then drains
    Ok(())
}

What is not here

  • QUIC: it runs on UDP but builds TLS 1.3 into the transport itself, so it gets its own crate later (quic-net) on top of this one's UDP socket.
  • DNS resolution: std covers it for now; a real resolver becomes its own crate later (dns-net).
  • A TLS implementation: TLS plugs in through the seam from a separate adapter crate, which keeps this crate dependency-free.
  • Application protocols, ban policy, authentication: these live in the crates above it.

Contributing

See dev/DIRECTIVES.md for engineering standards and the definition of done. Before a PR: cargo fmt --all, cargo clippy --all-targets --all-features -- -D warnings, and cargo test --all-features must be clean.