connection.rs

Overview

This file implements the Connection abstraction for managing QUIC connections using the msquic library. It provides the ability to create, start, accept, and shutdown connections, as well as open and accept streams, send and receive datagrams, and handle remote certificates. The Connection struct encapsulates an underlying msquic::Connection along with internal state and synchronization primitives to manage asynchronous events and concurrent access.

Key responsibilities include:

The file handles asynchronous operations through Rust futures and uses wakers to notify tasks of state changes. Internal synchronization is achieved via a Mutex guarding the connection's exclusive state.


Main Structs and Their Responsibilities

Connection

A thread-safe handle representing a QUIC connection. It wraps an Arc to a ConnectionInstance that contains the internal state and the actual msquic::Connection.

Key Methods

Other methods provide polling implementations to drive the futures returned by the above asynchronous operations.


Internal Structs

ConnectionInstance

Holds the actual msquic::Connection and an Arc to ConnectionInner. Implements Deref for convenient access to inner data.

ConnectionInner

Holds the shared NetCredential and a Mutex-protected ConnectionInnerExclusive struct that contains the mutable state.

ConnectionInnerExclusive

Manages the mutable connection state, including:


Connection State Machine

The connection state transitions are managed via the ConnectionState enum:

State transitions are triggered by msquic connection events handled in the callback_handler_impl method of ConnectionInner.


Event Handling and Callbacks

The ConnectionInner::callback_handler_impl method processes various msquic::ConnectionEvents:

All event handlers update the internal state and notify waiting futures by waking the appropriate Wakers.


Futures for Asynchronous Operations

Several structs implement Future for asynchronous connection operations:

Each future polls the connection's internal state and either completes immediately or registers its waker to be notified when the awaited event occurs.


Error Types

Several error enums represent different error conditions:

Each error type implements detailed error messages using the thiserror crate.


Interaction with Other Components

This file is central to managing connection-level functionality and serves as a foundation for stream and datagram operations.


Important Implementation Details


Visual Diagram

classDiagram
class Connection {
+new()
+start()
+accept()
+open_outbound_stream()
+open_send_stream()
+accept_inbound_stream()
+accept_inbound_uni_stream()
+send_datagram()
+get_local_addr()
+get_remote_addr()
+get_remote_certificate()
+watch_shutdown()
}
class ConnectionInstance {
-inner: Arc<ConnectionInner>
-msquic_conn: msquic::Connection
}
class ConnectionInner {
-credential: NetCredential
-exclusive: Mutex<ConnectionInnerExclusive>
+callback_handler_impl()
}
class ConnectionInnerExclusive {
-state: ConnectionState
-error: Option<ConnectionError>
-start_waiters: Vec<Waker>
-certificate_waiters: Vec<Waker>
-inbound_stream_waiters: Vec<Waker>
-inbound_uni_stream_waiters: Vec<Waker>
-inbound_streams: VecDeque<Stream>
-inbound_uni_streams: VecDeque<ReadStream>
-recv_buffers: VecDeque<Bytes>
-recv_waiters: Vec<Waker>
-write_pool: Vec<WriteBuffer>
-shutdown_waiters: Vec<Waker>
-negotiates_alpn: Vec<u8>
-certificate: Option<Result<CertificateDer, StartError>>
}
Connection "1" o-- "1" ConnectionInstance
ConnectionInstance "1" o-- "1" ConnectionInner
ConnectionInner "1" o-- "1" ConnectionInnerExclusive

Usage Examples

Creating and Starting a Connection

let registration = msquic::Registration::new("myapp")?;
let credential = NetCredential::new();
let conn = Connection::new(&registration, credential)?;
let configuration = msquic::Configuration::load_default()?;

conn.start(&configuration, "example.com", 443).await?;

Accepting an Inbound Bidirectional Stream

let stream = conn.accept_inbound_stream().await?;

Sending a Datagram

let data = Bytes::from("hello datagram");
conn.send_datagram(&data)?;

Receiving a Remote Certificate

let cert = conn.receive_remote_certificate().await?;

References

The asynchronous patterns and futures conform to Rust's async runtime model, detailed in Asynchronous Programming.