pub struct Connection { /* private fields */ }Expand description
An accepted HTTP/3 connection.
Implementations§
Source§impl Connection
impl Connection
Sourcepub async fn handshake(
quic: Connection,
within: Duration,
dropped_datagrams: Arc<AtomicU64>,
) -> Result<Self, ConnectionError>
pub async fn handshake( quic: Connection, within: Duration, dropped_datagrams: Arc<AtomicU64>, ) -> Result<Self, ConnectionError>
Performs the HTTP/3 handshake on an established QUIC connection.
The SETTINGS this sends are not a preference but a requirement: Surge
validates SETTINGS_ENABLE_CONNECT_PROTOCOL and SETTINGS_H3_DATAGRAM
during setup and disconnects if either is missing.
The two QPACK streams are opened even though RFC 9204 §4.2 permits omitting them (“An endpoint MAY avoid creating an encoder stream if it will not be used”). Nothing is ever written to them; they exist because every deployed stack opens them, and interoperating with one particular client is this server’s whole purpose.
§The deadline
within bounds all of that, and it has to: opening three unidirectional
streams is the peer’s decision, not this endpoint’s. Transport
parameters that allow fewer than three of them – or no data on them –
park the handshake with no way out, and the QUIC idle timeout is no
backstop, because crate::quic enables a keep-alive whose PINGs the
peer’s stack answers without any application ever being involved. Each
such connection would hold a max_connections slot for as long as the
peer cares to keep the socket open.
One idle timeout is the bound the caller passes, and it is generous by construction: a peer that cannot complete a three-stream handshake in the time it is allowed to say nothing at all is not going to complete it.
dropped_datagrams is where this connection counts every inbound HTTP
Datagram it drops rather than delivers. The caller supplies it, keeping
a clone of its own, because the count is read for the connection’s
closing log line – which is written after everything constructed here
is gone.
Sourcepub fn peer_datagrams(&self) -> Arc<AtomicBool> ⓘ
pub fn peer_datagrams(&self) -> Arc<AtomicBool> ⓘ
A live view of whether the peer advertised SETTINGS_H3_DATAGRAM = 1.
RFC 9297 §2.1.1 forbids sending HTTP Datagrams before this is true, and a CONNECT-UDP session falls back to capsules on the request stream while it is not. The flag is handed out rather than sampled, for the reason the module documentation gives.
Until the peer’s SETTINGS arrive it reads false, which is the safe
direction to be wrong in.
Sourcepub async fn accept(&mut self) -> Result<Option<Resolver>, ConnectionError>
pub async fn accept(&mut self) -> Result<Option<Resolver>, ConnectionError>
Waits for the next request stream.
Cancel-safe: [quinn::Connection::accept_bi] leaves an unaccepted stream
queued, so a caller may poll this inside a select!.
Ok(None) would mean “the peer will send no further requests”, and this
server never reports it. The only thing that could say so is a GOAWAY
from the client, which promises nothing about the requests already in
flight – while the caller reads Ok(None) as permission to drop the
connection, and dropping it would cut those requests off mid-tunnel. A
connection therefore ends when the peer closes it or the idle timeout
fires, both of which arrive here as Err.
Sourcepub async fn shutdown(&mut self) -> Result<(), ConnectionError>
pub async fn shutdown(&mut self) -> Result<(), ConnectionError>
Starts a graceful shutdown by sending GOAWAY (RFC 9114 §5.2).
The identifier is the first request this connection will not serve –
four past the last one accepted, or zero if none was – so everything
already in flight is untouched and the client knows to take new work
elsewhere. Requests arriving past it are rejected in Self::accept
with H3_REQUEST_REJECTED, the code a client may safely retry on.
Note what this does not do: it does not wait for anything, and the connection stays usable afterwards. Deciding when the existing tunnels are done is the caller’s job.
Sourcepub fn close_quietly(&self, reason: &'static str) -> ConnectionError
pub fn close_quietly(&self, reason: &'static str) -> ConnectionError
Ends the connection because this endpoint is done with it, not because anything went wrong.
The counterpart of the violation close: the same mechanism – RFC 9114 §8 makes a CONNECTION_CLOSE carrying an HTTP/3 code be the connection error – with the code §8.1 defines for having nothing to report:
reason reaches the peer in the CONNECTION_CLOSE frame and comes back
in the returned error, which crate::h3api::benign_close grades as a
routine ending rather than a fault – so the caller can break on it
and let the connection’s closing line stay at the level an idle timeout
gets. Returning the error rather than logging here is what keeps that
grading in one place (D50).
Trait Implementations§
Source§impl Drop for Connection
impl Drop for Connection
Source§fn drop(&mut self)
fn drop(&mut self)
Closes the QUIC connection and stops reading the peer’s streams and datagrams.
H3_NO_ERROR is RFC 9114 §8.1’s code for when “the connection or stream
needs to be closed, but there is no error to signal”. quic.rs depends
on this happening: it is why quinn::Connection::close_reason() cannot be used
to grade a connection’s closing log line, and why the error value
returned by conn::handle is graded instead.