net-io 0.6.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.6.0 Later
Transports TCP; Unix domain sockets with peer credentials and descriptor passing, and AF_UNIX on Windows; Windows named pipes with ACLs and the client's pid; UDP with budgets, an amplification guard, batches, multicast, and sessions GSO and GRO (after 1.0.0)
Drivers its own reactor on epoll, kqueue, and IOCP, the default: 10,000 idle connections in about 17 MB of heap with no read buffers; a bounded blocking worker pool for handlers; no allocation after warm-up on either; zero-copy file sends; worker placement and per-worker listeners; a public completion-shaped Driver interface an executor adapter (0.8.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
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); listeners added and removed while running; systemd and FastCGI inheritance; listener hand-off between processes on Unix and Windows
Seams the gate (admission before any byte is read, a check before every write, also for adopted and dialed connections), sans-IO sessions, an event sink, a completion queue for offloaded work; the PROXY protocol from trusted proxies; the TLS seam on listeners

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.6"

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.