Skip to main content

QuicDialOptions

Struct QuicDialOptions 

Source
pub struct QuicDialOptions {
    pub skip_cert_verification: bool,
    pub ca_certs: Vec<Vec<u8>>,
    pub alpn: Vec<Vec<u8>>,
    pub wt_protocols: Vec<Vec<u8>>,
    pub on_peer_certificates: Option<CertificateHook>,
    pub cipher_suites: Option<Vec<u16>>,
}
Expand description

How a QUIC dial is configured, independent of any draft.

alpn is a list because ALPN is: one handshake offers several protocols and the server picks, which is how a caller that does not know a peer’s draft finds out without dialling once per candidate.

Fields§

§skip_cert_verification: bool

Skip TLS certificate verification. Testing only.

§ca_certs: Vec<Vec<u8>>

Additional CA certificates to trust, DER-encoded, on top of the bundled Mozilla roots every dial starts from, on either transport.

§alpn: Vec<Vec<u8>>

ALPN protocols to offer, in preference order.

dial_quic returns the one the server selected. An empty list offers nothing and is refused by any peer that requires ALPN, which every MoQT relay does.

A WebTransport dial ignores this field: that session is HTTP/3 by definition and offers h3 alone, so the protocol name a WebTransport session negotiates is WT-Available-Protocols and not this. See wt_protocols. Everything else here applies to both transports.

§wt_protocols: Vec<Vec<u8>>

MOQT protocol identifiers to offer in the WT-Available-Protocols header of a WebTransport dial, in preference order.

WebTransport’s answer to ALPN, and the reason a MoQT draft can be negotiated over it at all. Drafts 15 and later state it in one sentence: “MOQT uses ALPN in QUIC and WT-Available-Protocols in WebTransport ([WebTransport], Section 3.3) to perform version negotiation” — draft-15 cites Section 3.4 of the same document and is otherwise word-for-word. Drafts 18 through 20 add the client’s half of it: “The client includes MOQT protocol identifiers in the WT-Available-Protocols header”. The identifiers are the ALPN names: moqt-15moqt-20.

Empty for drafts 07 through 14, which predate the header and settle their version in CLIENT_SETUP instead. Empty is not the same as absent by accident: a server that implements the negotiation and receives no offer has nothing to select, and may reject the session outright. imquic does, in as many words — “No WebTransport protocol offered”.

Ignored by a QUIC dial, where alpn carries the same names.

§Reading the answer needs a patched wtransport

A server names its choice in a WT-Protocol response header, and upstream wtransport 0.7 drops the CONNECT response once it has judged the status code. Transport::wt_protocol reads it — spelled as code because it exists only behind this crate’s wt-protocol feature, and a link to it would be broken in every build without that feature. The feature requires the patch in moqtap/vendor/wtransport and does not build without it.

Without that feature an accepted session says only that the server took one of the offers or ignored the header, and only a rejected one is conclusive — conclusive, then, about every identifier offered.

§on_peer_certificates: Option<CertificateHook>

Called with the peer’s certificate chain during the handshake, before it is judged — so it runs even for a chain that is about to be rejected, which is the case it exists for. See CertificateHook.

§cipher_suites: Option<Vec<u16>>

Restrict the TLS 1.3 cipher suites offered, by IANA codepoint.

None offers the crypto provider’s full set, which is what an ordinary client does and what every caller but a measuring one wants.

Some exists because the negotiated suite cannot be read back. quinn’s HandshakeData carries the ALPN and the server name and nothing else, and rustls does not surface the suite through it — so the only way to learn which suite a peer accepts is to offer exactly one and see whether the handshake completes. A successful dial is the measurement.

Codepoints rather than a rustls enum so that a rustls upgrade cannot change this crate’s public API. The three TLS 1.3 suites are 0x1301 AES-128-GCM-SHA256, 0x1302 AES-256-GCM-SHA384 and 0x1303 CHACHA20-POLY1305-SHA256. A codepoint the provider does not have is DialError::TlsConfig rather than a silent omission, because silently offering fewer suites than asked would make every answer a false negative.

Excluding 0x1301 is allowed, and is the interesting case. QUIC’s Initial packets must use AES-128-GCM and normally that makes such an offer unbuildable; the initial keys are taken from the default provider separately so that only the traffic suites are restricted.

Not honoured by webtransport::dial_webtransport_to, which reaches wtransport’s builder and cannot supply a separate initial suite through it. Spelled as code and not as a link on purpose: that module is behind the webtransport feature, and just doc-check builds these docs with the feature off.

Implementations§

Source§

impl QuicDialOptions

Source

pub fn new(alpn: Vec<Vec<u8>>) -> Self

Options offering alpn, verifying certificates against the bundled Mozilla roots, observing nothing.

A constructor and not a Default because there is no sensible default ALPN: an empty list is refused by every MoQT relay, so a QuicDialOptions::default() would be a value whose only outcome is TLS alert 120 — which in a conformance report reads as a defect in the relay rather than in the caller. Naming the offer is the one thing a dial cannot do without.

It is also the base for functional update, which is how the fields below stay additive:

QuicDialOptions { skip_cert_verification: true, ..QuicDialOptions::new(alpn) }
Source

pub fn insecure(self, yes: bool) -> Self

Accept any certificate. Testing only — see skip_cert_verification.

Source

pub fn ca_certs(self, certs: Vec<Vec<u8>>) -> Self

Trust these DER-encoded CAs on top of the bundled roots.

Source

pub fn observing(self, hook: CertificateHook) -> Self

Observe the peer’s certificate chain, accepted or not.

CertificateLog is the collector most callers want:

let log = CertificateLog::new();
let result = dial_quic_to(&target, &QuicDialOptions::new(alpn).observing(log.hook())).await;
let chain = log.chain();
Source

pub fn offering_cipher_suites(self, suites: Vec<u16>) -> Self

Offer only these cipher suites, by IANA codepoint. See cipher_suites.

Source

pub fn offering_wt_protocols(self, protocols: Vec<Vec<u8>>) -> Self

Offer these MOQT protocol identifiers to a WebTransport dial. See wt_protocols.

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