Skip to main content

ProxySessionConfig

Struct ProxySessionConfig 

Source
pub struct ProxySessionConfig {
    pub draft: DraftVersion,
    pub upstream_transport: UpstreamTransportType,
    pub upstream_addr: String,
    pub skip_upstream_cert_verify: bool,
    pub upstream_ca_certs: Vec<Vec<u8>>,
    pub upstream_connect_timeout_secs: u64,
    pub upstream_transport_config: Option<Arc<TransportConfig>>,
    pub upstream_transport_profile: Option<TransportProfile>,
    pub upstream_installer: Option<Arc<dyn TransportInstaller>>,
    pub upstream_socket: Option<Arc<dyn AsyncUdpSocket>>,
    pub egress: EgressConfig,
    pub shape: Option<ShapeProfile>,
}
Expand description

Configuration for a proxy session’s upstream connection.

Fields§

§draft: DraftVersion

The MoQT draft version to use for parsing.

§upstream_transport: UpstreamTransportType

The transport type to use for the upstream connection.

§upstream_addr: String

Upstream relay address (e.g., "192.168.1.10:4443" for QUIC).

§skip_upstream_cert_verify: bool

Whether to skip TLS verification for the upstream connection.

§upstream_ca_certs: Vec<Vec<u8>>

Custom CA certificates for the upstream connection (DER-encoded).

§upstream_connect_timeout_secs: u64

Timeout in seconds for the upstream connection attempt. 0 means no timeout.

§upstream_transport_config: Option<Arc<TransportConfig>>

Optional QUIC transport parameters — flow-control windows, MTU, keep-alive, congestion control — applied to the upstream relay connection.

None leaves quinn’s defaults in place. Ignored for WebTransport upstreams, which build their endpoint through wtransport.

Setting this and upstream_transport_profile is refused when the session connects, with ProxyError::TransportConfigAndProfile naming Leg::Upstream — see that variant for why the two cannot be merged. The refusal stands on a WebTransport upstream too, where both fields would have been ignored: a contradiction reported on one transport and swallowed on the other is worse than either answer.

§upstream_transport_profile: Option<TransportProfile>

The same parameters as upstream_transport_config, as a value that can be written down, checked and stored.

Some(_) builds the relay leg’s quinn::TransportConfig from this profile — through upstream_installer, or through crate::transport::DefaultInstaller when there is none — and installs it before the endpoint is built and before anything is dialled. A profile the installer refuses is ProxyError::TransportProfile, and no connection is attempted.

None is the behaviour callers had before this field existed. It is the only alternative to upstream_transport_config, never a companion to it.

§upstream_installer: Option<Arc<dyn TransportInstaller>>

How upstream_transport_profile becomes the config the relay leg installs.

None uses crate::transport::DefaultInstaller, which applies the profile over a fresh quinn::TransportConfig::default(). Supply one to start from a base of your own instead — the trait exists because a quinn::TransportConfig cannot be cloned, so the only way to have a base and a profile is to build the base again for each leg.

Inert without a profile. TransportInstaller::build takes a profile, so an installer set beside an empty upstream_transport_profile is never called and the leg installs nothing.

It composes with an upstream_qlog spec — named in plain code font because that field exists only under the qlog feature, so a link from this always-compiled one would not resolve. A leg carrying a profile, a spec and an installer builds its config here, once, and the capture sink is attached to what came back; TransportInstaller::build returns an owned quinn::TransportConfig precisely so that the two can stack.

§upstream_socket: Option<Arc<dyn AsyncUdpSocket>>

The socket every datagram of the upstream connection is sent on and received from.

None binds an ephemeral 0.0.0.0:0 socket, which is what this session has always done. Some(_) builds the upstream endpoint over the caller’s socket instead, so a decorating implementation — a tap, a counter, a network-impairment shim — sees and can alter the whole relay leg. Ownership is shared, so the caller keeps its handle on the socket while the session runs, and the relay sees the supplied socket’s address as this proxy’s.

This is the relay leg only. The client-facing leg is a separate endpoint over a separate socket, supplied — or not — when the listener is built.

§A WebTransport upstream cannot honour this

upstream_transport_config above is ignored for WebTransport upstreams, because wtransport builds their endpoint. A socket is not: it is refused. Connecting with UpstreamTransportType::WebTransport and a socket set returns ProxyError::UpstreamSocketUnsupported and connects to nothing.

The two are treated differently because the consequences of ignoring them are. A dropped transport config yields quinn’s defaults — a connection that works, with windows the caller did not pick. A dropped socket yields a relay leg that bypasses the caller’s shim entirely, so every impairment armed on it is reported by the shim and applied to nothing, and the run looks clean because it is clean. That failure is invisible from the outside, so it is made loud here instead.

§One socket, one session

Each session builds its own endpoint over the socket it is handed. Two endpoints reading one socket take each other’s datagrams — whichever polls first gets a packet, and a packet for a connection an endpoint does not own is discarded — so a socket shared across sessions running concurrently breaks all of them. Give concurrent sessions one socket each.

§egress: EgressConfig

Engine-side knobs for action execution — the per-stream deferred write queue’s byte budget and the ceiling on a hold.

Ignored when the hook’s crate::hook::ProxyHook::interest is Interest::NONE: nothing is ever queued, so nothing reads them.

§shape: Option<ShapeProfile>

How this session’s media egress is shaped — named token buckets, the class rules that aim at them, one bounded-queue policy and the discipline that arbitrates between classes.

None is today’s behaviour exactly: no scheduler is constructed, nothing extra is queued, and no deadline is armed.

Some(_) is configuration, not a hook capability, and that is the whole point of the field: it arms framing on its own, with no hook and no observer. A profile that only took effect when someone also attached a hook would let a user configure 500 kbps, get a byte pump, and read a successful run — which is the failure mode this knob exists to make impossible. Conversely, attaching an observer never arms shaping: see shaping_enabled on ForwardCtx.

Control streams are never shaped, on any path.

Implementations§

Source§

impl ProxySessionConfig

Source

pub fn upstream_alpn(&self, client_alpn: &[u8]) -> Vec<Vec<u8>>

Returns the ALPN protocol identifiers for the upstream connection.

For QUIC upstreams, mirrors the negotiated client ALPN so we connect to the relay with the same protocol the client is speaking. Falls back to self.draft.quic_alpn() if the client ALPN is empty (e.g., the listener didn’t capture it).

Trait Implementations§

Source§

impl Default for ProxySessionConfig

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

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.

Source§

impl<T> Instrument for T

Source§

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

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

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, <T as TryFrom<U>>::Error>

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.
Source§

impl<T> WithSubscriber for T

Source§

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
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

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