pub struct H3Connection { /* private fields */ }Expand description
Shared state for a single HTTP/3 QUIC connection.
Call the appropriate methods on this type for each stream accepted from the QUIC connection.
§Driver shape (vs h2)
h2 multiplexes everything onto a single TCP byte stream, so a single
H2Driver task suffices. h3 instead has the QUIC layer hand us multiple
independent streams: an inbound and outbound control stream, an inbound and outbound QPACK
encoder stream, an inbound and outbound QPACK decoder stream, and one bidi stream per
request. There is no single “h3 driver” — each stream is driven by its own future returned from
H3Connection’s run_* / process_* methods, and the caller decides how those futures are
scheduled.
The trillium-http boundary is runtime-free by design: this crate hands out anonymous futures
and lets the caller pick the executor. The in-tree consumers (trillium-server-common,
trillium-client) follow a task-per-stream pattern — spawn each long-lived control / encoder /
decoder future on its own task at connection setup, then spawn one task per accepted request
stream. Nothing in this crate requires that pattern; a caller could in principle race all the
futures on one task instead, with different perf characteristics.
Implementations§
Source§impl H3Connection
impl H3Connection
Sourcepub fn new(context: Arc<HttpContext>) -> Arc<Self>
pub fn new(context: Arc<HttpContext>) -> Arc<Self>
Construct a new H3Connection to manage HTTP/3 for a given peer.
Sourcepub fn register_priority_callback(
&self,
callback: impl Fn(u64, Priority, bool) + Send + Sync + 'static,
)
pub fn register_priority_callback( &self, callback: impl Fn(u64, Priority, bool) + Send + Sync + 'static, )
Register the sink for RFC 9218 priority signals on this connection.
The callback is invoked with (stream_id, priority, is_update) once per request when its
initial priority header is parsed (is_update = false), and again for every
PRIORITY_UPDATE received afterward (is_update = true). is_update lets the receiver
honor RFC 9218 precedence: a PRIORITY_UPDATE outranks the request’s initial header
priority regardless of arrival order, including when it arrives before the stream is
accepted.
This crate keeps no priority state of its own and does no scheduling: it parses each
signal and hands the Priority off through this callback, leaving the receiver to apply
it to whatever owns send scheduling. Without a registered callback, priority is parsed but
never applied.
Has no effect if a callback is already registered.
Sourcepub fn swansong(&self) -> &Swansong
pub fn swansong(&self) -> &Swansong
Retrieve the Swansong shutdown handle for this HTTP/3 connection. See also
H3Connection::shut_down
Sourcepub fn shut_down(&self) -> ShutdownCompletion
pub fn shut_down(&self) -> ShutdownCompletion
Attempt graceful shutdown of this HTTP/3 connection (all streams).
The returned ShutdownCompletion type can
either be awaited in an async context or blocked on with ShutdownCompletion::block in a
blocking context
Note that this will NOT shut down the server. To shut down the whole server, use
HttpContext::shut_down
Sourcepub fn context(&self) -> Arc<HttpContext>
pub fn context(&self) -> Arc<HttpContext>
Retrieve the HttpContext for this server.
Sourcepub fn peer_settings(&self) -> Option<&H3Settings>
pub fn peer_settings(&self) -> Option<&H3Settings>
Returns the peer’s HTTP/3 settings, available once the peer’s control stream has been processed.
Sourcepub fn process_inbound_bidi<Transport, Handler>(
self: Arc<Self>,
transport: Transport,
handler: Handler,
stream_id: u64,
) -> H3BidiRequest<Transport, Handler>
pub fn process_inbound_bidi<Transport, Handler>( self: Arc<Self>, transport: Transport, handler: Handler, stream_id: u64, ) -> H3BidiRequest<Transport, Handler>
Begin processing a single HTTP/3 request-response cycle on an accepted bidirectional stream.
Returns a builder. Attach an optional reset hook with
with_reset, then .await it to run one request/response
cycle. Awaiting resolves to H3StreamResult::WebTransport if the stream opens a
WebTransport session rather than a standard HTTP/3 request.
Without a reset hook, a stream-level protocol error drops the transport without
resetting it; attach with_reset to issue the RST that RFC 9114 requires for stream
errors.
RFC 9218 priority is delivered out of band via the callback registered with
register_priority_callback: this method emits the
request’s initial priority once the headers are parsed.
Sourcepub async fn process_inbound_bidi_with_reset<Transport, Handler, Fut, Reset>(
self: Arc<Self>,
transport: Transport,
handler: Handler,
stream_id: u64,
reset: Reset,
) -> Result<H3StreamResult<Transport>, H3Error>where
Transport: AsyncRead + AsyncWrite + Unpin + Send + Sync + 'static,
Handler: FnOnce(Conn<Transport>) -> Fut,
Fut: Future<Output = Conn<Transport>>,
Reset: FnOnce(&mut Transport, H3ErrorCode),
pub async fn process_inbound_bidi_with_reset<Transport, Handler, Fut, Reset>(
self: Arc<Self>,
transport: Transport,
handler: Handler,
stream_id: u64,
reset: Reset,
) -> Result<H3StreamResult<Transport>, H3Error>where
Transport: AsyncRead + AsyncWrite + Unpin + Send + Sync + 'static,
Handler: FnOnce(Conn<Transport>) -> Fut,
Fut: Future<Output = Conn<Transport>>,
Reset: FnOnce(&mut Transport, H3ErrorCode),
Process a single HTTP/3 request-response cycle on a bidirectional stream, calling
reset to issue a stream RST when a stream-level protocol error occurs.
On any H3Error::Protocol(code) produced by first-frame processing (HEADERS decode,
pseudo-header validation, etc.), reset is invoked with the still-owned transport and
the error code before the error is returned. This lets callers RST both the recv and
send halves of the bidi stream — required by RFC 9114 for stream errors like
H3_MESSAGE_ERROR. I/O errors and successful runs do not invoke reset.
reset is a FnOnce taking (&mut Transport, H3ErrorCode). trillium-http does not
itself depend on any reset capability of the transport; callers wire up the actual
stream-RST mechanism (e.g. quinn’s RecvStream::stop + SendStream::reset) inside
the closure.
§Errors
Returns an H3Error in case of io error or http/3 semantic error.
Sourcepub async fn run_outbound_control<T>(&self, stream: T) -> Result<(), H3Error>
pub async fn run_outbound_control<T>(&self, stream: T) -> Result<(), H3Error>
Run this connection’s HTTP/3 outbound control stream.
Sends the initial SETTINGS frame, then sends GOAWAY when the connection shuts down. Returns after GOAWAY is sent; keep the stream open until the QUIC connection closes (closing a control stream is a connection error).
§Errors
Returns an H3Error in case of io error or http/3 semantic error.
Sourcepub async fn run_encoder<T>(&self, stream: T) -> Result<(), H3Error>
pub async fn run_encoder<T>(&self, stream: T) -> Result<(), H3Error>
Run the outbound QPACK encoder stream for the duration of the connection.
Writes the stream type byte, then drains encoder-stream instructions from the encoder dynamic table as they are enqueued. Returns when the connection shuts down or the table is marked failed.
§Errors
Returns an H3Error in case of io error.
Sourcepub async fn run_decoder<T>(&self, stream: T) -> Result<(), H3Error>
pub async fn run_decoder<T>(&self, stream: T) -> Result<(), H3Error>
Run the outbound QPACK decoder stream for the duration of the connection.
Writes the stream type byte, then loops sending Section Acknowledgement and Insert Count Increment instructions as they become needed. Returns when the connection shuts down.
§Errors
Returns an H3Error in case of io error or http/3 semantic error.
Sourcepub async fn process_inbound_uni<T>(
&self,
stream: T,
) -> Result<UniStreamResult<T>, H3Error>
👎Deprecated since 1.2.0: use process_inbound_uni_with_close so connection-level protocol errors close the QUIC connection before the recv stream drops, avoiding a FINAL_SIZE_ERROR race with the peer’s response to STOP_SENDING
pub async fn process_inbound_uni<T>( &self, stream: T, ) -> Result<UniStreamResult<T>, H3Error>
use process_inbound_uni_with_close so connection-level protocol errors close the QUIC connection before the recv stream drops, avoiding a FINAL_SIZE_ERROR race with the peer’s response to STOP_SENDING
Handle an inbound unidirectional HTTP/3 stream from the peer.
Internal stream types (control, QPACK encoder/decoder) are handled automatically;
application streams are returned via UniStreamResult for the caller to process.
On a connection-level protocol error, this method drops the recv stream before
the caller can react. Quinn’s RecvStream::drop then sends STOP_SENDING, which
races against the caller’s connection.close — if the peer responds with a
malformed RESET_STREAM (notably final_offset = 0) before our app close is
applied, the transport-level error overrides our app error code on the wire.
Use process_inbound_uni_with_close to thread the close call through the
function so it fires before the stream drops.
§Errors
Returns a H3Error in case of io error or http/3 semantic error.
Sourcepub async fn process_inbound_uni_with_close<T, OnClose>(
&self,
stream: T,
on_close: OnClose,
) -> Result<UniStreamResult<T>, H3Error>
pub async fn process_inbound_uni_with_close<T, OnClose>( &self, stream: T, on_close: OnClose, ) -> Result<UniStreamResult<T>, H3Error>
Handle an inbound unidirectional HTTP/3 stream from the peer, calling on_close to
close the QUIC connection if a connection-level protocol error is detected.
Identical to process_inbound_uni except that on
any H3Error::Protocol(code) whose code is a connection-level error (RFC 9114,
RFC 9204), on_close is invoked with that code while the recv stream is still alive. This
lets callers send a CONNECTION_CLOSE before the stream drops — if the close call sets
quinn’s conn.error, quinn’s RecvStream::drop skips STOP_SENDING, eliminating a
peer race that otherwise causes FINAL_SIZE_ERROR to override the app error code.
on_close is a FnOnce taking H3ErrorCode. trillium-http does not itself
hold the QUIC connection; callers wire up the actual connection.close() call
inside the closure (e.g. quinn’s Connection::close).
§Errors
Returns a H3Error in case of io error or http/3 semantic error.