Skip to main content

Listener

Struct Listener 

Source
pub struct Listener {
    endpoint: Endpoint,
    server_config: ServerConfig,
}
Expand description

A transport-agnostic MoQT listener that accepts both raw-QUIC and WebTransport clients on the same UDP port.

Fields§

§endpoint: Endpoint§server_config: ServerConfig

The server configuration this endpoint was built with, kept so that Listener::set_transport can replace one field of it without rebuilding the rest.

A clone of the value handed to quinn rather than a fresh build, and the difference is not an optimisation. Rebuilding would re-parse the certificate — which means retaining the private key here, and PrivateKeyDer is not Clone — and quinn::ServerConfig::with_crypto draws a fresh random handshake-token master key each time it is called, which would invalidate every retry token already outstanding. Keeping the built value costs one Arc per field and none of that.

Implementations§

Source§

impl Listener

Source

pub fn bind(config: ListenerConfig) -> Result<Self, ProxyError>

Bind to the configured address and start listening.

The listener advertises every supported MoQT ALPN (moq-00 and moqt-<N> for all known drafts) plus h3 for WebTransport. The client picks which one to speak; the proxy forwards whatever arrives.

This binds an ordinary UDP socket at ListenerConfig::bind_addr, wraps it with quinn’s default runtime adapter and hands it to Listener::bind_with_socket. Must therefore be called from inside a tokio runtime context — as it always had to be, because quinn reaches for the same runtime when it binds a socket itself.

Source

pub fn bind_with_socket( config: ListenerConfig, socket: Arc<dyn AsyncUdpSocket>, ) -> Result<Self, ProxyError>

Bind the listener over a caller-supplied abstract socket.

Every datagram this listener sends to, or receives from, a client passes through socket, so a caller that supplies a decorating implementation — a tap, a counter, a network-impairment shim — observes and can alter the whole client-facing leg. Ownership is shared, so the caller keeps its handle on the socket after the endpoint is running.

ListenerConfig::bind_addr is ignored here: socket is already bound, and its address is the one Listener::local_addr reports. The rest of the configuration — the certificate, the advertised ALPN list, the transport parameters — applies exactly as it does to Listener::bind, which is a thin wrapper around this function.

§One socket covers WebTransport clients too

This single seam reaches raw-QUIC and WebTransport clients alike, because on the client-facing side the proxy never builds a WebTransport endpoint of its own. It builds the QUIC endpoint here, reads the negotiated ALPN off the handshake, and for h3 clients hands the still-connecting QUIC connection to the WebTransport library to finish. The library adopts a connection that already lives on this endpoint rather than binding a socket for it, so there is no second datagram path to intercept.

The relay leg to the upstream relay is a separate endpoint and is not affected by this socket.

Source

pub(crate) fn set_transport(&self, transport: Arc<TransportConfig>)

Install transport as the QUIC transport parameters this listener gives to the connections it accepts from now on.

§It cannot reach a connection that already exists

A quinn connection takes its TransportConfig once, out of the server configuration in force when its handshake began, and keeps that Arc for as long as it lives. There is no way to hand a live connection a different one — quinn exposes four setters on an accepted connection (the two stream-count limits and the two windows) and nothing else. So this changes what the next accepted connection gets and leaves every connection already running exactly as it was.

That is worth stating rather than glossing, because the failure it produces is silent: on a proxy nobody is connecting to any more, this call succeeds, changes the endpoint, and never reaches a single packet.

Everything else about the endpoint — the certificate, the advertised ALPN list, the handshake token key — is carried over from the configuration the listener bound with, so a client’s view of this server is unchanged apart from the transport parameters.

Source

pub async fn accept(&self) -> Result<AcceptedConn, ProxyError>

Accept the next incoming connection and dispatch based on the ALPN negotiated during the TLS handshake.

Raw-QUIC connections are returned immediately with the negotiated ALPN so the caller can pick the MoQT draft. For h3 clients the listener drives the HTTP/3 + extended-CONNECT handshake to completion before returning a ready wtransport::Connection.

Source

pub fn local_addr(&self) -> Result<SocketAddr, ProxyError>

Get the local address this listener is bound to.

Source

pub fn close(&self)

Stop accepting new connections.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more