listener.rs
Overview
The listener.rs file implements a robust asynchronous network listener designed to handle incoming connections over QUIC transport, leveraging the msquic library. It provides mechanisms to create, start, accept connections from, and stop a network listener while maintaining internal synchronization and state management. This listener supports asynchronous polling of new connections and graceful shutdown, integrating with futures and wakers for efficient async runtime compatibility.
Main Structs and Enums
Listener
The central struct representing the network listener. It encapsulates:
inner: An Arc-wrapped
ListenerInnercontaining shared and exclusive state.msquic_listener: The underlying QUIC listener from themsquiccrate.
ListenerInner
Holds the internal state of the listener, divided into:
exclusive: A mutex-guardedListenerInnerExclusivecontaining mutable state such as the connection queue and wakers.shared:ListenerInnerSharedwith immutable shared data like configuration and credentials.
ListenerInnerExclusive
Contains mutable state protected by a mutex:
state: CurrentListenerState.new_connections: Queue of newly acceptedConnections.new_connection_waiters: List of wakers waiting for new connections.shutdown_complete_waiters: List of wakers waiting for shutdown to complete.
ListenerInnerShared
Contains immutable shared data:
credential: Network credential used for security.configuration: QUIC configuration.
ListenerState (enum)
Represents the lifecycle state of the listener:
Open: Initial state before starting.StartComplete: Listener has started and is accepting connections.Shutdown: Shutdown initiated but not complete.ShutdownComplete: Shutdown fully completed.
Accept<'a>
A future returned by Listener::accept() for asynchronously awaiting a new incoming connection.
Stop<'a>
A future returned by Listener::stop() for asynchronously awaiting listener shutdown.
ListenError (enum)
Defines error states for listener operations:
NotStarted: Listener not started yet.AlreadyStarted: Listener already started.
Finished: Listener has finished its lifecycle.Failed: Generic failure.OtherError(msquic::Status): Miscellaneous error with
msquicstatus.
Detailed API and Methods
Listener
pub fn new(registration: &msquic::Registration, configuration: msquic::Configuration, credential: NetCredential) -> Result<Self, ListenError>
Constructs a new listener instance. It sets up the underlying msquic::Listener with an event callback closure to handle new connections and stop completion events.
Parameters:
registration: Reference tomsquic::Registrationused for listener creation.configuration: QUIC configuration.credential: Network credential for authentication/security.
Returns:
Ok(Self)on success orListenErroron failure.Implementation Details:
Uses an Arc to share inner state.
Registers event handler closures for
NewConnectionandStopCompleteevents.Traces creation for debugging.
pub fn start<T: AsRef<[msquic::BufferRef]>>(&self, alpn: &T, local_address: Option<SocketAddr>) -> Result<(), ListenError>
Starts the listener bound to an optional local address and configured with the specified ALPN protocols.
Parameters:
alpn: Reference to a slice of ALPN buffer references.local_address: Optional socket address to bind the listener.
Returns:
Ok(())if listener started successfully; otherwise, aListenError.Usage:
listener.start(&["hq-29"], Some("127.0.0.1:4433".parse().unwrap()))?;Implementation Details:
Locks exclusive state to check and update the listener state.
Prevents starting if already started or shutting down.
Converts
SocketAddrtomsquic::Addr.Calls underlying
msquic_listener.start.Updates state to
StartComplete.
pub fn accept(&self) -> Accept<'_>
Returns a future that resolves to the next incoming Connection.
Usage:
let connection = listener.accept().await?;Implementation Details: Returns a wrapper future
Acceptwhich delegates topoll_accept.
pub fn poll_accept(&self, cx: &mut Context<'_>) -> Poll<Result<Connection, ListenError>>
Polls for an incoming connection, waking the task when one is available.
Parameters:
cx: The task context used to register wakers.
Returns:
Poll::Ready(Ok(Connection))if a connection is ready.Poll::Ready(Err(ListenError))if listener is not started or finished.Poll::Pendingif no connection is currently available.
Implementation Details:
Locks exclusive state.
Pops a connection from the queue if available.
Registers current task's waker if pending.
Handles different listener states accordingly.
pub fn stop(&self) -> Stop<'_>
Returns a future that resolves when the listener has stopped.
Usage:
listener.stop().await?;Implementation Details: Returns a wrapper future
Stopwhich delegates topoll_stop.
pub fn poll_stop(&self, cx: &mut Context<'_>) -> Poll<Result<(), ListenError>>
Polls to stop the listener.
Parameters:
cx: The task context to register wakers.
Returns:
Poll::Ready(Ok(()))if shutdown is complete.Poll::Ready(Err(ListenError))if listener not started.Poll::Pendingif shutdown is in progress.
Implementation Details:
Locks exclusive state to check current state.
Initiates stop if in
StartCompletestate.Registers waker for shutdown completion notification.
Calls underlying
msquic_listener.stop()once.
pub fn local_addr(&self) -> Result<SocketAddr, ListenError>
Retrieves the local socket address the listener is bound to.
Returns:
Ok(SocketAddr)orListenError::Failedif unable to get address.Implementation Details: Uses
msquic_listener.get_local_addr()and converts toSocketAddr.
ListenerInner
fn new(configuration: msquic::Configuration, credential: NetCredential) -> Self
Initializes a new ListenerInner with default state and shared data.
Parameters:
configuration: QUIC configuration.credential: Network credential.
Returns: New instance with
ListenerState::Open.
fn handle_event_new_connection(&self, _info: msquic::NewConnectionInfo<'_>, connection: msquic::ConnectionRef) -> Result<(), msquic::Status>
Handles NewConnection events from msquic.
Parameters:
_info: Information about the new connection (unused).connection: Reference to the new connection.
Returns:
Ok(())on success ormsquic::Statuserror.Implementation Details:
Sets the QUIC configuration on the new connection.
Wraps the raw connection in a
Connectionstruct.Appends the new connection to the queue.
Wakes all tasks waiting for a new connection.
fn handle_event_stop_complete(&self, app_close_in_progress: bool) -> Result<(), msquic::Status>
Handles the StopComplete event indicating the listener has fully stopped.
Parameters:
app_close_in_progress: Indicates if app-initiated close is in progress.
Returns:
Ok(())ormsquic::Statuserror.Implementation Details:
Updates state to
ShutdownComplete.Wakes all tasks waiting for new connections and shutdown completion.
Traces state for debugging.
Futures: Accept and Stop
Both implement std::future::Future by delegating to Listener's polling methods.
Acceptresolves with aResult<Connection, ListenError>.Stopresolves with aResult<(), ListenError>.
ListenError
Defines error types for listener operations with human-readable messages.
Implementation Details and Algorithms
State Synchronization: Uses a
MutexaroundListenerInnerExclusiveto synchronize access to mutable internal state such as connection queues and waker lists.Waker Management: When a new connection arrives or shutdown completes, all registered wakers are drained and notified to resume polling tasks.
Event Handling: The listener registers callbacks with
msquic::Listenerfor handling connection and stop events asynchronously.Connection Queueing: Incoming connections are stored in a FIFO queue (
VecDeque), enabling orderly acceptance.State Transitions: The listener follows a defined state machine (
ListenerState) to prevent invalid operations like starting twice or accepting after shutdown.Error Handling: Operations return rich
ListenErrorvariants to indicate lifecycle and operational errors.
Interaction with Other System Components
msquicLibrary: Relies on themsquiccrate for low-level QUIC networking primitives. The listener wrapsmsquic::Listenerto provide a higher-level async interface.ConnectionStruct: Converts rawmsquic::ConnectionRefobjects intoConnectioninstances representing individual client connections. Interacts withconnection.rs.NetCredential: Uses credentials for secure network authentication embedded in the listener's shared state.Async Runtime: The listener integrates with the async runtime by implementing
poll_acceptandpoll_stopusingWakers andContextfrom the standard futures API.
Usage Example
let registration = msquic::Registration::new("MyApp")?;
let config = msquic::Configuration::new(...)?;
let credential = NetCredential::new(...)?;
let listener = Listener::new(®istration, config, credential)?;
listener.start(&["hq-29"], Some("0.0.0.0:4433".parse().unwrap()))?;
loop {
match listener.accept().await {
Ok(connection) => {
// Handle the connection
}
Err(ListenError::Finished) => break,
Err(e) => eprintln!("Error accepting connection: {:?}", e),
}
}
listener.stop().await?;
Mermaid Diagram: Listener Structure and Workflow
classDiagram
class Listener {
+new()
+start()
+accept()
+poll_accept()
+stop()
+poll_stop()
+local_addr()
}
class ListenerInner {
-exclusive: Mutex~ListenerInnerExclusive~
-shared: ListenerInnerShared
+new()
+handle_event_new_connection()
+handle_event_stop_complete()
}
class ListenerInnerExclusive {
-state: ListenerState
-new_connections: VecDeque~Connection~
-new_connection_waiters: Vec~Waker~
-shutdown_complete_waiters: Vec~Waker~
}
class ListenerInnerShared {
-credential: NetCredential
-configuration: msquic::Configuration
}
class Accept {
<<future>>
+poll()
}
class Stop {
<<future>>
+poll()
}
Listener --> ListenerInner : contains
ListenerInner --> ListenerInnerExclusive : mutex guards
ListenerInner --> ListenerInnerShared : contains
Listener --> Accept : returns future
Listener --> Stop : returns future
This diagram illustrates the core structures, their key members, and their relationships, emphasizing the flow from the Listener to internal state and the async futures Accept and Stop.
References
msquicQUIC Transport LibraryConnectionManagementNetCredentialAuthenticationAsynchronous programming and futures concepts in Rust Async Programming