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: DraftVersionThe MoQT draft version to use for parsing.
upstream_transport: UpstreamTransportTypeThe transport type to use for the upstream connection.
upstream_addr: StringUpstream relay address (e.g., "192.168.1.10:4443" for QUIC).
skip_upstream_cert_verify: boolWhether 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: u64Timeout 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: EgressConfigEngine-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
impl ProxySessionConfig
Sourcepub fn upstream_alpn(&self, client_alpn: &[u8]) -> Vec<Vec<u8>>
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).