Skip to main content

Crate harrow_server_monoio

Crate harrow_server_monoio 

Source
Expand description

Monoio-based HTTP/1.1 and HTTP/2 server for Harrow.

This crate provides a high-performance HTTP server using io_uring. It supports HTTP/1.1 with keep-alive and chunked transfer encoding, and HTTP/2 with multiplexed streams.

§Features

  • io_uring-based I/O: Zero-copy where possible, minimal syscalls
  • Cancellation Safety: Proper handling of io_uring operation cancellation
  • Buffer Pooling: Reusable buffers to reduce allocator pressure
  • HTTP/2 Support: Multiplexed streams with flow control

§Architecture

┌─────────────────────────────────────────────┐
│              Server (lib.rs)                │
└─────────────────────┬───────────────────────┘
                      │ TcpStream
                      ▼
┌─────────────────────────────────────────────┐
│           Connection Handler                │
│            (connection.rs)                  │
└─────────────────────┬───────────────────────┘
                      │
          ┌───────────┴───────────┐
          ▼                       ▼
┌─────────────────┐   ┌─────────────────────┐
│   H1 Handler    │   │   H2 Handler        │
│(h1/dispatcher.rs)│  │    (h2.rs)          │
└─────────────────┘   └─────────────────────┘

§Example

fn main() {
    // High-level thread-per-core bootstrap.
    harrow_server_monoio::run(
        || App::new().get("/hello", hello),
        "127.0.0.1:3000".parse().unwrap(),
    )
    .unwrap();
}

For advanced cases where you already own a monoio runtime, use the async serve / serve_with_shutdown / serve_with_config entrypoints instead.

§Cancellation Safety

This crate uses io_uring for async I/O. Unlike epoll-based runtimes, io_uring submits actual kernel operations. Dropping a Rust future does NOT automatically cancel the in-flight kernel operation.

This can lead to use-after-free (UAF) vulnerabilities:

  1. A read operation is submitted with a user buffer
  2. The future is dropped (e.g., due to timeout)
  3. The kernel writes to the buffer after it’s been freed/reused

§Mitigation

All I/O operations with timeout paths use CancelableAsyncReadRent and explicitly cancel kernel operations before returning:

let canceller = Canceller::new();
let handle = canceller.handle();

monoio::select! {
    result = stream.cancelable_read(buf, handle) => result,
    _ = timeout => {
        canceller.cancel(); // Explicit kernel cancellation
        // Await the operation to reclaim buffer
        let (_, buf) = read_fut.await;
        release_buffer(buf);
        return Err(Timeout);
    }
}

See cancel.rs for the implementation details.

Modules§

kernel_check
Kernel version and io_uring availability checks. Kernel version check for io_uring support.

Structs§

ServerConfig
Configuration for the monoio server.
ServerHandle
Handle returned by the high-level monoio bootstrap APIs.

Functions§

run
Start the application using Harrow’s thread-per-core monoio bootstrap.
run_with_config
Start the application using Harrow’s thread-per-core monoio bootstrap and block until shutdown.
serve
Serve the application on the given address using HTTP/1.1.
serve_with_config
Serve with a graceful shutdown signal and custom configuration.
serve_with_shutdown
Serve with a graceful shutdown signal.
start
Start the application using Harrow’s thread-per-core monoio bootstrap and return a handle for shutdown / test control.
start_with_config
Start the application using Harrow’s thread-per-core monoio bootstrap and return a handle for shutdown / test control.