Skip to main content

Crate simoom_h2

Crate simoom_h2 

Source
Expand description

Sans-io HTTP/2 (RFC 9113) connection engine for simoom, with DoS accounting.

A Connection takes received bytes plus the current time and produces Events and outbound bytes. It never touches sockets, threads or clocks; the event loop feeds it:

use simoom_h2::{Config, Connection, Event};
let mut server = Connection::server(Config::default());
let mut client = Connection::client(Config::default());
let id = client.send_request(b"GET", b"https", b"example.com", b"/", &[], true).unwrap();

let c2s = client.output().to_vec();
client.advance_output(c2s.len());
let mut request = None;
let used = server.recv(&c2s, 0, &mut |ev| {
    if let Event::Headers { stream, headers, .. } = ev {
        request = Some((stream, headers.path().unwrap().to_vec()));
    }
});
assert_eq!(used, c2s.len()); // a caller keeps unconsumed bytes for the next call
let (stream, path) = request.unwrap();
assert_eq!((stream, &path[..]), (id, &b"/"[..]));

server.send_response(stream, 200, &[(b"content-type", b"text/plain")], false).unwrap();
assert_eq!(server.send_data(stream, b"hello", true), Ok(5));
server.stream_finished(stream);

let s2c = server.output().to_vec();
server.advance_output(s2c.len());
let mut body = Vec::new();
client.recv(&s2c, 0, &mut |ev| {
    if let Event::Data { data, .. } = ev {
        body.extend_from_slice(data);
    }
});
assert_eq!(body, b"hello");

Received data stays charged to the flow-control windows until the application calls Connection::release; that bounds what a stream and the connection can buffer. Outbound data goes through Connection::send_data, which accepts only what the windows and the output buffer cap allow and reports the rest as backpressure; Connection::poll_writable names streams that can send again.

DoS accounting (plan §2.7): the concurrency limit counts streams whose handler is still running (the application calls Connection::stream_finished), not just open streams, so resets cannot free capacity while work continues (MadeYouReset, CVE-2025-8671; Rapid Reset, CVE-2023-44487). Sliding-window Budgets cap RST_STREAM (received and caused), PING, SETTINGS, empty frames, PRIORITY and small WINDOW_UPDATE frames; header blocks are capped in bytes and in CONTINUATION frames. Exceeding any of them sends GOAWAY(ENHANCE_YOUR_CALM).

Re-exports§

pub use frame::ErrorCode;
pub use frame::PREFACE;

Modules§

frame
HTTP/2 frame layout (RFC 9113 §4, §6): constants, the 9-byte header, and writers that append frames to an output buffer.

Structs§

Budgets
Limits per window. u32::MAX disables a budget.
Config
Settings and limits for one side of a connection.
Connection
One HTTP/2 connection, either end.
Headers
A received header block (request or response headers, or trailers).

Enums§

Error
Errors from the sending API.
Event
Something the peer did, reported by Connection::recv and Connection::handle_timeout.
Role
Which end of the connection this is.

Functions§

base64url_decode
Decodes base64url, with or without padding. Whitespace around the value is ignored; any other byte outside the alphabet is an error.
base64url_encode
Encodes bytes as unpadded base64url.
http2_settings_header
The HTTP2-Settings header value a client sends with an h2c upgrade request.