mod.rs
Overview
This file implements the MsQuic-based network transport layer providing QUIC protocol support. It defines the main transport struct MsQuicTransport and its associated connection and listener abstractions. The file handles connection establishment, listener creation, stream management, and data transmission over QUIC using the underlying msquic_async crate.
Key responsibilities include:
Managing QUIC connection registration and configuration.
Creating listeners bound to local socket addresses.
Establishing outgoing connections with ALPN and credentials.
Accepting incoming QUIC connections and requests.
Sending and receiving messages over QUIC streams with proper framing.
Handling certificate validation errors and connection shutdown.
The file integrates with abstractions defined in other modules such as NetTransport, NetConnection, NetListener, and NetIncomingRequest traits, enabling modular network transport support. It also uses TLS credential and certificate identity concepts defined externally.
Modules and Imports
msquic_async: Async wrappers around msquic QUIC implementation.
quic_settings: Configuration factory for server/client QUIC settings.
tests: Unit tests guarded by #[cfg(test)].
Standard library and external crates for async IO, synchronization, timing, and TLS primitives.
Uses msquic_async types such as
Connection,Listener,SendStream,ReadStream.Uses internal abstractions related to certificates, network connections, credentials, and transports.
Constants
STREAM_OP_TIMEOUT: Duration constant (12 seconds) used as timeout for stream operations such as opening or sending on streams.
Structs and Implementations
MsQuicTransport
Purpose: Main transport struct implementing
NetTransporttrait using MsQuic.Fields:
registration: Arc<RegistrationWrapper>: Shared QUIC registration object for msquic.
Key Methods:
new() -> Self: Creates a new transport instance with default registration.
Trait Implementations:
Default: Delegates to
new().NetTransport:create_listener: Creates a QUIC listener bound to a socket, configured with ALPN and TLS credentials.connect: Initiates an outgoing QUIC connection to a remote address with ALPN and credentials. Handles certificate validation errors and returns a wrappedMsQuicNetConnection.
RegistrationWrapper
Purpose: Wrapper around msquic
Registrationto ensure proper shutdown on drop.Fields:
0: Registration
Behavior:
Implements Drop to call
shutdown()on the inner registration when dropped.
MsQuicListener
Purpose: Represents a server-side QUIC listener.
Fields:
instance: Listener: Underlying msquic listener.local_identity: String: Identity string derived from local credential.
Trait Implementations:
Implements NetListener:
accept: Asynchronously accepts incoming QUIC connections, returning wrappedMsQuicNetIncomingRequest.
MsQuicNetIncomingRequest
Purpose: Represents an incoming QUIC connection request.
Fields:
connection: Connection: Underlying msquic connection.local_identity: String: Local identity string.
Trait Implementations:
Implements
NetIncomingRequest:remote_addr: Returns remote socket address.accept: Accepts the connection, handling certificate errors, and returns a fully establishedMsQuicNetConnection.
MsQuicNetConnection
Purpose: Represents an established QUIC connection.
Fields:
inner: Connection: The underlying msquic connection.local_identity: String: Local identity.remote_identity: String: Remote peer's identity derived from certificate hash.stream_pool: Arc<StreamPool>: Manages send and receive streams for the connection.
Key Methods:
new(inner, local_identity, remote_identity): Creates a new connection instance.
Trait Implementations:
Implements
NetConnection:local_addr,remote_addr: Return local and remote socket addresses.local_identity,remote_identity: Return identity strings.remote_certificate: Returns remote peer certificate if available.alpn_negotiated: Returns negotiated ALPN protocol string.send: Sends bytes over a send stream, managing stream acquisition and error recovery.recv: Receives a framed message from a receive stream.close: Closes the connection with a given code.watch_close: Asynchronously waits for connection shutdown.
StreamPool
Purpose: Manages pooled send and receive streams for a connection to reuse streams and avoid overhead.
Fields:
send: Mutex<Option<SendStream>>: Mutex-protected optional send stream.recv: Mutex<Option<ReadStream>>: Mutex-protected optional receive stream.
Methods:
new() -> Self: Initializes empty stream pool.acquire_send(connection) -> MutexGuard<Option<SendStream>>: Acquires or opens a send stream with timeout and error handling.acquire_recv(connection) -> MutexGuard<Option<ReadStream>>: Acquires or accepts an inbound receive stream with error handling.
Functions
write_buffer_to_stream
Purpose: Sends a length-prefixed byte buffer over a provided
SendStream.Parameters:
bytes: &[u8]: Data to send.stream: &mut SendStream: The stream to send data on.connection: &MsQuicNetConnection: Connection context for error resolution.
Returns:
anyhow::Result<()>Implementation details:
Prepends the data with its 4-byte big-endian length.
Uses a timeout for the send operation.
Handles connection lost errors by invoking
resolve_bad_certificate.
Usage: Used internally by MsQuicNetConnection::send.
read_message_from_stream
Purpose: Reads a length-prefixed message from a stream asynchronously.
Parameters:
stream: &mut (impl AsyncRead + Unpin): Stream to read from.
Returns:
anyhow::Result<(Vec<u8>, Duration)>- The message bytes and elapsed time since length read.Implementation details:
Reads exactly 4 bytes for message length.
Reads the message buffer of the specified length.
Measures elapsed time after length is read.
Usage: Used internally by MsQuicNetConnection::recv.
read_exact
Purpose: Reads exactly the requested number of bytes from an async stream.
Parameters:
stream: &mut (impl AsyncRead + Unpin): Stream to read from.buf: &mut [u8]: Buffer to fill.
Returns:
anyhow::Result<()>Implementation details:
Repeatedly reads until buffer is full.
Usage: Helper for read_message_from_stream.
resolve_bad_certificate
Purpose: Converts msquic connection errors related to bad certificates into descriptive anyhow errors.
Parameters:
err: &ConnectionError: The msquic connection error.connection: &Connection: The underlying connection.
Returns: anyhow::Error
Implementation details:
Checks if error is transport shutdown with
QUIC_STATUS_BAD_CERTIFICATE.Extracts public keys from local certificate to include in error message.
Returns enriched error message on certificate rejection.
Usage: Used when connection or stream failures may be caused by certificate validation.
Interaction with Other Parts of the System
Implements the
NetTransport, NetListener,NetConnection, andNetIncomingRequesttraits, enabling integration into network stacks expecting these abstractions.Uses ConfigFactory from quic_settings module to build QUIC configurations for client and server side.
Uses TLS credential and identity abstractions from
NetCredentialand CertHash to manage certificate-based authentication.Calls into msquic_async crate for QUIC protocol operations such as connection management, stream handling, and listener control.
Uses utility functions from tls module for public key extraction and certificate info formatting.
Employs Tokio asynchronous primitives for concurrency control and IO operations.
Usage Examples
Creating a Transport and Listener
let transport = MsQuicTransport::new();
let listener = transport.create_listener(bind_addr, &["my-alpn"], credential).await?;
Connecting to a Remote Peer
let connection = transport.connect(remote_addr, &["my-alpn"], credential).await?;
Accepting Incoming Connections
let incoming_request = listener.accept().await?;
let connection = incoming_request.accept().await?;
Sending and Receiving Data
connection.send(b"hello").await?;
let (data, duration) = connection.recv().await?;
println!("Received {} bytes in {:?}", data.len(), duration);
Important Implementation Details
The send and receive streams are pooled per connection to optimize resource usage and reduce stream creation overhead.
All stream operations are guarded by a 12-second timeout (
STREAM_OP_TIMEOUT) to avoid indefinite hangs.Length-prefixed framing is used for messages: a 4-byte big-endian length header followed by the message bytes.
Certificate validation errors are detected by inspecting msquic connection shutdown status codes and are converted into detailed error messages revealing the cause.
The
RegistrationWrapperensures proper resource cleanup by shutting down the msquic registration on drop.The connection's local and remote identities are maintained as string representations derived from certificate hashes, used for authentication and logging.
Mermaid Diagram
classDiagram
class MsQuicTransport {
+Arc<RegistrationWrapper> registration
+new()
+create_listener()
+connect()
}
class RegistrationWrapper {
-Registration 0
+drop()
}
MsQuicTransport --> RegistrationWrapper : owns
class MsQuicListener {
-Listener instance
-String local_identity
+accept()
}
MsQuicTransport ..> MsQuicListener : creates
class MsQuicNetIncomingRequest {
-Connection connection
-String local_identity
+remote_addr()
+accept()
}
MsQuicListener ..> MsQuicNetIncomingRequest : accepts
class MsQuicNetConnection {
-Connection inner
-String local_identity
-String remote_identity
-Arc<StreamPool> stream_pool
+local_addr()
+remote_addr()
+send()
+recv()
+close()
+watch_close()
}
MsQuicNetIncomingRequest ..> MsQuicNetConnection : accepts
class StreamPool {
-Mutex<Option<SendStream>> send
-Mutex<Option<ReadStream>> recv
+acquire_send()
+acquire_recv()
}
MsQuicNetConnection --> StreamPool : owns