tquic/
lib.rs

1// Copyright (c) 2023 The TQUIC Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! TQUIC is an implementation of the [IETF QUIC protocol](https://quicwg.org/).
16//! It is a high-performance, lightweight, and cross-platform QUIC library.
17//!
18//! ## Features and Advantages
19//!
20//! * **High Performance**: TQUIC is designed for high performance and low
21//!   latency.
22//! * **High Throughput**: TQUIC supports various congtestion control algorithms
23//!   (CUBIC, BBR, COPA), and Multipath QUIC for utilizing multiple paths within
24//!   a single connection.
25//! * **High Quality**: TQUIC employs extensive testing techniques, including
26//!   unit testing, fuzz testing, integration testing, benchmarking,
27//!   interoperability testing, and protocol conformance testing.
28//! * **Easy to Use**: TQUIC is easy to use, supporting flexible configuration
29//!   and detailed observability. It offers APIs for Rust/C/C++.
30//! * **Powered by Rust**: TQUIC is written in a memory-safe language, making it
31//!   immune to Buffer Overflow vulnerability and other memory-related bugs.
32//! * **Rich Features**: TQUIC supports all big features conforming with QUIC,
33//!   HTTP/3 RFCs.
34//!
35//! The [TQUIC project website](https://tquic.net/docs/intro) offers a
36//! comprehensive introduction to TQUIC.
37//!
38//! ## Get started
39//!
40//! See the [documents](https://tquic.net/docs/category/getting-started) and
41//! [examples](https://github.com/tencent/tquic/tree/master/tools/) to get
42//! started with TQUIC.
43//!
44//! ## Feature flags
45//!
46//! TQUIC defines several feature flags to reduce the amount of compiled code
47//! and dependencies:
48//!
49//! * `ffi`: Build and expose the FFI API
50//! * `qlog`: Enable support for qlog
51//! * `h3`: Enable support for HTTP/3
52
53#![allow(unused_imports)]
54#![allow(dead_code)]
55#![allow(unexpected_cfgs)]
56
57use std::cmp;
58use std::collections::VecDeque;
59use std::fmt;
60use std::net::IpAddr;
61use std::net::SocketAddr;
62use std::sync::Arc;
63use std::time;
64use std::time::Duration;
65use std::time::Instant;
66
67use bytes::Buf;
68use bytes::BufMut;
69use rand::RngCore;
70use ring::aead;
71use ring::aead::LessSafeKey;
72use ring::aead::UnboundKey;
73use ring::hmac;
74use rustc_hash::FxHashSet;
75
76use crate::codec::VINT_MAX;
77use crate::connection::stream;
78use crate::tls::TlsSession;
79use crate::token::ResetToken;
80use crate::trans_param::TransportParams;
81
82/// The current QUIC wire version.
83pub const QUIC_VERSION: u32 = QUIC_VERSION_V1;
84
85/// The QUIC Version 1
86pub const QUIC_VERSION_V1: u32 = 0x0000_0001;
87
88/// The Connection ID MUST NOT exceed 20 bytes in QUIC version 1.
89/// See RFC 9000 Section 17.2
90pub const MAX_CID_LEN: usize = 20;
91
92/// Max number of cid that are allowed to advertised to the peer.
93const MAX_CID_LIMIT: u64 = 8;
94
95/// The Stateless Reset Token is a 16-byte value.
96const RESET_TOKEN_LEN: usize = 16;
97
98/// For the Stateless Reset to appear as a valid QUIC packet, the Unpredictable
99/// Bits field needs to include at least 38 bits of data. The minimum length of
100/// a Stateless Reset Packet is 21 bytes.
101const MIN_RESET_PACKET_LEN: usize = 21;
102
103/// Assuming the maximum possible connection ID and packet number size, the 1RTT
104/// packet size is:
105/// 1 (header) + 20 (cid) + 4 (pkt num) + 1 (payload) + 16 (AEAD tag) = 42 bytes
106const MAX_RESET_PACKET_LEN: usize = 42;
107
108/// The encoded size of length field in long header.
109const LENGTH_FIELD_LEN: usize = 2;
110
111/// The minimum length of Initial packets sent by a client.
112pub const MIN_CLIENT_INITIAL_LEN: usize = 1200;
113
114const MIN_PAYLOAD_LEN: usize = 4;
115
116/// Ensure the ACK frame can fit in a single minimum-MTU packet.
117const MAX_ACK_RANGES: usize = 68;
118
119/// Default outgoing udp datagram payloads size.
120const DEFAULT_SEND_UDP_PAYLOAD_SIZE: usize = 1200;
121
122/// An endpoint MUST limit the amount of data it sends to the unvalidated
123/// address to three times the amount of data received from that address.
124const ANTI_AMPLIFICATION_FACTOR: usize = 3;
125
126/// The RECOMMENDED value of the timer granularity is 1 millisecond.
127/// See RFC 9002 Section 6.1
128pub const TIMER_GRANULARITY: Duration = Duration::from_millis(1);
129
130/// The largest count of streams for each type.
131const MAX_STREAMS_PER_TYPE: u64 = 1 << 60;
132
133/// Represents the minimum multiple by which the connection flow control window
134/// needs to be greater than the stream flow control window.
135const CONNECTION_WINDOW_FACTOR: f64 = 1.5;
136
137/// Resumed connections over the same network MAY use the previous connection's
138/// final smoothed RTT value as the resumed connection's initial RTT. When no
139/// previous RTT is available, the initial RTT SHOULD be set to 333 milliseconds.
140/// This results in handshakes starting with a PTO of 1 second, as recommended
141/// for TCP's initial RTO
142const INITIAL_RTT: Duration = Duration::from_millis(333);
143
144/// Default handshake timeout is 30 seconds.
145const DEFAULT_HANDSHAKE_TIMEOUT: Duration = Duration::from_secs(30);
146
147///  Default linear factor for calculating the probe timeout.
148const DEFAULT_PTO_LINEAR_FACTOR: u64 = 0;
149
150/// Default upper limit of probe timeout.
151const MAX_PTO: Duration = Duration::MAX;
152
153/// Result type for quic operations.
154pub type Result<T> = std::result::Result<T, Error>;
155
156/// Connection Id is an identifier used to identify a QUIC connection
157/// at an endpoint.
158#[repr(C)]
159#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
160pub struct ConnectionId {
161    /// length of cid
162    len: u8,
163    /// octets of cid
164    data: [u8; MAX_CID_LEN],
165}
166
167impl ConnectionId {
168    /// Construct cid from byte slice
169    pub fn new(bytes: &[u8]) -> Self {
170        let len = cmp::min(bytes.len(), MAX_CID_LEN);
171        let mut cid = Self {
172            len: len as u8,
173            data: [0; MAX_CID_LEN],
174        };
175        cid.data[..len].copy_from_slice(&bytes[..len]);
176        cid
177    }
178
179    /// Construct a random cid.
180    pub fn random() -> Self {
181        Self {
182            len: MAX_CID_LEN as u8,
183            data: rand::random::<[u8; MAX_CID_LEN]>(),
184        }
185    }
186}
187
188impl std::ops::Deref for ConnectionId {
189    type Target = [u8];
190    fn deref(&self) -> &[u8] {
191        &self.data[0..self.len as usize]
192    }
193}
194
195impl fmt::Debug for ConnectionId {
196    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197        for b in self.iter() {
198            write!(f, "{b:02x}")?;
199        }
200        Ok(())
201    }
202}
203
204impl fmt::Display for ConnectionId {
205    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206        fmt::Debug::fmt(self, f)
207    }
208}
209
210/// Generate QUIC connection ID
211pub trait ConnectionIdGenerator {
212    /// Generate a new CID
213    fn generate(&mut self) -> ConnectionId;
214
215    /// Return the length of a CID
216    fn cid_len(&self) -> usize;
217
218    /// Generate a new CID and associated reset token.
219    fn generate_cid_and_token(&mut self, reset_token_key: &hmac::Key) -> (ConnectionId, u128) {
220        let scid = self.generate();
221        let reset_token = ResetToken::generate(reset_token_key, &scid);
222        (scid, reset_token.to_u128())
223    }
224}
225
226/// Generates purely random connection IDs of a certain length
227#[derive(Debug, Clone, Copy)]
228pub struct RandomConnectionIdGenerator {
229    cid_len: usize,
230}
231
232impl RandomConnectionIdGenerator {
233    pub fn new(cid_len: usize) -> Self {
234        Self {
235            cid_len: cmp::min(cid_len, MAX_CID_LEN),
236        }
237    }
238}
239
240impl ConnectionIdGenerator for RandomConnectionIdGenerator {
241    fn generate(&mut self) -> ConnectionId {
242        let mut bytes = [0; MAX_CID_LEN];
243        rand::thread_rng().fill_bytes(&mut bytes[..self.cid_len]);
244        ConnectionId::new(&bytes[..self.cid_len])
245    }
246
247    fn cid_len(&self) -> usize {
248        self.cid_len
249    }
250}
251
252/// Meta information about a packet.
253#[derive(Clone, Copy, Debug)]
254pub struct PacketInfo {
255    /// The source address of the packet
256    pub src: SocketAddr,
257
258    /// The destination address of the packet
259    pub dst: SocketAddr,
260
261    /// The time when the packet arrived or the time to send the packet
262    pub time: time::Instant,
263}
264
265/// Address tuple.
266#[derive(Hash, Eq, PartialEq, Debug, Copy, Clone)]
267pub struct FourTuple {
268    /// The local address
269    pub local: SocketAddr,
270
271    /// The remote address
272    pub remote: SocketAddr,
273}
274
275/// An iterator over FourTuple.
276#[derive(Default)]
277pub struct FourTupleIter {
278    pub(crate) addrs: Vec<FourTuple>,
279}
280
281impl Iterator for FourTupleIter {
282    type Item = FourTuple;
283
284    #[inline]
285    fn next(&mut self) -> Option<Self::Item> {
286        self.addrs.pop()
287    }
288}
289
290impl ExactSizeIterator for FourTupleIter {
291    #[inline]
292    fn len(&self) -> usize {
293        self.addrs.len()
294    }
295}
296
297/// Check whether the protocol version is supported.
298fn version_is_supported(version: u32) -> bool {
299    matches!(version, QUIC_VERSION_V1)
300}
301
302/// Configurations about QUIC endpoint.
303#[derive(Clone)]
304pub struct Config {
305    /// QUIC transport configuration.
306    local_transport_params: TransportParams,
307
308    /// Handshake timeout in microseconds.
309    max_handshake_timeout: time::Duration,
310
311    /// Maximum number of concurrent connections.
312    max_concurrent_conns: u32,
313
314    /// Maximum size of the receiver connection flow control window.
315    max_connection_window: u64,
316
317    /// Maximum size of the receiver stream flow control window.
318    max_stream_window: u64,
319
320    /// Uses Retry packets to reduce load on servers by forcing the client to
321    /// prove ownership of its address
322    retry: bool,
323
324    /// Enable stateless reset or not.
325    stateless_reset: bool,
326
327    /// Duration after a retry token was issued for which it's considered valid.
328    address_token_lifetime: Duration,
329
330    /// Key for address token generation.
331    address_token_key: Vec<LessSafeKey>,
332
333    /// Key for stateless reset token generation.
334    reset_token_key: hmac::Key,
335
336    /// Length of source cid.
337    cid_len: usize,
338
339    /// Anti-amplification factor.
340    anti_amplification_factor: usize,
341
342    /// Maximum numbers of packets sent in a batch.
343    send_batch_size: usize,
344
345    /// Buffer size for early incoming zero rtt packets, in packets.
346    zerortt_buffer_size: usize,
347
348    /// The maximum number of undecryptable packets that can be stored by one connection, in packets.
349    max_undecryptable_packets: usize,
350
351    /// Configurations about loss recovery, congestion control, and pmtu discovery.
352    recovery: RecoveryConfig,
353
354    /// Multipath transport configurations.
355    multipath: MultipathConfig,
356
357    /// Find TLS config according to server name.
358    tls_config_selector: Option<Arc<dyn tls::TlsConfigSelector>>,
359}
360
361impl Config {
362    /// Create default configuration.
363    ///
364    /// The configuration may be customized by calling related set methods.
365    ///
366    /// ## Examples:
367    ///
368    /// ```
369    /// let mut conf = tquic::Config::new()?;
370    /// conf.set_max_idle_timeout(30000);
371    /// let alpn =  vec![b"h3".to_vec()];
372    /// let mut tls_config = tquic::TlsConfig::new_client_config(alpn, true)?;
373    /// conf.set_tls_config(tls_config);
374    /// # Ok::<(), tquic::error::Error>(())
375    /// ```
376    pub fn new() -> Result<Self> {
377        let local_transport_params = TransportParams {
378            initial_max_data: 10485760,
379            initial_max_stream_data_bidi_local: 5242880,
380            initial_max_stream_data_bidi_remote: 2097152,
381            initial_max_stream_data_uni: 1048576,
382            initial_max_streams_bidi: 200,
383            initial_max_streams_uni: 100,
384            ..TransportParams::default()
385        };
386
387        let reset_token_key = hmac::Key::new(hmac::HMAC_SHA256, &[]);
388
389        Ok(Self {
390            local_transport_params,
391            max_handshake_timeout: DEFAULT_HANDSHAKE_TIMEOUT,
392            max_concurrent_conns: 1000000,
393            max_connection_window: stream::MAX_CONNECTION_WINDOW,
394            max_stream_window: stream::MAX_STREAM_WINDOW,
395            retry: false,
396            stateless_reset: true,
397            address_token_lifetime: Duration::from_secs(86400),
398            address_token_key: Self::rand_address_token_key()?,
399            reset_token_key,
400            cid_len: 8,
401            anti_amplification_factor: ANTI_AMPLIFICATION_FACTOR,
402            send_batch_size: 64,
403            zerortt_buffer_size: 1000,
404            max_undecryptable_packets: 10,
405            recovery: RecoveryConfig::default(),
406            multipath: MultipathConfig::default(),
407            tls_config_selector: None,
408        })
409    }
410
411    /// Set the `max_idle_timeout` transport parameter in milliseconds.
412    /// Idle timeout is disabled by default.
413    pub fn set_max_idle_timeout(&mut self, v: u64) {
414        self.local_transport_params.max_idle_timeout = cmp::min(v, VINT_MAX);
415    }
416
417    /// Set handshake timeout in milliseconds. Zero turns the timeout off.
418    pub fn set_max_handshake_timeout(&mut self, v: u64) {
419        self.max_handshake_timeout = time::Duration::from_millis(v);
420    }
421
422    /// Set the `max_udp_payload_size` transport parameter in bytes. It limits
423    /// the size of UDP payloads that the endpoint is willing to receive. The
424    /// default value is `65527`.
425    pub fn set_recv_udp_payload_size(&mut self, v: u16) {
426        self.local_transport_params.max_udp_payload_size = cmp::min(v as u64, VINT_MAX);
427    }
428
429    /// Enable the Datagram Packetization Layer Path MTU Discovery
430    /// default value is true.
431    pub fn enable_dplpmtud(&mut self, v: bool) {
432        self.recovery.enable_dplpmtud = v;
433    }
434
435    /// Set the maximum outgoing UDP payload size in bytes.
436    /// It corresponds to the maximum datagram size that DPLPMTUD tries to discovery.
437    /// The default value is `1200` which means let DPLPMTUD choose a value.
438    pub fn set_send_udp_payload_size(&mut self, v: usize) {
439        self.recovery.max_datagram_size = cmp::max(v, DEFAULT_SEND_UDP_PAYLOAD_SIZE);
440    }
441
442    /// Set the `initial_max_data` transport parameter. It means the initial
443    /// value for the maximum amount of data that can be sent on the connection.
444    /// The value is capped by the setting `max_connection_window`.
445    /// The default value is `10485760`.
446    pub fn set_initial_max_data(&mut self, v: u64) {
447        self.local_transport_params.initial_max_data = cmp::min(v, self.max_connection_window);
448    }
449
450    /// Set the `initial_max_stream_data_bidi_local` transport parameter.
451    /// The value is capped by the setting `max_stream_window`.
452    /// The default value is `5242880`.
453    pub fn set_initial_max_stream_data_bidi_local(&mut self, v: u64) {
454        self.local_transport_params
455            .initial_max_stream_data_bidi_local = cmp::min(v, self.max_stream_window);
456    }
457
458    /// Set the `initial_max_stream_data_bidi_remote` transport parameter.
459    /// The value is capped by the setting `max_stream_window`.
460    /// The default value is `2097152`.
461    pub fn set_initial_max_stream_data_bidi_remote(&mut self, v: u64) {
462        self.local_transport_params
463            .initial_max_stream_data_bidi_remote = cmp::min(v, self.max_stream_window);
464    }
465
466    /// Set the `initial_max_stream_data_uni` transport parameter.
467    /// The value is capped by the setting `max_stream_window`.
468    /// The default value is `1048576`.
469    pub fn set_initial_max_stream_data_uni(&mut self, v: u64) {
470        self.local_transport_params.initial_max_stream_data_uni =
471            cmp::min(v, self.max_stream_window);
472    }
473
474    /// Set the `initial_max_streams_bidi` transport parameter.
475    /// The default value is `200`.
476    pub fn set_initial_max_streams_bidi(&mut self, v: u64) {
477        self.local_transport_params.initial_max_streams_bidi = cmp::min(v, VINT_MAX);
478    }
479
480    /// Set the `initial_max_streams_uni` transport parameter.
481    /// The default value is `100`.
482    pub fn set_initial_max_streams_uni(&mut self, v: u64) {
483        self.local_transport_params.initial_max_streams_uni = cmp::min(v, VINT_MAX);
484    }
485
486    /// Set the `ack_delay_exponent` transport parameter.
487    /// The default value is `3`.
488    pub fn set_ack_delay_exponent(&mut self, v: u64) {
489        self.local_transport_params.ack_delay_exponent = cmp::min(v, VINT_MAX);
490    }
491
492    /// Set the `max_ack_delay` transport parameter.
493    /// The default value is `25`.
494    pub fn set_max_ack_delay(&mut self, v: u64) {
495        self.local_transport_params.max_ack_delay = cmp::min(v, VINT_MAX);
496    }
497
498    /// Set the maximum number of ack-eliciting packets the endpoint receives before
499    /// sending an acknowledgment.
500    /// The default value is `2`.
501    pub fn set_ack_eliciting_threshold(&mut self, v: u64) {
502        self.recovery.ack_eliciting_threshold = v;
503    }
504
505    /// Set congestion control algorithm that the connection would use.
506    /// The default value is Bbr.
507    pub fn set_congestion_control_algorithm(&mut self, cca: CongestionControlAlgorithm) {
508        self.recovery.congestion_control_algorithm = cca;
509    }
510
511    /// Set the initial congestion window in packets.
512    /// The default value is 10.
513    pub fn set_initial_congestion_window(&mut self, packets: u64) {
514        self.recovery.initial_congestion_window = packets;
515    }
516
517    /// Set the minimal congestion window in packets.
518    /// The default value is 2.
519    pub fn set_min_congestion_window(&mut self, packets: u64) {
520        self.recovery.min_congestion_window = packets
521    }
522
523    /// Set the threshold for slow start in packets.
524    /// The default value is the maximum value of u64.
525    pub fn set_slow_start_thresh(&mut self, packets: u64) {
526        self.recovery.slow_start_thresh = packets
527    }
528
529    /// Set the minimum duration for BBR ProbeRTT state in milliseconds.
530    /// The default value is 200 milliseconds.
531    pub fn set_bbr_probe_rtt_duration(&mut self, millis: u64) {
532        self.recovery.bbr_probe_rtt_duration =
533            cmp::max(Duration::from_millis(millis), TIMER_GRANULARITY);
534    }
535
536    /// Enable using a cwnd based on bdp during ProbeRTT state.
537    /// The default value is false.
538    pub fn enable_bbr_probe_rtt_based_on_bdp(&mut self, v: bool) {
539        self.recovery.bbr_probe_rtt_based_on_bdp = v;
540    }
541
542    /// Set the cwnd gain for BBR ProbeRTT state.
543    /// This option is meaningful only when `bbr_probe_rtt_based_on_bdp` option
544    /// is set to true.
545    /// The default value is 0.75
546    pub fn set_bbr_probe_rtt_cwnd_gain(&mut self, v: f64) {
547        self.recovery.bbr_probe_rtt_cwnd_gain = v;
548    }
549
550    /// Set the length of the BBR RTProp min filter window in milliseconds.
551    /// The default value is 10000 milliseconds.
552    pub fn set_bbr_rtprop_filter_len(&mut self, millis: u64) {
553        self.recovery.bbr_rtprop_filter_len =
554            cmp::max(Duration::from_millis(millis), TIMER_GRANULARITY);
555    }
556
557    /// Set the cwnd gain for BBR ProbeBW state.
558    /// The default value is 2.0
559    pub fn set_bbr_probe_bw_cwnd_gain(&mut self, v: f64) {
560        self.recovery.bbr_probe_bw_cwnd_gain = v;
561    }
562
563    /// Set the delta in copa slow start state.
564    pub fn set_copa_slow_start_delta(&mut self, v: f64) {
565        self.recovery.copa_slow_start_delta = v;
566    }
567
568    /// Set the delta in coap steady state.
569    pub fn set_copa_steady_delta(&mut self, v: f64) {
570        self.recovery.copa_steady_delta = v;
571    }
572
573    /// Enable Using the rtt standing instead of the latest rtt to calculate queueing delay.
574    pub fn enable_copa_use_standing_rtt(&mut self, v: bool) {
575        self.recovery.copa_use_standing_rtt = v;
576    }
577
578    /// Set the initial RTT in milliseconds. The default value is 333ms.
579    ///
580    /// The configuration should be changed with caution. Setting a value less than the default
581    /// will cause retransmission of handshake packets to be more aggressive.
582    pub fn set_initial_rtt(&mut self, millis: u64) {
583        self.recovery.initial_rtt = cmp::max(Duration::from_millis(millis), TIMER_GRANULARITY);
584    }
585
586    /// Enable pacing to smooth the flow of packets sent onto the network.
587    /// The default value is true.
588    pub fn enable_pacing(&mut self, v: bool) {
589        self.recovery.enable_pacing = v;
590    }
591
592    /// Set clock granularity used by the pacer.
593    /// The default value is 1 milliseconds.
594    pub fn set_pacing_granularity(&mut self, millis: u64) {
595        self.recovery.pacing_granularity =
596            cmp::max(Duration::from_millis(millis), TIMER_GRANULARITY);
597    }
598
599    /// Set the linear factor for calculating the probe timeout.
600    /// The endpoint do not backoff the first `v` consecutive probe timeouts.
601    /// The default value is `0`.
602    /// The configuration should be changed with caution. Setting a value greater than the default
603    /// will cause retransmission to be more aggressive.
604    pub fn set_pto_linear_factor(&mut self, v: u64) {
605        self.recovery.pto_linear_factor = v;
606    }
607
608    /// Set the upper limit of probe timeout in milliseconds.
609    /// A Probe Timeout (PTO) triggers the sending of one or two probe datagrams and enables a
610    /// connection to recover from loss of tail packets or acknowledgments.
611    /// See RFC 9002 Section 6.2.
612    pub fn set_max_pto(&mut self, millis: u64) {
613        self.recovery.max_pto = cmp::max(Duration::from_millis(millis), TIMER_GRANULARITY);
614    }
615
616    /// Set the `active_connection_id_limit` transport parameter.
617    /// The default value is `2`. Lower values will be ignored.
618    pub fn set_active_connection_id_limit(&mut self, v: u64) {
619        if v >= 2 {
620            self.local_transport_params.active_conn_id_limit = cmp::min(v, VINT_MAX);
621        }
622    }
623
624    /// Set the `enable_multipath` transport parameter.
625    /// The default value is false. (Experimental)
626    pub fn enable_multipath(&mut self, v: bool) {
627        self.local_transport_params.enable_multipath = v;
628    }
629
630    /// Set the multipath scheduling algorithm
631    /// The default value is MultipathAlgorithm::MinRtt
632    pub fn set_multipath_algorithm(&mut self, v: MultipathAlgorithm) {
633        self.multipath.multipath_algorithm = v;
634    }
635
636    /// Set the maximum size of the connection flow control window.
637    /// The default value is MAX_CONNECTION_WINDOW (15 MB).
638    pub fn set_max_connection_window(&mut self, v: u64) {
639        self.max_connection_window = cmp::min(v, VINT_MAX);
640    }
641
642    /// Set the maximum size of the stream flow control window.
643    /// The value should not be greater than the setting `max_connection_window`.
644    /// The default value is MAX_STREAM_WINDOW (6 MB).
645    pub fn set_max_stream_window(&mut self, v: u64) {
646        self.max_stream_window = cmp::min(v, VINT_MAX);
647    }
648
649    /// Set the maximum number of concurrent connections.
650    /// The default value is `1000000`
651    pub fn set_max_concurrent_conns(&mut self, v: u32) {
652        self.max_concurrent_conns = v;
653    }
654
655    /// Set the key for reset token generation.
656    /// Applicable to Server only.
657    pub fn set_reset_token_key(&mut self, v: [u8; 64]) {
658        // HMAC-SHA256 use a 512-bit block length
659        self.reset_token_key = hmac::Key::new(hmac::HMAC_SHA256, &v);
660    }
661
662    /// Set the lifetime of address token.
663    /// Applicable to Server only.
664    pub fn set_address_token_lifetime(&mut self, seconds: u64) {
665        self.address_token_lifetime = Duration::from_secs(seconds);
666    }
667
668    /// Set the key for address token generation.
669    /// Applicable to Server only.
670    pub fn set_address_token_key(&mut self, keys: Vec<[u8; 16]>) -> Result<()> {
671        if keys.is_empty() {
672            return Err(Error::InvalidConfig("address token key empty".into()));
673        }
674
675        let mut address_token_key = vec![];
676        for key in keys {
677            // AES-128 uses a 128-bit key length
678            let key = UnboundKey::new(&aead::AES_128_GCM, &key).map_err(|_| Error::CryptoFail)?;
679            let key = LessSafeKey::new(key);
680            address_token_key.push(key);
681        }
682        self.address_token_key = address_token_key;
683
684        Ok(())
685    }
686
687    /// Set whether stateless retry is allowed. Default is not allowed.
688    /// Applicable to Server only.
689    pub fn enable_retry(&mut self, enable_retry: bool) {
690        self.retry = enable_retry;
691    }
692
693    /// Set whether stateless reset is allowed.
694    /// Applicable to Endpoint only.
695    pub fn enable_stateless_reset(&mut self, enable_stateless_reset: bool) {
696        self.stateless_reset = enable_stateless_reset;
697    }
698
699    /// Set the length of source cid.
700    /// Applicable to Endpoint only.
701    pub fn set_cid_len(&mut self, v: usize) {
702        self.cid_len = cmp::min(v, MAX_CID_LEN);
703    }
704
705    /// Set the anti-amplification factor.
706    ///
707    /// The server limits the data sent to an unvalidated address to
708    /// `anti_amplification_factor` times the received data.
709    pub fn set_anti_amplification_factor(&mut self, v: usize) {
710        self.anti_amplification_factor = cmp::max(v, ANTI_AMPLIFICATION_FACTOR);
711    }
712
713    /// Set the batch size for sending packets.
714    /// Applicable to Endpoint only.
715    pub fn set_send_batch_size(&mut self, v: usize) {
716        self.send_batch_size = cmp::max(v, 1);
717    }
718
719    /// Set the buffer size for disordered zerortt packets on the server.
720    /// The default value is `1000`. A value of 0 will be treated as default value.
721    /// Applicable to Server only.
722    pub fn set_zerortt_buffer_size(&mut self, v: usize) {
723        if v > 0 {
724            self.zerortt_buffer_size = v;
725        } else {
726            self.zerortt_buffer_size = 1000;
727        }
728    }
729
730    /// Set the maximum number of undecryptable packets that can be stored by one connection.
731    /// The default value is `10`. A value of 0 will be treated as default value.
732    pub fn set_max_undecryptable_packets(&mut self, v: usize) {
733        if v > 0 {
734            self.max_undecryptable_packets = v;
735        } else {
736            self.max_undecryptable_packets = 10;
737        }
738    }
739
740    /// Enable or disable encryption on 1-RTT packets. (Experimental)
741    /// The default value is true.
742    /// WARN: The The disable_1rtt_encryption extension is not meant to be used
743    /// for any practical application protocol on the open internet.
744    pub fn enable_encryption(&mut self, v: bool) {
745        self.local_transport_params.disable_encryption = !v;
746    }
747
748    /// Set TLS config.
749    pub fn set_tls_config(&mut self, tls_config: tls::TlsConfig) {
750        self.set_tls_config_selector(Arc::new(tls::DefaultTlsConfigSelector {
751            tls_config: Arc::new(tls_config),
752        }));
753    }
754
755    /// Set TLS config selector. Used for selecting TLS config according to SNI.
756    pub fn set_tls_config_selector(
757        &mut self,
758        tls_config_selector: Arc<dyn tls::TlsConfigSelector>,
759    ) {
760        self.tls_config_selector = Some(tls_config_selector);
761    }
762
763    /// Generate random address token key.
764    fn rand_address_token_key() -> Result<Vec<LessSafeKey>> {
765        let mut key = [0_u8; 16];
766        rand::thread_rng().fill_bytes(&mut key);
767        Ok(vec![LessSafeKey::new(
768            UnboundKey::new(&aead::AES_128_GCM, &key).map_err(|_| Error::CryptoFail)?,
769        )])
770    }
771
772    /// Create new tls session.
773    fn new_tls_session(&self, server_name: Option<&str>, is_server: bool) -> Result<TlsSession> {
774        if self.tls_config_selector.is_none() {
775            return Err(Error::TlsFail("tls config selector is not set".into()));
776        }
777        match self.tls_config_selector.as_ref().unwrap().get_default() {
778            Some(tls_config) => tls_config.new_session(server_name, is_server),
779            None => Err(Error::TlsFail("get tls config failed".into())),
780        }
781    }
782}
783
784/// Configurations about loss recovery, congestion control, and pmtu discovery.
785#[doc(hidden)]
786#[derive(Debug, Clone)]
787pub struct RecoveryConfig {
788    /// Enable Datagram Packetization Layer Path MTU Discovery.
789    pub enable_dplpmtud: bool,
790
791    /// The maximum size of outgoing UDP payloads.
792    pub max_datagram_size: usize,
793
794    /// The maximum amount of time the endpoint intends to delay acknowledgments
795    /// for packets in the Application Data packet number space.
796    max_ack_delay: Duration,
797
798    /// The maximum number of ack-eliciting packets the endpoint receives before
799    /// sending an acknowledgment.
800    ack_eliciting_threshold: u64,
801
802    /// The congestion control algorithm used for a path.
803    pub congestion_control_algorithm: CongestionControlAlgorithm,
804
805    /// The minimal congestion window in packets.
806    /// The RECOMMENDED value is 2 * max_datagram_size.
807    /// See RFC 9002 Section 7.2
808    pub min_congestion_window: u64,
809
810    /// The initial congestion window in packets.
811    /// Endpoints SHOULD use an initial congestion window of ten times the
812    /// maximum datagram size (max_datagram_size), while limiting the window to
813    /// the larger of 14,720 bytes or twice the maximum datagram size.
814    /// See RFC 9002 Section 7.2
815    pub initial_congestion_window: u64,
816
817    /// The threshold for slow start in packets.
818    pub slow_start_thresh: u64,
819
820    /// The minimum duration for BBR ProbeRTT state
821    pub bbr_probe_rtt_duration: Duration,
822
823    /// Enable using a cwnd based on bdp during ProbeRTT state.
824    pub bbr_probe_rtt_based_on_bdp: bool,
825
826    /// The cwnd gain for BBR ProbeRTT state
827    pub bbr_probe_rtt_cwnd_gain: f64,
828
829    /// The length of the RTProp min filter window
830    pub bbr_rtprop_filter_len: Duration,
831
832    /// The cwnd gain for ProbeBW state
833    pub bbr_probe_bw_cwnd_gain: f64,
834
835    /// Delta in copa slow start state.
836    pub copa_slow_start_delta: f64,
837
838    /// Delta in coap steady state.
839    pub copa_steady_delta: f64,
840
841    /// Use rtt standing instead of latest rtt to calculate queueing delay
842    pub copa_use_standing_rtt: bool,
843
844    /// The initial rtt, used before real rtt is estimated.
845    pub initial_rtt: Duration,
846
847    /// Enable pacing to smooth the flow of packets sent onto the network.
848    pub enable_pacing: bool,
849
850    /// Clock granularity used by the pacer.
851    pub pacing_granularity: Duration,
852
853    /// Linear factor for calculating the probe timeout.
854    pub pto_linear_factor: u64,
855
856    /// Upper limit of probe timeout.
857    pub max_pto: Duration,
858}
859
860impl Default for RecoveryConfig {
861    fn default() -> RecoveryConfig {
862        RecoveryConfig {
863            enable_dplpmtud: true,
864            max_datagram_size: DEFAULT_SEND_UDP_PAYLOAD_SIZE, // The upper limit is determined by DPLPMTUD
865            max_ack_delay: time::Duration::from_millis(0),
866            ack_eliciting_threshold: 2,
867            congestion_control_algorithm: CongestionControlAlgorithm::Bbr,
868            min_congestion_window: 2_u64,
869            initial_congestion_window: 10_u64,
870            slow_start_thresh: u64::MAX,
871            bbr_probe_rtt_duration: Duration::from_millis(200),
872            bbr_probe_rtt_based_on_bdp: false,
873            bbr_probe_rtt_cwnd_gain: 0.75,
874            bbr_rtprop_filter_len: Duration::from_secs(10),
875            bbr_probe_bw_cwnd_gain: 2.0,
876            copa_slow_start_delta: congestion_control::COPA_DELTA,
877            copa_steady_delta: congestion_control::COPA_DELTA,
878            copa_use_standing_rtt: true,
879            initial_rtt: INITIAL_RTT,
880            enable_pacing: true,
881            pacing_granularity: time::Duration::from_millis(1),
882            pto_linear_factor: DEFAULT_PTO_LINEAR_FACTOR,
883            max_pto: MAX_PTO,
884        }
885    }
886}
887
888/// Configurations about multipath transport.
889#[doc(hidden)]
890#[derive(Debug, Clone)]
891pub struct MultipathConfig {
892    /// Multipath scheduling algorithm.
893    multipath_algorithm: MultipathAlgorithm,
894}
895
896impl Default for MultipathConfig {
897    fn default() -> MultipathConfig {
898        MultipathConfig {
899            multipath_algorithm: MultipathAlgorithm::MinRtt,
900        }
901    }
902}
903
904/// Events sent from a Connection to an Endpoint.
905enum Event {
906    /// The connection handshake is complete.
907    ConnectionEstablished,
908
909    /// The client connection has received a NEW_TOKEN frame.
910    NewToken(Vec<u8>),
911
912    /// The connection need to advertise new scids via NEW_CONNECTION_ID frame.
913    ScidToAdvertise(u8),
914
915    /// The connection has received a RETIRE_CONNECTION_ID frame.
916    ScidRetired(ConnectionId),
917
918    /// The connection has received a dcid via NEW_CONNECTION_ID frame.
919    DcidAdvertised(ResetToken),
920
921    /// The connection has send a RETIRE_CONNECTION_ID frame.
922    DcidRetired(ResetToken),
923
924    /// The client connection has received a stateless reset token from transport
925    /// parameters extension.
926    ResetTokenAdvertised(ResetToken),
927
928    /// The stream is created.
929    StreamCreated(u64),
930
931    /// The stream is closed.
932    StreamClosed(u64),
933}
934
935#[derive(Default)]
936struct EventQueue(Option<VecDeque<Event>>);
937
938impl EventQueue {
939    /// Enable the event queue.
940    fn enable(&mut self) {
941        self.0 = Some(VecDeque::new());
942    }
943
944    /// Add an endpoint-faceing event.
945    fn add(&mut self, e: Event) -> bool {
946        if let Some(events) = &mut self.0 {
947            events.push_back(e);
948            return true;
949        }
950        false
951    }
952
953    /// Return an endpoint-facing event.
954    fn poll(&mut self) -> Option<Event> {
955        if let Some(events) = &mut self.0 {
956            return events.pop_front();
957        }
958        None
959    }
960
961    /// Check whether the event queue is empty.
962    fn is_empty(&self) -> bool {
963        if let Some(events) = &self.0 {
964            return events.is_empty();
965        }
966        true
967    }
968}
969
970struct ConnectionQueues {
971    /// Connections with timer or other events to process.
972    tickable: FxHashSet<u64>,
973
974    /// Connections with packets to be send.
975    sendable: FxHashSet<u64>,
976}
977
978impl ConnectionQueues {
979    fn new() -> Self {
980        Self {
981            tickable: FxHashSet::default(),
982            sendable: FxHashSet::default(),
983        }
984    }
985
986    fn is_empty(&self) -> bool {
987        self.tickable.is_empty() && self.sendable.is_empty()
988    }
989
990    fn tickable_next(&self) -> Option<u64> {
991        self.tickable.iter().next().copied()
992    }
993
994    fn sendable_next(&self) -> Option<u64> {
995        self.sendable.iter().next().copied()
996    }
997}
998
999/// The TransportHandler lists the callbacks used by the endpoint to
1000/// communicate with the user application code.
1001pub trait TransportHandler {
1002    /// Called when a new connection has been created. This callback is called
1003    /// as soon as connection object is created inside the endpoint, but
1004    /// before the handshake is done. The connection has progressed enough to
1005    /// send early data if possible.
1006    fn on_conn_created(&mut self, conn: &mut Connection);
1007
1008    /// Called when the handshake is completed.
1009    fn on_conn_established(&mut self, conn: &mut Connection);
1010
1011    /// Called when the connection is closed. The connection is no longer
1012    /// accessible after this callback returns. It is a good time to clean up
1013    /// the connection context.
1014    fn on_conn_closed(&mut self, conn: &mut Connection);
1015
1016    /// Called when the stream is created.
1017    fn on_stream_created(&mut self, conn: &mut Connection, stream_id: u64);
1018
1019    /// Called when the stream is readable. This callback is called when either
1020    /// there are bytes to be read or an error is ready to be collected.
1021    fn on_stream_readable(&mut self, conn: &mut Connection, stream_id: u64);
1022
1023    /// Called when the stream is writable.
1024    fn on_stream_writable(&mut self, conn: &mut Connection, stream_id: u64);
1025
1026    /// Called when the stream is closed. The stream is no longer accessible
1027    /// after this callback returns. It is a good time to clean up the stream
1028    /// context.
1029    fn on_stream_closed(&mut self, conn: &mut Connection, stream_id: u64);
1030
1031    /// Called when client receives a token in NEW_TOKEN frame.
1032    fn on_new_token(&mut self, conn: &mut Connection, token: Vec<u8>);
1033}
1034
1035/// The PacketSendHandler lists the callbacks used by the endpoint to
1036/// send packet out.
1037pub trait PacketSendHandler {
1038    /// Called when the connection is sending packets out.
1039    ///
1040    /// On success, `on_packets_send()` returns the number of messages sent. If
1041    /// this is less than `pkts.len()`, the connection will retry with a further
1042    /// `on_packets_send()` call to send the remaining messages.
1043    fn on_packets_send(&self, pkts: &[(Vec<u8>, PacketInfo)]) -> Result<usize>;
1044}
1045
1046/// The stream's side to shutdown.
1047#[repr(C)]
1048#[derive(PartialEq, Eq)]
1049pub enum Shutdown {
1050    /// Stop receiving data on the stream.
1051    Read = 0,
1052
1053    /// Stop sending data on the stream.
1054    Write = 1,
1055}
1056
1057/// Important events about path
1058pub enum PathEvent {
1059    /// The path has been validated.
1060    Validated(usize),
1061
1062    /// The path has been abandoned.
1063    Abandoned(usize),
1064}
1065
1066/// Statistics about path
1067#[repr(C)]
1068#[derive(Default)]
1069pub struct PathStats {
1070    /// The number of QUIC packets received.
1071    pub recv_count: u64,
1072
1073    /// The number of received bytes.
1074    pub recv_bytes: u64,
1075
1076    /// The number of QUIC packets sent.
1077    pub sent_count: u64,
1078
1079    /// The number of sent bytes.
1080    pub sent_bytes: u64,
1081
1082    /// The number of QUIC packets lost.
1083    pub lost_count: u64,
1084
1085    /// The number of lost bytes.
1086    pub lost_bytes: u64,
1087
1088    /// Total number of packets acked.
1089    pub acked_count: u64,
1090
1091    /// Total number of bytes acked.
1092    pub acked_bytes: u64,
1093
1094    /// Initial congestion window in bytes.
1095    pub init_cwnd: u64,
1096
1097    /// Final congestion window in bytes.
1098    pub final_cwnd: u64,
1099
1100    /// Maximum congestion window in bytes.
1101    pub max_cwnd: u64,
1102
1103    /// Minimum congestion window in bytes.
1104    pub min_cwnd: u64,
1105
1106    /// Maximum inflight data in bytes.
1107    pub max_inflight: u64,
1108
1109    /// Total loss events.
1110    pub loss_event_count: u64,
1111
1112    /// Total congestion window limited events.
1113    pub cwnd_limited_count: u64,
1114
1115    /// Total duration of congestion windowlimited events in microseconds.
1116    pub cwnd_limited_duration: u64,
1117
1118    /* Note: the following fields are lazily updated from Recovery */
1119    /// Minimum roundtrip time in microseconds.
1120    pub min_rtt: u64,
1121
1122    /// Maximum roundtrip time in microseconds.
1123    pub max_rtt: u64,
1124
1125    /// Smoothed roundtrip time in microseconds.
1126    pub srtt: u64,
1127
1128    /// Roundtrip time variation in microseconds.
1129    pub rttvar: u64,
1130
1131    /// Whether the congestion controller is in slow start status.
1132    pub in_slow_start: bool,
1133
1134    /// Pacing rate estimated by congestion control algorithm.
1135    pub pacing_rate: u64,
1136}
1137
1138#[cfg(test)]
1139mod tests {
1140    use super::*;
1141
1142    #[ctor::ctor]
1143    fn init() {
1144        env_logger::builder()
1145            .filter_level(log::LevelFilter::Trace)
1146            .format_timestamp_millis()
1147            .is_test(true)
1148            .init();
1149    }
1150
1151    #[test]
1152    fn connection_id() {
1153        let mut cid_gen = RandomConnectionIdGenerator::new(8);
1154        let cid = cid_gen.generate();
1155        assert_eq!(cid.len(), cid_gen.cid_len());
1156
1157        let cid = ConnectionId {
1158            len: 4,
1159            data: [0xa8; 20],
1160        };
1161        assert_eq!(format!("{}", cid), "a8a8a8a8");
1162    }
1163
1164    #[test]
1165    fn initial_rtt() -> Result<()> {
1166        let mut config = Config::new()?;
1167
1168        config.set_initial_rtt(0);
1169        assert_eq!(config.recovery.initial_rtt, TIMER_GRANULARITY);
1170
1171        config.set_initial_rtt(100);
1172        assert_eq!(config.recovery.initial_rtt, Duration::from_millis(100));
1173
1174        Ok(())
1175    }
1176
1177    #[test]
1178    fn pto_linear_factor() -> Result<()> {
1179        let mut config = Config::new()?;
1180        assert_eq!(config.recovery.pto_linear_factor, DEFAULT_PTO_LINEAR_FACTOR);
1181
1182        config.set_pto_linear_factor(0);
1183        assert_eq!(config.recovery.pto_linear_factor, 0);
1184
1185        config.set_pto_linear_factor(100);
1186        assert_eq!(config.recovery.pto_linear_factor, 100);
1187
1188        Ok(())
1189    }
1190
1191    #[test]
1192    fn max_pto() -> Result<()> {
1193        let mut config = Config::new()?;
1194        assert_eq!(config.recovery.max_pto, MAX_PTO);
1195
1196        config.set_max_pto(0);
1197        assert_eq!(config.recovery.max_pto, TIMER_GRANULARITY);
1198
1199        config.set_max_pto(300000);
1200        assert_eq!(config.recovery.max_pto, Duration::from_millis(300000));
1201
1202        Ok(())
1203    }
1204
1205    #[test]
1206    fn initial_max_streams_bidi() -> Result<()> {
1207        let mut config = Config::new()?;
1208        config.set_initial_max_streams_bidi(u64::MAX);
1209        assert_eq!(
1210            config.local_transport_params.initial_max_streams_bidi,
1211            VINT_MAX
1212        );
1213
1214        Ok(())
1215    }
1216}
1217
1218pub use crate::congestion_control::CongestionControlAlgorithm;
1219pub use crate::connection::path::Path;
1220pub use crate::connection::Connection;
1221pub use crate::endpoint::Endpoint;
1222pub use crate::error::Error;
1223pub use crate::multipath_scheduler::MultipathAlgorithm;
1224pub use crate::packet::PacketHeader;
1225pub use crate::tls::TlsConfig;
1226pub use crate::tls::TlsConfigSelector;
1227
1228#[path = "connection/connection.rs"]
1229pub mod connection;
1230
1231#[path = "congestion_control/congestion_control.rs"]
1232mod congestion_control;
1233
1234#[path = "multipath_scheduler/multipath_scheduler.rs"]
1235mod multipath_scheduler;
1236
1237#[path = "tls/tls.rs"]
1238mod tls;
1239
1240#[cfg(feature = "h3")]
1241#[path = "h3/h3.rs"]
1242pub mod h3;
1243
1244#[cfg(feature = "qlog")]
1245#[path = "qlog/qlog.rs"]
1246mod qlog;
1247
1248#[cfg(feature = "ffi")]
1249mod ffi;
1250
1251// Note: Workaround for the module path issue in cbindgen.
1252// DON'T enable this feature when building with cargo.
1253#[cfg(feature = "cbindgen")]
1254#[path = "h3/connection.rs"]
1255mod h3_connection;
1256
1257mod codec;
1258pub mod endpoint;
1259pub mod error;
1260mod frame;
1261mod packet;
1262mod ranges;
1263#[doc(hidden)]
1264pub mod timer_queue;
1265mod token;
1266mod trans_param;
1267mod window;