quiche/lib.rs
1// Copyright (C) 2018-2019, Cloudflare, Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10//
11// * Redistributions in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the distribution.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
19// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27//! 🥧 Savoury implementation of the QUIC transport protocol and HTTP/3.
28//!
29//! [quiche] is an implementation of the QUIC transport protocol and HTTP/3 as
30//! specified by the [IETF]. It provides a low level API for processing QUIC
31//! packets and handling connection state. The application is responsible for
32//! providing I/O (e.g. sockets handling) as well as an event loop with support
33//! for timers.
34//!
35//! [quiche]: https://github.com/cloudflare/quiche/
36//! [ietf]: https://quicwg.org/
37//!
38//! ## Configuring connections
39//!
40//! The first step in establishing a QUIC connection using quiche is creating a
41//! [`Config`] object:
42//!
43//! ```
44//! let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
45//! config.set_application_protos(&[b"example-proto"]);
46//!
47//! // Additional configuration specific to application and use case...
48//! # Ok::<(), quiche::Error>(())
49//! ```
50//!
51//! The [`Config`] object controls important aspects of the QUIC connection such
52//! as QUIC version, ALPN IDs, flow control, congestion control, idle timeout
53//! and other properties or features.
54//!
55//! QUIC is a general-purpose transport protocol and there are several
56//! configuration properties where there is no reasonable default value. For
57//! example, the permitted number of concurrent streams of any particular type
58//! is dependent on the application running over QUIC, and other use-case
59//! specific concerns.
60//!
61//! quiche defaults several properties to zero, applications most likely need
62//! to set these to something else to satisfy their needs using the following:
63//!
64//! - [`set_initial_max_streams_bidi()`]
65//! - [`set_initial_max_streams_uni()`]
66//! - [`set_initial_max_data()`]
67//! - [`set_initial_max_stream_data_bidi_local()`]
68//! - [`set_initial_max_stream_data_bidi_remote()`]
69//! - [`set_initial_max_stream_data_uni()`]
70//!
71//! [`Config`] also holds TLS configuration. This can be changed by mutators on
72//! the an existing object, or by constructing a TLS context manually and
73//! creating a configuration using [`with_boring_ssl_ctx_builder()`].
74//!
75//! A configuration object can be shared among multiple connections.
76//!
77//! ### Connection setup
78//!
79//! On the client-side the [`connect()`] utility function can be used to create
80//! a new connection, while [`accept()`] is for servers:
81//!
82//! ```
83//! # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
84//! # let server_name = "quic.tech";
85//! # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
86//! # let peer = "127.0.0.1:1234".parse().unwrap();
87//! # let local = "127.0.0.1:4321".parse().unwrap();
88//! // Client connection.
89//! let conn =
90//! quiche::connect(Some(&server_name), &scid, local, peer, &mut config)?;
91//!
92//! // Server connection.
93//! # let peer = "127.0.0.1:1234".parse().unwrap();
94//! # let local = "127.0.0.1:4321".parse().unwrap();
95//! let conn = quiche::accept(&scid, None, local, peer, &mut config)?;
96//! # Ok::<(), quiche::Error>(())
97//! ```
98//!
99//! In both cases, the application is responsible for generating a new source
100//! connection ID that will be used to identify the new connection.
101//!
102//! The application also need to pass the address of the remote peer of the
103//! connection: in the case of a client that would be the address of the server
104//! it is trying to connect to, and for a server that is the address of the
105//! client that initiated the connection.
106//!
107//! ## Handling incoming packets
108//!
109//! Using the connection's [`recv()`] method the application can process
110//! incoming packets that belong to that connection from the network:
111//!
112//! ```no_run
113//! # let mut buf = [0; 512];
114//! # let socket = std::net::UdpSocket::bind("127.0.0.1:0").unwrap();
115//! # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
116//! # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
117//! # let peer = "127.0.0.1:1234".parse().unwrap();
118//! # let local = "127.0.0.1:4321".parse().unwrap();
119//! # let mut conn = quiche::accept(&scid, None, local, peer, &mut config)?;
120//! let to = socket.local_addr().unwrap();
121//!
122//! loop {
123//! let (read, from) = socket.recv_from(&mut buf).unwrap();
124//!
125//! let recv_info = quiche::RecvInfo { from, to };
126//!
127//! let read = match conn.recv(&mut buf[..read], recv_info) {
128//! Ok(v) => v,
129//!
130//! Err(quiche::Error::Done) => {
131//! // Done reading.
132//! break;
133//! },
134//!
135//! Err(e) => {
136//! // An error occurred, handle it.
137//! break;
138//! },
139//! };
140//! }
141//! # Ok::<(), quiche::Error>(())
142//! ```
143//!
144//! The application has to pass a [`RecvInfo`] structure in order to provide
145//! additional information about the received packet (such as the address it
146//! was received from).
147//!
148//! ## Generating outgoing packets
149//!
150//! Outgoing packet are generated using the connection's [`send()`] method
151//! instead:
152//!
153//! ```no_run
154//! # let mut out = [0; 512];
155//! # let socket = std::net::UdpSocket::bind("127.0.0.1:0").unwrap();
156//! # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
157//! # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
158//! # let peer = "127.0.0.1:1234".parse().unwrap();
159//! # let local = "127.0.0.1:4321".parse().unwrap();
160//! # let mut conn = quiche::accept(&scid, None, local, peer, &mut config)?;
161//! loop {
162//! let (write, send_info) = match conn.send(&mut out) {
163//! Ok(v) => v,
164//!
165//! Err(quiche::Error::Done) => {
166//! // Done writing.
167//! break;
168//! },
169//!
170//! Err(e) => {
171//! // An error occurred, handle it.
172//! break;
173//! },
174//! };
175//!
176//! socket.send_to(&out[..write], &send_info.to).unwrap();
177//! }
178//! # Ok::<(), quiche::Error>(())
179//! ```
180//!
181//! The application will be provided with a [`SendInfo`] structure providing
182//! additional information about the newly created packet (such as the address
183//! the packet should be sent to).
184//!
185//! When packets are sent, the application is responsible for maintaining a
186//! timer to react to time-based connection events. The timer expiration can be
187//! obtained using the connection's [`timeout()`] method.
188//!
189//! ```
190//! # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
191//! # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
192//! # let peer = "127.0.0.1:1234".parse().unwrap();
193//! # let local = "127.0.0.1:4321".parse().unwrap();
194//! # let mut conn = quiche::accept(&scid, None, local, peer, &mut config)?;
195//! let timeout = conn.timeout();
196//! # Ok::<(), quiche::Error>(())
197//! ```
198//!
199//! The application is responsible for providing a timer implementation, which
200//! can be specific to the operating system or networking framework used. When
201//! a timer expires, the connection's [`on_timeout()`] method should be called,
202//! after which additional packets might need to be sent on the network:
203//!
204//! ```no_run
205//! # let mut out = [0; 512];
206//! # let socket = std::net::UdpSocket::bind("127.0.0.1:0").unwrap();
207//! # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
208//! # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
209//! # let peer = "127.0.0.1:1234".parse().unwrap();
210//! # let local = "127.0.0.1:4321".parse().unwrap();
211//! # let mut conn = quiche::accept(&scid, None, local, peer, &mut config)?;
212//! // Timeout expired, handle it.
213//! conn.on_timeout();
214//!
215//! // Send more packets as needed after timeout.
216//! loop {
217//! let (write, send_info) = match conn.send(&mut out) {
218//! Ok(v) => v,
219//!
220//! Err(quiche::Error::Done) => {
221//! // Done writing.
222//! break;
223//! },
224//!
225//! Err(e) => {
226//! // An error occurred, handle it.
227//! break;
228//! },
229//! };
230//!
231//! socket.send_to(&out[..write], &send_info.to).unwrap();
232//! }
233//! # Ok::<(), quiche::Error>(())
234//! ```
235//!
236//! ### Pacing
237//!
238//! It is recommended that applications [pace] sending of outgoing packets to
239//! avoid creating packet bursts that could cause short-term congestion and
240//! losses in the network.
241//!
242//! quiche exposes pacing hints for outgoing packets through the [`at`] field
243//! of the [`SendInfo`] structure that is returned by the [`send()`] method.
244//! This field represents the time when a specific packet should be sent into
245//! the network.
246//!
247//! Applications can use these hints by artificially delaying the sending of
248//! packets through platform-specific mechanisms (such as the [`SO_TXTIME`]
249//! socket option on Linux), or custom methods (for example by using user-space
250//! timers).
251//!
252//! [pace]: https://datatracker.ietf.org/doc/html/rfc9002#section-7.7
253//! [`SO_TXTIME`]: https://man7.org/linux/man-pages/man8/tc-etf.8.html
254//!
255//! ## Sending and receiving stream data
256//!
257//! After some back and forth, the connection will complete its handshake and
258//! will be ready for sending or receiving application data.
259//!
260//! Data can be sent on a stream by using the [`stream_send()`] method:
261//!
262//! ```no_run
263//! # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
264//! # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
265//! # let peer = "127.0.0.1:1234".parse().unwrap();
266//! # let local = "127.0.0.1:4321".parse().unwrap();
267//! # let mut conn = quiche::accept(&scid, None, local, peer, &mut config)?;
268//! if conn.is_established() {
269//! // Handshake completed, send some data on stream 0.
270//! conn.stream_send(0, b"hello", true)?;
271//! }
272//! # Ok::<(), quiche::Error>(())
273//! ```
274//!
275//! The application can check whether there are any readable streams by using
276//! the connection's [`readable()`] method, which returns an iterator over all
277//! the streams that have outstanding data to read.
278//!
279//! The [`stream_recv()`] method can then be used to retrieve the application
280//! data from the readable stream:
281//!
282//! ```no_run
283//! # let mut buf = [0; 512];
284//! # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
285//! # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
286//! # let peer = "127.0.0.1:1234".parse().unwrap();
287//! # let local = "127.0.0.1:4321".parse().unwrap();
288//! # let mut conn = quiche::accept(&scid, None, local, peer, &mut config)?;
289//! if conn.is_established() {
290//! // Iterate over readable streams.
291//! for stream_id in conn.readable() {
292//! // Stream is readable, read until there's no more data.
293//! while let Ok((read, fin)) = conn.stream_recv(stream_id, &mut buf) {
294//! println!("Got {} bytes on stream {}", read, stream_id);
295//! }
296//! }
297//! }
298//! # Ok::<(), quiche::Error>(())
299//! ```
300//!
301//! ## HTTP/3
302//!
303//! The quiche [HTTP/3 module] provides a high level API for sending and
304//! receiving HTTP requests and responses on top of the QUIC transport protocol.
305//!
306//! [`Config`]: https://docs.quic.tech/quiche/struct.Config.html
307//! [`set_initial_max_streams_bidi()`]: https://docs.rs/quiche/latest/quiche/struct.Config.html#method.set_initial_max_streams_bidi
308//! [`set_initial_max_streams_uni()`]: https://docs.rs/quiche/latest/quiche/struct.Config.html#method.set_initial_max_streams_uni
309//! [`set_initial_max_data()`]: https://docs.rs/quiche/latest/quiche/struct.Config.html#method.set_initial_max_data
310//! [`set_initial_max_stream_data_bidi_local()`]: https://docs.rs/quiche/latest/quiche/struct.Config.html#method.set_initial_max_stream_data_bidi_local
311//! [`set_initial_max_stream_data_bidi_remote()`]: https://docs.rs/quiche/latest/quiche/struct.Config.html#method.set_initial_max_stream_data_bidi_remote
312//! [`set_initial_max_stream_data_uni()`]: https://docs.rs/quiche/latest/quiche/struct.Config.html#method.set_initial_max_stream_data_uni
313//! [`with_boring_ssl_ctx_builder()`]: https://docs.quic.tech/quiche/struct.Config.html#method.with_boring_ssl_ctx_builder
314//! [`connect()`]: fn.connect.html
315//! [`accept()`]: fn.accept.html
316//! [`recv()`]: struct.Connection.html#method.recv
317//! [`RecvInfo`]: struct.RecvInfo.html
318//! [`send()`]: struct.Connection.html#method.send
319//! [`SendInfo`]: struct.SendInfo.html
320//! [`at`]: struct.SendInfo.html#structfield.at
321//! [`timeout()`]: struct.Connection.html#method.timeout
322//! [`on_timeout()`]: struct.Connection.html#method.on_timeout
323//! [`stream_send()`]: struct.Connection.html#method.stream_send
324//! [`readable()`]: struct.Connection.html#method.readable
325//! [`stream_recv()`]: struct.Connection.html#method.stream_recv
326//! [HTTP/3 module]: h3/index.html
327//!
328//! ## Congestion Control
329//!
330//! The quiche library provides a high-level API for configuring which
331//! congestion control algorithm to use throughout the QUIC connection.
332//!
333//! When a QUIC connection is created, the application can optionally choose
334//! which CC algorithm to use. See [`CongestionControlAlgorithm`] for currently
335//! available congestion control algorithms.
336//!
337//! For example:
338//!
339//! ```
340//! let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION).unwrap();
341//! config.set_cc_algorithm(quiche::CongestionControlAlgorithm::Reno);
342//! ```
343//!
344//! Alternatively, you can configure the congestion control algorithm to use
345//! by its name.
346//!
347//! ```
348//! let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION).unwrap();
349//! config.set_cc_algorithm_name("reno").unwrap();
350//! ```
351//!
352//! Note that the CC algorithm should be configured before calling [`connect()`]
353//! or [`accept()`]. Otherwise the connection will use a default CC algorithm.
354//!
355//! [`CongestionControlAlgorithm`]: enum.CongestionControlAlgorithm.html
356//!
357//! ## Feature flags
358//!
359//! quiche defines a number of [feature flags] to reduce the amount of compiled
360//! code and dependencies:
361//!
362//! * `boringssl-vendored` (default): Build the vendored BoringSSL library.
363//!
364//! * `boringssl-boring-crate`: Use the BoringSSL library provided by the
365//! [boring] crate. It takes precedence over `boringssl-vendored` if both
366//! features are enabled.
367//!
368//! * `pkg-config-meta`: Generate pkg-config metadata file for libquiche.
369//!
370//! * `ffi`: Build and expose the FFI API.
371//!
372//! * `qlog`: Enable support for the [qlog] logging format.
373//!
374//! [feature flags]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section
375//! [boring]: https://crates.io/crates/boring
376//! [qlog]: https://datatracker.ietf.org/doc/html/draft-ietf-quic-qlog-main-schema
377
378#![allow(clippy::upper_case_acronyms)]
379#![warn(missing_docs)]
380#![warn(unused_qualifications)]
381#![cfg_attr(docsrs, feature(doc_cfg))]
382
383#[macro_use]
384extern crate log;
385
386use std::cmp;
387
388use std::collections::HashSet;
389use std::collections::VecDeque;
390
391use std::convert::TryInto;
392
393use std::net::SocketAddr;
394
395use std::str::FromStr;
396
397use std::sync::Arc;
398
399use std::time::Duration;
400use std::time::Instant;
401
402#[cfg(feature = "qlog")]
403use qlog::events::connectivity::ConnectivityEventType;
404#[cfg(feature = "qlog")]
405use qlog::events::connectivity::TransportOwner;
406#[cfg(feature = "qlog")]
407use qlog::events::quic::RecoveryEventType;
408#[cfg(feature = "qlog")]
409use qlog::events::quic::TransportEventType;
410#[cfg(feature = "qlog")]
411use qlog::events::DataRecipient;
412#[cfg(feature = "qlog")]
413use qlog::events::Event;
414#[cfg(feature = "qlog")]
415use qlog::events::EventData;
416#[cfg(feature = "qlog")]
417use qlog::events::EventImportance;
418#[cfg(feature = "qlog")]
419use qlog::events::EventType;
420#[cfg(feature = "qlog")]
421use qlog::events::RawInfo;
422
423use smallvec::SmallVec;
424
425use crate::range_buf::DefaultBufFactory;
426
427use crate::recovery::OnAckReceivedOutcome;
428use crate::recovery::OnLossDetectionTimeoutOutcome;
429use crate::recovery::RecoveryOps;
430use crate::recovery::ReleaseDecision;
431
432use crate::stream::StreamPriorityKey;
433
434/// The current QUIC wire version.
435pub const PROTOCOL_VERSION: u32 = PROTOCOL_VERSION_V1;
436
437/// Supported QUIC versions.
438const PROTOCOL_VERSION_V1: u32 = 0x0000_0001;
439
440/// The maximum length of a connection ID.
441pub const MAX_CONN_ID_LEN: usize = packet::MAX_CID_LEN as usize;
442
443/// The minimum length of Initial packets sent by a client.
444pub const MIN_CLIENT_INITIAL_LEN: usize = 1200;
445
446/// The default initial RTT.
447const DEFAULT_INITIAL_RTT: Duration = Duration::from_millis(333);
448
449const PAYLOAD_MIN_LEN: usize = 4;
450
451// PATH_CHALLENGE (9 bytes) + AEAD tag (16 bytes).
452const MIN_PROBING_SIZE: usize = 25;
453
454const MAX_AMPLIFICATION_FACTOR: usize = 3;
455
456// The maximum number of tracked packet number ranges that need to be acked.
457//
458// This represents more or less how many ack blocks can fit in a typical packet.
459const MAX_ACK_RANGES: usize = 68;
460
461// The highest possible stream ID allowed.
462const MAX_STREAM_ID: u64 = 1 << 60;
463
464// The default max_datagram_size used in congestion control.
465const MAX_SEND_UDP_PAYLOAD_SIZE: usize = 1200;
466
467// The default length of DATAGRAM queues.
468const DEFAULT_MAX_DGRAM_QUEUE_LEN: usize = 0;
469
470// The default length of PATH_CHALLENGE receive queue.
471const DEFAULT_MAX_PATH_CHALLENGE_RX_QUEUE_LEN: usize = 3;
472
473// The DATAGRAM standard recommends either none or 65536 as maximum DATAGRAM
474// frames size. We enforce the recommendation for forward compatibility.
475const MAX_DGRAM_FRAME_SIZE: u64 = 65536;
476
477// The length of the payload length field.
478const PAYLOAD_LENGTH_LEN: usize = 2;
479
480// The number of undecryptable that can be buffered.
481const MAX_UNDECRYPTABLE_PACKETS: usize = 10;
482
483const RESERVED_VERSION_MASK: u32 = 0xfafafafa;
484
485// The default size of the receiver connection flow control window.
486const DEFAULT_CONNECTION_WINDOW: u64 = 48 * 1024;
487
488// The maximum size of the receiver connection flow control window.
489const MAX_CONNECTION_WINDOW: u64 = 24 * 1024 * 1024;
490
491// How much larger the connection flow control window need to be larger than
492// the stream flow control window.
493const CONNECTION_WINDOW_FACTOR: f64 = 1.5;
494
495// How many probing packet timeouts do we tolerate before considering the path
496// validation as failed.
497const MAX_PROBING_TIMEOUTS: usize = 3;
498
499// The default initial congestion window size in terms of packet count.
500const DEFAULT_INITIAL_CONGESTION_WINDOW_PACKETS: usize = 10;
501
502// The maximum data offset that can be stored in a crypto stream.
503const MAX_CRYPTO_STREAM_OFFSET: u64 = 1 << 16;
504
505// The send capacity factor.
506const TX_CAP_FACTOR: f64 = 1.0;
507
508/// Ancillary information about incoming packets.
509#[derive(Clone, Copy, Debug, PartialEq, Eq)]
510pub struct RecvInfo {
511 /// The remote address the packet was received from.
512 pub from: SocketAddr,
513
514 /// The local address the packet was received on.
515 pub to: SocketAddr,
516}
517
518/// Ancillary information about outgoing packets.
519#[derive(Clone, Copy, Debug, PartialEq, Eq)]
520pub struct SendInfo {
521 /// The local address the packet should be sent from.
522 pub from: SocketAddr,
523
524 /// The remote address the packet should be sent to.
525 pub to: SocketAddr,
526
527 /// The time to send the packet out.
528 ///
529 /// See [Pacing] for more details.
530 ///
531 /// [Pacing]: index.html#pacing
532 pub at: Instant,
533}
534
535/// The side of the stream to be shut down.
536///
537/// This should be used when calling [`stream_shutdown()`].
538///
539/// [`stream_shutdown()`]: struct.Connection.html#method.stream_shutdown
540#[repr(C)]
541#[derive(PartialEq, Eq)]
542pub enum Shutdown {
543 /// Stop receiving stream data.
544 Read = 0,
545
546 /// Stop sending stream data.
547 Write = 1,
548}
549
550/// Qlog logging level.
551#[repr(C)]
552#[cfg(feature = "qlog")]
553#[cfg_attr(docsrs, doc(cfg(feature = "qlog")))]
554pub enum QlogLevel {
555 /// Logs any events of Core importance.
556 Core = 0,
557
558 /// Logs any events of Core and Base importance.
559 Base = 1,
560
561 /// Logs any events of Core, Base and Extra importance
562 Extra = 2,
563}
564
565/// Stores configuration shared between multiple connections.
566pub struct Config {
567 local_transport_params: TransportParams,
568
569 version: u32,
570
571 tls_ctx: tls::Context,
572
573 application_protos: Vec<Vec<u8>>,
574
575 grease: bool,
576
577 cc_algorithm: CongestionControlAlgorithm,
578 custom_bbr_params: Option<BbrParams>,
579 initial_congestion_window_packets: usize,
580 enable_relaxed_loss_threshold: bool,
581
582 pmtud: bool,
583
584 hystart: bool,
585
586 pacing: bool,
587 /// Send rate limit in Mbps
588 max_pacing_rate: Option<u64>,
589
590 tx_cap_factor: f64,
591
592 dgram_recv_max_queue_len: usize,
593 dgram_send_max_queue_len: usize,
594
595 path_challenge_recv_max_queue_len: usize,
596
597 max_send_udp_payload_size: usize,
598
599 max_connection_window: u64,
600 max_stream_window: u64,
601
602 max_amplification_factor: usize,
603
604 disable_dcid_reuse: bool,
605
606 track_unknown_transport_params: Option<usize>,
607
608 initial_rtt: Duration,
609}
610
611// See https://quicwg.org/base-drafts/rfc9000.html#section-15
612fn is_reserved_version(version: u32) -> bool {
613 version & RESERVED_VERSION_MASK == version
614}
615
616impl Config {
617 /// Creates a config object with the given version.
618 ///
619 /// ## Examples:
620 ///
621 /// ```
622 /// let config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
623 /// # Ok::<(), quiche::Error>(())
624 /// ```
625 pub fn new(version: u32) -> Result<Config> {
626 Self::with_tls_ctx(version, tls::Context::new()?)
627 }
628
629 /// Creates a config object with the given version and
630 /// [`SslContextBuilder`].
631 ///
632 /// This is useful for applications that wish to manually configure
633 /// [`SslContextBuilder`].
634 ///
635 /// [`SslContextBuilder`]: https://docs.rs/boring/latest/boring/ssl/struct.SslContextBuilder.html
636 #[cfg(feature = "boringssl-boring-crate")]
637 #[cfg_attr(docsrs, doc(cfg(feature = "boringssl-boring-crate")))]
638 pub fn with_boring_ssl_ctx_builder(
639 version: u32, tls_ctx_builder: boring::ssl::SslContextBuilder,
640 ) -> Result<Config> {
641 Self::with_tls_ctx(version, tls::Context::from_boring(tls_ctx_builder))
642 }
643
644 fn with_tls_ctx(version: u32, tls_ctx: tls::Context) -> Result<Config> {
645 if !is_reserved_version(version) && !version_is_supported(version) {
646 return Err(Error::UnknownVersion);
647 }
648
649 Ok(Config {
650 local_transport_params: TransportParams::default(),
651 version,
652 tls_ctx,
653 application_protos: Vec::new(),
654 grease: true,
655 cc_algorithm: CongestionControlAlgorithm::CUBIC,
656 custom_bbr_params: None,
657 initial_congestion_window_packets:
658 DEFAULT_INITIAL_CONGESTION_WINDOW_PACKETS,
659 enable_relaxed_loss_threshold: false,
660 pmtud: false,
661 hystart: true,
662 pacing: true,
663 max_pacing_rate: None,
664
665 tx_cap_factor: TX_CAP_FACTOR,
666
667 dgram_recv_max_queue_len: DEFAULT_MAX_DGRAM_QUEUE_LEN,
668 dgram_send_max_queue_len: DEFAULT_MAX_DGRAM_QUEUE_LEN,
669
670 path_challenge_recv_max_queue_len:
671 DEFAULT_MAX_PATH_CHALLENGE_RX_QUEUE_LEN,
672
673 max_send_udp_payload_size: MAX_SEND_UDP_PAYLOAD_SIZE,
674
675 max_connection_window: MAX_CONNECTION_WINDOW,
676 max_stream_window: stream::MAX_STREAM_WINDOW,
677
678 max_amplification_factor: MAX_AMPLIFICATION_FACTOR,
679
680 disable_dcid_reuse: false,
681
682 track_unknown_transport_params: None,
683 initial_rtt: DEFAULT_INITIAL_RTT,
684 })
685 }
686
687 /// Configures the given certificate chain.
688 ///
689 /// The content of `file` is parsed as a PEM-encoded leaf certificate,
690 /// followed by optional intermediate certificates.
691 ///
692 /// ## Examples:
693 ///
694 /// ```no_run
695 /// # let mut config = quiche::Config::new(0xbabababa)?;
696 /// config.load_cert_chain_from_pem_file("/path/to/cert.pem")?;
697 /// # Ok::<(), quiche::Error>(())
698 /// ```
699 pub fn load_cert_chain_from_pem_file(&mut self, file: &str) -> Result<()> {
700 self.tls_ctx.use_certificate_chain_file(file)
701 }
702
703 /// Configures the given private key.
704 ///
705 /// The content of `file` is parsed as a PEM-encoded private key.
706 ///
707 /// ## Examples:
708 ///
709 /// ```no_run
710 /// # let mut config = quiche::Config::new(0xbabababa)?;
711 /// config.load_priv_key_from_pem_file("/path/to/key.pem")?;
712 /// # Ok::<(), quiche::Error>(())
713 /// ```
714 pub fn load_priv_key_from_pem_file(&mut self, file: &str) -> Result<()> {
715 self.tls_ctx.use_privkey_file(file)
716 }
717
718 /// Specifies a file where trusted CA certificates are stored for the
719 /// purposes of certificate verification.
720 ///
721 /// The content of `file` is parsed as a PEM-encoded certificate chain.
722 ///
723 /// ## Examples:
724 ///
725 /// ```no_run
726 /// # let mut config = quiche::Config::new(0xbabababa)?;
727 /// config.load_verify_locations_from_file("/path/to/cert.pem")?;
728 /// # Ok::<(), quiche::Error>(())
729 /// ```
730 pub fn load_verify_locations_from_file(&mut self, file: &str) -> Result<()> {
731 self.tls_ctx.load_verify_locations_from_file(file)
732 }
733
734 /// Specifies a directory where trusted CA certificates are stored for the
735 /// purposes of certificate verification.
736 ///
737 /// The content of `dir` a set of PEM-encoded certificate chains.
738 ///
739 /// ## Examples:
740 ///
741 /// ```no_run
742 /// # let mut config = quiche::Config::new(0xbabababa)?;
743 /// config.load_verify_locations_from_directory("/path/to/certs")?;
744 /// # Ok::<(), quiche::Error>(())
745 /// ```
746 pub fn load_verify_locations_from_directory(
747 &mut self, dir: &str,
748 ) -> Result<()> {
749 self.tls_ctx.load_verify_locations_from_directory(dir)
750 }
751
752 /// Configures whether to verify the peer's certificate.
753 ///
754 /// This should usually be `true` for client-side connections and `false`
755 /// for server-side ones.
756 ///
757 /// Note that by default, no verification is performed.
758 ///
759 /// Also note that on the server-side, enabling verification of the peer
760 /// will trigger a certificate request and make authentication errors
761 /// fatal, but will still allow anonymous clients (i.e. clients that
762 /// don't present a certificate at all). Servers can check whether a
763 /// client presented a certificate by calling [`peer_cert()`] if they
764 /// need to.
765 ///
766 /// [`peer_cert()`]: struct.Connection.html#method.peer_cert
767 pub fn verify_peer(&mut self, verify: bool) {
768 self.tls_ctx.set_verify(verify);
769 }
770
771 /// Configures whether to do path MTU discovery.
772 ///
773 /// The default value is `false`.
774 pub fn discover_pmtu(&mut self, discover: bool) {
775 self.pmtud = discover;
776 }
777
778 /// Configures whether to send GREASE values.
779 ///
780 /// The default value is `true`.
781 pub fn grease(&mut self, grease: bool) {
782 self.grease = grease;
783 }
784
785 /// Enables logging of secrets.
786 ///
787 /// When logging is enabled, the [`set_keylog()`] method must be called on
788 /// the connection for its cryptographic secrets to be logged in the
789 /// [keylog] format to the specified writer.
790 ///
791 /// [`set_keylog()`]: struct.Connection.html#method.set_keylog
792 /// [keylog]: https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format
793 pub fn log_keys(&mut self) {
794 self.tls_ctx.enable_keylog();
795 }
796
797 /// Configures the session ticket key material.
798 ///
799 /// On the server this key will be used to encrypt and decrypt session
800 /// tickets, used to perform session resumption without server-side state.
801 ///
802 /// By default a key is generated internally, and rotated regularly, so
803 /// applications don't need to call this unless they need to use a
804 /// specific key (e.g. in order to support resumption across multiple
805 /// servers), in which case the application is also responsible for
806 /// rotating the key to provide forward secrecy.
807 pub fn set_ticket_key(&mut self, key: &[u8]) -> Result<()> {
808 self.tls_ctx.set_ticket_key(key)
809 }
810
811 /// Enables sending or receiving early data.
812 pub fn enable_early_data(&mut self) {
813 self.tls_ctx.set_early_data_enabled(true);
814 }
815
816 /// Configures the list of supported application protocols.
817 ///
818 /// On the client this configures the list of protocols to send to the
819 /// server as part of the ALPN extension.
820 ///
821 /// On the server this configures the list of supported protocols to match
822 /// against the client-supplied list.
823 ///
824 /// Applications must set a value, but no default is provided.
825 ///
826 /// ## Examples:
827 ///
828 /// ```
829 /// # let mut config = quiche::Config::new(0xbabababa)?;
830 /// config.set_application_protos(&[b"http/1.1", b"http/0.9"]);
831 /// # Ok::<(), quiche::Error>(())
832 /// ```
833 pub fn set_application_protos(
834 &mut self, protos_list: &[&[u8]],
835 ) -> Result<()> {
836 self.application_protos =
837 protos_list.iter().map(|s| s.to_vec()).collect();
838
839 self.tls_ctx.set_alpn(protos_list)
840 }
841
842 /// Configures the list of supported application protocols using wire
843 /// format.
844 ///
845 /// The list of protocols `protos` must be a series of non-empty, 8-bit
846 /// length-prefixed strings.
847 ///
848 /// See [`set_application_protos`](Self::set_application_protos) for more
849 /// background about application protocols.
850 ///
851 /// ## Examples:
852 ///
853 /// ```
854 /// # let mut config = quiche::Config::new(0xbabababa)?;
855 /// config.set_application_protos_wire_format(b"\x08http/1.1\x08http/0.9")?;
856 /// # Ok::<(), quiche::Error>(())
857 /// ```
858 pub fn set_application_protos_wire_format(
859 &mut self, protos: &[u8],
860 ) -> Result<()> {
861 let mut b = octets::Octets::with_slice(protos);
862
863 let mut protos_list = Vec::new();
864
865 while let Ok(proto) = b.get_bytes_with_u8_length() {
866 protos_list.push(proto.buf());
867 }
868
869 self.set_application_protos(&protos_list)
870 }
871
872 /// Sets the anti-amplification limit factor.
873 ///
874 /// The default value is `3`.
875 pub fn set_max_amplification_factor(&mut self, v: usize) {
876 self.max_amplification_factor = v;
877 }
878
879 /// Sets the send capacity factor.
880 ///
881 /// The default value is `1`.
882 pub fn set_send_capacity_factor(&mut self, v: f64) {
883 self.tx_cap_factor = v;
884 }
885
886 /// Sets the connection's initial RTT.
887 ///
888 /// The default value is `333`.
889 pub fn set_initial_rtt(&mut self, v: Duration) {
890 self.initial_rtt = v;
891 }
892
893 /// Sets the `max_idle_timeout` transport parameter, in milliseconds.
894 ///
895 /// The default value is infinite, that is, no timeout is used.
896 pub fn set_max_idle_timeout(&mut self, v: u64) {
897 self.local_transport_params.max_idle_timeout =
898 cmp::min(v, octets::MAX_VAR_INT);
899 }
900
901 /// Sets the `max_udp_payload_size transport` parameter.
902 ///
903 /// The default value is `65527`.
904 pub fn set_max_recv_udp_payload_size(&mut self, v: usize) {
905 self.local_transport_params.max_udp_payload_size =
906 cmp::min(v as u64, octets::MAX_VAR_INT);
907 }
908
909 /// Sets the maximum outgoing UDP payload size.
910 ///
911 /// The default and minimum value is `1200`.
912 pub fn set_max_send_udp_payload_size(&mut self, v: usize) {
913 self.max_send_udp_payload_size = cmp::max(v, MAX_SEND_UDP_PAYLOAD_SIZE);
914 }
915
916 /// Sets the `initial_max_data` transport parameter.
917 ///
918 /// When set to a non-zero value quiche will only allow at most `v` bytes of
919 /// incoming stream data to be buffered for the whole connection (that is,
920 /// data that is not yet read by the application) and will allow more data
921 /// to be received as the buffer is consumed by the application.
922 ///
923 /// When set to zero, either explicitly or via the default, quiche will not
924 /// give any flow control to the peer, preventing it from sending any stream
925 /// data.
926 ///
927 /// The default value is `0`.
928 pub fn set_initial_max_data(&mut self, v: u64) {
929 self.local_transport_params.initial_max_data =
930 cmp::min(v, octets::MAX_VAR_INT);
931 }
932
933 /// Sets the `initial_max_stream_data_bidi_local` transport parameter.
934 ///
935 /// When set to a non-zero value quiche will only allow at most `v` bytes
936 /// of incoming stream data to be buffered for each locally-initiated
937 /// bidirectional stream (that is, data that is not yet read by the
938 /// application) and will allow more data to be received as the buffer is
939 /// consumed by the application.
940 ///
941 /// When set to zero, either explicitly or via the default, quiche will not
942 /// give any flow control to the peer, preventing it from sending any stream
943 /// data.
944 ///
945 /// The default value is `0`.
946 pub fn set_initial_max_stream_data_bidi_local(&mut self, v: u64) {
947 self.local_transport_params
948 .initial_max_stream_data_bidi_local =
949 cmp::min(v, octets::MAX_VAR_INT);
950 }
951
952 /// Sets the `initial_max_stream_data_bidi_remote` transport parameter.
953 ///
954 /// When set to a non-zero value quiche will only allow at most `v` bytes
955 /// of incoming stream data to be buffered for each remotely-initiated
956 /// bidirectional stream (that is, data that is not yet read by the
957 /// application) and will allow more data to be received as the buffer is
958 /// consumed by the application.
959 ///
960 /// When set to zero, either explicitly or via the default, quiche will not
961 /// give any flow control to the peer, preventing it from sending any stream
962 /// data.
963 ///
964 /// The default value is `0`.
965 pub fn set_initial_max_stream_data_bidi_remote(&mut self, v: u64) {
966 self.local_transport_params
967 .initial_max_stream_data_bidi_remote =
968 cmp::min(v, octets::MAX_VAR_INT);
969 }
970
971 /// Sets the `initial_max_stream_data_uni` transport parameter.
972 ///
973 /// When set to a non-zero value quiche will only allow at most `v` bytes
974 /// of incoming stream data to be buffered for each unidirectional stream
975 /// (that is, data that is not yet read by the application) and will allow
976 /// more data to be received as the buffer is consumed by the application.
977 ///
978 /// When set to zero, either explicitly or via the default, quiche will not
979 /// give any flow control to the peer, preventing it from sending any stream
980 /// data.
981 ///
982 /// The default value is `0`.
983 pub fn set_initial_max_stream_data_uni(&mut self, v: u64) {
984 self.local_transport_params.initial_max_stream_data_uni =
985 cmp::min(v, octets::MAX_VAR_INT);
986 }
987
988 /// Sets the `initial_max_streams_bidi` transport parameter.
989 ///
990 /// When set to a non-zero value quiche will only allow `v` number of
991 /// concurrent remotely-initiated bidirectional streams to be open at any
992 /// given time and will increase the limit automatically as streams are
993 /// completed.
994 ///
995 /// When set to zero, either explicitly or via the default, quiche will not
996 /// not allow the peer to open any bidirectional streams.
997 ///
998 /// A bidirectional stream is considered completed when all incoming data
999 /// has been read by the application (up to the `fin` offset) or the
1000 /// stream's read direction has been shutdown, and all outgoing data has
1001 /// been acked by the peer (up to the `fin` offset) or the stream's write
1002 /// direction has been shutdown.
1003 ///
1004 /// The default value is `0`.
1005 pub fn set_initial_max_streams_bidi(&mut self, v: u64) {
1006 self.local_transport_params.initial_max_streams_bidi =
1007 cmp::min(v, octets::MAX_VAR_INT);
1008 }
1009
1010 /// Sets the `initial_max_streams_uni` transport parameter.
1011 ///
1012 /// When set to a non-zero value quiche will only allow `v` number of
1013 /// concurrent remotely-initiated unidirectional streams to be open at any
1014 /// given time and will increase the limit automatically as streams are
1015 /// completed.
1016 ///
1017 /// When set to zero, either explicitly or via the default, quiche will not
1018 /// not allow the peer to open any unidirectional streams.
1019 ///
1020 /// A unidirectional stream is considered completed when all incoming data
1021 /// has been read by the application (up to the `fin` offset) or the
1022 /// stream's read direction has been shutdown.
1023 ///
1024 /// The default value is `0`.
1025 pub fn set_initial_max_streams_uni(&mut self, v: u64) {
1026 self.local_transport_params.initial_max_streams_uni =
1027 cmp::min(v, octets::MAX_VAR_INT);
1028 }
1029
1030 /// Sets the `ack_delay_exponent` transport parameter.
1031 ///
1032 /// The default value is `3`.
1033 pub fn set_ack_delay_exponent(&mut self, v: u64) {
1034 self.local_transport_params.ack_delay_exponent =
1035 cmp::min(v, octets::MAX_VAR_INT);
1036 }
1037
1038 /// Sets the `max_ack_delay` transport parameter.
1039 ///
1040 /// The default value is `25`.
1041 pub fn set_max_ack_delay(&mut self, v: u64) {
1042 self.local_transport_params.max_ack_delay =
1043 cmp::min(v, octets::MAX_VAR_INT);
1044 }
1045
1046 /// Sets the `active_connection_id_limit` transport parameter.
1047 ///
1048 /// The default value is `2`. Lower values will be ignored.
1049 pub fn set_active_connection_id_limit(&mut self, v: u64) {
1050 if v >= 2 {
1051 self.local_transport_params.active_conn_id_limit =
1052 cmp::min(v, octets::MAX_VAR_INT);
1053 }
1054 }
1055
1056 /// Sets the `disable_active_migration` transport parameter.
1057 ///
1058 /// The default value is `false`.
1059 pub fn set_disable_active_migration(&mut self, v: bool) {
1060 self.local_transport_params.disable_active_migration = v;
1061 }
1062
1063 /// Sets the congestion control algorithm used.
1064 ///
1065 /// The default value is `CongestionControlAlgorithm::CUBIC`.
1066 pub fn set_cc_algorithm(&mut self, algo: CongestionControlAlgorithm) {
1067 self.cc_algorithm = algo;
1068 }
1069
1070 /// Sets custom BBR settings.
1071 ///
1072 /// This API is experimental and will be removed in the future.
1073 ///
1074 /// Currently this only applies if cc_algorithm is
1075 /// `CongestionControlAlgorithm::Bbr2Gcongestion` is set.
1076 ///
1077 /// The default value is `None`.
1078 #[cfg(feature = "internal")]
1079 #[doc(hidden)]
1080 pub fn set_custom_bbr_params(&mut self, custom_bbr_settings: BbrParams) {
1081 self.custom_bbr_params = Some(custom_bbr_settings);
1082 }
1083
1084 /// Sets the congestion control algorithm used by string.
1085 ///
1086 /// The default value is `cubic`. On error `Error::CongestionControl`
1087 /// will be returned.
1088 ///
1089 /// ## Examples:
1090 ///
1091 /// ```
1092 /// # let mut config = quiche::Config::new(0xbabababa)?;
1093 /// config.set_cc_algorithm_name("reno");
1094 /// # Ok::<(), quiche::Error>(())
1095 /// ```
1096 pub fn set_cc_algorithm_name(&mut self, name: &str) -> Result<()> {
1097 self.cc_algorithm = CongestionControlAlgorithm::from_str(name)?;
1098
1099 Ok(())
1100 }
1101
1102 /// Sets initial congestion window size in terms of packet count.
1103 ///
1104 /// The default value is 10.
1105 pub fn set_initial_congestion_window_packets(&mut self, packets: usize) {
1106 self.initial_congestion_window_packets = packets;
1107 }
1108
1109 /// Configure whether to enable relaxed loss detection on spurious loss.
1110 ///
1111 /// The default value is false.
1112 pub fn set_enable_relaxed_loss_threshold(&mut self, enable: bool) {
1113 self.enable_relaxed_loss_threshold = enable;
1114 }
1115
1116 /// Configures whether to enable HyStart++.
1117 ///
1118 /// The default value is `true`.
1119 pub fn enable_hystart(&mut self, v: bool) {
1120 self.hystart = v;
1121 }
1122
1123 /// Configures whether to enable pacing.
1124 ///
1125 /// The default value is `true`.
1126 pub fn enable_pacing(&mut self, v: bool) {
1127 self.pacing = v;
1128 }
1129
1130 /// Sets the max value for pacing rate.
1131 ///
1132 /// By default pacing rate is not limited.
1133 pub fn set_max_pacing_rate(&mut self, v: u64) {
1134 self.max_pacing_rate = Some(v);
1135 }
1136
1137 /// Configures whether to enable receiving DATAGRAM frames.
1138 ///
1139 /// When enabled, the `max_datagram_frame_size` transport parameter is set
1140 /// to 65536 as recommended by draft-ietf-quic-datagram-01.
1141 ///
1142 /// The default is `false`.
1143 pub fn enable_dgram(
1144 &mut self, enabled: bool, recv_queue_len: usize, send_queue_len: usize,
1145 ) {
1146 self.local_transport_params.max_datagram_frame_size = if enabled {
1147 Some(MAX_DGRAM_FRAME_SIZE)
1148 } else {
1149 None
1150 };
1151 self.dgram_recv_max_queue_len = recv_queue_len;
1152 self.dgram_send_max_queue_len = send_queue_len;
1153 }
1154
1155 /// Configures the max number of queued received PATH_CHALLENGE frames.
1156 ///
1157 /// When an endpoint receives a PATH_CHALLENGE frame and the queue is full,
1158 /// the frame is discarded.
1159 ///
1160 /// The default is 3.
1161 pub fn set_path_challenge_recv_max_queue_len(&mut self, queue_len: usize) {
1162 self.path_challenge_recv_max_queue_len = queue_len;
1163 }
1164
1165 /// Sets the maximum size of the connection window.
1166 ///
1167 /// The default value is MAX_CONNECTION_WINDOW (24MBytes).
1168 pub fn set_max_connection_window(&mut self, v: u64) {
1169 self.max_connection_window = v;
1170 }
1171
1172 /// Sets the maximum size of the stream window.
1173 ///
1174 /// The default value is MAX_STREAM_WINDOW (16MBytes).
1175 pub fn set_max_stream_window(&mut self, v: u64) {
1176 self.max_stream_window = v;
1177 }
1178
1179 /// Sets the initial stateless reset token.
1180 ///
1181 /// This value is only advertised by servers. Setting a stateless retry
1182 /// token as a client has no effect on the connection.
1183 ///
1184 /// The default value is `None`.
1185 pub fn set_stateless_reset_token(&mut self, v: Option<u128>) {
1186 self.local_transport_params.stateless_reset_token = v;
1187 }
1188
1189 /// Sets whether the QUIC connection should avoid reusing DCIDs over
1190 /// different paths.
1191 ///
1192 /// When set to `true`, it ensures that a destination Connection ID is never
1193 /// reused on different paths. Such behaviour may lead to connection stall
1194 /// if the peer performs a non-voluntary migration (e.g., NAT rebinding) and
1195 /// does not provide additional destination Connection IDs to handle such
1196 /// event.
1197 ///
1198 /// The default value is `false`.
1199 pub fn set_disable_dcid_reuse(&mut self, v: bool) {
1200 self.disable_dcid_reuse = v;
1201 }
1202
1203 /// Enables tracking unknown transport parameters.
1204 ///
1205 /// Specify the maximum number of bytes used to track unknown transport
1206 /// parameters. The size includes the identifier and its value. If storing a
1207 /// transport parameter would cause the limit to be exceeded, it is quietly
1208 /// dropped.
1209 ///
1210 /// The default is that the feature is disabled.
1211 pub fn enable_track_unknown_transport_parameters(&mut self, size: usize) {
1212 self.track_unknown_transport_params = Some(size);
1213 }
1214}
1215
1216/// Tracks the health of the tx_buffered value.
1217#[derive(Clone, Copy, Debug, Default, PartialEq)]
1218pub enum TxBufferTrackingState {
1219 /// The send buffer is in a good state
1220 #[default]
1221 Ok,
1222 /// The send buffer is in an inconsistent state, which could lead to
1223 /// connection stalls or excess buffering due to bugs we haven't
1224 /// tracked down yet.
1225 Inconsistent,
1226}
1227
1228/// A QUIC connection.
1229pub struct Connection<F = DefaultBufFactory>
1230where
1231 F: BufFactory,
1232{
1233 /// QUIC wire version used for the connection.
1234 version: u32,
1235
1236 /// Connection Identifiers.
1237 ids: cid::ConnectionIdentifiers,
1238
1239 /// Unique opaque ID for the connection that can be used for logging.
1240 trace_id: String,
1241
1242 /// Packet number spaces.
1243 pkt_num_spaces: [packet::PktNumSpace; packet::Epoch::count()],
1244
1245 /// The crypto context.
1246 crypto_ctx: [packet::CryptoContext; packet::Epoch::count()],
1247
1248 /// Next packet number.
1249 next_pkt_num: u64,
1250
1251 // TODO
1252 // combine with `next_pkt_num`
1253 /// Track the packet skip context
1254 pkt_num_manager: packet::PktNumManager,
1255
1256 /// Peer's transport parameters.
1257 peer_transport_params: TransportParams,
1258
1259 /// If tracking unknown transport parameters from a peer, how much space to
1260 /// use in bytes.
1261 peer_transport_params_track_unknown: Option<usize>,
1262
1263 /// Local transport parameters.
1264 local_transport_params: TransportParams,
1265
1266 /// TLS handshake state.
1267 handshake: tls::Handshake,
1268
1269 /// Serialized TLS session buffer.
1270 ///
1271 /// This field is populated when a new session ticket is processed on the
1272 /// client. On the server this is empty.
1273 session: Option<Vec<u8>>,
1274
1275 /// The configuration for recovery.
1276 recovery_config: recovery::RecoveryConfig,
1277
1278 /// The path manager.
1279 paths: path::PathMap,
1280
1281 /// PATH_CHALLENGE receive queue max length.
1282 path_challenge_recv_max_queue_len: usize,
1283
1284 /// Total number of received PATH_CHALLENGE frames.
1285 path_challenge_rx_count: u64,
1286
1287 /// List of supported application protocols.
1288 application_protos: Vec<Vec<u8>>,
1289
1290 /// Total number of received packets.
1291 recv_count: usize,
1292
1293 /// Total number of sent packets.
1294 sent_count: usize,
1295
1296 /// Total number of lost packets.
1297 lost_count: usize,
1298
1299 /// Total number of lost packets that were later acked.
1300 spurious_lost_count: usize,
1301
1302 /// Total number of packets sent with data retransmitted.
1303 retrans_count: usize,
1304
1305 /// Total number of sent DATAGRAM frames.
1306 dgram_sent_count: usize,
1307
1308 /// Total number of received DATAGRAM frames.
1309 dgram_recv_count: usize,
1310
1311 /// Total number of bytes received from the peer.
1312 rx_data: u64,
1313
1314 /// Receiver flow controller.
1315 flow_control: flowcontrol::FlowControl,
1316
1317 /// Whether we send MAX_DATA frame.
1318 almost_full: bool,
1319
1320 /// Number of stream data bytes that can be buffered.
1321 tx_cap: usize,
1322
1323 /// The send capacity factor.
1324 tx_cap_factor: f64,
1325
1326 /// Number of bytes buffered in the send buffer.
1327 tx_buffered: usize,
1328
1329 /// Tracks the health of tx_buffered.
1330 tx_buffered_state: TxBufferTrackingState,
1331
1332 /// Total number of bytes sent to the peer.
1333 tx_data: u64,
1334
1335 /// Peer's flow control limit for the connection.
1336 max_tx_data: u64,
1337
1338 /// Last tx_data before running a full send() loop.
1339 last_tx_data: u64,
1340
1341 /// Total number of bytes retransmitted over the connection.
1342 /// This counts only STREAM and CRYPTO data.
1343 stream_retrans_bytes: u64,
1344
1345 /// Total number of bytes sent over the connection.
1346 sent_bytes: u64,
1347
1348 /// Total number of bytes received over the connection.
1349 recv_bytes: u64,
1350
1351 /// Total number of bytes sent acked over the connection.
1352 acked_bytes: u64,
1353
1354 /// Total number of bytes sent lost over the connection.
1355 lost_bytes: u64,
1356
1357 /// Streams map, indexed by stream ID.
1358 streams: stream::StreamMap<F>,
1359
1360 /// Peer's original destination connection ID. Used by the client to
1361 /// validate the server's transport parameter.
1362 odcid: Option<ConnectionId<'static>>,
1363
1364 /// Peer's retry source connection ID. Used by the client during stateless
1365 /// retry to validate the server's transport parameter.
1366 rscid: Option<ConnectionId<'static>>,
1367
1368 /// Received address verification token.
1369 token: Option<Vec<u8>>,
1370
1371 /// Error code and reason to be sent to the peer in a CONNECTION_CLOSE
1372 /// frame.
1373 local_error: Option<ConnectionError>,
1374
1375 /// Error code and reason received from the peer in a CONNECTION_CLOSE
1376 /// frame.
1377 peer_error: Option<ConnectionError>,
1378
1379 /// The connection-level limit at which send blocking occurred.
1380 blocked_limit: Option<u64>,
1381
1382 /// Idle timeout expiration time.
1383 idle_timer: Option<Instant>,
1384
1385 /// Draining timeout expiration time.
1386 draining_timer: Option<Instant>,
1387
1388 /// List of raw packets that were received before they could be decrypted.
1389 undecryptable_pkts: VecDeque<(Vec<u8>, RecvInfo)>,
1390
1391 /// The negotiated ALPN protocol.
1392 alpn: Vec<u8>,
1393
1394 /// Whether this is a server-side connection.
1395 is_server: bool,
1396
1397 /// Whether the initial secrets have been derived.
1398 derived_initial_secrets: bool,
1399
1400 /// Whether a version negotiation packet has already been received. Only
1401 /// relevant for client connections.
1402 did_version_negotiation: bool,
1403
1404 /// Whether stateless retry has been performed.
1405 did_retry: bool,
1406
1407 /// Whether the peer already updated its connection ID.
1408 got_peer_conn_id: bool,
1409
1410 /// Whether the peer verified our initial address.
1411 peer_verified_initial_address: bool,
1412
1413 /// Whether the peer's transport parameters were parsed.
1414 parsed_peer_transport_params: bool,
1415
1416 /// Whether the connection handshake has been completed.
1417 handshake_completed: bool,
1418
1419 /// Whether the HANDSHAKE_DONE frame has been sent.
1420 handshake_done_sent: bool,
1421
1422 /// Whether the HANDSHAKE_DONE frame has been acked.
1423 handshake_done_acked: bool,
1424
1425 /// Whether the connection handshake has been confirmed.
1426 handshake_confirmed: bool,
1427
1428 /// Key phase bit used for outgoing protected packets.
1429 key_phase: bool,
1430
1431 /// Whether an ack-eliciting packet has been sent since last receiving a
1432 /// packet.
1433 ack_eliciting_sent: bool,
1434
1435 /// Whether the connection is closed.
1436 closed: bool,
1437
1438 /// Whether the connection was timed out.
1439 timed_out: bool,
1440
1441 /// Whether to send GREASE.
1442 grease: bool,
1443
1444 /// TLS keylog writer.
1445 keylog: Option<Box<dyn std::io::Write + Send + Sync>>,
1446
1447 #[cfg(feature = "qlog")]
1448 qlog: QlogInfo,
1449
1450 /// DATAGRAM queues.
1451 dgram_recv_queue: dgram::DatagramQueue,
1452 dgram_send_queue: dgram::DatagramQueue,
1453
1454 /// Whether to emit DATAGRAM frames in the next packet.
1455 emit_dgram: bool,
1456
1457 /// Whether the connection should prevent from reusing destination
1458 /// Connection IDs when the peer migrates.
1459 disable_dcid_reuse: bool,
1460
1461 /// The number of streams reset by local.
1462 reset_stream_local_count: u64,
1463
1464 /// The number of streams stopped by local.
1465 stopped_stream_local_count: u64,
1466
1467 /// The number of streams reset by remote.
1468 reset_stream_remote_count: u64,
1469
1470 /// The number of streams stopped by remote.
1471 stopped_stream_remote_count: u64,
1472
1473 /// The number of DATA_BLOCKED frames sent due to hitting the connection
1474 /// flow control limit.
1475 data_blocked_sent_count: u64,
1476
1477 /// The number of STREAM_DATA_BLOCKED frames sent due to a stream hitting
1478 /// the stream flow control limit.
1479 stream_data_blocked_sent_count: u64,
1480
1481 /// The number of DATA_BLOCKED frames received from the remote endpoint.
1482 data_blocked_recv_count: u64,
1483
1484 /// The number of STREAM_DATA_BLOCKED frames received from the remote
1485 /// endpoint.
1486 stream_data_blocked_recv_count: u64,
1487
1488 /// The anti-amplification limit factor.
1489 max_amplification_factor: usize,
1490}
1491
1492/// Creates a new server-side connection.
1493///
1494/// The `scid` parameter represents the server's source connection ID, while
1495/// the optional `odcid` parameter represents the original destination ID the
1496/// client sent before a stateless retry (this is only required when using
1497/// the [`retry()`] function).
1498///
1499/// [`retry()`]: fn.retry.html
1500///
1501/// ## Examples:
1502///
1503/// ```no_run
1504/// # let mut config = quiche::Config::new(0xbabababa)?;
1505/// # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
1506/// # let local = "127.0.0.1:0".parse().unwrap();
1507/// # let peer = "127.0.0.1:1234".parse().unwrap();
1508/// let conn = quiche::accept(&scid, None, local, peer, &mut config)?;
1509/// # Ok::<(), quiche::Error>(())
1510/// ```
1511#[inline]
1512pub fn accept(
1513 scid: &ConnectionId, odcid: Option<&ConnectionId>, local: SocketAddr,
1514 peer: SocketAddr, config: &mut Config,
1515) -> Result<Connection> {
1516 let conn = Connection::new(scid, odcid, local, peer, config, true)?;
1517
1518 Ok(conn)
1519}
1520
1521/// Creates a new server-side connection, with a custom buffer generation
1522/// method.
1523///
1524/// The buffers generated can be anything that can be drereferenced as a byte
1525/// slice. See [`accept`] and [`BufFactory`] for more info.
1526#[inline]
1527pub fn accept_with_buf_factory<F: BufFactory>(
1528 scid: &ConnectionId, odcid: Option<&ConnectionId>, local: SocketAddr,
1529 peer: SocketAddr, config: &mut Config,
1530) -> Result<Connection<F>> {
1531 let conn = Connection::new(scid, odcid, local, peer, config, true)?;
1532
1533 Ok(conn)
1534}
1535
1536/// Creates a new client-side connection.
1537///
1538/// The `scid` parameter is used as the connection's source connection ID,
1539/// while the optional `server_name` parameter is used to verify the peer's
1540/// certificate.
1541///
1542/// ## Examples:
1543///
1544/// ```no_run
1545/// # let mut config = quiche::Config::new(0xbabababa)?;
1546/// # let server_name = "quic.tech";
1547/// # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
1548/// # let local = "127.0.0.1:4321".parse().unwrap();
1549/// # let peer = "127.0.0.1:1234".parse().unwrap();
1550/// let conn =
1551/// quiche::connect(Some(&server_name), &scid, local, peer, &mut config)?;
1552/// # Ok::<(), quiche::Error>(())
1553/// ```
1554#[inline]
1555pub fn connect(
1556 server_name: Option<&str>, scid: &ConnectionId, local: SocketAddr,
1557 peer: SocketAddr, config: &mut Config,
1558) -> Result<Connection> {
1559 let mut conn = Connection::new(scid, None, local, peer, config, false)?;
1560
1561 if let Some(server_name) = server_name {
1562 conn.handshake.set_host_name(server_name)?;
1563 }
1564
1565 Ok(conn)
1566}
1567
1568/// Creates a new client-side connection, with a custom buffer generation
1569/// method.
1570///
1571/// The buffers generated can be anything that can be drereferenced as a byte
1572/// slice. See [`connect`] and [`BufFactory`] for more info.
1573#[inline]
1574pub fn connect_with_buffer_factory<F: BufFactory>(
1575 server_name: Option<&str>, scid: &ConnectionId, local: SocketAddr,
1576 peer: SocketAddr, config: &mut Config,
1577) -> Result<Connection<F>> {
1578 let mut conn = Connection::new(scid, None, local, peer, config, false)?;
1579
1580 if let Some(server_name) = server_name {
1581 conn.handshake.set_host_name(server_name)?;
1582 }
1583
1584 Ok(conn)
1585}
1586
1587/// Writes a version negotiation packet.
1588///
1589/// The `scid` and `dcid` parameters are the source connection ID and the
1590/// destination connection ID extracted from the received client's Initial
1591/// packet that advertises an unsupported version.
1592///
1593/// ## Examples:
1594///
1595/// ```no_run
1596/// # let mut buf = [0; 512];
1597/// # let mut out = [0; 512];
1598/// # let socket = std::net::UdpSocket::bind("127.0.0.1:0").unwrap();
1599/// let (len, src) = socket.recv_from(&mut buf).unwrap();
1600///
1601/// let hdr =
1602/// quiche::Header::from_slice(&mut buf[..len], quiche::MAX_CONN_ID_LEN)?;
1603///
1604/// if hdr.version != quiche::PROTOCOL_VERSION {
1605/// let len = quiche::negotiate_version(&hdr.scid, &hdr.dcid, &mut out)?;
1606/// socket.send_to(&out[..len], &src).unwrap();
1607/// }
1608/// # Ok::<(), quiche::Error>(())
1609/// ```
1610#[inline]
1611pub fn negotiate_version(
1612 scid: &ConnectionId, dcid: &ConnectionId, out: &mut [u8],
1613) -> Result<usize> {
1614 packet::negotiate_version(scid, dcid, out)
1615}
1616
1617/// Writes a stateless retry packet.
1618///
1619/// The `scid` and `dcid` parameters are the source connection ID and the
1620/// destination connection ID extracted from the received client's Initial
1621/// packet, while `new_scid` is the server's new source connection ID and
1622/// `token` is the address validation token the client needs to echo back.
1623///
1624/// The application is responsible for generating the address validation
1625/// token to be sent to the client, and verifying tokens sent back by the
1626/// client. The generated token should include the `dcid` parameter, such
1627/// that it can be later extracted from the token and passed to the
1628/// [`accept()`] function as its `odcid` parameter.
1629///
1630/// [`accept()`]: fn.accept.html
1631///
1632/// ## Examples:
1633///
1634/// ```no_run
1635/// # let mut config = quiche::Config::new(0xbabababa)?;
1636/// # let mut buf = [0; 512];
1637/// # let mut out = [0; 512];
1638/// # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
1639/// # let socket = std::net::UdpSocket::bind("127.0.0.1:0").unwrap();
1640/// # let local = socket.local_addr().unwrap();
1641/// # fn mint_token(hdr: &quiche::Header, src: &std::net::SocketAddr) -> Vec<u8> {
1642/// # vec![]
1643/// # }
1644/// # fn validate_token<'a>(src: &std::net::SocketAddr, token: &'a [u8]) -> Option<quiche::ConnectionId<'a>> {
1645/// # None
1646/// # }
1647/// let (len, peer) = socket.recv_from(&mut buf).unwrap();
1648///
1649/// let hdr = quiche::Header::from_slice(&mut buf[..len], quiche::MAX_CONN_ID_LEN)?;
1650///
1651/// let token = hdr.token.as_ref().unwrap();
1652///
1653/// // No token sent by client, create a new one.
1654/// if token.is_empty() {
1655/// let new_token = mint_token(&hdr, &peer);
1656///
1657/// let len = quiche::retry(
1658/// &hdr.scid, &hdr.dcid, &scid, &new_token, hdr.version, &mut out,
1659/// )?;
1660///
1661/// socket.send_to(&out[..len], &peer).unwrap();
1662/// return Ok(());
1663/// }
1664///
1665/// // Client sent token, validate it.
1666/// let odcid = validate_token(&peer, token);
1667///
1668/// if odcid.is_none() {
1669/// // Invalid address validation token.
1670/// return Ok(());
1671/// }
1672///
1673/// let conn = quiche::accept(&scid, odcid.as_ref(), local, peer, &mut config)?;
1674/// # Ok::<(), quiche::Error>(())
1675/// ```
1676#[inline]
1677pub fn retry(
1678 scid: &ConnectionId, dcid: &ConnectionId, new_scid: &ConnectionId,
1679 token: &[u8], version: u32, out: &mut [u8],
1680) -> Result<usize> {
1681 packet::retry(scid, dcid, new_scid, token, version, out)
1682}
1683
1684/// Returns true if the given protocol version is supported.
1685#[inline]
1686pub fn version_is_supported(version: u32) -> bool {
1687 matches!(version, PROTOCOL_VERSION_V1)
1688}
1689
1690/// Pushes a frame to the output packet if there is enough space.
1691///
1692/// Returns `true` on success, `false` otherwise. In case of failure it means
1693/// there is no room to add the frame in the packet. You may retry to add the
1694/// frame later.
1695macro_rules! push_frame_to_pkt {
1696 ($out:expr, $frames:expr, $frame:expr, $left:expr) => {{
1697 if $frame.wire_len() <= $left {
1698 $left -= $frame.wire_len();
1699
1700 $frame.to_bytes(&mut $out)?;
1701
1702 $frames.push($frame);
1703
1704 true
1705 } else {
1706 false
1707 }
1708 }};
1709}
1710
1711/// Executes the provided body if the qlog feature is enabled, quiche has been
1712/// configured with a log writer, the event's importance is within the
1713/// configured level.
1714macro_rules! qlog_with_type {
1715 ($ty:expr, $qlog:expr, $qlog_streamer_ref:ident, $body:block) => {{
1716 #[cfg(feature = "qlog")]
1717 {
1718 if EventImportance::from($ty).is_contained_in(&$qlog.level) {
1719 if let Some($qlog_streamer_ref) = &mut $qlog.streamer {
1720 $body
1721 }
1722 }
1723 }
1724 }};
1725}
1726
1727#[cfg(feature = "qlog")]
1728const QLOG_PARAMS_SET: EventType =
1729 EventType::TransportEventType(TransportEventType::ParametersSet);
1730
1731#[cfg(feature = "qlog")]
1732const QLOG_PACKET_RX: EventType =
1733 EventType::TransportEventType(TransportEventType::PacketReceived);
1734
1735#[cfg(feature = "qlog")]
1736const QLOG_PACKET_TX: EventType =
1737 EventType::TransportEventType(TransportEventType::PacketSent);
1738
1739#[cfg(feature = "qlog")]
1740const QLOG_DATA_MV: EventType =
1741 EventType::TransportEventType(TransportEventType::DataMoved);
1742
1743#[cfg(feature = "qlog")]
1744const QLOG_METRICS: EventType =
1745 EventType::RecoveryEventType(RecoveryEventType::MetricsUpdated);
1746
1747#[cfg(feature = "qlog")]
1748const QLOG_CONNECTION_CLOSED: EventType =
1749 EventType::ConnectivityEventType(ConnectivityEventType::ConnectionClosed);
1750
1751#[cfg(feature = "qlog")]
1752struct QlogInfo {
1753 streamer: Option<qlog::streamer::QlogStreamer>,
1754 logged_peer_params: bool,
1755 level: EventImportance,
1756}
1757
1758#[cfg(feature = "qlog")]
1759impl Default for QlogInfo {
1760 fn default() -> Self {
1761 QlogInfo {
1762 streamer: None,
1763 logged_peer_params: false,
1764 level: EventImportance::Base,
1765 }
1766 }
1767}
1768
1769impl<F: BufFactory> Connection<F> {
1770 fn new(
1771 scid: &ConnectionId, odcid: Option<&ConnectionId>, local: SocketAddr,
1772 peer: SocketAddr, config: &mut Config, is_server: bool,
1773 ) -> Result<Connection<F>> {
1774 let tls = config.tls_ctx.new_handshake()?;
1775 Connection::with_tls(scid, odcid, local, peer, config, tls, is_server)
1776 }
1777
1778 fn with_tls(
1779 scid: &ConnectionId, odcid: Option<&ConnectionId>, local: SocketAddr,
1780 peer: SocketAddr, config: &Config, tls: tls::Handshake, is_server: bool,
1781 ) -> Result<Connection<F>> {
1782 let max_rx_data = config.local_transport_params.initial_max_data;
1783
1784 let scid_as_hex: Vec<String> =
1785 scid.iter().map(|b| format!("{b:02x}")).collect();
1786
1787 let reset_token = if is_server {
1788 config.local_transport_params.stateless_reset_token
1789 } else {
1790 None
1791 };
1792
1793 let recovery_config = recovery::RecoveryConfig::from_config(config);
1794
1795 let mut path = path::Path::new(
1796 local,
1797 peer,
1798 &recovery_config,
1799 config.path_challenge_recv_max_queue_len,
1800 true,
1801 Some(config),
1802 );
1803
1804 // If we did stateless retry assume the peer's address is verified.
1805 path.verified_peer_address = odcid.is_some();
1806 // Assume clients validate the server's address implicitly.
1807 path.peer_verified_local_address = is_server;
1808
1809 // Do not allocate more than the number of active CIDs.
1810 let paths = path::PathMap::new(
1811 path,
1812 config.local_transport_params.active_conn_id_limit as usize,
1813 is_server,
1814 );
1815
1816 let active_path_id = paths.get_active_path_id()?;
1817
1818 let ids = cid::ConnectionIdentifiers::new(
1819 config.local_transport_params.active_conn_id_limit as usize,
1820 scid,
1821 active_path_id,
1822 reset_token,
1823 );
1824
1825 let mut conn = Connection {
1826 version: config.version,
1827
1828 ids,
1829
1830 trace_id: scid_as_hex.join(""),
1831
1832 pkt_num_spaces: [
1833 packet::PktNumSpace::new(),
1834 packet::PktNumSpace::new(),
1835 packet::PktNumSpace::new(),
1836 ],
1837
1838 crypto_ctx: [
1839 packet::CryptoContext::new(),
1840 packet::CryptoContext::new(),
1841 packet::CryptoContext::new(),
1842 ],
1843
1844 next_pkt_num: 0,
1845
1846 pkt_num_manager: packet::PktNumManager::new(),
1847
1848 peer_transport_params: TransportParams::default(),
1849
1850 peer_transport_params_track_unknown: config
1851 .track_unknown_transport_params,
1852
1853 local_transport_params: config.local_transport_params.clone(),
1854
1855 handshake: tls,
1856
1857 session: None,
1858
1859 recovery_config,
1860
1861 paths,
1862 path_challenge_recv_max_queue_len: config
1863 .path_challenge_recv_max_queue_len,
1864 path_challenge_rx_count: 0,
1865
1866 application_protos: config.application_protos.clone(),
1867
1868 recv_count: 0,
1869 sent_count: 0,
1870 lost_count: 0,
1871 spurious_lost_count: 0,
1872 retrans_count: 0,
1873 dgram_sent_count: 0,
1874 dgram_recv_count: 0,
1875 sent_bytes: 0,
1876 recv_bytes: 0,
1877 acked_bytes: 0,
1878 lost_bytes: 0,
1879
1880 rx_data: 0,
1881 flow_control: flowcontrol::FlowControl::new(
1882 max_rx_data,
1883 cmp::min(max_rx_data / 2 * 3, DEFAULT_CONNECTION_WINDOW),
1884 config.max_connection_window,
1885 ),
1886 almost_full: false,
1887
1888 tx_cap: 0,
1889 tx_cap_factor: config.tx_cap_factor,
1890
1891 tx_buffered: 0,
1892 tx_buffered_state: TxBufferTrackingState::Ok,
1893
1894 tx_data: 0,
1895 max_tx_data: 0,
1896 last_tx_data: 0,
1897
1898 stream_retrans_bytes: 0,
1899
1900 streams: stream::StreamMap::new(
1901 config.local_transport_params.initial_max_streams_bidi,
1902 config.local_transport_params.initial_max_streams_uni,
1903 config.max_stream_window,
1904 ),
1905
1906 odcid: None,
1907
1908 rscid: None,
1909
1910 token: None,
1911
1912 local_error: None,
1913
1914 peer_error: None,
1915
1916 blocked_limit: None,
1917
1918 idle_timer: None,
1919
1920 draining_timer: None,
1921
1922 undecryptable_pkts: VecDeque::new(),
1923
1924 alpn: Vec::new(),
1925
1926 is_server,
1927
1928 derived_initial_secrets: false,
1929
1930 did_version_negotiation: false,
1931
1932 did_retry: false,
1933
1934 got_peer_conn_id: false,
1935
1936 // Assume clients validate the server's address implicitly.
1937 peer_verified_initial_address: is_server,
1938
1939 parsed_peer_transport_params: false,
1940
1941 handshake_completed: false,
1942
1943 handshake_done_sent: false,
1944 handshake_done_acked: false,
1945
1946 handshake_confirmed: false,
1947
1948 key_phase: false,
1949
1950 ack_eliciting_sent: false,
1951
1952 closed: false,
1953
1954 timed_out: false,
1955
1956 grease: config.grease,
1957
1958 keylog: None,
1959
1960 #[cfg(feature = "qlog")]
1961 qlog: Default::default(),
1962
1963 dgram_recv_queue: dgram::DatagramQueue::new(
1964 config.dgram_recv_max_queue_len,
1965 ),
1966
1967 dgram_send_queue: dgram::DatagramQueue::new(
1968 config.dgram_send_max_queue_len,
1969 ),
1970
1971 emit_dgram: true,
1972
1973 disable_dcid_reuse: config.disable_dcid_reuse,
1974
1975 reset_stream_local_count: 0,
1976 stopped_stream_local_count: 0,
1977 reset_stream_remote_count: 0,
1978 stopped_stream_remote_count: 0,
1979
1980 data_blocked_sent_count: 0,
1981 stream_data_blocked_sent_count: 0,
1982 data_blocked_recv_count: 0,
1983 stream_data_blocked_recv_count: 0,
1984
1985 max_amplification_factor: config.max_amplification_factor,
1986 };
1987
1988 if let Some(odcid) = odcid {
1989 conn.local_transport_params
1990 .original_destination_connection_id = Some(odcid.to_vec().into());
1991
1992 conn.local_transport_params.retry_source_connection_id =
1993 Some(conn.ids.get_scid(0)?.cid.to_vec().into());
1994
1995 conn.did_retry = true;
1996 }
1997
1998 conn.local_transport_params.initial_source_connection_id =
1999 Some(conn.ids.get_scid(0)?.cid.to_vec().into());
2000
2001 conn.handshake.init(is_server)?;
2002
2003 conn.handshake
2004 .use_legacy_codepoint(config.version != PROTOCOL_VERSION_V1);
2005
2006 conn.encode_transport_params()?;
2007
2008 // Derive initial secrets for the client. We can do this here because
2009 // we already generated the random destination connection ID.
2010 if !is_server {
2011 let mut dcid = [0; 16];
2012 rand::rand_bytes(&mut dcid[..]);
2013
2014 let (aead_open, aead_seal) = crypto::derive_initial_key_material(
2015 &dcid,
2016 conn.version,
2017 conn.is_server,
2018 false,
2019 )?;
2020
2021 let reset_token = conn.peer_transport_params.stateless_reset_token;
2022 conn.set_initial_dcid(
2023 dcid.to_vec().into(),
2024 reset_token,
2025 active_path_id,
2026 )?;
2027
2028 conn.crypto_ctx[packet::Epoch::Initial].crypto_open = Some(aead_open);
2029 conn.crypto_ctx[packet::Epoch::Initial].crypto_seal = Some(aead_seal);
2030
2031 conn.derived_initial_secrets = true;
2032 }
2033
2034 Ok(conn)
2035 }
2036
2037 /// Sets keylog output to the designated [`Writer`].
2038 ///
2039 /// This needs to be called as soon as the connection is created, to avoid
2040 /// missing some early logs.
2041 ///
2042 /// [`Writer`]: https://doc.rust-lang.org/std/io/trait.Write.html
2043 #[inline]
2044 pub fn set_keylog(&mut self, writer: Box<dyn std::io::Write + Send + Sync>) {
2045 self.keylog = Some(writer);
2046 }
2047
2048 /// Sets qlog output to the designated [`Writer`].
2049 ///
2050 /// Only events included in `QlogLevel::Base` are written. The serialization
2051 /// format is JSON-SEQ.
2052 ///
2053 /// This needs to be called as soon as the connection is created, to avoid
2054 /// missing some early logs.
2055 ///
2056 /// [`Writer`]: https://doc.rust-lang.org/std/io/trait.Write.html
2057 #[cfg(feature = "qlog")]
2058 #[cfg_attr(docsrs, doc(cfg(feature = "qlog")))]
2059 pub fn set_qlog(
2060 &mut self, writer: Box<dyn std::io::Write + Send + Sync>, title: String,
2061 description: String,
2062 ) {
2063 self.set_qlog_with_level(writer, title, description, QlogLevel::Base)
2064 }
2065
2066 /// Sets qlog output to the designated [`Writer`].
2067 ///
2068 /// Only qlog events included in the specified `QlogLevel` are written. The
2069 /// serialization format is JSON-SEQ.
2070 ///
2071 /// This needs to be called as soon as the connection is created, to avoid
2072 /// missing some early logs.
2073 ///
2074 /// [`Writer`]: https://doc.rust-lang.org/std/io/trait.Write.html
2075 #[cfg(feature = "qlog")]
2076 #[cfg_attr(docsrs, doc(cfg(feature = "qlog")))]
2077 pub fn set_qlog_with_level(
2078 &mut self, writer: Box<dyn std::io::Write + Send + Sync>, title: String,
2079 description: String, qlog_level: QlogLevel,
2080 ) {
2081 let vp = if self.is_server {
2082 qlog::VantagePointType::Server
2083 } else {
2084 qlog::VantagePointType::Client
2085 };
2086
2087 let level = match qlog_level {
2088 QlogLevel::Core => EventImportance::Core,
2089
2090 QlogLevel::Base => EventImportance::Base,
2091
2092 QlogLevel::Extra => EventImportance::Extra,
2093 };
2094
2095 self.qlog.level = level;
2096
2097 let trace = qlog::TraceSeq::new(
2098 qlog::VantagePoint {
2099 name: None,
2100 ty: vp,
2101 flow: None,
2102 },
2103 Some(title.to_string()),
2104 Some(description.to_string()),
2105 Some(qlog::Configuration {
2106 time_offset: Some(0.0),
2107 original_uris: None,
2108 }),
2109 None,
2110 );
2111
2112 let mut streamer = qlog::streamer::QlogStreamer::new(
2113 qlog::QLOG_VERSION.to_string(),
2114 Some(title),
2115 Some(description),
2116 None,
2117 Instant::now(),
2118 trace,
2119 self.qlog.level,
2120 writer,
2121 );
2122
2123 streamer.start_log().ok();
2124
2125 let ev_data = self
2126 .local_transport_params
2127 .to_qlog(TransportOwner::Local, self.handshake.cipher());
2128
2129 // This event occurs very early, so just mark the relative time as 0.0.
2130 streamer.add_event(Event::with_time(0.0, ev_data)).ok();
2131
2132 self.qlog.streamer = Some(streamer);
2133 }
2134
2135 /// Returns a mutable reference to the QlogStreamer, if it exists.
2136 #[cfg(feature = "qlog")]
2137 #[cfg_attr(docsrs, doc(cfg(feature = "qlog")))]
2138 pub fn qlog_streamer(&mut self) -> Option<&mut qlog::streamer::QlogStreamer> {
2139 self.qlog.streamer.as_mut()
2140 }
2141
2142 /// Configures the given session for resumption.
2143 ///
2144 /// On the client, this can be used to offer the given serialized session,
2145 /// as returned by [`session()`], for resumption.
2146 ///
2147 /// This must only be called immediately after creating a connection, that
2148 /// is, before any packet is sent or received.
2149 ///
2150 /// [`session()`]: struct.Connection.html#method.session
2151 #[inline]
2152 pub fn set_session(&mut self, session: &[u8]) -> Result<()> {
2153 let mut b = octets::Octets::with_slice(session);
2154
2155 let session_len = b.get_u64()? as usize;
2156 let session_bytes = b.get_bytes(session_len)?;
2157
2158 self.handshake.set_session(session_bytes.as_ref())?;
2159
2160 let raw_params_len = b.get_u64()? as usize;
2161 let raw_params_bytes = b.get_bytes(raw_params_len)?;
2162
2163 let peer_params = TransportParams::decode(
2164 raw_params_bytes.as_ref(),
2165 self.is_server,
2166 self.peer_transport_params_track_unknown,
2167 )?;
2168
2169 self.process_peer_transport_params(peer_params)?;
2170
2171 Ok(())
2172 }
2173
2174 /// Sets the `max_idle_timeout` transport parameter, in milliseconds.
2175 ///
2176 /// This must only be called immediately after creating a connection, that
2177 /// is, before any packet is sent or received.
2178 ///
2179 /// The default value is infinite, that is, no timeout is used unless
2180 /// already configured when creating the connection.
2181 pub fn set_max_idle_timeout(&mut self, v: u64) -> Result<()> {
2182 self.local_transport_params.max_idle_timeout =
2183 cmp::min(v, octets::MAX_VAR_INT);
2184
2185 self.encode_transport_params()
2186 }
2187
2188 /// Sets the congestion control algorithm used.
2189 ///
2190 /// This function can only be called inside one of BoringSSL's handshake
2191 /// callbacks, before any packet has been sent. Calling this function any
2192 /// other time will have no effect.
2193 ///
2194 /// See [`Config::set_cc_algorithm()`].
2195 ///
2196 /// [`Config::set_cc_algorithm()`]: struct.Config.html#method.set_cc_algorithm
2197 #[cfg(feature = "boringssl-boring-crate")]
2198 #[cfg_attr(docsrs, doc(cfg(feature = "boringssl-boring-crate")))]
2199 pub fn set_cc_algorithm_in_handshake(
2200 ssl: &mut boring::ssl::SslRef, algo: CongestionControlAlgorithm,
2201 ) -> Result<()> {
2202 let ex_data = tls::ExData::from_ssl_ref(ssl).ok_or(Error::TlsFail)?;
2203
2204 ex_data.recovery_config.cc_algorithm = algo;
2205
2206 Ok(())
2207 }
2208
2209 /// Sets custom BBR settings.
2210 ///
2211 /// This API is experimental and will be removed in the future.
2212 ///
2213 /// Currently this only applies if cc_algorithm is
2214 /// `CongestionControlAlgorithm::Bbr2Gcongestion` is set.
2215 ///
2216 /// This function can only be called inside one of BoringSSL's handshake
2217 /// callbacks, before any packet has been sent. Calling this function any
2218 /// other time will have no effect.
2219 ///
2220 /// See [`Config::set_custom_bbr_settings()`].
2221 ///
2222 /// [`Config::set_custom_bbr_settings()`]: struct.Config.html#method.set_custom_bbr_settings
2223 #[cfg(all(feature = "boringssl-boring-crate", feature = "internal"))]
2224 #[cfg_attr(docsrs, doc(cfg(feature = "boringssl-boring-crate")))]
2225 #[doc(hidden)]
2226 pub fn set_custom_bbr_settings_in_handshake(
2227 ssl: &mut boring::ssl::SslRef, custom_bbr_params: BbrParams,
2228 ) -> Result<()> {
2229 let ex_data = tls::ExData::from_ssl_ref(ssl).ok_or(Error::TlsFail)?;
2230
2231 ex_data.recovery_config.custom_bbr_params = Some(custom_bbr_params);
2232
2233 Ok(())
2234 }
2235
2236 /// Sets the congestion control algorithm used by string.
2237 ///
2238 /// This function can only be called inside one of BoringSSL's handshake
2239 /// callbacks, before any packet has been sent. Calling this function any
2240 /// other time will have no effect.
2241 ///
2242 /// See [`Config::set_cc_algorithm_name()`].
2243 ///
2244 /// [`Config::set_cc_algorithm_name()`]: struct.Config.html#method.set_cc_algorithm_name
2245 #[cfg(feature = "boringssl-boring-crate")]
2246 #[cfg_attr(docsrs, doc(cfg(feature = "boringssl-boring-crate")))]
2247 pub fn set_cc_algorithm_name_in_handshake(
2248 ssl: &mut boring::ssl::SslRef, name: &str,
2249 ) -> Result<()> {
2250 let cc_algo = CongestionControlAlgorithm::from_str(name)?;
2251 Self::set_cc_algorithm_in_handshake(ssl, cc_algo)
2252 }
2253
2254 /// Sets initial congestion window size in terms of packet count.
2255 ///
2256 /// This function can only be called inside one of BoringSSL's handshake
2257 /// callbacks, before any packet has been sent. Calling this function any
2258 /// other time will have no effect.
2259 ///
2260 /// See [`Config::set_initial_congestion_window_packets()`].
2261 ///
2262 /// [`Config::set_initial_congestion_window_packets()`]: struct.Config.html#method.set_initial_congestion_window_packets
2263 #[cfg(feature = "boringssl-boring-crate")]
2264 #[cfg_attr(docsrs, doc(cfg(feature = "boringssl-boring-crate")))]
2265 pub fn set_initial_congestion_window_packets_in_handshake(
2266 ssl: &mut boring::ssl::SslRef, packets: usize,
2267 ) -> Result<()> {
2268 let ex_data = tls::ExData::from_ssl_ref(ssl).ok_or(Error::TlsFail)?;
2269
2270 ex_data.recovery_config.initial_congestion_window_packets = packets;
2271
2272 Ok(())
2273 }
2274
2275 /// Configure whether to enable relaxed loss detection on spurious loss.
2276 ///
2277 /// This function can only be called inside one of BoringSSL's handshake
2278 /// callbacks, before any packet has been sent. Calling this function any
2279 /// other time will have no effect.
2280 ///
2281 /// See [`Config::set_enable_relaxed_loss_threshold()`].
2282 ///
2283 /// [`Config::set_enable_relaxed_loss_threshold()`]: struct.Config.html#method.set_enable_relaxed_loss_threshold
2284 #[cfg(feature = "boringssl-boring-crate")]
2285 #[cfg_attr(docsrs, doc(cfg(feature = "boringssl-boring-crate")))]
2286 pub fn set_enable_relaxed_loss_threshold_in_handshake(
2287 ssl: &mut boring::ssl::SslRef, enable: bool,
2288 ) -> Result<()> {
2289 let ex_data = tls::ExData::from_ssl_ref(ssl).ok_or(Error::TlsFail)?;
2290
2291 ex_data.recovery_config.enable_relaxed_loss_threshold = enable;
2292
2293 Ok(())
2294 }
2295
2296 /// Configures whether to enable HyStart++.
2297 ///
2298 /// This function can only be called inside one of BoringSSL's handshake
2299 /// callbacks, before any packet has been sent. Calling this function any
2300 /// other time will have no effect.
2301 ///
2302 /// See [`Config::enable_hystart()`].
2303 ///
2304 /// [`Config::enable_hystart()`]: struct.Config.html#method.enable_hystart
2305 #[cfg(feature = "boringssl-boring-crate")]
2306 #[cfg_attr(docsrs, doc(cfg(feature = "boringssl-boring-crate")))]
2307 pub fn set_hystart_in_handshake(
2308 ssl: &mut boring::ssl::SslRef, v: bool,
2309 ) -> Result<()> {
2310 let ex_data = tls::ExData::from_ssl_ref(ssl).ok_or(Error::TlsFail)?;
2311
2312 ex_data.recovery_config.hystart = v;
2313
2314 Ok(())
2315 }
2316
2317 /// Configures whether to enable pacing.
2318 ///
2319 /// This function can only be called inside one of BoringSSL's handshake
2320 /// callbacks, before any packet has been sent. Calling this function any
2321 /// other time will have no effect.
2322 ///
2323 /// See [`Config::enable_pacing()`].
2324 ///
2325 /// [`Config::enable_pacing()`]: struct.Config.html#method.enable_pacing
2326 #[cfg(feature = "boringssl-boring-crate")]
2327 #[cfg_attr(docsrs, doc(cfg(feature = "boringssl-boring-crate")))]
2328 pub fn set_pacing_in_handshake(
2329 ssl: &mut boring::ssl::SslRef, v: bool,
2330 ) -> Result<()> {
2331 let ex_data = tls::ExData::from_ssl_ref(ssl).ok_or(Error::TlsFail)?;
2332
2333 ex_data.recovery_config.pacing = v;
2334
2335 Ok(())
2336 }
2337
2338 /// Sets the max value for pacing rate.
2339 ///
2340 /// This function can only be called inside one of BoringSSL's handshake
2341 /// callbacks, before any packet has been sent. Calling this function any
2342 /// other time will have no effect.
2343 ///
2344 /// See [`Config::set_max_pacing_rate()`].
2345 ///
2346 /// [`Config::set_max_pacing_rate()`]: struct.Config.html#method.set_max_pacing_rate
2347 #[cfg(feature = "boringssl-boring-crate")]
2348 #[cfg_attr(docsrs, doc(cfg(feature = "boringssl-boring-crate")))]
2349 pub fn set_max_pacing_rate_in_handshake(
2350 ssl: &mut boring::ssl::SslRef, v: Option<u64>,
2351 ) -> Result<()> {
2352 let ex_data = tls::ExData::from_ssl_ref(ssl).ok_or(Error::TlsFail)?;
2353
2354 ex_data.recovery_config.max_pacing_rate = v;
2355
2356 Ok(())
2357 }
2358
2359 /// Sets the maximum outgoing UDP payload size.
2360 ///
2361 /// This function can only be called inside one of BoringSSL's handshake
2362 /// callbacks, before any packet has been sent. Calling this function any
2363 /// other time will have no effect.
2364 ///
2365 /// See [`Config::set_max_send_udp_payload_size()`].
2366 ///
2367 /// [`Config::set_max_send_udp_payload_size()`]: struct.Config.html#method.set_max_send_udp_payload_size
2368 #[cfg(feature = "boringssl-boring-crate")]
2369 #[cfg_attr(docsrs, doc(cfg(feature = "boringssl-boring-crate")))]
2370 pub fn set_max_send_udp_payload_size_in_handshake(
2371 ssl: &mut boring::ssl::SslRef, v: usize,
2372 ) -> Result<()> {
2373 let ex_data = tls::ExData::from_ssl_ref(ssl).ok_or(Error::TlsFail)?;
2374
2375 ex_data.recovery_config.max_send_udp_payload_size = v;
2376
2377 Ok(())
2378 }
2379
2380 /// Sets the send capacity factor.
2381 ///
2382 /// This function can only be called inside one of BoringSSL's handshake
2383 /// callbacks, before any packet has been sent. Calling this function any
2384 /// other time will have no effect.
2385 ///
2386 /// See [`Config::set_send_capacity_factor()`].
2387 ///
2388 /// [`Config::set_max_send_udp_payload_size()`]: struct.Config.html#method.set_send_capacity_factor
2389 #[cfg(feature = "boringssl-boring-crate")]
2390 #[cfg_attr(docsrs, doc(cfg(feature = "boringssl-boring-crate")))]
2391 pub fn set_send_capacity_factor_in_handshake(
2392 ssl: &mut boring::ssl::SslRef, v: f64,
2393 ) -> Result<()> {
2394 let ex_data = tls::ExData::from_ssl_ref(ssl).ok_or(Error::TlsFail)?;
2395
2396 ex_data.tx_cap_factor = v;
2397
2398 Ok(())
2399 }
2400
2401 /// Configures whether to do path MTU discovery.
2402 ///
2403 /// This function can only be called inside one of BoringSSL's handshake
2404 /// callbacks, before any packet has been sent. Calling this function any
2405 /// other time will have no effect.
2406 ///
2407 /// See [`Config::discover_pmtu()`].
2408 ///
2409 /// [`Config::discover_pmtu()`]: struct.Config.html#method.discover_pmtu
2410 #[cfg(feature = "boringssl-boring-crate")]
2411 #[cfg_attr(docsrs, doc(cfg(feature = "boringssl-boring-crate")))]
2412 pub fn set_discover_pmtu_in_handshake(
2413 ssl: &mut boring::ssl::SslRef, discover: bool,
2414 ) -> Result<()> {
2415 let ex_data = tls::ExData::from_ssl_ref(ssl).ok_or(Error::TlsFail)?;
2416
2417 ex_data.pmtud = Some(discover);
2418
2419 Ok(())
2420 }
2421
2422 /// Sets the `max_idle_timeout` transport parameter, in milliseconds.
2423 ///
2424 /// This function can only be called inside one of BoringSSL's handshake
2425 /// callbacks, before any packet has been sent. Calling this function any
2426 /// other time will have no effect.
2427 ///
2428 /// See [`Config::set_max_idle_timeout()`].
2429 ///
2430 /// [`Config::set_max_idle_timeout()`]: struct.Config.html#method.set_max_idle_timeout
2431 #[cfg(feature = "boringssl-boring-crate")]
2432 #[cfg_attr(docsrs, doc(cfg(feature = "boringssl-boring-crate")))]
2433 pub fn set_max_idle_timeout_in_handshake(
2434 ssl: &mut boring::ssl::SslRef, v: u64,
2435 ) -> Result<()> {
2436 let ex_data = tls::ExData::from_ssl_ref(ssl).ok_or(Error::TlsFail)?;
2437
2438 ex_data.local_transport_params.max_idle_timeout = v;
2439
2440 Self::set_transport_parameters_in_hanshake(
2441 ex_data.local_transport_params.clone(),
2442 ex_data.is_server,
2443 ssl,
2444 )
2445 }
2446
2447 /// Sets the `initial_max_streams_bidi` transport parameter.
2448 ///
2449 /// This function can only be called inside one of BoringSSL's handshake
2450 /// callbacks, before any packet has been sent. Calling this function any
2451 /// other time will have no effect.
2452 ///
2453 /// See [`Config::set_initial_max_streams_bidi()`].
2454 ///
2455 /// [`Config::set_initial_max_streams_bidi()`]: struct.Config.html#method.set_initial_max_streams_bidi
2456 #[cfg(feature = "boringssl-boring-crate")]
2457 #[cfg_attr(docsrs, doc(cfg(feature = "boringssl-boring-crate")))]
2458 pub fn set_initial_max_streams_bidi_in_handshake(
2459 ssl: &mut boring::ssl::SslRef, v: u64,
2460 ) -> Result<()> {
2461 let ex_data = tls::ExData::from_ssl_ref(ssl).ok_or(Error::TlsFail)?;
2462
2463 ex_data.local_transport_params.initial_max_streams_bidi = v;
2464
2465 Self::set_transport_parameters_in_hanshake(
2466 ex_data.local_transport_params.clone(),
2467 ex_data.is_server,
2468 ssl,
2469 )
2470 }
2471
2472 #[cfg(feature = "boringssl-boring-crate")]
2473 fn set_transport_parameters_in_hanshake(
2474 params: TransportParams, is_server: bool, ssl: &mut boring::ssl::SslRef,
2475 ) -> Result<()> {
2476 use foreign_types_shared::ForeignTypeRef;
2477
2478 // In order to apply the new parameter to the TLS state before TPs are
2479 // written into a TLS message, we need to re-encode all TPs immediately.
2480 //
2481 // Since we don't have direct access to the main `Connection` object, we
2482 // need to re-create the `Handshake` state from the `SslRef`.
2483 //
2484 // SAFETY: the `Handshake` object must not be drop()ed, otherwise it
2485 // would free the underlying BoringSSL structure.
2486 let mut handshake =
2487 unsafe { tls::Handshake::from_ptr(ssl.as_ptr() as _) };
2488 handshake.set_quic_transport_params(¶ms, is_server)?;
2489
2490 // Avoid running `drop(handshake)` as that would free the underlying
2491 // handshake state.
2492 std::mem::forget(handshake);
2493
2494 Ok(())
2495 }
2496
2497 /// Processes QUIC packets received from the peer.
2498 ///
2499 /// On success the number of bytes processed from the input buffer is
2500 /// returned. On error the connection will be closed by calling [`close()`]
2501 /// with the appropriate error code.
2502 ///
2503 /// Coalesced packets will be processed as necessary.
2504 ///
2505 /// Note that the contents of the input buffer `buf` might be modified by
2506 /// this function due to, for example, in-place decryption.
2507 ///
2508 /// [`close()`]: struct.Connection.html#method.close
2509 ///
2510 /// ## Examples:
2511 ///
2512 /// ```no_run
2513 /// # let mut buf = [0; 512];
2514 /// # let socket = std::net::UdpSocket::bind("127.0.0.1:0").unwrap();
2515 /// # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
2516 /// # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
2517 /// # let peer = "127.0.0.1:1234".parse().unwrap();
2518 /// # let local = socket.local_addr().unwrap();
2519 /// # let mut conn = quiche::accept(&scid, None, local, peer, &mut config)?;
2520 /// loop {
2521 /// let (read, from) = socket.recv_from(&mut buf).unwrap();
2522 ///
2523 /// let recv_info = quiche::RecvInfo {
2524 /// from,
2525 /// to: local,
2526 /// };
2527 ///
2528 /// let read = match conn.recv(&mut buf[..read], recv_info) {
2529 /// Ok(v) => v,
2530 ///
2531 /// Err(e) => {
2532 /// // An error occurred, handle it.
2533 /// break;
2534 /// },
2535 /// };
2536 /// }
2537 /// # Ok::<(), quiche::Error>(())
2538 /// ```
2539 pub fn recv(&mut self, buf: &mut [u8], info: RecvInfo) -> Result<usize> {
2540 let len = buf.len();
2541
2542 if len == 0 {
2543 return Err(Error::BufferTooShort);
2544 }
2545
2546 let recv_pid = self.paths.path_id_from_addrs(&(info.to, info.from));
2547
2548 if let Some(recv_pid) = recv_pid {
2549 let recv_path = self.paths.get_mut(recv_pid)?;
2550
2551 // Keep track of how many bytes we received from the client, so we
2552 // can limit bytes sent back before address validation, to a
2553 // multiple of this. The limit needs to be increased early on, so
2554 // that if there is an error there is enough credit to send a
2555 // CONNECTION_CLOSE.
2556 //
2557 // It doesn't matter if the packets received were valid or not, we
2558 // only need to track the total amount of bytes received.
2559 //
2560 // Note that we also need to limit the number of bytes we sent on a
2561 // path if we are not the host that initiated its usage.
2562 if self.is_server && !recv_path.verified_peer_address {
2563 recv_path.max_send_bytes += len * self.max_amplification_factor;
2564 }
2565 } else if !self.is_server {
2566 // If a client receives packets from an unknown server address,
2567 // the client MUST discard these packets.
2568 trace!(
2569 "{} client received packet from unknown address {:?}, dropping",
2570 self.trace_id,
2571 info,
2572 );
2573
2574 return Ok(len);
2575 }
2576
2577 let mut done = 0;
2578 let mut left = len;
2579
2580 // Process coalesced packets.
2581 while left > 0 {
2582 let read = match self.recv_single(
2583 &mut buf[len - left..len],
2584 &info,
2585 recv_pid,
2586 ) {
2587 Ok(v) => v,
2588
2589 Err(Error::Done) => {
2590 // If the packet can't be processed or decrypted, check if
2591 // it's a stateless reset.
2592 if self.is_stateless_reset(&buf[len - left..len]) {
2593 trace!("{} packet is a stateless reset", self.trace_id);
2594
2595 self.mark_closed();
2596 }
2597
2598 left
2599 },
2600
2601 Err(e) => {
2602 // In case of error processing the incoming packet, close
2603 // the connection.
2604 self.close(false, e.to_wire(), b"").ok();
2605 return Err(e);
2606 },
2607 };
2608
2609 done += read;
2610 left -= read;
2611 }
2612
2613 // Even though the packet was previously "accepted", it
2614 // should be safe to forward the error, as it also comes
2615 // from the `recv()` method.
2616 self.process_undecrypted_0rtt_packets()?;
2617
2618 Ok(done)
2619 }
2620
2621 fn process_undecrypted_0rtt_packets(&mut self) -> Result<()> {
2622 // Process previously undecryptable 0-RTT packets if the decryption key
2623 // is now available.
2624 if self.crypto_ctx[packet::Epoch::Application]
2625 .crypto_0rtt_open
2626 .is_some()
2627 {
2628 while let Some((mut pkt, info)) = self.undecryptable_pkts.pop_front()
2629 {
2630 if let Err(e) = self.recv(&mut pkt, info) {
2631 self.undecryptable_pkts.clear();
2632
2633 return Err(e);
2634 }
2635 }
2636 }
2637 Ok(())
2638 }
2639
2640 /// Returns true if a QUIC packet is a stateless reset.
2641 fn is_stateless_reset(&self, buf: &[u8]) -> bool {
2642 // If the packet is too small, then we just throw it away.
2643 let buf_len = buf.len();
2644 if buf_len < 21 {
2645 return false;
2646 }
2647
2648 // TODO: we should iterate over all active destination connection IDs
2649 // and check against their reset token.
2650 match self.peer_transport_params.stateless_reset_token {
2651 Some(token) => {
2652 let token_len = 16;
2653
2654 crypto::verify_slices_are_equal(
2655 &token.to_be_bytes(),
2656 &buf[buf_len - token_len..buf_len],
2657 )
2658 .is_ok()
2659 },
2660
2661 None => false,
2662 }
2663 }
2664
2665 /// Processes a single QUIC packet received from the peer.
2666 ///
2667 /// On success the number of bytes processed from the input buffer is
2668 /// returned. When the [`Done`] error is returned, processing of the
2669 /// remainder of the incoming UDP datagram should be interrupted.
2670 ///
2671 /// Note that a server might observe a new 4-tuple, preventing to
2672 /// know in advance to which path the incoming packet belongs to (`recv_pid`
2673 /// is `None`). As a client, packets from unknown 4-tuple are dropped
2674 /// beforehand (see `recv()`).
2675 ///
2676 /// On error, an error other than [`Done`] is returned.
2677 ///
2678 /// [`Done`]: enum.Error.html#variant.Done
2679 fn recv_single(
2680 &mut self, buf: &mut [u8], info: &RecvInfo, recv_pid: Option<usize>,
2681 ) -> Result<usize> {
2682 let now = Instant::now();
2683
2684 if buf.is_empty() {
2685 return Err(Error::Done);
2686 }
2687
2688 if self.is_closed() || self.is_draining() {
2689 return Err(Error::Done);
2690 }
2691
2692 let is_closing = self.local_error.is_some();
2693
2694 if is_closing {
2695 return Err(Error::Done);
2696 }
2697
2698 let buf_len = buf.len();
2699
2700 let mut b = octets::OctetsMut::with_slice(buf);
2701
2702 let mut hdr = Header::from_bytes(&mut b, self.source_id().len())
2703 .map_err(|e| {
2704 drop_pkt_on_err(
2705 e,
2706 self.recv_count,
2707 self.is_server,
2708 &self.trace_id,
2709 )
2710 })?;
2711
2712 if hdr.ty == Type::VersionNegotiation {
2713 // Version negotiation packets can only be sent by the server.
2714 if self.is_server {
2715 return Err(Error::Done);
2716 }
2717
2718 // Ignore duplicate version negotiation.
2719 if self.did_version_negotiation {
2720 return Err(Error::Done);
2721 }
2722
2723 // Ignore version negotiation if any other packet has already been
2724 // successfully processed.
2725 if self.recv_count > 0 {
2726 return Err(Error::Done);
2727 }
2728
2729 if hdr.dcid != self.source_id() {
2730 return Err(Error::Done);
2731 }
2732
2733 if hdr.scid != self.destination_id() {
2734 return Err(Error::Done);
2735 }
2736
2737 trace!("{} rx pkt {:?}", self.trace_id, hdr);
2738
2739 let versions = hdr.versions.ok_or(Error::Done)?;
2740
2741 // Ignore version negotiation if the version already selected is
2742 // listed.
2743 if versions.contains(&self.version) {
2744 return Err(Error::Done);
2745 }
2746
2747 let supported_versions =
2748 versions.iter().filter(|&&v| version_is_supported(v));
2749
2750 let mut found_version = false;
2751
2752 for &v in supported_versions {
2753 found_version = true;
2754
2755 // The final version takes precedence over draft ones.
2756 if v == PROTOCOL_VERSION_V1 {
2757 self.version = v;
2758 break;
2759 }
2760
2761 self.version = cmp::max(self.version, v);
2762 }
2763
2764 if !found_version {
2765 // We don't support any of the versions offered.
2766 //
2767 // While a man-in-the-middle attacker might be able to
2768 // inject a version negotiation packet that triggers this
2769 // failure, the window of opportunity is very small and
2770 // this error is quite useful for debugging, so don't just
2771 // ignore the packet.
2772 return Err(Error::UnknownVersion);
2773 }
2774
2775 self.did_version_negotiation = true;
2776
2777 // Derive Initial secrets based on the new version.
2778 let (aead_open, aead_seal) = crypto::derive_initial_key_material(
2779 &self.destination_id(),
2780 self.version,
2781 self.is_server,
2782 true,
2783 )?;
2784
2785 // Reset connection state to force sending another Initial packet.
2786 self.drop_epoch_state(packet::Epoch::Initial, now);
2787 self.got_peer_conn_id = false;
2788 self.handshake.clear()?;
2789
2790 self.crypto_ctx[packet::Epoch::Initial].crypto_open = Some(aead_open);
2791 self.crypto_ctx[packet::Epoch::Initial].crypto_seal = Some(aead_seal);
2792
2793 self.handshake
2794 .use_legacy_codepoint(self.version != PROTOCOL_VERSION_V1);
2795
2796 // Encode transport parameters again, as the new version might be
2797 // using a different format.
2798 self.encode_transport_params()?;
2799
2800 return Err(Error::Done);
2801 }
2802
2803 if hdr.ty == Type::Retry {
2804 // Retry packets can only be sent by the server.
2805 if self.is_server {
2806 return Err(Error::Done);
2807 }
2808
2809 // Ignore duplicate retry.
2810 if self.did_retry {
2811 return Err(Error::Done);
2812 }
2813
2814 // Check if Retry packet is valid.
2815 if packet::verify_retry_integrity(
2816 &b,
2817 &self.destination_id(),
2818 self.version,
2819 )
2820 .is_err()
2821 {
2822 return Err(Error::Done);
2823 }
2824
2825 trace!("{} rx pkt {:?}", self.trace_id, hdr);
2826
2827 self.token = hdr.token;
2828 self.did_retry = true;
2829
2830 // Remember peer's new connection ID.
2831 self.odcid = Some(self.destination_id().into_owned());
2832
2833 self.set_initial_dcid(
2834 hdr.scid.clone(),
2835 None,
2836 self.paths.get_active_path_id()?,
2837 )?;
2838
2839 self.rscid = Some(self.destination_id().into_owned());
2840
2841 // Derive Initial secrets using the new connection ID.
2842 let (aead_open, aead_seal) = crypto::derive_initial_key_material(
2843 &hdr.scid,
2844 self.version,
2845 self.is_server,
2846 true,
2847 )?;
2848
2849 // Reset connection state to force sending another Initial packet.
2850 self.drop_epoch_state(packet::Epoch::Initial, now);
2851 self.got_peer_conn_id = false;
2852 self.handshake.clear()?;
2853
2854 self.crypto_ctx[packet::Epoch::Initial].crypto_open = Some(aead_open);
2855 self.crypto_ctx[packet::Epoch::Initial].crypto_seal = Some(aead_seal);
2856
2857 return Err(Error::Done);
2858 }
2859
2860 if self.is_server && !self.did_version_negotiation {
2861 if !version_is_supported(hdr.version) {
2862 return Err(Error::UnknownVersion);
2863 }
2864
2865 self.version = hdr.version;
2866 self.did_version_negotiation = true;
2867
2868 self.handshake
2869 .use_legacy_codepoint(self.version != PROTOCOL_VERSION_V1);
2870
2871 // Encode transport parameters again, as the new version might be
2872 // using a different format.
2873 self.encode_transport_params()?;
2874 }
2875
2876 if hdr.ty != Type::Short && hdr.version != self.version {
2877 // At this point version negotiation was already performed, so
2878 // ignore packets that don't match the connection's version.
2879 return Err(Error::Done);
2880 }
2881
2882 // Long header packets have an explicit payload length, but short
2883 // packets don't so just use the remaining capacity in the buffer.
2884 let payload_len = if hdr.ty == Type::Short {
2885 b.cap()
2886 } else {
2887 b.get_varint().map_err(|e| {
2888 drop_pkt_on_err(
2889 e.into(),
2890 self.recv_count,
2891 self.is_server,
2892 &self.trace_id,
2893 )
2894 })? as usize
2895 };
2896
2897 // Make sure the buffer is same or larger than an explicit
2898 // payload length.
2899 if payload_len > b.cap() {
2900 return Err(drop_pkt_on_err(
2901 Error::InvalidPacket,
2902 self.recv_count,
2903 self.is_server,
2904 &self.trace_id,
2905 ));
2906 }
2907
2908 // Derive initial secrets on the server.
2909 if !self.derived_initial_secrets {
2910 let (aead_open, aead_seal) = crypto::derive_initial_key_material(
2911 &hdr.dcid,
2912 self.version,
2913 self.is_server,
2914 false,
2915 )?;
2916
2917 self.crypto_ctx[packet::Epoch::Initial].crypto_open = Some(aead_open);
2918 self.crypto_ctx[packet::Epoch::Initial].crypto_seal = Some(aead_seal);
2919
2920 self.derived_initial_secrets = true;
2921 }
2922
2923 // Select packet number space epoch based on the received packet's type.
2924 let epoch = hdr.ty.to_epoch()?;
2925
2926 // Select AEAD context used to open incoming packet.
2927 let aead = if hdr.ty == Type::ZeroRTT {
2928 // Only use 0-RTT key if incoming packet is 0-RTT.
2929 self.crypto_ctx[epoch].crypto_0rtt_open.as_ref()
2930 } else {
2931 // Otherwise use the packet number space's main key.
2932 self.crypto_ctx[epoch].crypto_open.as_ref()
2933 };
2934
2935 // Finally, discard packet if no usable key is available.
2936 let mut aead = match aead {
2937 Some(v) => v,
2938
2939 None => {
2940 if hdr.ty == Type::ZeroRTT &&
2941 self.undecryptable_pkts.len() < MAX_UNDECRYPTABLE_PACKETS &&
2942 !self.is_established()
2943 {
2944 // Buffer 0-RTT packets when the required read key is not
2945 // available yet, and process them later.
2946 //
2947 // TODO: in the future we might want to buffer other types
2948 // of undecryptable packets as well.
2949 let pkt_len = b.off() + payload_len;
2950 let pkt = (b.buf()[..pkt_len]).to_vec();
2951
2952 self.undecryptable_pkts.push_back((pkt, *info));
2953 return Ok(pkt_len);
2954 }
2955
2956 let e = drop_pkt_on_err(
2957 Error::CryptoFail,
2958 self.recv_count,
2959 self.is_server,
2960 &self.trace_id,
2961 );
2962
2963 return Err(e);
2964 },
2965 };
2966
2967 let aead_tag_len = aead.alg().tag_len();
2968
2969 packet::decrypt_hdr(&mut b, &mut hdr, aead).map_err(|e| {
2970 drop_pkt_on_err(e, self.recv_count, self.is_server, &self.trace_id)
2971 })?;
2972
2973 let pn = packet::decode_pkt_num(
2974 self.pkt_num_spaces[epoch].largest_rx_pkt_num,
2975 hdr.pkt_num,
2976 hdr.pkt_num_len,
2977 );
2978
2979 let pn_len = hdr.pkt_num_len;
2980
2981 trace!(
2982 "{} rx pkt {:?} len={} pn={} {}",
2983 self.trace_id,
2984 hdr,
2985 payload_len,
2986 pn,
2987 AddrTupleFmt(info.from, info.to)
2988 );
2989
2990 #[cfg(feature = "qlog")]
2991 let mut qlog_frames = vec![];
2992
2993 // Check for key update.
2994 let mut aead_next = None;
2995
2996 if self.handshake_confirmed &&
2997 hdr.ty != Type::ZeroRTT &&
2998 hdr.key_phase != self.key_phase
2999 {
3000 // Check if this packet arrived before key update.
3001 if let Some(key_update) = self.crypto_ctx[epoch]
3002 .key_update
3003 .as_ref()
3004 .and_then(|key_update| {
3005 (pn < key_update.pn_on_update).then_some(key_update)
3006 })
3007 {
3008 aead = &key_update.crypto_open;
3009 } else {
3010 trace!("{} peer-initiated key update", self.trace_id);
3011
3012 aead_next = Some((
3013 self.crypto_ctx[epoch]
3014 .crypto_open
3015 .as_ref()
3016 .unwrap()
3017 .derive_next_packet_key()?,
3018 self.crypto_ctx[epoch]
3019 .crypto_seal
3020 .as_ref()
3021 .unwrap()
3022 .derive_next_packet_key()?,
3023 ));
3024
3025 // `aead_next` is always `Some()` at this point, so the `unwrap()`
3026 // will never fail.
3027 aead = &aead_next.as_ref().unwrap().0;
3028 }
3029 }
3030
3031 let mut payload = packet::decrypt_pkt(
3032 &mut b,
3033 pn,
3034 pn_len,
3035 payload_len,
3036 aead,
3037 )
3038 .map_err(|e| {
3039 drop_pkt_on_err(e, self.recv_count, self.is_server, &self.trace_id)
3040 })?;
3041
3042 if self.pkt_num_spaces[epoch].recv_pkt_num.contains(pn) {
3043 trace!("{} ignored duplicate packet {}", self.trace_id, pn);
3044 return Err(Error::Done);
3045 }
3046
3047 // Packets with no frames are invalid.
3048 if payload.cap() == 0 {
3049 return Err(Error::InvalidPacket);
3050 }
3051
3052 // Now that we decrypted the packet, let's see if we can map it to an
3053 // existing path.
3054 let recv_pid = if hdr.ty == Type::Short && self.got_peer_conn_id {
3055 let pkt_dcid = ConnectionId::from_ref(&hdr.dcid);
3056 self.get_or_create_recv_path_id(recv_pid, &pkt_dcid, buf_len, info)?
3057 } else {
3058 // During handshake, we are on the initial path.
3059 self.paths.get_active_path_id()?
3060 };
3061
3062 // The key update is verified once a packet is successfully decrypted
3063 // using the new keys.
3064 if let Some((open_next, seal_next)) = aead_next {
3065 if !self.crypto_ctx[epoch]
3066 .key_update
3067 .as_ref()
3068 .is_none_or(|prev| prev.update_acked)
3069 {
3070 // Peer has updated keys twice without awaiting confirmation.
3071 return Err(Error::KeyUpdate);
3072 }
3073
3074 trace!("{} key update verified", self.trace_id);
3075
3076 let _ = self.crypto_ctx[epoch].crypto_seal.replace(seal_next);
3077
3078 let open_prev = self.crypto_ctx[epoch]
3079 .crypto_open
3080 .replace(open_next)
3081 .unwrap();
3082
3083 let recv_path = self.paths.get_mut(recv_pid)?;
3084
3085 self.crypto_ctx[epoch].key_update = Some(packet::KeyUpdate {
3086 crypto_open: open_prev,
3087 pn_on_update: pn,
3088 update_acked: false,
3089 timer: now + (recv_path.recovery.pto() * 3),
3090 });
3091
3092 self.key_phase = !self.key_phase;
3093
3094 qlog_with_type!(QLOG_PACKET_RX, self.qlog, q, {
3095 let trigger = Some(
3096 qlog::events::security::KeyUpdateOrRetiredTrigger::RemoteUpdate,
3097 );
3098
3099 let ev_data_client =
3100 EventData::KeyUpdated(qlog::events::security::KeyUpdated {
3101 key_type:
3102 qlog::events::security::KeyType::Client1RttSecret,
3103 trigger: trigger.clone(),
3104 ..Default::default()
3105 });
3106
3107 q.add_event_data_with_instant(ev_data_client, now).ok();
3108
3109 let ev_data_server =
3110 EventData::KeyUpdated(qlog::events::security::KeyUpdated {
3111 key_type:
3112 qlog::events::security::KeyType::Server1RttSecret,
3113 trigger,
3114 ..Default::default()
3115 });
3116
3117 q.add_event_data_with_instant(ev_data_server, now).ok();
3118 });
3119 }
3120
3121 if !self.is_server && !self.got_peer_conn_id {
3122 if self.odcid.is_none() {
3123 self.odcid = Some(self.destination_id().into_owned());
3124 }
3125
3126 // Replace the randomly generated destination connection ID with
3127 // the one supplied by the server.
3128 self.set_initial_dcid(
3129 hdr.scid.clone(),
3130 self.peer_transport_params.stateless_reset_token,
3131 recv_pid,
3132 )?;
3133
3134 self.got_peer_conn_id = true;
3135 }
3136
3137 if self.is_server && !self.got_peer_conn_id {
3138 self.set_initial_dcid(hdr.scid.clone(), None, recv_pid)?;
3139
3140 if !self.did_retry {
3141 self.local_transport_params
3142 .original_destination_connection_id =
3143 Some(hdr.dcid.to_vec().into());
3144
3145 self.encode_transport_params()?;
3146 }
3147
3148 self.got_peer_conn_id = true;
3149 }
3150
3151 // To avoid sending an ACK in response to an ACK-only packet, we need
3152 // to keep track of whether this packet contains any frame other than
3153 // ACK and PADDING.
3154 let mut ack_elicited = false;
3155
3156 // Process packet payload. If a frame cannot be processed, store the
3157 // error and stop further packet processing.
3158 let mut frame_processing_err = None;
3159
3160 // To know if the peer migrated the connection, we need to keep track
3161 // whether this is a non-probing packet.
3162 let mut probing = true;
3163
3164 // Process packet payload.
3165 while payload.cap() > 0 {
3166 let frame = frame::Frame::from_bytes(&mut payload, hdr.ty)?;
3167
3168 qlog_with_type!(QLOG_PACKET_RX, self.qlog, _q, {
3169 qlog_frames.push(frame.to_qlog());
3170 });
3171
3172 if frame.ack_eliciting() {
3173 ack_elicited = true;
3174 }
3175
3176 if !frame.probing() {
3177 probing = false;
3178 }
3179
3180 if let Err(e) = self.process_frame(frame, &hdr, recv_pid, epoch, now)
3181 {
3182 frame_processing_err = Some(e);
3183 break;
3184 }
3185 }
3186
3187 qlog_with_type!(QLOG_PACKET_RX, self.qlog, q, {
3188 let packet_size = b.len();
3189
3190 let qlog_pkt_hdr = qlog::events::quic::PacketHeader::with_type(
3191 hdr.ty.to_qlog(),
3192 Some(pn),
3193 Some(hdr.version),
3194 Some(&hdr.scid),
3195 Some(&hdr.dcid),
3196 );
3197
3198 let qlog_raw_info = RawInfo {
3199 length: Some(packet_size as u64),
3200 payload_length: Some(payload_len as u64),
3201 data: None,
3202 };
3203
3204 let ev_data =
3205 EventData::PacketReceived(qlog::events::quic::PacketReceived {
3206 header: qlog_pkt_hdr,
3207 frames: Some(qlog_frames),
3208 raw: Some(qlog_raw_info),
3209 ..Default::default()
3210 });
3211
3212 q.add_event_data_with_instant(ev_data, now).ok();
3213 });
3214
3215 qlog_with_type!(QLOG_PACKET_RX, self.qlog, q, {
3216 let recv_path = self.paths.get_mut(recv_pid)?;
3217 recv_path.recovery.maybe_qlog(q, now);
3218 });
3219
3220 if let Some(e) = frame_processing_err {
3221 // Any frame error is terminal, so now just return.
3222 return Err(e);
3223 }
3224
3225 // Only log the remote transport parameters once the connection is
3226 // established (i.e. after frames have been fully parsed) and only
3227 // once per connection.
3228 if self.is_established() {
3229 qlog_with_type!(QLOG_PARAMS_SET, self.qlog, q, {
3230 if !self.qlog.logged_peer_params {
3231 let ev_data = self
3232 .peer_transport_params
3233 .to_qlog(TransportOwner::Remote, self.handshake.cipher());
3234
3235 q.add_event_data_with_instant(ev_data, now).ok();
3236
3237 self.qlog.logged_peer_params = true;
3238 }
3239 });
3240 }
3241
3242 // Process acked frames. Note that several packets from several paths
3243 // might have been acked by the received packet.
3244 for (_, p) in self.paths.iter_mut() {
3245 while let Some(acked) = p.recovery.next_acked_frame(epoch) {
3246 match acked {
3247 frame::Frame::Ping {
3248 mtu_probe: Some(mtu_probe),
3249 } =>
3250 if let Some(pmtud) = p.pmtud.as_mut() {
3251 trace!(
3252 "{} pmtud probe acked; probe size {:?}",
3253 self.trace_id,
3254 mtu_probe
3255 );
3256
3257 // Ensure the probe is within the supported MTU range
3258 // before updating the max datagram size
3259 if let Some(current_mtu) =
3260 pmtud.successful_probe(mtu_probe)
3261 {
3262 qlog_with_type!(
3263 EventType::ConnectivityEventType(
3264 ConnectivityEventType::MtuUpdated
3265 ),
3266 self.qlog,
3267 q,
3268 {
3269 let pmtu_data = EventData::MtuUpdated(
3270 qlog::events::connectivity::MtuUpdated {
3271 old: Some(
3272 p.recovery.max_datagram_size()
3273 as u16,
3274 ),
3275 new: current_mtu as u16,
3276 done: Some(true),
3277 },
3278 );
3279
3280 q.add_event_data_with_instant(
3281 pmtu_data, now,
3282 )
3283 .ok();
3284 }
3285 );
3286
3287 p.recovery
3288 .pmtud_update_max_datagram_size(current_mtu);
3289 }
3290 },
3291
3292 frame::Frame::ACK { ranges, .. } => {
3293 // Stop acknowledging packets less than or equal to the
3294 // largest acknowledged in the sent ACK frame that, in
3295 // turn, got acked.
3296 if let Some(largest_acked) = ranges.last() {
3297 self.pkt_num_spaces[epoch]
3298 .recv_pkt_need_ack
3299 .remove_until(largest_acked);
3300 }
3301 },
3302
3303 frame::Frame::CryptoHeader { offset, length } => {
3304 self.crypto_ctx[epoch]
3305 .crypto_stream
3306 .send
3307 .ack_and_drop(offset, length);
3308 },
3309
3310 frame::Frame::StreamHeader {
3311 stream_id,
3312 offset,
3313 length,
3314 ..
3315 } => {
3316 // Update tx_buffered and emit qlog before checking if the
3317 // stream still exists. The client does need to ACK
3318 // frames that were received after the client sends a
3319 // ResetStream.
3320 self.tx_buffered =
3321 self.tx_buffered.saturating_sub(length);
3322
3323 qlog_with_type!(QLOG_DATA_MV, self.qlog, q, {
3324 let ev_data = EventData::DataMoved(
3325 qlog::events::quic::DataMoved {
3326 stream_id: Some(stream_id),
3327 offset: Some(offset),
3328 length: Some(length as u64),
3329 from: Some(DataRecipient::Transport),
3330 to: Some(DataRecipient::Dropped),
3331 ..Default::default()
3332 },
3333 );
3334
3335 q.add_event_data_with_instant(ev_data, now).ok();
3336 });
3337
3338 let stream = match self.streams.get_mut(stream_id) {
3339 Some(v) => v,
3340
3341 None => continue,
3342 };
3343
3344 stream.send.ack_and_drop(offset, length);
3345
3346 let priority_key = Arc::clone(&stream.priority_key);
3347
3348 // Only collect the stream if it is complete and not
3349 // readable or writable.
3350 //
3351 // If it is readable, it will get collected when
3352 // stream_recv() is next used.
3353 //
3354 // If it is writable, it might mean that the stream
3355 // has been stopped by the peer (i.e. a STOP_SENDING
3356 // frame is received), in which case before collecting
3357 // the stream we will need to propagate the
3358 // `StreamStopped` error to the application. It will
3359 // instead get collected when one of stream_capacity(),
3360 // stream_writable(), stream_send(), ... is next called.
3361 //
3362 // Note that we can't use `is_writable()` here because
3363 // it returns false if the stream is stopped. Instead,
3364 // since the stream is marked as writable when a
3365 // STOP_SENDING frame is received, we check the writable
3366 // queue directly instead.
3367 let is_writable = priority_key.writable.is_linked() &&
3368 // Ensure that the stream is actually stopped.
3369 stream.send.is_stopped();
3370
3371 let is_complete = stream.is_complete();
3372 let is_readable = stream.is_readable();
3373
3374 if is_complete && !is_readable && !is_writable {
3375 let local = stream.local;
3376 self.streams.collect(stream_id, local);
3377 }
3378 },
3379
3380 frame::Frame::HandshakeDone => {
3381 // Explicitly set this to true, so that if the frame was
3382 // already scheduled for retransmission, it is aborted.
3383 self.handshake_done_sent = true;
3384
3385 self.handshake_done_acked = true;
3386 },
3387
3388 frame::Frame::ResetStream { stream_id, .. } => {
3389 let stream = match self.streams.get_mut(stream_id) {
3390 Some(v) => v,
3391
3392 None => continue,
3393 };
3394
3395 let priority_key = Arc::clone(&stream.priority_key);
3396
3397 // Only collect the stream if it is complete and not
3398 // readable or writable.
3399 //
3400 // If it is readable, it will get collected when
3401 // stream_recv() is next used.
3402 //
3403 // If it is writable, it might mean that the stream
3404 // has been stopped by the peer (i.e. a STOP_SENDING
3405 // frame is received), in which case before collecting
3406 // the stream we will need to propagate the
3407 // `StreamStopped` error to the application. It will
3408 // instead get collected when one of stream_capacity(),
3409 // stream_writable(), stream_send(), ... is next called.
3410 //
3411 // Note that we can't use `is_writable()` here because
3412 // it returns false if the stream is stopped. Instead,
3413 // since the stream is marked as writable when a
3414 // STOP_SENDING frame is received, we check the writable
3415 // queue directly instead.
3416 let is_writable = priority_key.writable.is_linked() &&
3417 // Ensure that the stream is actually stopped.
3418 stream.send.is_stopped();
3419
3420 let is_complete = stream.is_complete();
3421 let is_readable = stream.is_readable();
3422
3423 if is_complete && !is_readable && !is_writable {
3424 let local = stream.local;
3425 self.streams.collect(stream_id, local);
3426 }
3427 },
3428
3429 _ => (),
3430 }
3431 }
3432 }
3433
3434 // Now that we processed all the frames, if there is a path that has no
3435 // Destination CID, try to allocate one.
3436 let no_dcid = self
3437 .paths
3438 .iter_mut()
3439 .filter(|(_, p)| p.active_dcid_seq.is_none());
3440
3441 for (pid, p) in no_dcid {
3442 if self.ids.zero_length_dcid() {
3443 p.active_dcid_seq = Some(0);
3444 continue;
3445 }
3446
3447 let dcid_seq = match self.ids.lowest_available_dcid_seq() {
3448 Some(seq) => seq,
3449 None => break,
3450 };
3451
3452 self.ids.link_dcid_to_path_id(dcid_seq, pid)?;
3453
3454 p.active_dcid_seq = Some(dcid_seq);
3455 }
3456
3457 // We only record the time of arrival of the largest packet number
3458 // that still needs to be acked, to be used for ACK delay calculation.
3459 if self.pkt_num_spaces[epoch].recv_pkt_need_ack.last() < Some(pn) {
3460 self.pkt_num_spaces[epoch].largest_rx_pkt_time = now;
3461 }
3462
3463 self.pkt_num_spaces[epoch].recv_pkt_num.insert(pn);
3464
3465 self.pkt_num_spaces[epoch].recv_pkt_need_ack.push_item(pn);
3466
3467 self.pkt_num_spaces[epoch].ack_elicited =
3468 cmp::max(self.pkt_num_spaces[epoch].ack_elicited, ack_elicited);
3469
3470 self.pkt_num_spaces[epoch].largest_rx_pkt_num =
3471 cmp::max(self.pkt_num_spaces[epoch].largest_rx_pkt_num, pn);
3472
3473 if !probing {
3474 self.pkt_num_spaces[epoch].largest_rx_non_probing_pkt_num = cmp::max(
3475 self.pkt_num_spaces[epoch].largest_rx_non_probing_pkt_num,
3476 pn,
3477 );
3478
3479 // Did the peer migrated to another path?
3480 let active_path_id = self.paths.get_active_path_id()?;
3481
3482 if self.is_server &&
3483 recv_pid != active_path_id &&
3484 self.pkt_num_spaces[epoch].largest_rx_non_probing_pkt_num == pn
3485 {
3486 self.on_peer_migrated(recv_pid, self.disable_dcid_reuse, now)?;
3487 }
3488 }
3489
3490 if let Some(idle_timeout) = self.idle_timeout() {
3491 self.idle_timer = Some(now + idle_timeout);
3492 }
3493
3494 // Update send capacity.
3495 self.update_tx_cap();
3496
3497 self.recv_count += 1;
3498 self.paths.get_mut(recv_pid)?.recv_count += 1;
3499
3500 let read = b.off() + aead_tag_len;
3501
3502 self.recv_bytes += read as u64;
3503 self.paths.get_mut(recv_pid)?.recv_bytes += read as u64;
3504
3505 // An Handshake packet has been received from the client and has been
3506 // successfully processed, so we can drop the initial state and consider
3507 // the client's address to be verified.
3508 if self.is_server && hdr.ty == Type::Handshake {
3509 self.drop_epoch_state(packet::Epoch::Initial, now);
3510
3511 self.paths.get_mut(recv_pid)?.verified_peer_address = true;
3512 }
3513
3514 self.ack_eliciting_sent = false;
3515
3516 Ok(read)
3517 }
3518
3519 /// Writes a single QUIC packet to be sent to the peer.
3520 ///
3521 /// On success the number of bytes written to the output buffer is
3522 /// returned, or [`Done`] if there was nothing to write.
3523 ///
3524 /// The application should call `send()` multiple times until [`Done`] is
3525 /// returned, indicating that there are no more packets to send. It is
3526 /// recommended that `send()` be called in the following cases:
3527 ///
3528 /// * When the application receives QUIC packets from the peer (that is,
3529 /// any time [`recv()`] is also called).
3530 ///
3531 /// * When the connection timer expires (that is, any time [`on_timeout()`]
3532 /// is also called).
3533 ///
3534 /// * When the application sends data to the peer (for example, any time
3535 /// [`stream_send()`] or [`stream_shutdown()`] are called).
3536 ///
3537 /// * When the application receives data from the peer (for example any
3538 /// time [`stream_recv()`] is called).
3539 ///
3540 /// Once [`is_draining()`] returns `true`, it is no longer necessary to call
3541 /// `send()` and all calls will return [`Done`].
3542 ///
3543 /// [`Done`]: enum.Error.html#variant.Done
3544 /// [`recv()`]: struct.Connection.html#method.recv
3545 /// [`on_timeout()`]: struct.Connection.html#method.on_timeout
3546 /// [`stream_send()`]: struct.Connection.html#method.stream_send
3547 /// [`stream_shutdown()`]: struct.Connection.html#method.stream_shutdown
3548 /// [`stream_recv()`]: struct.Connection.html#method.stream_recv
3549 /// [`is_draining()`]: struct.Connection.html#method.is_draining
3550 ///
3551 /// ## Examples:
3552 ///
3553 /// ```no_run
3554 /// # let mut out = [0; 512];
3555 /// # let socket = std::net::UdpSocket::bind("127.0.0.1:0").unwrap();
3556 /// # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
3557 /// # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
3558 /// # let peer = "127.0.0.1:1234".parse().unwrap();
3559 /// # let local = socket.local_addr().unwrap();
3560 /// # let mut conn = quiche::accept(&scid, None, local, peer, &mut config)?;
3561 /// loop {
3562 /// let (write, send_info) = match conn.send(&mut out) {
3563 /// Ok(v) => v,
3564 ///
3565 /// Err(quiche::Error::Done) => {
3566 /// // Done writing.
3567 /// break;
3568 /// },
3569 ///
3570 /// Err(e) => {
3571 /// // An error occurred, handle it.
3572 /// break;
3573 /// },
3574 /// };
3575 ///
3576 /// socket.send_to(&out[..write], &send_info.to).unwrap();
3577 /// }
3578 /// # Ok::<(), quiche::Error>(())
3579 /// ```
3580 pub fn send(&mut self, out: &mut [u8]) -> Result<(usize, SendInfo)> {
3581 self.send_on_path(out, None, None)
3582 }
3583
3584 /// Writes a single QUIC packet to be sent to the peer from the specified
3585 /// local address `from` to the destination address `to`.
3586 ///
3587 /// The behavior of this method differs depending on the value of the `from`
3588 /// and `to` parameters:
3589 ///
3590 /// * If both are `Some`, then the method only consider the 4-tuple
3591 /// (`from`, `to`). Application can monitor the 4-tuple availability,
3592 /// either by monitoring [`path_event_next()`] events or by relying on
3593 /// the [`paths_iter()`] method. If the provided 4-tuple does not exist
3594 /// on the connection (anymore), it returns an [`InvalidState`].
3595 ///
3596 /// * If `from` is `Some` and `to` is `None`, then the method only
3597 /// considers sending packets on paths having `from` as local address.
3598 ///
3599 /// * If `to` is `Some` and `from` is `None`, then the method only
3600 /// considers sending packets on paths having `to` as peer address.
3601 ///
3602 /// * If both are `None`, all available paths are considered.
3603 ///
3604 /// On success the number of bytes written to the output buffer is
3605 /// returned, or [`Done`] if there was nothing to write.
3606 ///
3607 /// The application should call `send_on_path()` multiple times until
3608 /// [`Done`] is returned, indicating that there are no more packets to
3609 /// send. It is recommended that `send_on_path()` be called in the
3610 /// following cases:
3611 ///
3612 /// * When the application receives QUIC packets from the peer (that is,
3613 /// any time [`recv()`] is also called).
3614 ///
3615 /// * When the connection timer expires (that is, any time [`on_timeout()`]
3616 /// is also called).
3617 ///
3618 /// * When the application sends data to the peer (for examples, any time
3619 /// [`stream_send()`] or [`stream_shutdown()`] are called).
3620 ///
3621 /// * When the application receives data from the peer (for example any
3622 /// time [`stream_recv()`] is called).
3623 ///
3624 /// Once [`is_draining()`] returns `true`, it is no longer necessary to call
3625 /// `send_on_path()` and all calls will return [`Done`].
3626 ///
3627 /// [`Done`]: enum.Error.html#variant.Done
3628 /// [`InvalidState`]: enum.Error.html#InvalidState
3629 /// [`recv()`]: struct.Connection.html#method.recv
3630 /// [`on_timeout()`]: struct.Connection.html#method.on_timeout
3631 /// [`stream_send()`]: struct.Connection.html#method.stream_send
3632 /// [`stream_shutdown()`]: struct.Connection.html#method.stream_shutdown
3633 /// [`stream_recv()`]: struct.Connection.html#method.stream_recv
3634 /// [`path_event_next()`]: struct.Connection.html#method.path_event_next
3635 /// [`paths_iter()`]: struct.Connection.html#method.paths_iter
3636 /// [`is_draining()`]: struct.Connection.html#method.is_draining
3637 ///
3638 /// ## Examples:
3639 ///
3640 /// ```no_run
3641 /// # let mut out = [0; 512];
3642 /// # let socket = std::net::UdpSocket::bind("127.0.0.1:0").unwrap();
3643 /// # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
3644 /// # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
3645 /// # let peer = "127.0.0.1:1234".parse().unwrap();
3646 /// # let local = socket.local_addr().unwrap();
3647 /// # let mut conn = quiche::accept(&scid, None, local, peer, &mut config)?;
3648 /// loop {
3649 /// let (write, send_info) = match conn.send_on_path(&mut out, Some(local), Some(peer)) {
3650 /// Ok(v) => v,
3651 ///
3652 /// Err(quiche::Error::Done) => {
3653 /// // Done writing.
3654 /// break;
3655 /// },
3656 ///
3657 /// Err(e) => {
3658 /// // An error occurred, handle it.
3659 /// break;
3660 /// },
3661 /// };
3662 ///
3663 /// socket.send_to(&out[..write], &send_info.to).unwrap();
3664 /// }
3665 /// # Ok::<(), quiche::Error>(())
3666 /// ```
3667 pub fn send_on_path(
3668 &mut self, out: &mut [u8], from: Option<SocketAddr>,
3669 to: Option<SocketAddr>,
3670 ) -> Result<(usize, SendInfo)> {
3671 if out.is_empty() {
3672 return Err(Error::BufferTooShort);
3673 }
3674
3675 if self.is_closed() || self.is_draining() {
3676 return Err(Error::Done);
3677 }
3678
3679 let now = Instant::now();
3680
3681 if self.local_error.is_none() {
3682 self.do_handshake(now)?;
3683 }
3684
3685 // Forwarding the error value here could confuse
3686 // applications, as they may not expect getting a `recv()`
3687 // error when calling `send()`.
3688 //
3689 // We simply fall-through to sending packets, which should
3690 // take care of terminating the connection as needed.
3691 let _ = self.process_undecrypted_0rtt_packets();
3692
3693 // There's no point in trying to send a packet if the Initial secrets
3694 // have not been derived yet, so return early.
3695 if !self.derived_initial_secrets {
3696 return Err(Error::Done);
3697 }
3698
3699 let mut has_initial = false;
3700
3701 let mut done = 0;
3702
3703 // Limit output packet size to respect the sender and receiver's
3704 // maximum UDP payload size limit.
3705 let mut left = cmp::min(out.len(), self.max_send_udp_payload_size());
3706
3707 let send_pid = match (from, to) {
3708 (Some(f), Some(t)) => self
3709 .paths
3710 .path_id_from_addrs(&(f, t))
3711 .ok_or(Error::InvalidState)?,
3712
3713 _ => self.get_send_path_id(from, to)?,
3714 };
3715
3716 let send_path = self.paths.get_mut(send_pid)?;
3717
3718 // Update max datagram size to allow path MTU discovery probe to be sent.
3719 if let Some(pmtud) = send_path.pmtud.as_mut() {
3720 if pmtud.should_probe() {
3721 let size = if self.handshake_confirmed || self.handshake_completed
3722 {
3723 pmtud.get_probe_size()
3724 } else {
3725 pmtud.get_current_mtu()
3726 };
3727
3728 send_path.recovery.pmtud_update_max_datagram_size(size);
3729
3730 left =
3731 cmp::min(out.len(), send_path.recovery.max_datagram_size());
3732 }
3733 }
3734
3735 // Limit data sent by the server based on the amount of data received
3736 // from the client before its address is validated.
3737 if !send_path.verified_peer_address && self.is_server {
3738 left = cmp::min(left, send_path.max_send_bytes);
3739 }
3740
3741 // Generate coalesced packets.
3742 while left > 0 {
3743 let (ty, written) = match self.send_single(
3744 &mut out[done..done + left],
3745 send_pid,
3746 has_initial,
3747 now,
3748 ) {
3749 Ok(v) => v,
3750
3751 Err(Error::BufferTooShort) | Err(Error::Done) => break,
3752
3753 Err(e) => return Err(e),
3754 };
3755
3756 done += written;
3757 left -= written;
3758
3759 match ty {
3760 Type::Initial => has_initial = true,
3761
3762 // No more packets can be coalesced after a 1-RTT.
3763 Type::Short => break,
3764
3765 _ => (),
3766 };
3767
3768 // When sending multiple PTO probes, don't coalesce them together,
3769 // so they are sent on separate UDP datagrams.
3770 if let Ok(epoch) = ty.to_epoch() {
3771 if self.paths.get_mut(send_pid)?.recovery.loss_probes(epoch) > 0 {
3772 break;
3773 }
3774 }
3775
3776 // Don't coalesce packets that must go on different paths.
3777 if !(from.is_some() && to.is_some()) &&
3778 self.get_send_path_id(from, to)? != send_pid
3779 {
3780 break;
3781 }
3782 }
3783
3784 if done == 0 {
3785 self.last_tx_data = self.tx_data;
3786
3787 return Err(Error::Done);
3788 }
3789
3790 if has_initial && left > 0 && done < MIN_CLIENT_INITIAL_LEN {
3791 let pad_len = cmp::min(left, MIN_CLIENT_INITIAL_LEN - done);
3792
3793 // Fill padding area with null bytes, to avoid leaking information
3794 // in case the application reuses the packet buffer.
3795 out[done..done + pad_len].fill(0);
3796
3797 done += pad_len;
3798 }
3799
3800 let send_path = self.paths.get(send_pid)?;
3801
3802 let info = SendInfo {
3803 from: send_path.local_addr(),
3804 to: send_path.peer_addr(),
3805
3806 at: send_path.recovery.get_packet_send_time(now),
3807 };
3808
3809 Ok((done, info))
3810 }
3811
3812 fn send_single(
3813 &mut self, out: &mut [u8], send_pid: usize, has_initial: bool,
3814 now: Instant,
3815 ) -> Result<(Type, usize)> {
3816 if out.is_empty() {
3817 return Err(Error::BufferTooShort);
3818 }
3819
3820 if self.is_draining() {
3821 return Err(Error::Done);
3822 }
3823
3824 let is_closing = self.local_error.is_some();
3825
3826 let out_len = out.len();
3827
3828 let mut b = octets::OctetsMut::with_slice(out);
3829
3830 let pkt_type = self.write_pkt_type(send_pid)?;
3831
3832 let max_dgram_len = if !self.dgram_send_queue.is_empty() {
3833 self.dgram_max_writable_len()
3834 } else {
3835 None
3836 };
3837
3838 let epoch = pkt_type.to_epoch()?;
3839 let pkt_space = &mut self.pkt_num_spaces[epoch];
3840 let crypto_ctx = &mut self.crypto_ctx[epoch];
3841
3842 // Process lost frames. There might be several paths having lost frames.
3843 for (_, p) in self.paths.iter_mut() {
3844 while let Some(lost) = p.recovery.next_lost_frame(epoch) {
3845 match lost {
3846 frame::Frame::CryptoHeader { offset, length } => {
3847 crypto_ctx.crypto_stream.send.retransmit(offset, length);
3848
3849 self.stream_retrans_bytes += length as u64;
3850 p.stream_retrans_bytes += length as u64;
3851
3852 self.retrans_count += 1;
3853 p.retrans_count += 1;
3854 },
3855
3856 frame::Frame::StreamHeader {
3857 stream_id,
3858 offset,
3859 length,
3860 fin,
3861 } => {
3862 let stream = match self.streams.get_mut(stream_id) {
3863 // Only retransmit data if the stream is not closed
3864 // or stopped.
3865 Some(v) if !v.send.is_stopped() => v,
3866
3867 // Data on a closed stream will not be retransmitted
3868 // or acked after it is declared lost, so update
3869 // tx_buffered and qlog.
3870 _ => {
3871 self.tx_buffered =
3872 self.tx_buffered.saturating_sub(length);
3873
3874 qlog_with_type!(QLOG_DATA_MV, self.qlog, q, {
3875 let ev_data = EventData::DataMoved(
3876 qlog::events::quic::DataMoved {
3877 stream_id: Some(stream_id),
3878 offset: Some(offset),
3879 length: Some(length as u64),
3880 from: Some(DataRecipient::Transport),
3881 to: Some(DataRecipient::Dropped),
3882 ..Default::default()
3883 },
3884 );
3885
3886 q.add_event_data_with_instant(ev_data, now)
3887 .ok();
3888 });
3889
3890 continue;
3891 },
3892 };
3893
3894 let was_flushable = stream.is_flushable();
3895
3896 let empty_fin = length == 0 && fin;
3897
3898 stream.send.retransmit(offset, length);
3899
3900 // If the stream is now flushable push it to the
3901 // flushable queue, but only if it wasn't already
3902 // queued.
3903 //
3904 // Consider the stream flushable also when we are
3905 // sending a zero-length frame that has the fin flag
3906 // set.
3907 if (stream.is_flushable() || empty_fin) && !was_flushable
3908 {
3909 let priority_key = Arc::clone(&stream.priority_key);
3910 self.streams.insert_flushable(&priority_key);
3911 }
3912
3913 self.stream_retrans_bytes += length as u64;
3914 p.stream_retrans_bytes += length as u64;
3915
3916 self.retrans_count += 1;
3917 p.retrans_count += 1;
3918 },
3919
3920 frame::Frame::ACK { .. } => {
3921 pkt_space.ack_elicited = true;
3922 },
3923
3924 frame::Frame::ResetStream {
3925 stream_id,
3926 error_code,
3927 final_size,
3928 } =>
3929 if self.streams.get(stream_id).is_some() {
3930 self.streams
3931 .insert_reset(stream_id, error_code, final_size);
3932 },
3933
3934 // Retransmit HANDSHAKE_DONE only if it hasn't been acked at
3935 // least once already.
3936 frame::Frame::HandshakeDone if !self.handshake_done_acked => {
3937 self.handshake_done_sent = false;
3938 },
3939
3940 frame::Frame::MaxStreamData { stream_id, .. } => {
3941 if self.streams.get(stream_id).is_some() {
3942 self.streams.insert_almost_full(stream_id);
3943 }
3944 },
3945
3946 frame::Frame::MaxData { .. } => {
3947 self.almost_full = true;
3948 },
3949
3950 frame::Frame::NewConnectionId { seq_num, .. } => {
3951 self.ids.mark_advertise_new_scid_seq(seq_num, true);
3952 },
3953
3954 frame::Frame::RetireConnectionId { seq_num } => {
3955 self.ids.mark_retire_dcid_seq(seq_num, true)?;
3956 },
3957
3958 frame::Frame::Ping {
3959 mtu_probe: Some(failed_probe),
3960 } =>
3961 if let Some(pmtud) = p.pmtud.as_mut() {
3962 trace!("pmtud probe dropped: {failed_probe}");
3963 pmtud.failed_probe(failed_probe);
3964 },
3965
3966 _ => (),
3967 }
3968 }
3969 }
3970 self.check_tx_buffered_invariant();
3971
3972 let is_app_limited = self.delivery_rate_check_if_app_limited();
3973 let n_paths = self.paths.len();
3974 let path = self.paths.get_mut(send_pid)?;
3975 let flow_control = &mut self.flow_control;
3976 let pkt_space = &mut self.pkt_num_spaces[epoch];
3977 let crypto_ctx = &mut self.crypto_ctx[epoch];
3978 let pkt_num_manager = &mut self.pkt_num_manager;
3979
3980 let mut left = if let Some(pmtud) = path.pmtud.as_mut() {
3981 // Limit output buffer size by estimated path MTU.
3982 cmp::min(pmtud.get_current_mtu(), b.cap())
3983 } else {
3984 b.cap()
3985 };
3986
3987 if pkt_num_manager.should_skip_pn(self.handshake_completed) {
3988 pkt_num_manager.set_skip_pn(Some(self.next_pkt_num));
3989 self.next_pkt_num += 1;
3990 };
3991 let pn = self.next_pkt_num;
3992
3993 let largest_acked_pkt =
3994 path.recovery.get_largest_acked_on_epoch(epoch).unwrap_or(0);
3995 let pn_len = packet::pkt_num_len(pn, largest_acked_pkt);
3996
3997 // The AEAD overhead at the current encryption level.
3998 let crypto_overhead = crypto_ctx.crypto_overhead().ok_or(Error::Done)?;
3999
4000 let dcid_seq = path.active_dcid_seq.ok_or(Error::OutOfIdentifiers)?;
4001
4002 let dcid =
4003 ConnectionId::from_ref(self.ids.get_dcid(dcid_seq)?.cid.as_ref());
4004
4005 let scid = if let Some(scid_seq) = path.active_scid_seq {
4006 ConnectionId::from_ref(self.ids.get_scid(scid_seq)?.cid.as_ref())
4007 } else if pkt_type == Type::Short {
4008 ConnectionId::default()
4009 } else {
4010 return Err(Error::InvalidState);
4011 };
4012
4013 let hdr = Header {
4014 ty: pkt_type,
4015
4016 version: self.version,
4017
4018 dcid,
4019 scid,
4020
4021 pkt_num: 0,
4022 pkt_num_len: pn_len,
4023
4024 // Only clone token for Initial packets, as other packets don't have
4025 // this field (Retry doesn't count, as it's not encoded as part of
4026 // this code path).
4027 token: if pkt_type == Type::Initial {
4028 self.token.clone()
4029 } else {
4030 None
4031 },
4032
4033 versions: None,
4034 key_phase: self.key_phase,
4035 };
4036
4037 hdr.to_bytes(&mut b)?;
4038
4039 let hdr_trace = if log::max_level() == log::LevelFilter::Trace {
4040 Some(format!("{hdr:?}"))
4041 } else {
4042 None
4043 };
4044
4045 let hdr_ty = hdr.ty;
4046
4047 #[cfg(feature = "qlog")]
4048 let qlog_pkt_hdr = self.qlog.streamer.as_ref().map(|_q| {
4049 qlog::events::quic::PacketHeader::with_type(
4050 hdr.ty.to_qlog(),
4051 Some(pn),
4052 Some(hdr.version),
4053 Some(&hdr.scid),
4054 Some(&hdr.dcid),
4055 )
4056 });
4057
4058 // Calculate the space required for the packet, including the header
4059 // the payload length, the packet number and the AEAD overhead.
4060 let mut overhead = b.off() + pn_len + crypto_overhead;
4061
4062 // We assume that the payload length, which is only present in long
4063 // header packets, can always be encoded with a 2-byte varint.
4064 if pkt_type != Type::Short {
4065 overhead += PAYLOAD_LENGTH_LEN;
4066 }
4067
4068 // Make sure we have enough space left for the packet overhead.
4069 match left.checked_sub(overhead) {
4070 Some(v) => left = v,
4071
4072 None => {
4073 // We can't send more because there isn't enough space available
4074 // in the output buffer.
4075 //
4076 // This usually happens when we try to send a new packet but
4077 // failed because cwnd is almost full. In such case app_limited
4078 // is set to false here to make cwnd grow when ACK is received.
4079 path.recovery.update_app_limited(false);
4080 return Err(Error::Done);
4081 },
4082 }
4083
4084 // Make sure there is enough space for the minimum payload length.
4085 if left < PAYLOAD_MIN_LEN {
4086 path.recovery.update_app_limited(false);
4087 return Err(Error::Done);
4088 }
4089
4090 let mut frames: SmallVec<[frame::Frame; 1]> = SmallVec::new();
4091
4092 let mut ack_eliciting = false;
4093 let mut in_flight = false;
4094 let mut is_pmtud_probe = false;
4095 let mut has_data = false;
4096
4097 // Whether or not we should explicitly elicit an ACK via PING frame if we
4098 // implicitly elicit one otherwise.
4099 let ack_elicit_required = path.recovery.should_elicit_ack(epoch);
4100
4101 let header_offset = b.off();
4102
4103 // Reserve space for payload length in advance. Since we don't yet know
4104 // what the final length will be, we reserve 2 bytes in all cases.
4105 //
4106 // Only long header packets have an explicit length field.
4107 if pkt_type != Type::Short {
4108 b.skip(PAYLOAD_LENGTH_LEN)?;
4109 }
4110
4111 packet::encode_pkt_num(pn, pn_len, &mut b)?;
4112
4113 let payload_offset = b.off();
4114
4115 let cwnd_available =
4116 path.recovery.cwnd_available().saturating_sub(overhead);
4117
4118 let left_before_packing_ack_frame = left;
4119
4120 // Create ACK frame.
4121 //
4122 // When we need to explicitly elicit an ACK via PING later, go ahead and
4123 // generate an ACK (if there's anything to ACK) since we're going to
4124 // send a packet with PING anyways, even if we haven't received anything
4125 // ACK eliciting.
4126 if pkt_space.recv_pkt_need_ack.len() > 0 &&
4127 (pkt_space.ack_elicited || ack_elicit_required) &&
4128 (!is_closing ||
4129 (pkt_type == Type::Handshake &&
4130 self.local_error
4131 .as_ref()
4132 .is_some_and(|le| le.is_app))) &&
4133 path.active()
4134 {
4135 #[cfg(not(feature = "fuzzing"))]
4136 let ack_delay = pkt_space.largest_rx_pkt_time.elapsed();
4137
4138 #[cfg(not(feature = "fuzzing"))]
4139 let ack_delay = ack_delay.as_micros() as u64 /
4140 2_u64
4141 .pow(self.local_transport_params.ack_delay_exponent as u32);
4142
4143 // pseudo-random reproducible ack delays when fuzzing
4144 #[cfg(feature = "fuzzing")]
4145 let ack_delay = rand::rand_u8() as u64 + 1;
4146
4147 let frame = frame::Frame::ACK {
4148 ack_delay,
4149 ranges: pkt_space.recv_pkt_need_ack.clone(),
4150 ecn_counts: None, // sending ECN is not supported at this time
4151 };
4152
4153 // When a PING frame needs to be sent, avoid sending the ACK if
4154 // there is not enough cwnd available for both (note that PING
4155 // frames are always 1 byte, so we just need to check that the
4156 // ACK's length is lower than cwnd).
4157 if pkt_space.ack_elicited || frame.wire_len() < cwnd_available {
4158 // ACK-only packets are not congestion controlled so ACKs must
4159 // be bundled considering the buffer capacity only, and not the
4160 // available cwnd.
4161 if push_frame_to_pkt!(b, frames, frame, left) {
4162 pkt_space.ack_elicited = false;
4163 }
4164 }
4165 }
4166
4167 // Limit output packet size by congestion window size.
4168 left = cmp::min(
4169 left,
4170 // Bytes consumed by ACK frames.
4171 cwnd_available.saturating_sub(left_before_packing_ack_frame - left),
4172 );
4173
4174 let mut challenge_data = None;
4175
4176 let active_path = self.paths.get_active_mut()?;
4177
4178 if pkt_type == Type::Short {
4179 // Create PMTUD probe.
4180 //
4181 // In order to send a PMTUD probe the current `left` value, which was
4182 // already limited by the current PMTU measure, needs to be ignored,
4183 // but the outgoing packet still needs to be limited by
4184 // the output buffer size, as well as the congestion
4185 // window.
4186 //
4187 // In addition, the PMTUD probe is only generated when the handshake
4188 // is confirmed, to avoid interfering with the handshake
4189 // (e.g. due to the anti-amplification limits).
4190 let should_probe_pmtu = active_path.should_send_pmtu_probe(
4191 self.handshake_confirmed,
4192 self.handshake_completed,
4193 out_len,
4194 is_closing,
4195 frames.is_empty(),
4196 );
4197
4198 if should_probe_pmtu {
4199 if let Some(pmtud) = active_path.pmtud.as_mut() {
4200 let probe_size = pmtud.get_probe_size();
4201 trace!(
4202 "{} sending pmtud probe pmtu_probe={} estimated_pmtu={}",
4203 self.trace_id,
4204 probe_size,
4205 pmtud.get_current_mtu(),
4206 );
4207
4208 left = probe_size;
4209
4210 match left.checked_sub(overhead) {
4211 Some(v) => left = v,
4212
4213 None => {
4214 // We can't send more because there isn't enough space
4215 // available in the output buffer.
4216 //
4217 // This usually happens when we try to send a new
4218 // packet but failed
4219 // because cwnd is almost full.
4220 //
4221 // In such case app_limited is set to false here to
4222 // make cwnd grow when ACK
4223 // is received.
4224 active_path.recovery.update_app_limited(false);
4225 return Err(Error::Done);
4226 },
4227 }
4228
4229 let frame = frame::Frame::Padding {
4230 len: probe_size - overhead - 1,
4231 };
4232
4233 if push_frame_to_pkt!(b, frames, frame, left) {
4234 let frame = frame::Frame::Ping {
4235 mtu_probe: Some(probe_size),
4236 };
4237
4238 if push_frame_to_pkt!(b, frames, frame, left) {
4239 ack_eliciting = true;
4240 in_flight = true;
4241 }
4242 }
4243
4244 // Reset probe flag after sending to prevent duplicate probes
4245 // in a single flight.
4246 pmtud.set_in_flight(true);
4247 is_pmtud_probe = true;
4248 }
4249 }
4250
4251 let path = self.paths.get_mut(send_pid)?;
4252 // Create PATH_RESPONSE frame if needed.
4253 // We do not try to ensure that these are really sent.
4254 while let Some(challenge) = path.pop_received_challenge() {
4255 let frame = frame::Frame::PathResponse { data: challenge };
4256
4257 if push_frame_to_pkt!(b, frames, frame, left) {
4258 ack_eliciting = true;
4259 in_flight = true;
4260 } else {
4261 // If there are other pending PATH_RESPONSE, don't lose them
4262 // now.
4263 break;
4264 }
4265 }
4266
4267 // Create PATH_CHALLENGE frame if needed.
4268 if path.validation_requested() {
4269 // TODO: ensure that data is unique over paths.
4270 let data = rand::rand_u64().to_be_bytes();
4271
4272 let frame = frame::Frame::PathChallenge { data };
4273
4274 if push_frame_to_pkt!(b, frames, frame, left) {
4275 // Let's notify the path once we know the packet size.
4276 challenge_data = Some(data);
4277
4278 ack_eliciting = true;
4279 in_flight = true;
4280 }
4281 }
4282
4283 if let Some(key_update) = crypto_ctx.key_update.as_mut() {
4284 key_update.update_acked = true;
4285 }
4286 }
4287
4288 let path = self.paths.get_mut(send_pid)?;
4289
4290 if pkt_type == Type::Short && !is_closing {
4291 // Create NEW_CONNECTION_ID frames as needed.
4292 while let Some(seq_num) = self.ids.next_advertise_new_scid_seq() {
4293 let frame = self.ids.get_new_connection_id_frame_for(seq_num)?;
4294
4295 if push_frame_to_pkt!(b, frames, frame, left) {
4296 self.ids.mark_advertise_new_scid_seq(seq_num, false);
4297
4298 ack_eliciting = true;
4299 in_flight = true;
4300 } else {
4301 break;
4302 }
4303 }
4304 }
4305
4306 if pkt_type == Type::Short && !is_closing && path.active() {
4307 // Create HANDSHAKE_DONE frame.
4308 // self.should_send_handshake_done() but without the need to borrow
4309 if self.handshake_completed &&
4310 !self.handshake_done_sent &&
4311 self.is_server
4312 {
4313 let frame = frame::Frame::HandshakeDone;
4314
4315 if push_frame_to_pkt!(b, frames, frame, left) {
4316 self.handshake_done_sent = true;
4317
4318 ack_eliciting = true;
4319 in_flight = true;
4320 }
4321 }
4322
4323 // Create MAX_STREAMS_BIDI frame.
4324 if self.streams.should_update_max_streams_bidi() {
4325 let frame = frame::Frame::MaxStreamsBidi {
4326 max: self.streams.max_streams_bidi_next(),
4327 };
4328
4329 if push_frame_to_pkt!(b, frames, frame, left) {
4330 self.streams.update_max_streams_bidi();
4331
4332 ack_eliciting = true;
4333 in_flight = true;
4334 }
4335 }
4336
4337 // Create MAX_STREAMS_UNI frame.
4338 if self.streams.should_update_max_streams_uni() {
4339 let frame = frame::Frame::MaxStreamsUni {
4340 max: self.streams.max_streams_uni_next(),
4341 };
4342
4343 if push_frame_to_pkt!(b, frames, frame, left) {
4344 self.streams.update_max_streams_uni();
4345
4346 ack_eliciting = true;
4347 in_flight = true;
4348 }
4349 }
4350
4351 // Create DATA_BLOCKED frame.
4352 if let Some(limit) = self.blocked_limit {
4353 let frame = frame::Frame::DataBlocked { limit };
4354
4355 if push_frame_to_pkt!(b, frames, frame, left) {
4356 self.blocked_limit = None;
4357 self.data_blocked_sent_count =
4358 self.data_blocked_sent_count.saturating_add(1);
4359
4360 ack_eliciting = true;
4361 in_flight = true;
4362 }
4363 }
4364
4365 // Create MAX_STREAM_DATA frames as needed.
4366 for stream_id in self.streams.almost_full() {
4367 let stream = match self.streams.get_mut(stream_id) {
4368 Some(v) => v,
4369
4370 None => {
4371 // The stream doesn't exist anymore, so remove it from
4372 // the almost full set.
4373 self.streams.remove_almost_full(stream_id);
4374 continue;
4375 },
4376 };
4377
4378 // Autotune the stream window size.
4379 stream.recv.autotune_window(now, path.recovery.rtt());
4380
4381 let frame = frame::Frame::MaxStreamData {
4382 stream_id,
4383 max: stream.recv.max_data_next(),
4384 };
4385
4386 if push_frame_to_pkt!(b, frames, frame, left) {
4387 let recv_win = stream.recv.window();
4388
4389 stream.recv.update_max_data(now);
4390
4391 self.streams.remove_almost_full(stream_id);
4392
4393 ack_eliciting = true;
4394 in_flight = true;
4395
4396 // Make sure the connection window always has some
4397 // room compared to the stream window.
4398 flow_control.ensure_window_lower_bound(
4399 (recv_win as f64 * CONNECTION_WINDOW_FACTOR) as u64,
4400 );
4401
4402 // Also send MAX_DATA when MAX_STREAM_DATA is sent, to avoid a
4403 // potential race condition.
4404 self.almost_full = true;
4405 }
4406 }
4407
4408 // Create MAX_DATA frame as needed.
4409 if self.almost_full &&
4410 flow_control.max_data() < flow_control.max_data_next()
4411 {
4412 // Autotune the connection window size.
4413 flow_control.autotune_window(now, path.recovery.rtt());
4414
4415 let frame = frame::Frame::MaxData {
4416 max: flow_control.max_data_next(),
4417 };
4418
4419 if push_frame_to_pkt!(b, frames, frame, left) {
4420 self.almost_full = false;
4421
4422 // Commits the new max_rx_data limit.
4423 flow_control.update_max_data(now);
4424
4425 ack_eliciting = true;
4426 in_flight = true;
4427 }
4428 }
4429
4430 // Create STOP_SENDING frames as needed.
4431 for (stream_id, error_code) in self
4432 .streams
4433 .stopped()
4434 .map(|(&k, &v)| (k, v))
4435 .collect::<Vec<(u64, u64)>>()
4436 {
4437 let frame = frame::Frame::StopSending {
4438 stream_id,
4439 error_code,
4440 };
4441
4442 if push_frame_to_pkt!(b, frames, frame, left) {
4443 self.streams.remove_stopped(stream_id);
4444
4445 ack_eliciting = true;
4446 in_flight = true;
4447 }
4448 }
4449
4450 // Create RESET_STREAM frames as needed.
4451 for (stream_id, (error_code, final_size)) in self
4452 .streams
4453 .reset()
4454 .map(|(&k, &v)| (k, v))
4455 .collect::<Vec<(u64, (u64, u64))>>()
4456 {
4457 let frame = frame::Frame::ResetStream {
4458 stream_id,
4459 error_code,
4460 final_size,
4461 };
4462
4463 if push_frame_to_pkt!(b, frames, frame, left) {
4464 self.streams.remove_reset(stream_id);
4465
4466 ack_eliciting = true;
4467 in_flight = true;
4468 }
4469 }
4470
4471 // Create STREAM_DATA_BLOCKED frames as needed.
4472 for (stream_id, limit) in self
4473 .streams
4474 .blocked()
4475 .map(|(&k, &v)| (k, v))
4476 .collect::<Vec<(u64, u64)>>()
4477 {
4478 let frame = frame::Frame::StreamDataBlocked { stream_id, limit };
4479
4480 if push_frame_to_pkt!(b, frames, frame, left) {
4481 self.streams.remove_blocked(stream_id);
4482 self.stream_data_blocked_sent_count =
4483 self.stream_data_blocked_sent_count.saturating_add(1);
4484
4485 ack_eliciting = true;
4486 in_flight = true;
4487 }
4488 }
4489
4490 // Create RETIRE_CONNECTION_ID frames as needed.
4491 let retire_dcid_seqs = self.ids.retire_dcid_seqs();
4492
4493 for seq_num in retire_dcid_seqs {
4494 // The sequence number specified in a RETIRE_CONNECTION_ID frame
4495 // MUST NOT refer to the Destination Connection ID field of the
4496 // packet in which the frame is contained.
4497 let dcid_seq = path.active_dcid_seq.ok_or(Error::InvalidState)?;
4498
4499 if seq_num == dcid_seq {
4500 continue;
4501 }
4502
4503 let frame = frame::Frame::RetireConnectionId { seq_num };
4504
4505 if push_frame_to_pkt!(b, frames, frame, left) {
4506 self.ids.mark_retire_dcid_seq(seq_num, false)?;
4507
4508 ack_eliciting = true;
4509 in_flight = true;
4510 } else {
4511 break;
4512 }
4513 }
4514 }
4515
4516 // Create CONNECTION_CLOSE frame. Try to send this only on the active
4517 // path, unless it is the last one available.
4518 if path.active() || n_paths == 1 {
4519 if let Some(conn_err) = self.local_error.as_ref() {
4520 if conn_err.is_app {
4521 // Create ApplicationClose frame.
4522 if pkt_type == Type::Short {
4523 let frame = frame::Frame::ApplicationClose {
4524 error_code: conn_err.error_code,
4525 reason: conn_err.reason.clone(),
4526 };
4527
4528 if push_frame_to_pkt!(b, frames, frame, left) {
4529 let pto = path.recovery.pto();
4530 self.draining_timer = Some(now + (pto * 3));
4531
4532 ack_eliciting = true;
4533 in_flight = true;
4534 }
4535 }
4536 } else {
4537 // Create ConnectionClose frame.
4538 let frame = frame::Frame::ConnectionClose {
4539 error_code: conn_err.error_code,
4540 frame_type: 0,
4541 reason: conn_err.reason.clone(),
4542 };
4543
4544 if push_frame_to_pkt!(b, frames, frame, left) {
4545 let pto = path.recovery.pto();
4546 self.draining_timer = Some(now + (pto * 3));
4547
4548 ack_eliciting = true;
4549 in_flight = true;
4550 }
4551 }
4552 }
4553 }
4554
4555 // Create CRYPTO frame.
4556 if crypto_ctx.crypto_stream.is_flushable() &&
4557 left > frame::MAX_CRYPTO_OVERHEAD &&
4558 !is_closing &&
4559 path.active()
4560 {
4561 let crypto_off = crypto_ctx.crypto_stream.send.off_front();
4562
4563 // Encode the frame.
4564 //
4565 // Instead of creating a `frame::Frame` object, encode the frame
4566 // directly into the packet buffer.
4567 //
4568 // First we reserve some space in the output buffer for writing the
4569 // frame header (we assume the length field is always a 2-byte
4570 // varint as we don't know the value yet).
4571 //
4572 // Then we emit the data from the crypto stream's send buffer.
4573 //
4574 // Finally we go back and encode the frame header with the now
4575 // available information.
4576 let hdr_off = b.off();
4577 let hdr_len = 1 + // frame type
4578 octets::varint_len(crypto_off) + // offset
4579 2; // length, always encode as 2-byte varint
4580
4581 if let Some(max_len) = left.checked_sub(hdr_len) {
4582 let (mut crypto_hdr, mut crypto_payload) =
4583 b.split_at(hdr_off + hdr_len)?;
4584
4585 // Write stream data into the packet buffer.
4586 let (len, _) = crypto_ctx
4587 .crypto_stream
4588 .send
4589 .emit(&mut crypto_payload.as_mut()[..max_len])?;
4590
4591 // Encode the frame's header.
4592 //
4593 // Due to how `OctetsMut::split_at()` works, `crypto_hdr` starts
4594 // from the initial offset of `b` (rather than the current
4595 // offset), so it needs to be advanced to the
4596 // initial frame offset.
4597 crypto_hdr.skip(hdr_off)?;
4598
4599 frame::encode_crypto_header(
4600 crypto_off,
4601 len as u64,
4602 &mut crypto_hdr,
4603 )?;
4604
4605 // Advance the packet buffer's offset.
4606 b.skip(hdr_len + len)?;
4607
4608 let frame = frame::Frame::CryptoHeader {
4609 offset: crypto_off,
4610 length: len,
4611 };
4612
4613 if push_frame_to_pkt!(b, frames, frame, left) {
4614 ack_eliciting = true;
4615 in_flight = true;
4616 has_data = true;
4617 }
4618 }
4619 }
4620
4621 // The preference of data-bearing frame to include in a packet
4622 // is managed by `self.emit_dgram`. However, whether any frames
4623 // can be sent depends on the state of their buffers. In the case
4624 // where one type is preferred but its buffer is empty, fall back
4625 // to the other type in order not to waste this function call.
4626 let mut dgram_emitted = false;
4627 let dgrams_to_emit = max_dgram_len.is_some();
4628 let stream_to_emit = self.streams.has_flushable();
4629
4630 let mut do_dgram = self.emit_dgram && dgrams_to_emit;
4631 let do_stream = !self.emit_dgram && stream_to_emit;
4632
4633 if !do_stream && dgrams_to_emit {
4634 do_dgram = true;
4635 }
4636
4637 // Create DATAGRAM frame.
4638 if (pkt_type == Type::Short || pkt_type == Type::ZeroRTT) &&
4639 left > frame::MAX_DGRAM_OVERHEAD &&
4640 !is_closing &&
4641 path.active() &&
4642 do_dgram
4643 {
4644 if let Some(max_dgram_payload) = max_dgram_len {
4645 while let Some(len) = self.dgram_send_queue.peek_front_len() {
4646 let hdr_off = b.off();
4647 let hdr_len = 1 + // frame type
4648 2; // length, always encode as 2-byte varint
4649
4650 if (hdr_len + len) <= left {
4651 // Front of the queue fits this packet, send it.
4652 match self.dgram_send_queue.pop() {
4653 Some(data) => {
4654 // Encode the frame.
4655 //
4656 // Instead of creating a `frame::Frame` object,
4657 // encode the frame directly into the packet
4658 // buffer.
4659 //
4660 // First we reserve some space in the output
4661 // buffer for writing the frame header (we
4662 // assume the length field is always a 2-byte
4663 // varint as we don't know the value yet).
4664 //
4665 // Then we emit the data from the DATAGRAM's
4666 // buffer.
4667 //
4668 // Finally we go back and encode the frame
4669 // header with the now available information.
4670 let (mut dgram_hdr, mut dgram_payload) =
4671 b.split_at(hdr_off + hdr_len)?;
4672
4673 dgram_payload.as_mut()[..len]
4674 .copy_from_slice(&data);
4675
4676 // Encode the frame's header.
4677 //
4678 // Due to how `OctetsMut::split_at()` works,
4679 // `dgram_hdr` starts from the initial offset
4680 // of `b` (rather than the current offset), so
4681 // it needs to be advanced to the initial frame
4682 // offset.
4683 dgram_hdr.skip(hdr_off)?;
4684
4685 frame::encode_dgram_header(
4686 len as u64,
4687 &mut dgram_hdr,
4688 )?;
4689
4690 // Advance the packet buffer's offset.
4691 b.skip(hdr_len + len)?;
4692
4693 let frame =
4694 frame::Frame::DatagramHeader { length: len };
4695
4696 if push_frame_to_pkt!(b, frames, frame, left) {
4697 ack_eliciting = true;
4698 in_flight = true;
4699 dgram_emitted = true;
4700 self.dgram_sent_count =
4701 self.dgram_sent_count.saturating_add(1);
4702 path.dgram_sent_count =
4703 path.dgram_sent_count.saturating_add(1);
4704 }
4705 },
4706
4707 None => continue,
4708 };
4709 } else if len > max_dgram_payload {
4710 // This dgram frame will never fit. Let's purge it.
4711 self.dgram_send_queue.pop();
4712 } else {
4713 break;
4714 }
4715 }
4716 }
4717 }
4718
4719 // Create a single STREAM frame for the first stream that is flushable.
4720 if (pkt_type == Type::Short || pkt_type == Type::ZeroRTT) &&
4721 left > frame::MAX_STREAM_OVERHEAD &&
4722 !is_closing &&
4723 path.active() &&
4724 !dgram_emitted
4725 {
4726 while let Some(priority_key) = self.streams.peek_flushable() {
4727 let stream_id = priority_key.id;
4728 let stream = match self.streams.get_mut(stream_id) {
4729 // Avoid sending frames for streams that were already stopped.
4730 //
4731 // This might happen if stream data was buffered but not yet
4732 // flushed on the wire when a STOP_SENDING frame is received.
4733 Some(v) if !v.send.is_stopped() => v,
4734 _ => {
4735 self.streams.remove_flushable(&priority_key);
4736 continue;
4737 },
4738 };
4739
4740 let stream_off = stream.send.off_front();
4741
4742 // Encode the frame.
4743 //
4744 // Instead of creating a `frame::Frame` object, encode the frame
4745 // directly into the packet buffer.
4746 //
4747 // First we reserve some space in the output buffer for writing
4748 // the frame header (we assume the length field is always a
4749 // 2-byte varint as we don't know the value yet).
4750 //
4751 // Then we emit the data from the stream's send buffer.
4752 //
4753 // Finally we go back and encode the frame header with the now
4754 // available information.
4755 let hdr_off = b.off();
4756 let hdr_len = 1 + // frame type
4757 octets::varint_len(stream_id) + // stream_id
4758 octets::varint_len(stream_off) + // offset
4759 2; // length, always encode as 2-byte varint
4760
4761 let max_len = match left.checked_sub(hdr_len) {
4762 Some(v) => v,
4763 None => {
4764 let priority_key = Arc::clone(&stream.priority_key);
4765 self.streams.remove_flushable(&priority_key);
4766
4767 continue;
4768 },
4769 };
4770
4771 let (mut stream_hdr, mut stream_payload) =
4772 b.split_at(hdr_off + hdr_len)?;
4773
4774 // Write stream data into the packet buffer.
4775 let (len, fin) =
4776 stream.send.emit(&mut stream_payload.as_mut()[..max_len])?;
4777
4778 // Encode the frame's header.
4779 //
4780 // Due to how `OctetsMut::split_at()` works, `stream_hdr` starts
4781 // from the initial offset of `b` (rather than the current
4782 // offset), so it needs to be advanced to the initial frame
4783 // offset.
4784 stream_hdr.skip(hdr_off)?;
4785
4786 frame::encode_stream_header(
4787 stream_id,
4788 stream_off,
4789 len as u64,
4790 fin,
4791 &mut stream_hdr,
4792 )?;
4793
4794 // Advance the packet buffer's offset.
4795 b.skip(hdr_len + len)?;
4796
4797 let frame = frame::Frame::StreamHeader {
4798 stream_id,
4799 offset: stream_off,
4800 length: len,
4801 fin,
4802 };
4803
4804 if push_frame_to_pkt!(b, frames, frame, left) {
4805 ack_eliciting = true;
4806 in_flight = true;
4807 has_data = true;
4808 }
4809
4810 let priority_key = Arc::clone(&stream.priority_key);
4811 // If the stream is no longer flushable, remove it from the queue
4812 if !stream.is_flushable() {
4813 self.streams.remove_flushable(&priority_key);
4814 } else if stream.incremental {
4815 // Shuffle the incremental stream to the back of the
4816 // queue.
4817 self.streams.remove_flushable(&priority_key);
4818 self.streams.insert_flushable(&priority_key);
4819 }
4820
4821 #[cfg(feature = "fuzzing")]
4822 // Coalesce STREAM frames when fuzzing.
4823 if left > frame::MAX_STREAM_OVERHEAD {
4824 continue;
4825 }
4826
4827 break;
4828 }
4829 }
4830
4831 // Alternate trying to send DATAGRAMs next time.
4832 self.emit_dgram = !dgram_emitted;
4833
4834 // If no other ack-eliciting frame is sent, include a PING frame
4835 // - if PTO probe needed; OR
4836 // - if we've sent too many non ack-eliciting packets without having
4837 // sent an ACK eliciting one; OR
4838 // - the application requested an ack-eliciting frame be sent.
4839 if (ack_elicit_required || path.needs_ack_eliciting) &&
4840 !ack_eliciting &&
4841 left >= 1 &&
4842 !is_closing
4843 {
4844 let frame = frame::Frame::Ping { mtu_probe: None };
4845
4846 if push_frame_to_pkt!(b, frames, frame, left) {
4847 ack_eliciting = true;
4848 in_flight = true;
4849 }
4850 }
4851
4852 if ack_eliciting && !is_pmtud_probe {
4853 path.needs_ack_eliciting = false;
4854 path.recovery.ping_sent(epoch);
4855 }
4856
4857 if !has_data &&
4858 !dgram_emitted &&
4859 cwnd_available > frame::MAX_STREAM_OVERHEAD
4860 {
4861 path.recovery.on_app_limited();
4862 }
4863
4864 if frames.is_empty() {
4865 // When we reach this point we are not able to write more, so set
4866 // app_limited to false.
4867 path.recovery.update_app_limited(false);
4868 return Err(Error::Done);
4869 }
4870
4871 // When coalescing a 1-RTT packet, we can't add padding in the UDP
4872 // datagram, so use PADDING frames instead.
4873 //
4874 // This is only needed if
4875 // 1) an Initial packet has already been written to the UDP datagram,
4876 // as Initial always requires padding.
4877 //
4878 // 2) this is a probing packet towards an unvalidated peer address.
4879 if (has_initial || !path.validated()) &&
4880 pkt_type == Type::Short &&
4881 left >= 1
4882 {
4883 let frame = frame::Frame::Padding { len: left };
4884
4885 if push_frame_to_pkt!(b, frames, frame, left) {
4886 in_flight = true;
4887 }
4888 }
4889
4890 // Pad payload so that it's always at least 4 bytes.
4891 if b.off() - payload_offset < PAYLOAD_MIN_LEN {
4892 let payload_len = b.off() - payload_offset;
4893
4894 let frame = frame::Frame::Padding {
4895 len: PAYLOAD_MIN_LEN - payload_len,
4896 };
4897
4898 #[allow(unused_assignments)]
4899 if push_frame_to_pkt!(b, frames, frame, left) {
4900 in_flight = true;
4901 }
4902 }
4903
4904 let payload_len = b.off() - payload_offset;
4905
4906 // Fill in payload length.
4907 if pkt_type != Type::Short {
4908 let len = pn_len + payload_len + crypto_overhead;
4909
4910 let (_, mut payload_with_len) = b.split_at(header_offset)?;
4911 payload_with_len
4912 .put_varint_with_len(len as u64, PAYLOAD_LENGTH_LEN)?;
4913 }
4914
4915 trace!(
4916 "{} tx pkt {} len={} pn={} {}",
4917 self.trace_id,
4918 hdr_trace.unwrap_or_default(),
4919 payload_len,
4920 pn,
4921 AddrTupleFmt(path.local_addr(), path.peer_addr())
4922 );
4923
4924 #[cfg(feature = "qlog")]
4925 let mut qlog_frames: SmallVec<
4926 [qlog::events::quic::QuicFrame; 1],
4927 > = SmallVec::with_capacity(frames.len());
4928
4929 for frame in &mut frames {
4930 trace!("{} tx frm {:?}", self.trace_id, frame);
4931
4932 qlog_with_type!(QLOG_PACKET_TX, self.qlog, _q, {
4933 qlog_frames.push(frame.to_qlog());
4934 });
4935 }
4936
4937 qlog_with_type!(QLOG_PACKET_TX, self.qlog, q, {
4938 if let Some(header) = qlog_pkt_hdr {
4939 // Qlog packet raw info described at
4940 // https://datatracker.ietf.org/doc/html/draft-ietf-quic-qlog-main-schema-00#section-5.1
4941 //
4942 // `length` includes packet headers and trailers (AEAD tag).
4943 let length = payload_len + payload_offset + crypto_overhead;
4944 let qlog_raw_info = RawInfo {
4945 length: Some(length as u64),
4946 payload_length: Some(payload_len as u64),
4947 data: None,
4948 };
4949
4950 let send_at_time =
4951 now.duration_since(q.start_time()).as_secs_f32() * 1000.0;
4952
4953 let ev_data =
4954 EventData::PacketSent(qlog::events::quic::PacketSent {
4955 header,
4956 frames: Some(qlog_frames),
4957 raw: Some(qlog_raw_info),
4958 send_at_time: Some(send_at_time),
4959 ..Default::default()
4960 });
4961
4962 q.add_event_data_with_instant(ev_data, now).ok();
4963 }
4964 });
4965
4966 let aead = match crypto_ctx.crypto_seal {
4967 Some(ref v) => v,
4968 None => return Err(Error::InvalidState),
4969 };
4970
4971 let written = packet::encrypt_pkt(
4972 &mut b,
4973 pn,
4974 pn_len,
4975 payload_len,
4976 payload_offset,
4977 None,
4978 aead,
4979 )?;
4980
4981 let sent_pkt_has_data = if path.recovery.gcongestion_enabled() {
4982 has_data || dgram_emitted
4983 } else {
4984 has_data
4985 };
4986
4987 let sent_pkt = recovery::Sent {
4988 pkt_num: pn,
4989 frames,
4990 time_sent: now,
4991 time_acked: None,
4992 time_lost: None,
4993 size: if ack_eliciting { written } else { 0 },
4994 ack_eliciting,
4995 in_flight,
4996 delivered: 0,
4997 delivered_time: now,
4998 first_sent_time: now,
4999 is_app_limited: false,
5000 tx_in_flight: 0,
5001 lost: 0,
5002 has_data: sent_pkt_has_data,
5003 is_pmtud_probe,
5004 };
5005
5006 if in_flight && is_app_limited {
5007 path.recovery.delivery_rate_update_app_limited(true);
5008 }
5009
5010 self.next_pkt_num += 1;
5011
5012 let handshake_status = recovery::HandshakeStatus {
5013 has_handshake_keys: self.crypto_ctx[packet::Epoch::Handshake]
5014 .has_keys(),
5015 peer_verified_address: self.peer_verified_initial_address,
5016 completed: self.handshake_completed,
5017 };
5018
5019 self.on_packet_sent(send_pid, sent_pkt, epoch, handshake_status, now)?;
5020
5021 let path = self.paths.get_mut(send_pid)?;
5022 qlog_with_type!(QLOG_METRICS, self.qlog, q, {
5023 path.recovery.maybe_qlog(q, now);
5024 });
5025
5026 // Record sent packet size if we probe the path.
5027 if let Some(data) = challenge_data {
5028 path.add_challenge_sent(data, written, now);
5029 }
5030
5031 self.sent_count += 1;
5032 self.sent_bytes += written as u64;
5033 path.sent_count += 1;
5034 path.sent_bytes += written as u64;
5035
5036 if self.dgram_send_queue.byte_size() > path.recovery.cwnd_available() {
5037 path.recovery.update_app_limited(false);
5038 }
5039
5040 path.max_send_bytes = path.max_send_bytes.saturating_sub(written);
5041
5042 // On the client, drop initial state after sending an Handshake packet.
5043 if !self.is_server && hdr_ty == Type::Handshake {
5044 self.drop_epoch_state(packet::Epoch::Initial, now);
5045 }
5046
5047 // (Re)start the idle timer if we are sending the first ack-eliciting
5048 // packet since last receiving a packet.
5049 if ack_eliciting && !self.ack_eliciting_sent {
5050 if let Some(idle_timeout) = self.idle_timeout() {
5051 self.idle_timer = Some(now + idle_timeout);
5052 }
5053 }
5054
5055 if ack_eliciting {
5056 self.ack_eliciting_sent = true;
5057 }
5058
5059 Ok((pkt_type, written))
5060 }
5061
5062 fn on_packet_sent(
5063 &mut self, send_pid: usize, sent_pkt: recovery::Sent,
5064 epoch: packet::Epoch, handshake_status: recovery::HandshakeStatus,
5065 now: Instant,
5066 ) -> Result<()> {
5067 let path = self.paths.get_mut(send_pid)?;
5068
5069 // It's fine to set the skip counter based on a non-active path's values.
5070 let cwnd = path.recovery.cwnd();
5071 let max_datagram_size = path.recovery.max_datagram_size();
5072 self.pkt_num_spaces[epoch].on_packet_sent(&sent_pkt);
5073 self.pkt_num_manager.on_packet_sent(
5074 cwnd,
5075 max_datagram_size,
5076 self.handshake_completed,
5077 );
5078
5079 path.recovery.on_packet_sent(
5080 sent_pkt,
5081 epoch,
5082 handshake_status,
5083 now,
5084 &self.trace_id,
5085 );
5086
5087 Ok(())
5088 }
5089
5090 /// Returns the desired send time for the next packet.
5091 #[inline]
5092 pub fn get_next_release_time(&self) -> Option<ReleaseDecision> {
5093 Some(
5094 self.paths
5095 .get_active()
5096 .ok()?
5097 .recovery
5098 .get_next_release_time(),
5099 )
5100 }
5101
5102 /// Returns whether gcongestion is enabled.
5103 #[inline]
5104 pub fn gcongestion_enabled(&self) -> Option<bool> {
5105 Some(self.paths.get_active().ok()?.recovery.gcongestion_enabled())
5106 }
5107
5108 /// Returns the maximum pacing into the future.
5109 ///
5110 /// Equals 1/8 of the smoothed RTT, but at least 1ms and not greater than
5111 /// 5ms.
5112 pub fn max_release_into_future(&self) -> Duration {
5113 self.paths
5114 .get_active()
5115 .map(|p| p.recovery.rtt().mul_f64(0.125))
5116 .unwrap_or(Duration::from_millis(1))
5117 .max(Duration::from_millis(1))
5118 .min(Duration::from_millis(5))
5119 }
5120
5121 /// Returns whether pacing is enabled.
5122 #[inline]
5123 pub fn pacing_enabled(&self) -> bool {
5124 self.recovery_config.pacing
5125 }
5126
5127 /// Returns the size of the send quantum, in bytes.
5128 ///
5129 /// This represents the maximum size of a packet burst as determined by the
5130 /// congestion control algorithm in use.
5131 ///
5132 /// Applications can, for example, use it in conjunction with segmentation
5133 /// offloading mechanisms as the maximum limit for outgoing aggregates of
5134 /// multiple packets.
5135 #[inline]
5136 pub fn send_quantum(&self) -> usize {
5137 match self.paths.get_active() {
5138 Ok(p) => p.recovery.send_quantum(),
5139 _ => 0,
5140 }
5141 }
5142
5143 /// Returns the size of the send quantum over the given 4-tuple, in bytes.
5144 ///
5145 /// This represents the maximum size of a packet burst as determined by the
5146 /// congestion control algorithm in use.
5147 ///
5148 /// Applications can, for example, use it in conjunction with segmentation
5149 /// offloading mechanisms as the maximum limit for outgoing aggregates of
5150 /// multiple packets.
5151 ///
5152 /// If the (`local_addr`, peer_addr`) 4-tuple relates to a non-existing
5153 /// path, this method returns 0.
5154 pub fn send_quantum_on_path(
5155 &self, local_addr: SocketAddr, peer_addr: SocketAddr,
5156 ) -> usize {
5157 self.paths
5158 .path_id_from_addrs(&(local_addr, peer_addr))
5159 .and_then(|pid| self.paths.get(pid).ok())
5160 .map(|path| path.recovery.send_quantum())
5161 .unwrap_or(0)
5162 }
5163
5164 /// Reads contiguous data from a stream into the provided slice.
5165 ///
5166 /// The slice must be sized by the caller and will be populated up to its
5167 /// capacity.
5168 ///
5169 /// On success the amount of bytes read and a flag indicating the fin state
5170 /// is returned as a tuple, or [`Done`] if there is no data to read.
5171 ///
5172 /// Reading data from a stream may trigger queueing of control messages
5173 /// (e.g. MAX_STREAM_DATA). [`send()`] should be called after reading.
5174 ///
5175 /// [`Done`]: enum.Error.html#variant.Done
5176 /// [`send()`]: struct.Connection.html#method.send
5177 ///
5178 /// ## Examples:
5179 ///
5180 /// ```no_run
5181 /// # let mut buf = [0; 512];
5182 /// # let socket = std::net::UdpSocket::bind("127.0.0.1:0").unwrap();
5183 /// # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
5184 /// # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
5185 /// # let peer = "127.0.0.1:1234".parse().unwrap();
5186 /// # let local = socket.local_addr().unwrap();
5187 /// # let mut conn = quiche::accept(&scid, None, local, peer, &mut config)?;
5188 /// # let stream_id = 0;
5189 /// while let Ok((read, fin)) = conn.stream_recv(stream_id, &mut buf) {
5190 /// println!("Got {} bytes on stream {}", read, stream_id);
5191 /// }
5192 /// # Ok::<(), quiche::Error>(())
5193 /// ```
5194 pub fn stream_recv(
5195 &mut self, stream_id: u64, out: &mut [u8],
5196 ) -> Result<(usize, bool)> {
5197 // We can't read on our own unidirectional streams.
5198 if !stream::is_bidi(stream_id) &&
5199 stream::is_local(stream_id, self.is_server)
5200 {
5201 return Err(Error::InvalidStreamState(stream_id));
5202 }
5203
5204 let stream = self
5205 .streams
5206 .get_mut(stream_id)
5207 .ok_or(Error::InvalidStreamState(stream_id))?;
5208
5209 if !stream.is_readable() {
5210 return Err(Error::Done);
5211 }
5212
5213 let local = stream.local;
5214 let priority_key = Arc::clone(&stream.priority_key);
5215
5216 #[cfg(feature = "qlog")]
5217 let offset = stream.recv.off_front();
5218
5219 let (read, fin) = match stream.recv.emit(out) {
5220 Ok(v) => v,
5221
5222 Err(e) => {
5223 // Collect the stream if it is now complete. This can happen if
5224 // we got a `StreamReset` error which will now be propagated to
5225 // the application, so we don't need to keep the stream's state
5226 // anymore.
5227 if stream.is_complete() {
5228 self.streams.collect(stream_id, local);
5229 }
5230
5231 self.streams.remove_readable(&priority_key);
5232 return Err(e);
5233 },
5234 };
5235
5236 self.flow_control.add_consumed(read as u64);
5237
5238 let readable = stream.is_readable();
5239
5240 let complete = stream.is_complete();
5241
5242 if stream.recv.almost_full() {
5243 self.streams.insert_almost_full(stream_id);
5244 }
5245
5246 if !readable {
5247 self.streams.remove_readable(&priority_key);
5248 }
5249
5250 if complete {
5251 self.streams.collect(stream_id, local);
5252 }
5253
5254 qlog_with_type!(QLOG_DATA_MV, self.qlog, q, {
5255 let ev_data = EventData::DataMoved(qlog::events::quic::DataMoved {
5256 stream_id: Some(stream_id),
5257 offset: Some(offset),
5258 length: Some(read as u64),
5259 from: Some(DataRecipient::Transport),
5260 to: Some(DataRecipient::Application),
5261 ..Default::default()
5262 });
5263
5264 let now = Instant::now();
5265 q.add_event_data_with_instant(ev_data, now).ok();
5266 });
5267
5268 if self.should_update_max_data() {
5269 self.almost_full = true;
5270 }
5271
5272 if priority_key.incremental && readable {
5273 // Shuffle the incremental stream to the back of the queue.
5274 self.streams.remove_readable(&priority_key);
5275 self.streams.insert_readable(&priority_key);
5276 }
5277
5278 Ok((read, fin))
5279 }
5280
5281 /// Writes data to a stream.
5282 ///
5283 /// On success the number of bytes written is returned, or [`Done`] if no
5284 /// data was written (e.g. because the stream has no capacity).
5285 ///
5286 /// Applications can provide a 0-length buffer with the fin flag set to
5287 /// true. This will lead to a 0-length FIN STREAM frame being sent at the
5288 /// latest offset. The `Ok(0)` value is only returned when the application
5289 /// provided a 0-length buffer.
5290 ///
5291 /// In addition, if the peer has signalled that it doesn't want to receive
5292 /// any more data from this stream by sending the `STOP_SENDING` frame, the
5293 /// [`StreamStopped`] error will be returned instead of any data.
5294 ///
5295 /// Note that in order to avoid buffering an infinite amount of data in the
5296 /// stream's send buffer, streams are only allowed to buffer outgoing data
5297 /// up to the amount that the peer allows it to send (that is, up to the
5298 /// stream's outgoing flow control capacity).
5299 ///
5300 /// This means that the number of written bytes returned can be lower than
5301 /// the length of the input buffer when the stream doesn't have enough
5302 /// capacity for the operation to complete. The application should retry the
5303 /// operation once the stream is reported as writable again.
5304 ///
5305 /// Applications should call this method only after the handshake is
5306 /// completed (whenever [`is_established()`] returns `true`) or during
5307 /// early data if enabled (whenever [`is_in_early_data()`] returns `true`).
5308 ///
5309 /// [`Done`]: enum.Error.html#variant.Done
5310 /// [`StreamStopped`]: enum.Error.html#variant.StreamStopped
5311 /// [`is_established()`]: struct.Connection.html#method.is_established
5312 /// [`is_in_early_data()`]: struct.Connection.html#method.is_in_early_data
5313 ///
5314 /// ## Examples:
5315 ///
5316 /// ```no_run
5317 /// # let mut buf = [0; 512];
5318 /// # let socket = std::net::UdpSocket::bind("127.0.0.1:0").unwrap();
5319 /// # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
5320 /// # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
5321 /// # let peer = "127.0.0.1:1234".parse().unwrap();
5322 /// # let local = "127.0.0.1:4321".parse().unwrap();
5323 /// # let mut conn = quiche::accept(&scid, None, local, peer, &mut config)?;
5324 /// # let stream_id = 0;
5325 /// conn.stream_send(stream_id, b"hello", true)?;
5326 /// # Ok::<(), quiche::Error>(())
5327 /// ```
5328 pub fn stream_send(
5329 &mut self, stream_id: u64, buf: &[u8], fin: bool,
5330 ) -> Result<usize> {
5331 self.stream_do_send(
5332 stream_id,
5333 buf,
5334 fin,
5335 |stream: &mut stream::Stream<F>,
5336 buf: &[u8],
5337 cap: usize,
5338 fin: bool| {
5339 stream.send.write(&buf[..cap], fin).map(|v| (v, v))
5340 },
5341 )
5342 }
5343
5344 /// Writes data to a stream with zero copying, instead, it appends the
5345 /// provided buffer directly to the send queue if the capacity allows
5346 /// it.
5347 ///
5348 /// When a partial write happens (including when [`Error::Done`] is
5349 /// returned) the remaining (unwritten) buffer will also be returned.
5350 /// The application should retry the operation once the stream is
5351 /// reported as writable again.
5352 pub fn stream_send_zc(
5353 &mut self, stream_id: u64, buf: F::Buf, len: Option<usize>, fin: bool,
5354 ) -> Result<(usize, Option<F::Buf>)>
5355 where
5356 F::Buf: BufSplit,
5357 {
5358 self.stream_do_send(
5359 stream_id,
5360 buf,
5361 fin,
5362 |stream: &mut stream::Stream<F>,
5363 buf: F::Buf,
5364 cap: usize,
5365 fin: bool| {
5366 let len = len.unwrap_or(usize::MAX).min(cap);
5367 let (sent, remaining) = stream.send.append_buf(buf, len, fin)?;
5368 Ok((sent, (sent, remaining)))
5369 },
5370 )
5371 }
5372
5373 fn stream_do_send<B, R, SND>(
5374 &mut self, stream_id: u64, buf: B, fin: bool, write_fn: SND,
5375 ) -> Result<R>
5376 where
5377 B: AsRef<[u8]>,
5378 SND: FnOnce(&mut stream::Stream<F>, B, usize, bool) -> Result<(usize, R)>,
5379 {
5380 // We can't write on the peer's unidirectional streams.
5381 if !stream::is_bidi(stream_id) &&
5382 !stream::is_local(stream_id, self.is_server)
5383 {
5384 return Err(Error::InvalidStreamState(stream_id));
5385 }
5386
5387 let len = buf.as_ref().len();
5388
5389 // Mark the connection as blocked if the connection-level flow control
5390 // limit doesn't let us buffer all the data.
5391 //
5392 // Note that this is separate from "send capacity" as that also takes
5393 // congestion control into consideration.
5394 if self.max_tx_data - self.tx_data < len as u64 {
5395 self.blocked_limit = Some(self.max_tx_data);
5396 }
5397
5398 let cap = self.tx_cap;
5399
5400 // Get existing stream or create a new one.
5401 let stream = self.get_or_create_stream(stream_id, true)?;
5402
5403 #[cfg(feature = "qlog")]
5404 let offset = stream.send.off_back();
5405
5406 let was_writable = stream.is_writable();
5407
5408 let was_flushable = stream.is_flushable();
5409
5410 let is_complete = stream.is_complete();
5411 let is_readable = stream.is_readable();
5412
5413 let priority_key = Arc::clone(&stream.priority_key);
5414
5415 // Return early if the stream has been stopped, and collect its state
5416 // if complete.
5417 if let Err(Error::StreamStopped(e)) = stream.send.cap() {
5418 // Only collect the stream if it is complete and not readable.
5419 // If it is readable, it will get collected when stream_recv()
5420 // is used.
5421 //
5422 // The stream can't be writable if it has been stopped.
5423 if is_complete && !is_readable {
5424 let local = stream.local;
5425 self.streams.collect(stream_id, local);
5426 }
5427
5428 return Err(Error::StreamStopped(e));
5429 };
5430
5431 // Truncate the input buffer based on the connection's send capacity if
5432 // necessary.
5433 //
5434 // When the cap is zero, the method returns Ok(0) *only* when the passed
5435 // buffer is empty. We return Error::Done otherwise.
5436 if cap == 0 && len > 0 {
5437 if was_writable {
5438 // When `stream_writable_next()` returns a stream, the writable
5439 // mark is removed, but because the stream is blocked by the
5440 // connection-level send capacity it won't be marked as writable
5441 // again once the capacity increases.
5442 //
5443 // Since the stream is writable already, mark it here instead.
5444 self.streams.insert_writable(&priority_key);
5445 }
5446
5447 return Err(Error::Done);
5448 }
5449
5450 let (cap, fin, blocked_by_cap) = if cap < len {
5451 (cap, false, true)
5452 } else {
5453 (len, fin, false)
5454 };
5455
5456 let (sent, ret) = match write_fn(stream, buf, cap, fin) {
5457 Ok(v) => v,
5458
5459 Err(e) => {
5460 self.streams.remove_writable(&priority_key);
5461 return Err(e);
5462 },
5463 };
5464
5465 let incremental = stream.incremental;
5466 let priority_key = Arc::clone(&stream.priority_key);
5467
5468 let flushable = stream.is_flushable();
5469
5470 let writable = stream.is_writable();
5471
5472 let empty_fin = len == 0 && fin;
5473
5474 if sent < cap {
5475 let max_off = stream.send.max_off();
5476
5477 if stream.send.blocked_at() != Some(max_off) {
5478 stream.send.update_blocked_at(Some(max_off));
5479 self.streams.insert_blocked(stream_id, max_off);
5480 }
5481 } else {
5482 stream.send.update_blocked_at(None);
5483 self.streams.remove_blocked(stream_id);
5484 }
5485
5486 // If the stream is now flushable push it to the flushable queue, but
5487 // only if it wasn't already queued.
5488 //
5489 // Consider the stream flushable also when we are sending a zero-length
5490 // frame that has the fin flag set.
5491 if (flushable || empty_fin) && !was_flushable {
5492 self.streams.insert_flushable(&priority_key);
5493 }
5494
5495 if !writable {
5496 self.streams.remove_writable(&priority_key);
5497 } else if was_writable && blocked_by_cap {
5498 // When `stream_writable_next()` returns a stream, the writable
5499 // mark is removed, but because the stream is blocked by the
5500 // connection-level send capacity it won't be marked as writable
5501 // again once the capacity increases.
5502 //
5503 // Since the stream is writable already, mark it here instead.
5504 self.streams.insert_writable(&priority_key);
5505 }
5506
5507 self.tx_cap -= sent;
5508
5509 self.tx_data += sent as u64;
5510
5511 self.tx_buffered += sent;
5512 self.check_tx_buffered_invariant();
5513
5514 qlog_with_type!(QLOG_DATA_MV, self.qlog, q, {
5515 let ev_data = EventData::DataMoved(qlog::events::quic::DataMoved {
5516 stream_id: Some(stream_id),
5517 offset: Some(offset),
5518 length: Some(sent as u64),
5519 from: Some(DataRecipient::Application),
5520 to: Some(DataRecipient::Transport),
5521 ..Default::default()
5522 });
5523
5524 let now = Instant::now();
5525 q.add_event_data_with_instant(ev_data, now).ok();
5526 });
5527
5528 if sent == 0 && cap > 0 {
5529 return Err(Error::Done);
5530 }
5531
5532 if incremental && writable {
5533 // Shuffle the incremental stream to the back of the queue.
5534 self.streams.remove_writable(&priority_key);
5535 self.streams.insert_writable(&priority_key);
5536 }
5537
5538 Ok(ret)
5539 }
5540
5541 /// Sets the priority for a stream.
5542 ///
5543 /// A stream's priority determines the order in which stream data is sent
5544 /// on the wire (streams with lower priority are sent first). Streams are
5545 /// created with a default priority of `127`.
5546 ///
5547 /// The target stream is created if it did not exist before calling this
5548 /// method.
5549 pub fn stream_priority(
5550 &mut self, stream_id: u64, urgency: u8, incremental: bool,
5551 ) -> Result<()> {
5552 // Get existing stream or create a new one, but if the stream
5553 // has already been closed and collected, ignore the prioritization.
5554 let stream = match self.get_or_create_stream(stream_id, true) {
5555 Ok(v) => v,
5556
5557 Err(Error::Done) => return Ok(()),
5558
5559 Err(e) => return Err(e),
5560 };
5561
5562 if stream.urgency == urgency && stream.incremental == incremental {
5563 return Ok(());
5564 }
5565
5566 stream.urgency = urgency;
5567 stream.incremental = incremental;
5568
5569 let new_priority_key = Arc::new(StreamPriorityKey {
5570 urgency: stream.urgency,
5571 incremental: stream.incremental,
5572 id: stream_id,
5573 ..Default::default()
5574 });
5575
5576 let old_priority_key =
5577 std::mem::replace(&mut stream.priority_key, new_priority_key.clone());
5578
5579 self.streams
5580 .update_priority(&old_priority_key, &new_priority_key);
5581
5582 Ok(())
5583 }
5584
5585 /// Shuts down reading or writing from/to the specified stream.
5586 ///
5587 /// When the `direction` argument is set to [`Shutdown::Read`], outstanding
5588 /// data in the stream's receive buffer is dropped, and no additional data
5589 /// is added to it. Data received after calling this method is still
5590 /// validated and acked but not stored, and [`stream_recv()`] will not
5591 /// return it to the application. In addition, a `STOP_SENDING` frame will
5592 /// be sent to the peer to signal it to stop sending data.
5593 ///
5594 /// When the `direction` argument is set to [`Shutdown::Write`], outstanding
5595 /// data in the stream's send buffer is dropped, and no additional data is
5596 /// added to it. Data passed to [`stream_send()`] after calling this method
5597 /// will be ignored. In addition, a `RESET_STREAM` frame will be sent to the
5598 /// peer to signal the reset.
5599 ///
5600 /// Locally-initiated unidirectional streams can only be closed in the
5601 /// [`Shutdown::Write`] direction. Remotely-initiated unidirectional streams
5602 /// can only be closed in the [`Shutdown::Read`] direction. Using an
5603 /// incorrect direction will return [`InvalidStreamState`].
5604 ///
5605 /// [`Shutdown::Read`]: enum.Shutdown.html#variant.Read
5606 /// [`Shutdown::Write`]: enum.Shutdown.html#variant.Write
5607 /// [`stream_recv()`]: struct.Connection.html#method.stream_recv
5608 /// [`stream_send()`]: struct.Connection.html#method.stream_send
5609 /// [`InvalidStreamState`]: enum.Error.html#variant.InvalidStreamState
5610 pub fn stream_shutdown(
5611 &mut self, stream_id: u64, direction: Shutdown, err: u64,
5612 ) -> Result<()> {
5613 // Don't try to stop a local unidirectional stream.
5614 if direction == Shutdown::Read &&
5615 stream::is_local(stream_id, self.is_server) &&
5616 !stream::is_bidi(stream_id)
5617 {
5618 return Err(Error::InvalidStreamState(stream_id));
5619 }
5620
5621 // Don't try to reset a remote unidirectional stream.
5622 if direction == Shutdown::Write &&
5623 !stream::is_local(stream_id, self.is_server) &&
5624 !stream::is_bidi(stream_id)
5625 {
5626 return Err(Error::InvalidStreamState(stream_id));
5627 }
5628
5629 // Get existing stream.
5630 let stream = self.streams.get_mut(stream_id).ok_or(Error::Done)?;
5631
5632 let priority_key = Arc::clone(&stream.priority_key);
5633
5634 match direction {
5635 Shutdown::Read => {
5636 let consumed = stream.recv.shutdown()?;
5637 self.flow_control.add_consumed(consumed);
5638 if self.flow_control.should_update_max_data() {
5639 self.almost_full = true;
5640 }
5641
5642 if !stream.recv.is_fin() {
5643 self.streams.insert_stopped(stream_id, err);
5644 }
5645
5646 // Once shutdown, the stream is guaranteed to be non-readable.
5647 self.streams.remove_readable(&priority_key);
5648
5649 self.stopped_stream_local_count =
5650 self.stopped_stream_local_count.saturating_add(1);
5651 },
5652
5653 Shutdown::Write => {
5654 let (final_size, unsent) = stream.send.shutdown()?;
5655
5656 // Claw back some flow control allowance from data that was
5657 // buffered but not actually sent before the stream was reset.
5658 self.tx_data = self.tx_data.saturating_sub(unsent);
5659
5660 self.tx_buffered =
5661 self.tx_buffered.saturating_sub(unsent as usize);
5662
5663 // These drops in qlog are a bit weird, but the only way to ensure
5664 // that all bytes that are moved from App to Transport in
5665 // stream_do_send are eventually moved from Transport to Dropped.
5666 // Ideally we would add a Transport to Network transition also as
5667 // a way to indicate when bytes were transmitted vs dropped
5668 // without ever being sent.
5669 qlog_with_type!(QLOG_DATA_MV, self.qlog, q, {
5670 let ev_data =
5671 EventData::DataMoved(qlog::events::quic::DataMoved {
5672 stream_id: Some(stream_id),
5673 offset: Some(final_size),
5674 length: Some(unsent),
5675 from: Some(DataRecipient::Transport),
5676 to: Some(DataRecipient::Dropped),
5677 ..Default::default()
5678 });
5679
5680 q.add_event_data_with_instant(ev_data, Instant::now()).ok();
5681 });
5682
5683 // Update send capacity.
5684 self.update_tx_cap();
5685
5686 self.streams.insert_reset(stream_id, err, final_size);
5687
5688 // Once shutdown, the stream is guaranteed to be non-writable.
5689 self.streams.remove_writable(&priority_key);
5690
5691 self.reset_stream_local_count =
5692 self.reset_stream_local_count.saturating_add(1);
5693 },
5694 }
5695
5696 Ok(())
5697 }
5698
5699 /// Returns the stream's send capacity in bytes.
5700 ///
5701 /// If the specified stream doesn't exist (including when it has already
5702 /// been completed and closed), the [`InvalidStreamState`] error will be
5703 /// returned.
5704 ///
5705 /// In addition, if the peer has signalled that it doesn't want to receive
5706 /// any more data from this stream by sending the `STOP_SENDING` frame, the
5707 /// [`StreamStopped`] error will be returned.
5708 ///
5709 /// [`InvalidStreamState`]: enum.Error.html#variant.InvalidStreamState
5710 /// [`StreamStopped`]: enum.Error.html#variant.StreamStopped
5711 #[inline]
5712 pub fn stream_capacity(&mut self, stream_id: u64) -> Result<usize> {
5713 if let Some(stream) = self.streams.get(stream_id) {
5714 let stream_cap = match stream.send.cap() {
5715 Ok(v) => v,
5716
5717 Err(Error::StreamStopped(e)) => {
5718 // Only collect the stream if it is complete and not
5719 // readable. If it is readable, it will get collected when
5720 // stream_recv() is used.
5721 if stream.is_complete() && !stream.is_readable() {
5722 let local = stream.local;
5723 self.streams.collect(stream_id, local);
5724 }
5725
5726 return Err(Error::StreamStopped(e));
5727 },
5728
5729 Err(e) => return Err(e),
5730 };
5731
5732 let cap = cmp::min(self.tx_cap, stream_cap);
5733 return Ok(cap);
5734 };
5735
5736 Err(Error::InvalidStreamState(stream_id))
5737 }
5738
5739 /// Returns the next stream that has data to read.
5740 ///
5741 /// Note that once returned by this method, a stream ID will not be returned
5742 /// again until it is "re-armed".
5743 ///
5744 /// The application will need to read all of the pending data on the stream,
5745 /// and new data has to be received before the stream is reported again.
5746 ///
5747 /// This is unlike the [`readable()`] method, that returns the same list of
5748 /// readable streams when called multiple times in succession.
5749 ///
5750 /// [`readable()`]: struct.Connection.html#method.readable
5751 pub fn stream_readable_next(&mut self) -> Option<u64> {
5752 let priority_key = self.streams.readable.front().clone_pointer()?;
5753
5754 self.streams.remove_readable(&priority_key);
5755
5756 Some(priority_key.id)
5757 }
5758
5759 /// Returns true if the stream has data that can be read.
5760 pub fn stream_readable(&self, stream_id: u64) -> bool {
5761 let stream = match self.streams.get(stream_id) {
5762 Some(v) => v,
5763
5764 None => return false,
5765 };
5766
5767 stream.is_readable()
5768 }
5769
5770 /// Returns the next stream that can be written to.
5771 ///
5772 /// Note that once returned by this method, a stream ID will not be returned
5773 /// again until it is "re-armed".
5774 ///
5775 /// This is unlike the [`writable()`] method, that returns the same list of
5776 /// writable streams when called multiple times in succession. It is not
5777 /// advised to use both `stream_writable_next()` and [`writable()`] on the
5778 /// same connection, as it may lead to unexpected results.
5779 ///
5780 /// The [`stream_writable()`] method can also be used to fine-tune when a
5781 /// stream is reported as writable again.
5782 ///
5783 /// [`stream_writable()`]: struct.Connection.html#method.stream_writable
5784 /// [`writable()`]: struct.Connection.html#method.writable
5785 pub fn stream_writable_next(&mut self) -> Option<u64> {
5786 // If there is not enough connection-level send capacity, none of the
5787 // streams are writable.
5788 if self.tx_cap == 0 {
5789 return None;
5790 }
5791
5792 let mut cursor = self.streams.writable.front();
5793
5794 while let Some(priority_key) = cursor.clone_pointer() {
5795 if let Some(stream) = self.streams.get(priority_key.id) {
5796 let cap = match stream.send.cap() {
5797 Ok(v) => v,
5798
5799 // Return the stream to the application immediately if it's
5800 // stopped.
5801 Err(_) =>
5802 return {
5803 self.streams.remove_writable(&priority_key);
5804
5805 Some(priority_key.id)
5806 },
5807 };
5808
5809 if cmp::min(self.tx_cap, cap) >= stream.send_lowat {
5810 self.streams.remove_writable(&priority_key);
5811 return Some(priority_key.id);
5812 }
5813 }
5814
5815 cursor.move_next();
5816 }
5817
5818 None
5819 }
5820
5821 /// Returns true if the stream has enough send capacity.
5822 ///
5823 /// When `len` more bytes can be buffered into the given stream's send
5824 /// buffer, `true` will be returned, `false` otherwise.
5825 ///
5826 /// In the latter case, if the additional data can't be buffered due to
5827 /// flow control limits, the peer will also be notified, and a "low send
5828 /// watermark" will be set for the stream, such that it is not going to be
5829 /// reported as writable again by [`stream_writable_next()`] until its send
5830 /// capacity reaches `len`.
5831 ///
5832 /// If the specified stream doesn't exist (including when it has already
5833 /// been completed and closed), the [`InvalidStreamState`] error will be
5834 /// returned.
5835 ///
5836 /// In addition, if the peer has signalled that it doesn't want to receive
5837 /// any more data from this stream by sending the `STOP_SENDING` frame, the
5838 /// [`StreamStopped`] error will be returned.
5839 ///
5840 /// [`stream_writable_next()`]: struct.Connection.html#method.stream_writable_next
5841 /// [`InvalidStreamState`]: enum.Error.html#variant.InvalidStreamState
5842 /// [`StreamStopped`]: enum.Error.html#variant.StreamStopped
5843 #[inline]
5844 pub fn stream_writable(
5845 &mut self, stream_id: u64, len: usize,
5846 ) -> Result<bool> {
5847 if self.stream_capacity(stream_id)? >= len {
5848 return Ok(true);
5849 }
5850
5851 let stream = match self.streams.get_mut(stream_id) {
5852 Some(v) => v,
5853
5854 None => return Err(Error::InvalidStreamState(stream_id)),
5855 };
5856
5857 stream.send_lowat = cmp::max(1, len);
5858
5859 let is_writable = stream.is_writable();
5860
5861 let priority_key = Arc::clone(&stream.priority_key);
5862
5863 if self.max_tx_data - self.tx_data < len as u64 {
5864 self.blocked_limit = Some(self.max_tx_data);
5865 }
5866
5867 if stream.send.cap()? < len {
5868 let max_off = stream.send.max_off();
5869 if stream.send.blocked_at() != Some(max_off) {
5870 stream.send.update_blocked_at(Some(max_off));
5871 self.streams.insert_blocked(stream_id, max_off);
5872 }
5873 } else if is_writable {
5874 // When `stream_writable_next()` returns a stream, the writable
5875 // mark is removed, but because the stream is blocked by the
5876 // connection-level send capacity it won't be marked as writable
5877 // again once the capacity increases.
5878 //
5879 // Since the stream is writable already, mark it here instead.
5880 self.streams.insert_writable(&priority_key);
5881 }
5882
5883 Ok(false)
5884 }
5885
5886 /// Returns true if all the data has been read from the specified stream.
5887 ///
5888 /// This instructs the application that all the data received from the
5889 /// peer on the stream has been read, and there won't be anymore in the
5890 /// future.
5891 ///
5892 /// Basically this returns true when the peer either set the `fin` flag
5893 /// for the stream, or sent `RESET_STREAM`.
5894 #[inline]
5895 pub fn stream_finished(&self, stream_id: u64) -> bool {
5896 let stream = match self.streams.get(stream_id) {
5897 Some(v) => v,
5898
5899 None => return true,
5900 };
5901
5902 stream.recv.is_fin()
5903 }
5904
5905 /// Returns the number of bidirectional streams that can be created
5906 /// before the peer's stream count limit is reached.
5907 ///
5908 /// This can be useful to know if it's possible to create a bidirectional
5909 /// stream without trying it first.
5910 #[inline]
5911 pub fn peer_streams_left_bidi(&self) -> u64 {
5912 self.streams.peer_streams_left_bidi()
5913 }
5914
5915 /// Returns the number of unidirectional streams that can be created
5916 /// before the peer's stream count limit is reached.
5917 ///
5918 /// This can be useful to know if it's possible to create a unidirectional
5919 /// stream without trying it first.
5920 #[inline]
5921 pub fn peer_streams_left_uni(&self) -> u64 {
5922 self.streams.peer_streams_left_uni()
5923 }
5924
5925 /// Returns an iterator over streams that have outstanding data to read.
5926 ///
5927 /// Note that the iterator will only include streams that were readable at
5928 /// the time the iterator itself was created (i.e. when `readable()` was
5929 /// called). To account for newly readable streams, the iterator needs to
5930 /// be created again.
5931 ///
5932 /// ## Examples:
5933 ///
5934 /// ```no_run
5935 /// # let mut buf = [0; 512];
5936 /// # let socket = std::net::UdpSocket::bind("127.0.0.1:0").unwrap();
5937 /// # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
5938 /// # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
5939 /// # let peer = "127.0.0.1:1234".parse().unwrap();
5940 /// # let local = socket.local_addr().unwrap();
5941 /// # let mut conn = quiche::accept(&scid, None, local, peer, &mut config)?;
5942 /// // Iterate over readable streams.
5943 /// for stream_id in conn.readable() {
5944 /// // Stream is readable, read until there's no more data.
5945 /// while let Ok((read, fin)) = conn.stream_recv(stream_id, &mut buf) {
5946 /// println!("Got {} bytes on stream {}", read, stream_id);
5947 /// }
5948 /// }
5949 /// # Ok::<(), quiche::Error>(())
5950 /// ```
5951 #[inline]
5952 pub fn readable(&self) -> StreamIter {
5953 self.streams.readable()
5954 }
5955
5956 /// Returns an iterator over streams that can be written in priority order.
5957 ///
5958 /// The priority order is based on RFC 9218 scheduling recommendations.
5959 /// Stream priority can be controlled using [`stream_priority()`]. In order
5960 /// to support fairness requirements, each time this method is called,
5961 /// internal state is updated. Therefore the iterator ordering can change
5962 /// between calls, even if no streams were added or removed.
5963 ///
5964 /// A "writable" stream is a stream that has enough flow control capacity to
5965 /// send data to the peer. To avoid buffering an infinite amount of data,
5966 /// streams are only allowed to buffer outgoing data up to the amount that
5967 /// the peer allows to send.
5968 ///
5969 /// Note that the iterator will only include streams that were writable at
5970 /// the time the iterator itself was created (i.e. when `writable()` was
5971 /// called). To account for newly writable streams, the iterator needs to be
5972 /// created again.
5973 ///
5974 /// ## Examples:
5975 ///
5976 /// ```no_run
5977 /// # let mut buf = [0; 512];
5978 /// # let socket = std::net::UdpSocket::bind("127.0.0.1:0").unwrap();
5979 /// # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
5980 /// # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
5981 /// # let local = socket.local_addr().unwrap();
5982 /// # let peer = "127.0.0.1:1234".parse().unwrap();
5983 /// # let mut conn = quiche::accept(&scid, None, local, peer, &mut config)?;
5984 /// // Iterate over writable streams.
5985 /// for stream_id in conn.writable() {
5986 /// // Stream is writable, write some data.
5987 /// if let Ok(written) = conn.stream_send(stream_id, &buf, false) {
5988 /// println!("Written {} bytes on stream {}", written, stream_id);
5989 /// }
5990 /// }
5991 /// # Ok::<(), quiche::Error>(())
5992 /// ```
5993 /// [`stream_priority()`]: struct.Connection.html#method.stream_priority
5994 #[inline]
5995 pub fn writable(&self) -> StreamIter {
5996 // If there is not enough connection-level send capacity, none of the
5997 // streams are writable, so return an empty iterator.
5998 if self.tx_cap == 0 {
5999 return StreamIter::default();
6000 }
6001
6002 self.streams.writable()
6003 }
6004
6005 /// Returns the maximum possible size of egress UDP payloads.
6006 ///
6007 /// This is the maximum size of UDP payloads that can be sent, and depends
6008 /// on both the configured maximum send payload size of the local endpoint
6009 /// (as configured with [`set_max_send_udp_payload_size()`]), as well as
6010 /// the transport parameter advertised by the remote peer.
6011 ///
6012 /// Note that this value can change during the lifetime of the connection,
6013 /// but should remain stable across consecutive calls to [`send()`].
6014 ///
6015 /// [`set_max_send_udp_payload_size()`]:
6016 /// struct.Config.html#method.set_max_send_udp_payload_size
6017 /// [`send()`]: struct.Connection.html#method.send
6018 pub fn max_send_udp_payload_size(&self) -> usize {
6019 let max_datagram_size = self
6020 .paths
6021 .get_active()
6022 .ok()
6023 .map(|p| p.recovery.max_datagram_size());
6024
6025 if let Some(max_datagram_size) = max_datagram_size {
6026 if self.is_established() {
6027 // We cap the maximum packet size to 16KB or so, so that it can be
6028 // always encoded with a 2-byte varint.
6029 return cmp::min(16383, max_datagram_size);
6030 }
6031 }
6032
6033 // Allow for 1200 bytes (minimum QUIC packet size) during the
6034 // handshake.
6035 MIN_CLIENT_INITIAL_LEN
6036 }
6037
6038 /// Schedule an ack-eliciting packet on the active path.
6039 ///
6040 /// QUIC packets might not contain ack-eliciting frames during normal
6041 /// operating conditions. If the packet would already contain
6042 /// ack-eliciting frames, this method does not change any behavior.
6043 /// However, if the packet would not ordinarily contain ack-eliciting
6044 /// frames, this method ensures that a PING frame sent.
6045 ///
6046 /// Calling this method multiple times before [`send()`] has no effect.
6047 ///
6048 /// [`send()`]: struct.Connection.html#method.send
6049 pub fn send_ack_eliciting(&mut self) -> Result<()> {
6050 if self.is_closed() || self.is_draining() {
6051 return Ok(());
6052 }
6053 self.paths.get_active_mut()?.needs_ack_eliciting = true;
6054 Ok(())
6055 }
6056
6057 /// Schedule an ack-eliciting packet on the specified path.
6058 ///
6059 /// See [`send_ack_eliciting()`] for more detail. [`InvalidState`] is
6060 /// returned if there is no record of the path.
6061 ///
6062 /// [`send_ack_eliciting()`]: struct.Connection.html#method.send_ack_eliciting
6063 /// [`InvalidState`]: enum.Error.html#variant.InvalidState
6064 pub fn send_ack_eliciting_on_path(
6065 &mut self, local: SocketAddr, peer: SocketAddr,
6066 ) -> Result<()> {
6067 if self.is_closed() || self.is_draining() {
6068 return Ok(());
6069 }
6070 let path_id = self
6071 .paths
6072 .path_id_from_addrs(&(local, peer))
6073 .ok_or(Error::InvalidState)?;
6074 self.paths.get_mut(path_id)?.needs_ack_eliciting = true;
6075 Ok(())
6076 }
6077
6078 /// Reads the first received DATAGRAM.
6079 ///
6080 /// On success the DATAGRAM's data is returned along with its size.
6081 ///
6082 /// [`Done`] is returned if there is no data to read.
6083 ///
6084 /// [`BufferTooShort`] is returned if the provided buffer is too small for
6085 /// the DATAGRAM.
6086 ///
6087 /// [`Done`]: enum.Error.html#variant.Done
6088 /// [`BufferTooShort`]: enum.Error.html#variant.BufferTooShort
6089 ///
6090 /// ## Examples:
6091 ///
6092 /// ```no_run
6093 /// # let mut buf = [0; 512];
6094 /// # let socket = std::net::UdpSocket::bind("127.0.0.1:0").unwrap();
6095 /// # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
6096 /// # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
6097 /// # let peer = "127.0.0.1:1234".parse().unwrap();
6098 /// # let local = socket.local_addr().unwrap();
6099 /// # let mut conn = quiche::accept(&scid, None, local, peer, &mut config)?;
6100 /// let mut dgram_buf = [0; 512];
6101 /// while let Ok((len)) = conn.dgram_recv(&mut dgram_buf) {
6102 /// println!("Got {} bytes of DATAGRAM", len);
6103 /// }
6104 /// # Ok::<(), quiche::Error>(())
6105 /// ```
6106 #[inline]
6107 pub fn dgram_recv(&mut self, buf: &mut [u8]) -> Result<usize> {
6108 match self.dgram_recv_queue.pop() {
6109 Some(d) => {
6110 if d.len() > buf.len() {
6111 return Err(Error::BufferTooShort);
6112 }
6113
6114 buf[..d.len()].copy_from_slice(&d);
6115 Ok(d.len())
6116 },
6117
6118 None => Err(Error::Done),
6119 }
6120 }
6121
6122 /// Reads the first received DATAGRAM.
6123 ///
6124 /// This is the same as [`dgram_recv()`] but returns the DATAGRAM as a
6125 /// `Vec<u8>` instead of copying into the provided buffer.
6126 ///
6127 /// [`dgram_recv()`]: struct.Connection.html#method.dgram_recv
6128 #[inline]
6129 pub fn dgram_recv_vec(&mut self) -> Result<Vec<u8>> {
6130 match self.dgram_recv_queue.pop() {
6131 Some(d) => Ok(d),
6132
6133 None => Err(Error::Done),
6134 }
6135 }
6136
6137 /// Reads the first received DATAGRAM without removing it from the queue.
6138 ///
6139 /// On success the DATAGRAM's data is returned along with the actual number
6140 /// of bytes peeked. The requested length cannot exceed the DATAGRAM's
6141 /// actual length.
6142 ///
6143 /// [`Done`] is returned if there is no data to read.
6144 ///
6145 /// [`BufferTooShort`] is returned if the provided buffer is smaller the
6146 /// number of bytes to peek.
6147 ///
6148 /// [`Done`]: enum.Error.html#variant.Done
6149 /// [`BufferTooShort`]: enum.Error.html#variant.BufferTooShort
6150 #[inline]
6151 pub fn dgram_recv_peek(&self, buf: &mut [u8], len: usize) -> Result<usize> {
6152 self.dgram_recv_queue.peek_front_bytes(buf, len)
6153 }
6154
6155 /// Returns the length of the first stored DATAGRAM.
6156 #[inline]
6157 pub fn dgram_recv_front_len(&self) -> Option<usize> {
6158 self.dgram_recv_queue.peek_front_len()
6159 }
6160
6161 /// Returns the number of items in the DATAGRAM receive queue.
6162 #[inline]
6163 pub fn dgram_recv_queue_len(&self) -> usize {
6164 self.dgram_recv_queue.len()
6165 }
6166
6167 /// Returns the total size of all items in the DATAGRAM receive queue.
6168 #[inline]
6169 pub fn dgram_recv_queue_byte_size(&self) -> usize {
6170 self.dgram_recv_queue.byte_size()
6171 }
6172
6173 /// Returns the number of items in the DATAGRAM send queue.
6174 #[inline]
6175 pub fn dgram_send_queue_len(&self) -> usize {
6176 self.dgram_send_queue.len()
6177 }
6178
6179 /// Returns the total size of all items in the DATAGRAM send queue.
6180 #[inline]
6181 pub fn dgram_send_queue_byte_size(&self) -> usize {
6182 self.dgram_send_queue.byte_size()
6183 }
6184
6185 /// Returns whether or not the DATAGRAM send queue is full.
6186 #[inline]
6187 pub fn is_dgram_send_queue_full(&self) -> bool {
6188 self.dgram_send_queue.is_full()
6189 }
6190
6191 /// Returns whether or not the DATAGRAM recv queue is full.
6192 #[inline]
6193 pub fn is_dgram_recv_queue_full(&self) -> bool {
6194 self.dgram_recv_queue.is_full()
6195 }
6196
6197 /// Sends data in a DATAGRAM frame.
6198 ///
6199 /// [`Done`] is returned if no data was written.
6200 /// [`InvalidState`] is returned if the peer does not support DATAGRAM.
6201 /// [`BufferTooShort`] is returned if the DATAGRAM frame length is larger
6202 /// than peer's supported DATAGRAM frame length. Use
6203 /// [`dgram_max_writable_len()`] to get the largest supported DATAGRAM
6204 /// frame length.
6205 ///
6206 /// Note that there is no flow control of DATAGRAM frames, so in order to
6207 /// avoid buffering an infinite amount of frames we apply an internal
6208 /// limit.
6209 ///
6210 /// [`Done`]: enum.Error.html#variant.Done
6211 /// [`InvalidState`]: enum.Error.html#variant.InvalidState
6212 /// [`BufferTooShort`]: enum.Error.html#variant.BufferTooShort
6213 /// [`dgram_max_writable_len()`]:
6214 /// struct.Connection.html#method.dgram_max_writable_len
6215 ///
6216 /// ## Examples:
6217 ///
6218 /// ```no_run
6219 /// # let mut buf = [0; 512];
6220 /// # let socket = std::net::UdpSocket::bind("127.0.0.1:0").unwrap();
6221 /// # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
6222 /// # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
6223 /// # let peer = "127.0.0.1:1234".parse().unwrap();
6224 /// # let local = socket.local_addr().unwrap();
6225 /// # let mut conn = quiche::accept(&scid, None, local, peer, &mut config)?;
6226 /// conn.dgram_send(b"hello")?;
6227 /// # Ok::<(), quiche::Error>(())
6228 /// ```
6229 pub fn dgram_send(&mut self, buf: &[u8]) -> Result<()> {
6230 let max_payload_len = match self.dgram_max_writable_len() {
6231 Some(v) => v,
6232
6233 None => return Err(Error::InvalidState),
6234 };
6235
6236 if buf.len() > max_payload_len {
6237 return Err(Error::BufferTooShort);
6238 }
6239
6240 self.dgram_send_queue.push(buf.to_vec())?;
6241
6242 let active_path = self.paths.get_active_mut()?;
6243
6244 if self.dgram_send_queue.byte_size() >
6245 active_path.recovery.cwnd_available()
6246 {
6247 active_path.recovery.update_app_limited(false);
6248 }
6249
6250 Ok(())
6251 }
6252
6253 /// Sends data in a DATAGRAM frame.
6254 ///
6255 /// This is the same as [`dgram_send()`] but takes a `Vec<u8>` instead of
6256 /// a slice.
6257 ///
6258 /// [`dgram_send()`]: struct.Connection.html#method.dgram_send
6259 pub fn dgram_send_vec(&mut self, buf: Vec<u8>) -> Result<()> {
6260 let max_payload_len = match self.dgram_max_writable_len() {
6261 Some(v) => v,
6262
6263 None => return Err(Error::InvalidState),
6264 };
6265
6266 if buf.len() > max_payload_len {
6267 return Err(Error::BufferTooShort);
6268 }
6269
6270 self.dgram_send_queue.push(buf)?;
6271
6272 let active_path = self.paths.get_active_mut()?;
6273
6274 if self.dgram_send_queue.byte_size() >
6275 active_path.recovery.cwnd_available()
6276 {
6277 active_path.recovery.update_app_limited(false);
6278 }
6279
6280 Ok(())
6281 }
6282
6283 /// Purges queued outgoing DATAGRAMs matching the predicate.
6284 ///
6285 /// In other words, remove all elements `e` such that `f(&e)` returns true.
6286 ///
6287 /// ## Examples:
6288 /// ```no_run
6289 /// # let socket = std::net::UdpSocket::bind("127.0.0.1:0").unwrap();
6290 /// # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
6291 /// # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
6292 /// # let peer = "127.0.0.1:1234".parse().unwrap();
6293 /// # let local = socket.local_addr().unwrap();
6294 /// # let mut conn = quiche::accept(&scid, None, local, peer, &mut config)?;
6295 /// conn.dgram_send(b"hello")?;
6296 /// conn.dgram_purge_outgoing(&|d: &[u8]| -> bool { d[0] == 0 });
6297 /// # Ok::<(), quiche::Error>(())
6298 /// ```
6299 #[inline]
6300 pub fn dgram_purge_outgoing<FN: Fn(&[u8]) -> bool>(&mut self, f: FN) {
6301 self.dgram_send_queue.purge(f);
6302 }
6303
6304 /// Returns the maximum DATAGRAM payload that can be sent.
6305 ///
6306 /// [`None`] is returned if the peer hasn't advertised a maximum DATAGRAM
6307 /// frame size.
6308 ///
6309 /// ## Examples:
6310 ///
6311 /// ```no_run
6312 /// # let mut buf = [0; 512];
6313 /// # let socket = std::net::UdpSocket::bind("127.0.0.1:0").unwrap();
6314 /// # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
6315 /// # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
6316 /// # let peer = "127.0.0.1:1234".parse().unwrap();
6317 /// # let local = socket.local_addr().unwrap();
6318 /// # let mut conn = quiche::accept(&scid, None, local, peer, &mut config)?;
6319 /// if let Some(payload_size) = conn.dgram_max_writable_len() {
6320 /// if payload_size > 5 {
6321 /// conn.dgram_send(b"hello")?;
6322 /// }
6323 /// }
6324 /// # Ok::<(), quiche::Error>(())
6325 /// ```
6326 #[inline]
6327 pub fn dgram_max_writable_len(&self) -> Option<usize> {
6328 match self.peer_transport_params.max_datagram_frame_size {
6329 None => None,
6330 Some(peer_frame_len) => {
6331 let dcid = self.destination_id();
6332 // Start from the maximum packet size...
6333 let mut max_len = self.max_send_udp_payload_size();
6334 // ...subtract the Short packet header overhead...
6335 // (1 byte of pkt_len + len of dcid)
6336 max_len = max_len.saturating_sub(1 + dcid.len());
6337 // ...subtract the packet number (max len)...
6338 max_len = max_len.saturating_sub(packet::MAX_PKT_NUM_LEN);
6339 // ...subtract the crypto overhead...
6340 max_len = max_len.saturating_sub(
6341 self.crypto_ctx[packet::Epoch::Application]
6342 .crypto_overhead()?,
6343 );
6344 // ...clamp to what peer can support...
6345 max_len = cmp::min(peer_frame_len as usize, max_len);
6346 // ...subtract frame overhead, checked for underflow.
6347 // (1 byte of frame type + len of length )
6348 max_len.checked_sub(1 + frame::MAX_DGRAM_OVERHEAD)
6349 },
6350 }
6351 }
6352
6353 fn dgram_enabled(&self) -> bool {
6354 self.local_transport_params
6355 .max_datagram_frame_size
6356 .is_some()
6357 }
6358
6359 /// Returns when the next timeout event will occur.
6360 ///
6361 /// Once the timeout Instant has been reached, the [`on_timeout()`] method
6362 /// should be called. A timeout of `None` means that the timer should be
6363 /// disarmed.
6364 ///
6365 /// [`on_timeout()`]: struct.Connection.html#method.on_timeout
6366 pub fn timeout_instant(&self) -> Option<Instant> {
6367 if self.is_closed() {
6368 return None;
6369 }
6370
6371 if self.is_draining() {
6372 // Draining timer takes precedence over all other timers. If it is
6373 // set it means the connection is closing so there's no point in
6374 // processing the other timers.
6375 self.draining_timer
6376 } else {
6377 // Use the lowest timer value (i.e. "sooner") among idle and loss
6378 // detection timers. If they are both unset (i.e. `None`) then the
6379 // result is `None`, but if at least one of them is set then a
6380 // `Some(...)` value is returned.
6381 let path_timer = self
6382 .paths
6383 .iter()
6384 .filter_map(|(_, p)| p.recovery.loss_detection_timer())
6385 .min();
6386
6387 let key_update_timer = self.crypto_ctx[packet::Epoch::Application]
6388 .key_update
6389 .as_ref()
6390 .map(|key_update| key_update.timer);
6391
6392 let timers = [self.idle_timer, path_timer, key_update_timer];
6393
6394 timers.iter().filter_map(|&x| x).min()
6395 }
6396 }
6397
6398 /// Returns the amount of time until the next timeout event.
6399 ///
6400 /// Once the given duration has elapsed, the [`on_timeout()`] method should
6401 /// be called. A timeout of `None` means that the timer should be disarmed.
6402 ///
6403 /// [`on_timeout()`]: struct.Connection.html#method.on_timeout
6404 pub fn timeout(&self) -> Option<Duration> {
6405 self.timeout_instant().map(|timeout| {
6406 let now = Instant::now();
6407
6408 if timeout <= now {
6409 Duration::ZERO
6410 } else {
6411 timeout.duration_since(now)
6412 }
6413 })
6414 }
6415
6416 /// Processes a timeout event.
6417 ///
6418 /// If no timeout has occurred it does nothing.
6419 pub fn on_timeout(&mut self) {
6420 let now = Instant::now();
6421
6422 if let Some(draining_timer) = self.draining_timer {
6423 if draining_timer <= now {
6424 trace!("{} draining timeout expired", self.trace_id);
6425
6426 self.mark_closed();
6427 }
6428
6429 // Draining timer takes precedence over all other timers. If it is
6430 // set it means the connection is closing so there's no point in
6431 // processing the other timers.
6432 return;
6433 }
6434
6435 if let Some(timer) = self.idle_timer {
6436 if timer <= now {
6437 trace!("{} idle timeout expired", self.trace_id);
6438
6439 self.mark_closed();
6440 self.timed_out = true;
6441 return;
6442 }
6443 }
6444
6445 if let Some(timer) = self.crypto_ctx[packet::Epoch::Application]
6446 .key_update
6447 .as_ref()
6448 .map(|key_update| key_update.timer)
6449 {
6450 if timer <= now {
6451 // Discard previous key once key update timer expired.
6452 let _ = self.crypto_ctx[packet::Epoch::Application]
6453 .key_update
6454 .take();
6455 }
6456 }
6457
6458 let handshake_status = self.handshake_status();
6459
6460 for (_, p) in self.paths.iter_mut() {
6461 if let Some(timer) = p.recovery.loss_detection_timer() {
6462 if timer <= now {
6463 trace!("{} loss detection timeout expired", self.trace_id);
6464
6465 let OnLossDetectionTimeoutOutcome {
6466 lost_packets,
6467 lost_bytes,
6468 } = p.on_loss_detection_timeout(
6469 handshake_status,
6470 now,
6471 self.is_server,
6472 &self.trace_id,
6473 );
6474
6475 self.lost_count += lost_packets;
6476 self.lost_bytes += lost_bytes as u64;
6477
6478 qlog_with_type!(QLOG_METRICS, self.qlog, q, {
6479 p.recovery.maybe_qlog(q, now);
6480 });
6481 }
6482 }
6483 }
6484
6485 // Notify timeout events to the application.
6486 self.paths.notify_failed_validations();
6487
6488 // If the active path failed, try to find a new candidate.
6489 if self.paths.get_active_path_id().is_err() {
6490 match self.paths.find_candidate_path() {
6491 Some(pid) => {
6492 if self.set_active_path(pid, now).is_err() {
6493 // The connection cannot continue.
6494 self.mark_closed();
6495 }
6496 },
6497
6498 // The connection cannot continue.
6499 None => {
6500 self.mark_closed();
6501 },
6502 }
6503 }
6504 }
6505
6506 /// Requests the stack to perform path validation of the proposed 4-tuple.
6507 ///
6508 /// Probing new paths requires spare Connection IDs at both the host and the
6509 /// peer sides. If it is not the case, it raises an [`OutOfIdentifiers`].
6510 ///
6511 /// The probing of new addresses can only be done by the client. The server
6512 /// can only probe network paths that were previously advertised by
6513 /// [`PathEvent::New`]. If the server tries to probe such an unseen network
6514 /// path, this call raises an [`InvalidState`].
6515 ///
6516 /// The caller might also want to probe an existing path. In such case, it
6517 /// triggers a PATH_CHALLENGE frame, but it does not require spare CIDs.
6518 ///
6519 /// A server always probes a new path it observes. Calling this method is
6520 /// hence not required to validate a new path. However, a server can still
6521 /// request an additional path validation of the proposed 4-tuple.
6522 ///
6523 /// Calling this method several times before calling [`send()`] or
6524 /// [`send_on_path()`] results in a single probe being generated. An
6525 /// application wanting to send multiple in-flight probes must call this
6526 /// method again after having sent packets.
6527 ///
6528 /// Returns the Destination Connection ID sequence number associated to that
6529 /// path.
6530 ///
6531 /// [`PathEvent::New`]: enum.PathEvent.html#variant.New
6532 /// [`OutOfIdentifiers`]: enum.Error.html#OutOfIdentifiers
6533 /// [`InvalidState`]: enum.Error.html#InvalidState
6534 /// [`send()`]: struct.Connection.html#method.send
6535 /// [`send_on_path()`]: struct.Connection.html#method.send_on_path
6536 pub fn probe_path(
6537 &mut self, local_addr: SocketAddr, peer_addr: SocketAddr,
6538 ) -> Result<u64> {
6539 // We may want to probe an existing path.
6540 let pid = match self.paths.path_id_from_addrs(&(local_addr, peer_addr)) {
6541 Some(pid) => pid,
6542 None => self.create_path_on_client(local_addr, peer_addr)?,
6543 };
6544
6545 let path = self.paths.get_mut(pid)?;
6546 path.request_validation();
6547
6548 path.active_dcid_seq.ok_or(Error::InvalidState)
6549 }
6550
6551 /// Migrates the connection to a new local address `local_addr`.
6552 ///
6553 /// The behavior is similar to [`migrate()`], with the nuance that the
6554 /// connection only changes the local address, but not the peer one.
6555 ///
6556 /// See [`migrate()`] for the full specification of this method.
6557 ///
6558 /// [`migrate()`]: struct.Connection.html#method.migrate
6559 pub fn migrate_source(&mut self, local_addr: SocketAddr) -> Result<u64> {
6560 let peer_addr = self.paths.get_active()?.peer_addr();
6561 self.migrate(local_addr, peer_addr)
6562 }
6563
6564 /// Migrates the connection over the given network path between `local_addr`
6565 /// and `peer_addr`.
6566 ///
6567 /// Connection migration can only be initiated by the client. Calling this
6568 /// method as a server returns [`InvalidState`].
6569 ///
6570 /// To initiate voluntary migration, there should be enough Connection IDs
6571 /// at both sides. If this requirement is not satisfied, this call returns
6572 /// [`OutOfIdentifiers`].
6573 ///
6574 /// Returns the Destination Connection ID associated to that migrated path.
6575 ///
6576 /// [`OutOfIdentifiers`]: enum.Error.html#OutOfIdentifiers
6577 /// [`InvalidState`]: enum.Error.html#InvalidState
6578 pub fn migrate(
6579 &mut self, local_addr: SocketAddr, peer_addr: SocketAddr,
6580 ) -> Result<u64> {
6581 if self.is_server {
6582 return Err(Error::InvalidState);
6583 }
6584
6585 // If the path already exists, mark it as the active one.
6586 let (pid, dcid_seq) = if let Some(pid) =
6587 self.paths.path_id_from_addrs(&(local_addr, peer_addr))
6588 {
6589 let path = self.paths.get_mut(pid)?;
6590
6591 // If it is already active, do nothing.
6592 if path.active() {
6593 return path.active_dcid_seq.ok_or(Error::OutOfIdentifiers);
6594 }
6595
6596 // Ensures that a Source Connection ID has been dedicated to this
6597 // path, or a free one is available. This is only required if the
6598 // host uses non-zero length Source Connection IDs.
6599 if !self.ids.zero_length_scid() &&
6600 path.active_scid_seq.is_none() &&
6601 self.ids.available_scids() == 0
6602 {
6603 return Err(Error::OutOfIdentifiers);
6604 }
6605
6606 // Ensures that the migrated path has a Destination Connection ID.
6607 let dcid_seq = if let Some(dcid_seq) = path.active_dcid_seq {
6608 dcid_seq
6609 } else {
6610 let dcid_seq = self
6611 .ids
6612 .lowest_available_dcid_seq()
6613 .ok_or(Error::OutOfIdentifiers)?;
6614
6615 self.ids.link_dcid_to_path_id(dcid_seq, pid)?;
6616 path.active_dcid_seq = Some(dcid_seq);
6617
6618 dcid_seq
6619 };
6620
6621 (pid, dcid_seq)
6622 } else {
6623 let pid = self.create_path_on_client(local_addr, peer_addr)?;
6624
6625 let dcid_seq = self
6626 .paths
6627 .get(pid)?
6628 .active_dcid_seq
6629 .ok_or(Error::InvalidState)?;
6630
6631 (pid, dcid_seq)
6632 };
6633
6634 // Change the active path.
6635 self.set_active_path(pid, Instant::now())?;
6636
6637 Ok(dcid_seq)
6638 }
6639
6640 /// Provides additional source Connection IDs that the peer can use to reach
6641 /// this host.
6642 ///
6643 /// This triggers sending NEW_CONNECTION_ID frames if the provided Source
6644 /// Connection ID is not already present. In the case the caller tries to
6645 /// reuse a Connection ID with a different reset token, this raises an
6646 /// `InvalidState`.
6647 ///
6648 /// At any time, the peer cannot have more Destination Connection IDs than
6649 /// the maximum number of active Connection IDs it negotiated. In such case
6650 /// (i.e., when [`scids_left()`] returns 0), if the host agrees to
6651 /// request the removal of previous connection IDs, it sets the
6652 /// `retire_if_needed` parameter. Otherwise, an [`IdLimit`] is returned.
6653 ///
6654 /// Note that setting `retire_if_needed` does not prevent this function from
6655 /// returning an [`IdLimit`] in the case the caller wants to retire still
6656 /// unannounced Connection IDs.
6657 ///
6658 /// The caller is responsible for ensuring that the provided `scid` is not
6659 /// repeated several times over the connection. quiche ensures that as long
6660 /// as the provided Connection ID is still in use (i.e., not retired), it
6661 /// does not assign a different sequence number.
6662 ///
6663 /// Note that if the host uses zero-length Source Connection IDs, it cannot
6664 /// advertise Source Connection IDs and calling this method returns an
6665 /// [`InvalidState`].
6666 ///
6667 /// Returns the sequence number associated to the provided Connection ID.
6668 ///
6669 /// [`scids_left()`]: struct.Connection.html#method.scids_left
6670 /// [`IdLimit`]: enum.Error.html#IdLimit
6671 /// [`InvalidState`]: enum.Error.html#InvalidState
6672 pub fn new_scid(
6673 &mut self, scid: &ConnectionId, reset_token: u128, retire_if_needed: bool,
6674 ) -> Result<u64> {
6675 self.ids.new_scid(
6676 scid.to_vec().into(),
6677 Some(reset_token),
6678 true,
6679 None,
6680 retire_if_needed,
6681 )
6682 }
6683
6684 /// Returns the number of source Connection IDs that are active. This is
6685 /// only meaningful if the host uses non-zero length Source Connection IDs.
6686 pub fn active_scids(&self) -> usize {
6687 self.ids.active_source_cids()
6688 }
6689
6690 /// Returns the number of source Connection IDs that should be provided
6691 /// to the peer without exceeding the limit it advertised.
6692 ///
6693 /// This will automatically limit the number of Connection IDs to the
6694 /// minimum between the locally configured active connection ID limit,
6695 /// and the one sent by the peer.
6696 ///
6697 /// To obtain the maximum possible value allowed by the peer an application
6698 /// can instead inspect the [`peer_active_conn_id_limit`] value.
6699 ///
6700 /// [`peer_active_conn_id_limit`]: struct.Stats.html#structfield.peer_active_conn_id_limit
6701 #[inline]
6702 pub fn scids_left(&self) -> usize {
6703 let max_active_source_cids = cmp::min(
6704 self.peer_transport_params.active_conn_id_limit,
6705 self.local_transport_params.active_conn_id_limit,
6706 ) as usize;
6707
6708 max_active_source_cids - self.active_scids()
6709 }
6710
6711 /// Requests the retirement of the destination Connection ID used by the
6712 /// host to reach its peer.
6713 ///
6714 /// This triggers sending RETIRE_CONNECTION_ID frames.
6715 ///
6716 /// If the application tries to retire a non-existing Destination Connection
6717 /// ID sequence number, or if it uses zero-length Destination Connection ID,
6718 /// this method returns an [`InvalidState`].
6719 ///
6720 /// At any time, the host must have at least one Destination ID. If the
6721 /// application tries to retire the last one, or if the caller tries to
6722 /// retire the destination Connection ID used by the current active path
6723 /// while having neither spare Destination Connection IDs nor validated
6724 /// network paths, this method returns an [`OutOfIdentifiers`]. This
6725 /// behavior prevents the caller from stalling the connection due to the
6726 /// lack of validated path to send non-probing packets.
6727 ///
6728 /// [`InvalidState`]: enum.Error.html#InvalidState
6729 /// [`OutOfIdentifiers`]: enum.Error.html#OutOfIdentifiers
6730 pub fn retire_dcid(&mut self, dcid_seq: u64) -> Result<()> {
6731 if self.ids.zero_length_dcid() {
6732 return Err(Error::InvalidState);
6733 }
6734
6735 let active_path_dcid_seq = self
6736 .paths
6737 .get_active()?
6738 .active_dcid_seq
6739 .ok_or(Error::InvalidState)?;
6740
6741 let active_path_id = self.paths.get_active_path_id()?;
6742
6743 if active_path_dcid_seq == dcid_seq &&
6744 self.ids.lowest_available_dcid_seq().is_none() &&
6745 !self
6746 .paths
6747 .iter()
6748 .any(|(pid, p)| pid != active_path_id && p.usable())
6749 {
6750 return Err(Error::OutOfIdentifiers);
6751 }
6752
6753 if let Some(pid) = self.ids.retire_dcid(dcid_seq)? {
6754 // The retired Destination CID was associated to a given path. Let's
6755 // find an available DCID to associate to that path.
6756 let path = self.paths.get_mut(pid)?;
6757 let dcid_seq = self.ids.lowest_available_dcid_seq();
6758
6759 if let Some(dcid_seq) = dcid_seq {
6760 self.ids.link_dcid_to_path_id(dcid_seq, pid)?;
6761 }
6762
6763 path.active_dcid_seq = dcid_seq;
6764 }
6765
6766 Ok(())
6767 }
6768
6769 /// Processes path-specific events.
6770 ///
6771 /// On success it returns a [`PathEvent`], or `None` when there are no
6772 /// events to report. Please refer to [`PathEvent`] for the exhaustive event
6773 /// list.
6774 ///
6775 /// Note that all events are edge-triggered, meaning that once reported they
6776 /// will not be reported again by calling this method again, until the event
6777 /// is re-armed.
6778 ///
6779 /// [`PathEvent`]: enum.PathEvent.html
6780 pub fn path_event_next(&mut self) -> Option<PathEvent> {
6781 self.paths.pop_event()
6782 }
6783
6784 /// Returns the number of source Connection IDs that are retired.
6785 pub fn retired_scids(&self) -> usize {
6786 self.ids.retired_source_cids()
6787 }
6788
6789 /// Returns a source `ConnectionId` that has been retired.
6790 ///
6791 /// On success it returns a [`ConnectionId`], or `None` when there are no
6792 /// more retired connection IDs.
6793 ///
6794 /// [`ConnectionId`]: struct.ConnectionId.html
6795 pub fn retired_scid_next(&mut self) -> Option<ConnectionId<'static>> {
6796 self.ids.pop_retired_scid()
6797 }
6798
6799 /// Returns the number of spare Destination Connection IDs, i.e.,
6800 /// Destination Connection IDs that are still unused.
6801 ///
6802 /// Note that this function returns 0 if the host uses zero length
6803 /// Destination Connection IDs.
6804 pub fn available_dcids(&self) -> usize {
6805 self.ids.available_dcids()
6806 }
6807
6808 /// Returns an iterator over destination `SockAddr`s whose association
6809 /// with `from` forms a known QUIC path on which packets can be sent to.
6810 ///
6811 /// This function is typically used in combination with [`send_on_path()`].
6812 ///
6813 /// Note that the iterator includes all the possible combination of
6814 /// destination `SockAddr`s, even those whose sending is not required now.
6815 /// In other words, this is another way for the application to recall from
6816 /// past [`PathEvent::New`] events.
6817 ///
6818 /// [`PathEvent::New`]: enum.PathEvent.html#variant.New
6819 /// [`send_on_path()`]: struct.Connection.html#method.send_on_path
6820 ///
6821 /// ## Examples:
6822 ///
6823 /// ```no_run
6824 /// # let mut out = [0; 512];
6825 /// # let socket = std::net::UdpSocket::bind("127.0.0.1:0").unwrap();
6826 /// # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
6827 /// # let scid = quiche::ConnectionId::from_ref(&[0xba; 16]);
6828 /// # let local = socket.local_addr().unwrap();
6829 /// # let peer = "127.0.0.1:1234".parse().unwrap();
6830 /// # let mut conn = quiche::accept(&scid, None, local, peer, &mut config)?;
6831 /// // Iterate over possible destinations for the given local `SockAddr`.
6832 /// for dest in conn.paths_iter(local) {
6833 /// loop {
6834 /// let (write, send_info) =
6835 /// match conn.send_on_path(&mut out, Some(local), Some(dest)) {
6836 /// Ok(v) => v,
6837 ///
6838 /// Err(quiche::Error::Done) => {
6839 /// // Done writing for this destination.
6840 /// break;
6841 /// },
6842 ///
6843 /// Err(e) => {
6844 /// // An error occurred, handle it.
6845 /// break;
6846 /// },
6847 /// };
6848 ///
6849 /// socket.send_to(&out[..write], &send_info.to).unwrap();
6850 /// }
6851 /// }
6852 /// # Ok::<(), quiche::Error>(())
6853 /// ```
6854 #[inline]
6855 pub fn paths_iter(&self, from: SocketAddr) -> SocketAddrIter {
6856 // Instead of trying to identify whether packets will be sent on the
6857 // given 4-tuple, simply filter paths that cannot be used.
6858 SocketAddrIter {
6859 sockaddrs: self
6860 .paths
6861 .iter()
6862 .filter(|(_, p)| p.active_dcid_seq.is_some())
6863 .filter(|(_, p)| p.usable() || p.probing_required())
6864 .filter(|(_, p)| p.local_addr() == from)
6865 .map(|(_, p)| p.peer_addr())
6866 .collect(),
6867
6868 index: 0,
6869 }
6870 }
6871
6872 /// Closes the connection with the given error and reason.
6873 ///
6874 /// The `app` parameter specifies whether an application close should be
6875 /// sent to the peer. Otherwise a normal connection close is sent.
6876 ///
6877 /// If `app` is true but the connection is not in a state that is safe to
6878 /// send an application error (not established nor in early data), in
6879 /// accordance with [RFC
6880 /// 9000](https://www.rfc-editor.org/rfc/rfc9000.html#section-10.2.3-3), the
6881 /// error code is changed to APPLICATION_ERROR and the reason phrase is
6882 /// cleared.
6883 ///
6884 /// Returns [`Done`] if the connection had already been closed.
6885 ///
6886 /// Note that the connection will not be closed immediately. An application
6887 /// should continue calling the [`recv()`], [`send()`], [`timeout()`] and
6888 /// [`on_timeout()`] methods as normal, until the [`is_closed()`] method
6889 /// returns `true`.
6890 ///
6891 /// [`Done`]: enum.Error.html#variant.Done
6892 /// [`recv()`]: struct.Connection.html#method.recv
6893 /// [`send()`]: struct.Connection.html#method.send
6894 /// [`timeout()`]: struct.Connection.html#method.timeout
6895 /// [`on_timeout()`]: struct.Connection.html#method.on_timeout
6896 /// [`is_closed()`]: struct.Connection.html#method.is_closed
6897 pub fn close(&mut self, app: bool, err: u64, reason: &[u8]) -> Result<()> {
6898 if self.is_closed() || self.is_draining() {
6899 return Err(Error::Done);
6900 }
6901
6902 if self.local_error.is_some() {
6903 return Err(Error::Done);
6904 }
6905
6906 let is_safe_to_send_app_data =
6907 self.is_established() || self.is_in_early_data();
6908
6909 if app && !is_safe_to_send_app_data {
6910 // Clear error information.
6911 self.local_error = Some(ConnectionError {
6912 is_app: false,
6913 error_code: 0x0c,
6914 reason: vec![],
6915 });
6916 } else {
6917 self.local_error = Some(ConnectionError {
6918 is_app: app,
6919 error_code: err,
6920 reason: reason.to_vec(),
6921 });
6922 }
6923
6924 // When no packet was successfully processed close connection immediately.
6925 if self.recv_count == 0 {
6926 self.mark_closed();
6927 }
6928
6929 Ok(())
6930 }
6931
6932 /// Returns a string uniquely representing the connection.
6933 ///
6934 /// This can be used for logging purposes to differentiate between multiple
6935 /// connections.
6936 #[inline]
6937 pub fn trace_id(&self) -> &str {
6938 &self.trace_id
6939 }
6940
6941 /// Returns the negotiated ALPN protocol.
6942 ///
6943 /// If no protocol has been negotiated, the returned value is empty.
6944 #[inline]
6945 pub fn application_proto(&self) -> &[u8] {
6946 self.alpn.as_ref()
6947 }
6948
6949 /// Returns the server name requested by the client.
6950 #[inline]
6951 pub fn server_name(&self) -> Option<&str> {
6952 self.handshake.server_name()
6953 }
6954
6955 /// Returns the peer's leaf certificate (if any) as a DER-encoded buffer.
6956 #[inline]
6957 pub fn peer_cert(&self) -> Option<&[u8]> {
6958 self.handshake.peer_cert()
6959 }
6960
6961 /// Returns the peer's certificate chain (if any) as a vector of DER-encoded
6962 /// buffers.
6963 ///
6964 /// The certificate at index 0 is the peer's leaf certificate, the other
6965 /// certificates (if any) are the chain certificate authorities used to
6966 /// sign the leaf certificate.
6967 #[inline]
6968 pub fn peer_cert_chain(&self) -> Option<Vec<&[u8]>> {
6969 self.handshake.peer_cert_chain()
6970 }
6971
6972 /// Returns the serialized cryptographic session for the connection.
6973 ///
6974 /// This can be used by a client to cache a connection's session, and resume
6975 /// it later using the [`set_session()`] method.
6976 ///
6977 /// [`set_session()`]: struct.Connection.html#method.set_session
6978 #[inline]
6979 pub fn session(&self) -> Option<&[u8]> {
6980 self.session.as_deref()
6981 }
6982
6983 /// Returns the source connection ID.
6984 ///
6985 /// When there are multiple IDs, and if there is an active path, the ID used
6986 /// on that path is returned. Otherwise the oldest ID is returned.
6987 ///
6988 /// Note that the value returned can change throughout the connection's
6989 /// lifetime.
6990 #[inline]
6991 pub fn source_id(&self) -> ConnectionId<'_> {
6992 if let Ok(path) = self.paths.get_active() {
6993 if let Some(active_scid_seq) = path.active_scid_seq {
6994 if let Ok(e) = self.ids.get_scid(active_scid_seq) {
6995 return ConnectionId::from_ref(e.cid.as_ref());
6996 }
6997 }
6998 }
6999
7000 let e = self.ids.oldest_scid();
7001 ConnectionId::from_ref(e.cid.as_ref())
7002 }
7003
7004 /// Returns all active source connection IDs.
7005 ///
7006 /// An iterator is returned for all active IDs (i.e. ones that have not
7007 /// been explicitly retired yet).
7008 #[inline]
7009 pub fn source_ids(&self) -> impl Iterator<Item = &ConnectionId<'_>> {
7010 self.ids.scids_iter()
7011 }
7012
7013 /// Returns the destination connection ID.
7014 ///
7015 /// Note that the value returned can change throughout the connection's
7016 /// lifetime.
7017 #[inline]
7018 pub fn destination_id(&self) -> ConnectionId<'_> {
7019 if let Ok(path) = self.paths.get_active() {
7020 if let Some(active_dcid_seq) = path.active_dcid_seq {
7021 if let Ok(e) = self.ids.get_dcid(active_dcid_seq) {
7022 return ConnectionId::from_ref(e.cid.as_ref());
7023 }
7024 }
7025 }
7026
7027 let e = self.ids.oldest_dcid();
7028 ConnectionId::from_ref(e.cid.as_ref())
7029 }
7030
7031 /// Returns the PMTU for the active path if it exists.
7032 ///
7033 /// This requires no additonal packets to be sent but simply checks if PMTUD
7034 /// has completed and has found a valid PMTU.
7035 #[inline]
7036 pub fn pmtu(&self) -> Option<usize> {
7037 if let Ok(path) = self.paths.get_active() {
7038 path.pmtud.as_ref().and_then(|pmtud| pmtud.get_pmtu())
7039 } else {
7040 None
7041 }
7042 }
7043
7044 /// Revalidates the PMTU for the active path by sending a new probe packet
7045 /// of PMTU size. If the probe is dropped PMTUD will restart and find a new
7046 /// valid PMTU.
7047 #[inline]
7048 pub fn revalidate_pmtu(&mut self) {
7049 if let Ok(active_path) = self.paths.get_active_mut() {
7050 if let Some(pmtud) = active_path.pmtud.as_mut() {
7051 pmtud.revalidate_pmtu();
7052 }
7053 }
7054 }
7055
7056 /// Returns true if the connection handshake is complete.
7057 #[inline]
7058 pub fn is_established(&self) -> bool {
7059 self.handshake_completed
7060 }
7061
7062 /// Returns true if the connection is resumed.
7063 #[inline]
7064 pub fn is_resumed(&self) -> bool {
7065 self.handshake.is_resumed()
7066 }
7067
7068 /// Returns true if the connection has a pending handshake that has
7069 /// progressed enough to send or receive early data.
7070 #[inline]
7071 pub fn is_in_early_data(&self) -> bool {
7072 self.handshake.is_in_early_data()
7073 }
7074
7075 /// Returns the early data reason for the connection.
7076 ///
7077 /// This status can be useful for logging and debugging. See [BoringSSL]
7078 /// documentation for a definition of the reasons.
7079 ///
7080 /// [BoringSSL]: https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#ssl_early_data_reason_t
7081 #[inline]
7082 pub fn early_data_reason(&self) -> u32 {
7083 self.handshake.early_data_reason()
7084 }
7085
7086 /// Returns whether there is stream or DATAGRAM data available to read.
7087 #[inline]
7088 pub fn is_readable(&self) -> bool {
7089 self.streams.has_readable() || self.dgram_recv_front_len().is_some()
7090 }
7091
7092 /// Returns whether the network path with local address `from` and remote
7093 /// address `peer` has been validated.
7094 ///
7095 /// If the 4-tuple does not exist over the connection, returns an
7096 /// [`InvalidState`].
7097 ///
7098 /// [`InvalidState`]: enum.Error.html#variant.InvalidState
7099 pub fn is_path_validated(
7100 &self, from: SocketAddr, to: SocketAddr,
7101 ) -> Result<bool> {
7102 let pid = self
7103 .paths
7104 .path_id_from_addrs(&(from, to))
7105 .ok_or(Error::InvalidState)?;
7106
7107 Ok(self.paths.get(pid)?.validated())
7108 }
7109
7110 /// Returns true if the connection is draining.
7111 ///
7112 /// If this returns `true`, the connection object cannot yet be dropped, but
7113 /// no new application data can be sent or received. An application should
7114 /// continue calling the [`recv()`], [`timeout()`], and [`on_timeout()`]
7115 /// methods as normal, until the [`is_closed()`] method returns `true`.
7116 ///
7117 /// In contrast, once `is_draining()` returns `true`, calling [`send()`]
7118 /// is not required because no new outgoing packets will be generated.
7119 ///
7120 /// [`recv()`]: struct.Connection.html#method.recv
7121 /// [`send()`]: struct.Connection.html#method.send
7122 /// [`timeout()`]: struct.Connection.html#method.timeout
7123 /// [`on_timeout()`]: struct.Connection.html#method.on_timeout
7124 /// [`is_closed()`]: struct.Connection.html#method.is_closed
7125 #[inline]
7126 pub fn is_draining(&self) -> bool {
7127 self.draining_timer.is_some()
7128 }
7129
7130 /// Returns true if the connection is closed.
7131 ///
7132 /// If this returns true, the connection object can be dropped.
7133 #[inline]
7134 pub fn is_closed(&self) -> bool {
7135 self.closed
7136 }
7137
7138 /// Returns true if the connection was closed due to the idle timeout.
7139 #[inline]
7140 pub fn is_timed_out(&self) -> bool {
7141 self.timed_out
7142 }
7143
7144 /// Returns the error received from the peer, if any.
7145 ///
7146 /// Note that a `Some` return value does not necessarily imply
7147 /// [`is_closed()`] or any other connection state.
7148 ///
7149 /// [`is_closed()`]: struct.Connection.html#method.is_closed
7150 #[inline]
7151 pub fn peer_error(&self) -> Option<&ConnectionError> {
7152 self.peer_error.as_ref()
7153 }
7154
7155 /// Returns the error [`close()`] was called with, or internally
7156 /// created quiche errors, if any.
7157 ///
7158 /// Note that a `Some` return value does not necessarily imply
7159 /// [`is_closed()`] or any other connection state.
7160 /// `Some` also does not guarantee that the error has been sent to
7161 /// or received by the peer.
7162 ///
7163 /// [`close()`]: struct.Connection.html#method.close
7164 /// [`is_closed()`]: struct.Connection.html#method.is_closed
7165 #[inline]
7166 pub fn local_error(&self) -> Option<&ConnectionError> {
7167 self.local_error.as_ref()
7168 }
7169
7170 /// Collects and returns statistics about the connection.
7171 #[inline]
7172 pub fn stats(&self) -> Stats {
7173 Stats {
7174 recv: self.recv_count,
7175 sent: self.sent_count,
7176 lost: self.lost_count,
7177 spurious_lost: self.spurious_lost_count,
7178 retrans: self.retrans_count,
7179 sent_bytes: self.sent_bytes,
7180 recv_bytes: self.recv_bytes,
7181 acked_bytes: self.acked_bytes,
7182 lost_bytes: self.lost_bytes,
7183 stream_retrans_bytes: self.stream_retrans_bytes,
7184 dgram_recv: self.dgram_recv_count,
7185 dgram_sent: self.dgram_sent_count,
7186 paths_count: self.paths.len(),
7187 reset_stream_count_local: self.reset_stream_local_count,
7188 stopped_stream_count_local: self.stopped_stream_local_count,
7189 reset_stream_count_remote: self.reset_stream_remote_count,
7190 stopped_stream_count_remote: self.stopped_stream_remote_count,
7191 data_blocked_sent_count: self.data_blocked_sent_count,
7192 stream_data_blocked_sent_count: self.stream_data_blocked_sent_count,
7193 data_blocked_recv_count: self.data_blocked_recv_count,
7194 stream_data_blocked_recv_count: self.stream_data_blocked_recv_count,
7195 path_challenge_rx_count: self.path_challenge_rx_count,
7196 bytes_in_flight_duration: self.bytes_in_flight_duration(),
7197 tx_buffered_state: self.tx_buffered_state,
7198 }
7199 }
7200
7201 /// Returns the sum of the durations when each path in the
7202 /// connection was actively sending bytes or waiting for acks.
7203 /// Note that this could result in a duration that is longer than
7204 /// the actual connection duration in cases where multiple paths
7205 /// are active for extended periods of time. In practice only 1
7206 /// path is typically active at a time.
7207 /// TODO revisit computation if in the future multiple paths are
7208 /// often active at the same time.
7209 fn bytes_in_flight_duration(&self) -> Duration {
7210 self.paths.iter().fold(Duration::ZERO, |acc, (_, path)| {
7211 acc + path.bytes_in_flight_duration()
7212 })
7213 }
7214
7215 /// Returns reference to peer's transport parameters. Returns `None` if we
7216 /// have not yet processed the peer's transport parameters.
7217 pub fn peer_transport_params(&self) -> Option<&TransportParams> {
7218 if !self.parsed_peer_transport_params {
7219 return None;
7220 }
7221
7222 Some(&self.peer_transport_params)
7223 }
7224
7225 /// Collects and returns statistics about each known path for the
7226 /// connection.
7227 pub fn path_stats(&self) -> impl Iterator<Item = PathStats> + '_ {
7228 self.paths.iter().map(|(_, p)| p.stats())
7229 }
7230
7231 /// Returns whether or not this is a server-side connection.
7232 pub fn is_server(&self) -> bool {
7233 self.is_server
7234 }
7235
7236 fn encode_transport_params(&mut self) -> Result<()> {
7237 self.handshake.set_quic_transport_params(
7238 &self.local_transport_params,
7239 self.is_server,
7240 )
7241 }
7242
7243 fn parse_peer_transport_params(
7244 &mut self, peer_params: TransportParams,
7245 ) -> Result<()> {
7246 // Validate initial_source_connection_id.
7247 match &peer_params.initial_source_connection_id {
7248 Some(v) if v != &self.destination_id() =>
7249 return Err(Error::InvalidTransportParam),
7250
7251 Some(_) => (),
7252
7253 // initial_source_connection_id must be sent by
7254 // both endpoints.
7255 None => return Err(Error::InvalidTransportParam),
7256 }
7257
7258 // Validate original_destination_connection_id.
7259 if let Some(odcid) = &self.odcid {
7260 match &peer_params.original_destination_connection_id {
7261 Some(v) if v != odcid =>
7262 return Err(Error::InvalidTransportParam),
7263
7264 Some(_) => (),
7265
7266 // original_destination_connection_id must be
7267 // sent by the server.
7268 None if !self.is_server =>
7269 return Err(Error::InvalidTransportParam),
7270
7271 None => (),
7272 }
7273 }
7274
7275 // Validate retry_source_connection_id.
7276 if let Some(rscid) = &self.rscid {
7277 match &peer_params.retry_source_connection_id {
7278 Some(v) if v != rscid =>
7279 return Err(Error::InvalidTransportParam),
7280
7281 Some(_) => (),
7282
7283 // retry_source_connection_id must be sent by
7284 // the server.
7285 None => return Err(Error::InvalidTransportParam),
7286 }
7287 }
7288
7289 self.process_peer_transport_params(peer_params)?;
7290
7291 self.parsed_peer_transport_params = true;
7292
7293 Ok(())
7294 }
7295
7296 fn process_peer_transport_params(
7297 &mut self, peer_params: TransportParams,
7298 ) -> Result<()> {
7299 self.max_tx_data = peer_params.initial_max_data;
7300
7301 // Update send capacity.
7302 self.update_tx_cap();
7303
7304 self.streams
7305 .update_peer_max_streams_bidi(peer_params.initial_max_streams_bidi);
7306 self.streams
7307 .update_peer_max_streams_uni(peer_params.initial_max_streams_uni);
7308
7309 let max_ack_delay = Duration::from_millis(peer_params.max_ack_delay);
7310
7311 self.recovery_config.max_ack_delay = max_ack_delay;
7312
7313 let active_path = self.paths.get_active_mut()?;
7314
7315 active_path.recovery.update_max_ack_delay(max_ack_delay);
7316
7317 if active_path
7318 .pmtud
7319 .as_ref()
7320 .map(|pmtud| pmtud.should_probe())
7321 .unwrap_or(false)
7322 {
7323 active_path.recovery.pmtud_update_max_datagram_size(
7324 active_path
7325 .pmtud
7326 .as_mut()
7327 .expect("PMTUD existence verified above")
7328 .get_probe_size()
7329 .min(peer_params.max_udp_payload_size as usize),
7330 );
7331 } else {
7332 active_path.recovery.update_max_datagram_size(
7333 peer_params.max_udp_payload_size as usize,
7334 );
7335 }
7336
7337 // Record the max_active_conn_id parameter advertised by the peer.
7338 self.ids
7339 .set_source_conn_id_limit(peer_params.active_conn_id_limit);
7340
7341 self.peer_transport_params = peer_params;
7342
7343 Ok(())
7344 }
7345
7346 /// Continues the handshake.
7347 ///
7348 /// If the connection is already established, it does nothing.
7349 fn do_handshake(&mut self, now: Instant) -> Result<()> {
7350 let mut ex_data = tls::ExData {
7351 application_protos: &self.application_protos,
7352
7353 crypto_ctx: &mut self.crypto_ctx,
7354
7355 session: &mut self.session,
7356
7357 local_error: &mut self.local_error,
7358
7359 keylog: self.keylog.as_mut(),
7360
7361 trace_id: &self.trace_id,
7362
7363 local_transport_params: self.local_transport_params.clone(),
7364
7365 recovery_config: self.recovery_config,
7366
7367 tx_cap_factor: self.tx_cap_factor,
7368
7369 pmtud: None,
7370
7371 is_server: self.is_server,
7372 };
7373
7374 if self.handshake_completed {
7375 return self.handshake.process_post_handshake(&mut ex_data);
7376 }
7377
7378 match self.handshake.do_handshake(&mut ex_data) {
7379 Ok(_) => (),
7380
7381 Err(Error::Done) => {
7382 // Apply in-handshake configuration from callbacks before any
7383 // packet has been sent.
7384 if self.sent_count == 0 {
7385 if ex_data.recovery_config != self.recovery_config {
7386 if let Ok(path) = self.paths.get_active_mut() {
7387 self.recovery_config = ex_data.recovery_config;
7388 path.reinit_recovery(&self.recovery_config);
7389 }
7390 }
7391
7392 if ex_data.tx_cap_factor != self.tx_cap_factor {
7393 self.tx_cap_factor = ex_data.tx_cap_factor;
7394 }
7395
7396 if let Some(discover) = ex_data.pmtud {
7397 self.paths.set_discover_pmtu_on_existing_paths(
7398 discover,
7399 self.recovery_config.max_send_udp_payload_size,
7400 );
7401 }
7402
7403 if ex_data.local_transport_params !=
7404 self.local_transport_params
7405 {
7406 self.streams.set_max_streams_bidi(
7407 ex_data
7408 .local_transport_params
7409 .initial_max_streams_bidi,
7410 );
7411
7412 self.local_transport_params =
7413 ex_data.local_transport_params;
7414 }
7415 }
7416
7417 // Try to parse transport parameters as soon as the first flight
7418 // of handshake data is processed.
7419 //
7420 // This is potentially dangerous as the handshake hasn't been
7421 // completed yet, though it's required to be able to send data
7422 // in 0.5 RTT.
7423 let raw_params = self.handshake.quic_transport_params();
7424
7425 if !self.parsed_peer_transport_params && !raw_params.is_empty() {
7426 let peer_params = TransportParams::decode(
7427 raw_params,
7428 self.is_server,
7429 self.peer_transport_params_track_unknown,
7430 )?;
7431
7432 self.parse_peer_transport_params(peer_params)?;
7433 }
7434
7435 return Ok(());
7436 },
7437
7438 Err(e) => return Err(e),
7439 };
7440
7441 self.handshake_completed = self.handshake.is_completed();
7442
7443 self.alpn = self.handshake.alpn_protocol().to_vec();
7444
7445 let raw_params = self.handshake.quic_transport_params();
7446
7447 if !self.parsed_peer_transport_params && !raw_params.is_empty() {
7448 let peer_params = TransportParams::decode(
7449 raw_params,
7450 self.is_server,
7451 self.peer_transport_params_track_unknown,
7452 )?;
7453
7454 self.parse_peer_transport_params(peer_params)?;
7455 }
7456
7457 if self.handshake_completed {
7458 // The handshake is considered confirmed at the server when the
7459 // handshake completes, at which point we can also drop the
7460 // handshake epoch.
7461 if self.is_server {
7462 self.handshake_confirmed = true;
7463
7464 self.drop_epoch_state(packet::Epoch::Handshake, now);
7465 }
7466
7467 // Once the handshake is completed there's no point in processing
7468 // 0-RTT packets anymore, so clear the buffer now.
7469 self.undecryptable_pkts.clear();
7470
7471 trace!("{} connection established: proto={:?} cipher={:?} curve={:?} sigalg={:?} resumed={} {:?}",
7472 &self.trace_id,
7473 std::str::from_utf8(self.application_proto()),
7474 self.handshake.cipher(),
7475 self.handshake.curve(),
7476 self.handshake.sigalg(),
7477 self.handshake.is_resumed(),
7478 self.peer_transport_params);
7479 }
7480
7481 Ok(())
7482 }
7483
7484 /// Selects the packet type for the next outgoing packet.
7485 fn write_pkt_type(&self, send_pid: usize) -> Result<Type> {
7486 // On error send packet in the latest epoch available, but only send
7487 // 1-RTT ones when the handshake is completed.
7488 if self
7489 .local_error
7490 .as_ref()
7491 .is_some_and(|conn_err| !conn_err.is_app)
7492 {
7493 let epoch = match self.handshake.write_level() {
7494 crypto::Level::Initial => packet::Epoch::Initial,
7495 crypto::Level::ZeroRTT => unreachable!(),
7496 crypto::Level::Handshake => packet::Epoch::Handshake,
7497 crypto::Level::OneRTT => packet::Epoch::Application,
7498 };
7499
7500 if !self.handshake_confirmed {
7501 match epoch {
7502 // Downgrade the epoch to Handshake as the handshake is not
7503 // completed yet.
7504 packet::Epoch::Application => return Ok(Type::Handshake),
7505
7506 // Downgrade the epoch to Initial as the remote peer might
7507 // not be able to decrypt handshake packets yet.
7508 packet::Epoch::Handshake
7509 if self.crypto_ctx[packet::Epoch::Initial].has_keys() =>
7510 return Ok(Type::Initial),
7511
7512 _ => (),
7513 };
7514 }
7515
7516 return Ok(Type::from_epoch(epoch));
7517 }
7518
7519 for &epoch in packet::Epoch::epochs(
7520 packet::Epoch::Initial..=packet::Epoch::Application,
7521 ) {
7522 let crypto_ctx = &self.crypto_ctx[epoch];
7523 let pkt_space = &self.pkt_num_spaces[epoch];
7524
7525 // Only send packets in a space when we have the send keys for it.
7526 if crypto_ctx.crypto_seal.is_none() {
7527 continue;
7528 }
7529
7530 // We are ready to send data for this packet number space.
7531 if crypto_ctx.data_available() || pkt_space.ready() {
7532 return Ok(Type::from_epoch(epoch));
7533 }
7534
7535 // There are lost frames in this packet number space.
7536 for (_, p) in self.paths.iter() {
7537 if p.recovery.has_lost_frames(epoch) {
7538 return Ok(Type::from_epoch(epoch));
7539 }
7540
7541 // We need to send PTO probe packets.
7542 if p.recovery.loss_probes(epoch) > 0 {
7543 return Ok(Type::from_epoch(epoch));
7544 }
7545 }
7546 }
7547
7548 // If there are flushable, almost full or blocked streams, use the
7549 // Application epoch.
7550 let send_path = self.paths.get(send_pid)?;
7551 if (self.is_established() || self.is_in_early_data()) &&
7552 (self.should_send_handshake_done() ||
7553 self.almost_full ||
7554 self.blocked_limit.is_some() ||
7555 self.dgram_send_queue.has_pending() ||
7556 self.local_error
7557 .as_ref()
7558 .is_some_and(|conn_err| conn_err.is_app) ||
7559 self.streams.should_update_max_streams_bidi() ||
7560 self.streams.should_update_max_streams_uni() ||
7561 self.streams.has_flushable() ||
7562 self.streams.has_almost_full() ||
7563 self.streams.has_blocked() ||
7564 self.streams.has_reset() ||
7565 self.streams.has_stopped() ||
7566 self.ids.has_new_scids() ||
7567 self.ids.has_retire_dcids() ||
7568 send_path
7569 .pmtud
7570 .as_ref()
7571 .is_some_and(|pmtud| pmtud.should_probe()) ||
7572 send_path.needs_ack_eliciting ||
7573 send_path.probing_required())
7574 {
7575 // Only clients can send 0-RTT packets.
7576 if !self.is_server && self.is_in_early_data() {
7577 return Ok(Type::ZeroRTT);
7578 }
7579
7580 return Ok(Type::Short);
7581 }
7582
7583 Err(Error::Done)
7584 }
7585
7586 /// Returns the mutable stream with the given ID if it exists, or creates
7587 /// a new one otherwise.
7588 fn get_or_create_stream(
7589 &mut self, id: u64, local: bool,
7590 ) -> Result<&mut stream::Stream<F>> {
7591 self.streams.get_or_create(
7592 id,
7593 &self.local_transport_params,
7594 &self.peer_transport_params,
7595 local,
7596 self.is_server,
7597 )
7598 }
7599
7600 /// Processes an incoming frame.
7601 fn process_frame(
7602 &mut self, frame: frame::Frame, hdr: &Header, recv_path_id: usize,
7603 epoch: packet::Epoch, now: Instant,
7604 ) -> Result<()> {
7605 trace!("{} rx frm {:?}", self.trace_id, frame);
7606
7607 match frame {
7608 frame::Frame::Padding { .. } => (),
7609
7610 frame::Frame::Ping { .. } => (),
7611
7612 frame::Frame::ACK {
7613 ranges, ack_delay, ..
7614 } => {
7615 let ack_delay = ack_delay
7616 .checked_mul(2_u64.pow(
7617 self.peer_transport_params.ack_delay_exponent as u32,
7618 ))
7619 .ok_or(Error::InvalidFrame)?;
7620
7621 if epoch == packet::Epoch::Handshake ||
7622 (epoch == packet::Epoch::Application &&
7623 self.is_established())
7624 {
7625 self.peer_verified_initial_address = true;
7626 }
7627
7628 let handshake_status = self.handshake_status();
7629
7630 let is_app_limited = self.delivery_rate_check_if_app_limited();
7631
7632 let largest_acked = ranges.last().expect(
7633 "ACK frames should always have at least one ack range",
7634 );
7635
7636 for (_, p) in self.paths.iter_mut() {
7637 if self.pkt_num_spaces[epoch]
7638 .largest_tx_pkt_num
7639 .is_some_and(|largest_sent| largest_sent < largest_acked)
7640 {
7641 // https://www.rfc-editor.org/rfc/rfc9000#section-13.1
7642 // An endpoint SHOULD treat receipt of an acknowledgment
7643 // for a packet it did not send as
7644 // a connection error of type PROTOCOL_VIOLATION
7645 return Err(Error::InvalidAckRange);
7646 }
7647
7648 if is_app_limited {
7649 p.recovery.delivery_rate_update_app_limited(true);
7650 }
7651
7652 let OnAckReceivedOutcome {
7653 lost_packets,
7654 lost_bytes,
7655 acked_bytes,
7656 spurious_losses,
7657 } = p.recovery.on_ack_received(
7658 &ranges,
7659 ack_delay,
7660 epoch,
7661 handshake_status,
7662 now,
7663 self.pkt_num_manager.skip_pn(),
7664 &self.trace_id,
7665 )?;
7666
7667 let skip_pn = self.pkt_num_manager.skip_pn();
7668 let largest_acked =
7669 p.recovery.get_largest_acked_on_epoch(epoch);
7670
7671 // Consider the skip_pn validated if the peer has sent an ack
7672 // for a larger pkt number.
7673 if let Some((largest_acked, skip_pn)) =
7674 largest_acked.zip(skip_pn)
7675 {
7676 if largest_acked > skip_pn {
7677 self.pkt_num_manager.set_skip_pn(None);
7678 }
7679 }
7680
7681 self.lost_count += lost_packets;
7682 self.lost_bytes += lost_bytes as u64;
7683 self.acked_bytes += acked_bytes as u64;
7684 self.spurious_lost_count += spurious_losses;
7685 }
7686 },
7687
7688 frame::Frame::ResetStream {
7689 stream_id,
7690 error_code,
7691 final_size,
7692 } => {
7693 // Peer can't send on our unidirectional streams.
7694 if !stream::is_bidi(stream_id) &&
7695 stream::is_local(stream_id, self.is_server)
7696 {
7697 return Err(Error::InvalidStreamState(stream_id));
7698 }
7699
7700 let max_rx_data_left = self.max_rx_data() - self.rx_data;
7701
7702 // Get existing stream or create a new one, but if the stream
7703 // has already been closed and collected, ignore the frame.
7704 //
7705 // This can happen if e.g. an ACK frame is lost, and the peer
7706 // retransmits another frame before it realizes that the stream
7707 // is gone.
7708 //
7709 // Note that it makes it impossible to check if the frame is
7710 // illegal, since we have no state, but since we ignore the
7711 // frame, it should be fine.
7712 let stream = match self.get_or_create_stream(stream_id, false) {
7713 Ok(v) => v,
7714
7715 Err(Error::Done) => return Ok(()),
7716
7717 Err(e) => return Err(e),
7718 };
7719
7720 let was_readable = stream.is_readable();
7721 let priority_key = Arc::clone(&stream.priority_key);
7722
7723 let stream::RecvBufResetReturn {
7724 max_data_delta,
7725 consumed_flowcontrol,
7726 } = stream.recv.reset(error_code, final_size)?;
7727
7728 if max_data_delta > max_rx_data_left {
7729 return Err(Error::FlowControl);
7730 }
7731
7732 if !was_readable && stream.is_readable() {
7733 self.streams.insert_readable(&priority_key);
7734 }
7735
7736 self.rx_data += max_data_delta;
7737 // We dropped the receive buffer, return connection level
7738 // flow-control
7739 self.flow_control.add_consumed(consumed_flowcontrol);
7740
7741 // ... and check if need to send an updated MAX_DATA frame
7742 if self.should_update_max_data() {
7743 self.almost_full = true;
7744 }
7745
7746 self.reset_stream_remote_count =
7747 self.reset_stream_remote_count.saturating_add(1);
7748 },
7749
7750 frame::Frame::StopSending {
7751 stream_id,
7752 error_code,
7753 } => {
7754 // STOP_SENDING on a receive-only stream is a fatal error.
7755 if !stream::is_local(stream_id, self.is_server) &&
7756 !stream::is_bidi(stream_id)
7757 {
7758 return Err(Error::InvalidStreamState(stream_id));
7759 }
7760
7761 // Get existing stream or create a new one, but if the stream
7762 // has already been closed and collected, ignore the frame.
7763 //
7764 // This can happen if e.g. an ACK frame is lost, and the peer
7765 // retransmits another frame before it realizes that the stream
7766 // is gone.
7767 //
7768 // Note that it makes it impossible to check if the frame is
7769 // illegal, since we have no state, but since we ignore the
7770 // frame, it should be fine.
7771 let stream = match self.get_or_create_stream(stream_id, false) {
7772 Ok(v) => v,
7773
7774 Err(Error::Done) => return Ok(()),
7775
7776 Err(e) => return Err(e),
7777 };
7778
7779 let was_writable = stream.is_writable();
7780
7781 let priority_key = Arc::clone(&stream.priority_key);
7782
7783 // Try stopping the stream.
7784 if let Ok((final_size, unsent)) = stream.send.stop(error_code) {
7785 // Claw back some flow control allowance from data that was
7786 // buffered but not actually sent before the stream was
7787 // reset.
7788 //
7789 // Note that `tx_cap` will be updated later on, so no need
7790 // to touch it here.
7791 self.tx_data = self.tx_data.saturating_sub(unsent);
7792
7793 self.tx_buffered =
7794 self.tx_buffered.saturating_sub(unsent as usize);
7795
7796 // These drops in qlog are a bit weird, but the only way to
7797 // ensure that all bytes that are moved from App to Transport
7798 // in stream_do_send are eventually moved from Transport to
7799 // Dropped. Ideally we would add a Transport to Network
7800 // transition also as a way to indicate when bytes were
7801 // transmitted vs dropped without ever being sent.
7802 qlog_with_type!(QLOG_DATA_MV, self.qlog, q, {
7803 let ev_data =
7804 EventData::DataMoved(qlog::events::quic::DataMoved {
7805 stream_id: Some(stream_id),
7806 offset: Some(final_size),
7807 length: Some(unsent),
7808 from: Some(DataRecipient::Transport),
7809 to: Some(DataRecipient::Dropped),
7810 ..Default::default()
7811 });
7812
7813 q.add_event_data_with_instant(ev_data, now).ok();
7814 });
7815
7816 self.streams.insert_reset(stream_id, error_code, final_size);
7817
7818 if !was_writable {
7819 self.streams.insert_writable(&priority_key);
7820 }
7821
7822 self.stopped_stream_remote_count =
7823 self.stopped_stream_remote_count.saturating_add(1);
7824 self.reset_stream_local_count =
7825 self.reset_stream_local_count.saturating_add(1);
7826 }
7827 },
7828
7829 frame::Frame::Crypto { data } => {
7830 if data.max_off() >= MAX_CRYPTO_STREAM_OFFSET {
7831 return Err(Error::CryptoBufferExceeded);
7832 }
7833
7834 // Push the data to the stream so it can be re-ordered.
7835 self.crypto_ctx[epoch].crypto_stream.recv.write(data)?;
7836
7837 // Feed crypto data to the TLS state, if there's data
7838 // available at the expected offset.
7839 let mut crypto_buf = [0; 512];
7840
7841 let level = crypto::Level::from_epoch(epoch);
7842
7843 let stream = &mut self.crypto_ctx[epoch].crypto_stream;
7844
7845 while let Ok((read, _)) = stream.recv.emit(&mut crypto_buf) {
7846 let recv_buf = &crypto_buf[..read];
7847 self.handshake.provide_data(level, recv_buf)?;
7848 }
7849
7850 self.do_handshake(now)?;
7851 },
7852
7853 frame::Frame::CryptoHeader { .. } => unreachable!(),
7854
7855 // TODO: implement stateless retry
7856 frame::Frame::NewToken { .. } =>
7857 if self.is_server {
7858 return Err(Error::InvalidPacket);
7859 },
7860
7861 frame::Frame::Stream { stream_id, data } => {
7862 // Peer can't send on our unidirectional streams.
7863 if !stream::is_bidi(stream_id) &&
7864 stream::is_local(stream_id, self.is_server)
7865 {
7866 return Err(Error::InvalidStreamState(stream_id));
7867 }
7868
7869 let max_rx_data_left = self.max_rx_data() - self.rx_data;
7870
7871 // Get existing stream or create a new one, but if the stream
7872 // has already been closed and collected, ignore the frame.
7873 //
7874 // This can happen if e.g. an ACK frame is lost, and the peer
7875 // retransmits another frame before it realizes that the stream
7876 // is gone.
7877 //
7878 // Note that it makes it impossible to check if the frame is
7879 // illegal, since we have no state, but since we ignore the
7880 // frame, it should be fine.
7881 let stream = match self.get_or_create_stream(stream_id, false) {
7882 Ok(v) => v,
7883
7884 Err(Error::Done) => return Ok(()),
7885
7886 Err(e) => return Err(e),
7887 };
7888
7889 // Check for the connection-level flow control limit.
7890 let max_off_delta =
7891 data.max_off().saturating_sub(stream.recv.max_off());
7892
7893 if max_off_delta > max_rx_data_left {
7894 return Err(Error::FlowControl);
7895 }
7896
7897 let was_readable = stream.is_readable();
7898 let priority_key = Arc::clone(&stream.priority_key);
7899
7900 let was_draining = stream.recv.is_draining();
7901
7902 stream.recv.write(data)?;
7903
7904 if !was_readable && stream.is_readable() {
7905 self.streams.insert_readable(&priority_key);
7906 }
7907
7908 self.rx_data += max_off_delta;
7909
7910 if was_draining {
7911 // When a stream is in draining state it will not queue
7912 // incoming data for the application to read, so consider
7913 // the received data as consumed, which might trigger a flow
7914 // control update.
7915 self.flow_control.add_consumed(max_off_delta);
7916
7917 if self.should_update_max_data() {
7918 self.almost_full = true;
7919 }
7920 }
7921 },
7922
7923 frame::Frame::StreamHeader { .. } => unreachable!(),
7924
7925 frame::Frame::MaxData { max } => {
7926 self.max_tx_data = cmp::max(self.max_tx_data, max);
7927 },
7928
7929 frame::Frame::MaxStreamData { stream_id, max } => {
7930 // Peer can't receive on its own unidirectional streams.
7931 if !stream::is_bidi(stream_id) &&
7932 !stream::is_local(stream_id, self.is_server)
7933 {
7934 return Err(Error::InvalidStreamState(stream_id));
7935 }
7936
7937 // Get existing stream or create a new one, but if the stream
7938 // has already been closed and collected, ignore the frame.
7939 //
7940 // This can happen if e.g. an ACK frame is lost, and the peer
7941 // retransmits another frame before it realizes that the stream
7942 // is gone.
7943 //
7944 // Note that it makes it impossible to check if the frame is
7945 // illegal, since we have no state, but since we ignore the
7946 // frame, it should be fine.
7947 let stream = match self.get_or_create_stream(stream_id, false) {
7948 Ok(v) => v,
7949
7950 Err(Error::Done) => return Ok(()),
7951
7952 Err(e) => return Err(e),
7953 };
7954
7955 let was_flushable = stream.is_flushable();
7956
7957 stream.send.update_max_data(max);
7958
7959 let writable = stream.is_writable();
7960
7961 let priority_key = Arc::clone(&stream.priority_key);
7962
7963 // If the stream is now flushable push it to the flushable queue,
7964 // but only if it wasn't already queued.
7965 if stream.is_flushable() && !was_flushable {
7966 let priority_key = Arc::clone(&stream.priority_key);
7967 self.streams.insert_flushable(&priority_key);
7968 }
7969
7970 if writable {
7971 self.streams.insert_writable(&priority_key);
7972 }
7973 },
7974
7975 frame::Frame::MaxStreamsBidi { max } => {
7976 if max > MAX_STREAM_ID {
7977 return Err(Error::InvalidFrame);
7978 }
7979
7980 self.streams.update_peer_max_streams_bidi(max);
7981 },
7982
7983 frame::Frame::MaxStreamsUni { max } => {
7984 if max > MAX_STREAM_ID {
7985 return Err(Error::InvalidFrame);
7986 }
7987
7988 self.streams.update_peer_max_streams_uni(max);
7989 },
7990
7991 frame::Frame::DataBlocked { .. } => {
7992 self.data_blocked_recv_count =
7993 self.data_blocked_recv_count.saturating_add(1);
7994 },
7995
7996 frame::Frame::StreamDataBlocked { .. } => {
7997 self.stream_data_blocked_recv_count =
7998 self.stream_data_blocked_recv_count.saturating_add(1);
7999 },
8000
8001 frame::Frame::StreamsBlockedBidi { limit } => {
8002 if limit > MAX_STREAM_ID {
8003 return Err(Error::InvalidFrame);
8004 }
8005 },
8006
8007 frame::Frame::StreamsBlockedUni { limit } => {
8008 if limit > MAX_STREAM_ID {
8009 return Err(Error::InvalidFrame);
8010 }
8011 },
8012
8013 frame::Frame::NewConnectionId {
8014 seq_num,
8015 retire_prior_to,
8016 conn_id,
8017 reset_token,
8018 } => {
8019 if self.ids.zero_length_dcid() {
8020 return Err(Error::InvalidState);
8021 }
8022
8023 let mut retired_path_ids = SmallVec::new();
8024
8025 // Retire pending path IDs before propagating the error code to
8026 // make sure retired connection IDs are not in use anymore.
8027 let new_dcid_res = self.ids.new_dcid(
8028 conn_id.into(),
8029 seq_num,
8030 u128::from_be_bytes(reset_token),
8031 retire_prior_to,
8032 &mut retired_path_ids,
8033 );
8034
8035 for (dcid_seq, pid) in retired_path_ids {
8036 let path = self.paths.get_mut(pid)?;
8037
8038 // Maybe the path already switched to another DCID.
8039 if path.active_dcid_seq != Some(dcid_seq) {
8040 continue;
8041 }
8042
8043 if let Some(new_dcid_seq) =
8044 self.ids.lowest_available_dcid_seq()
8045 {
8046 path.active_dcid_seq = Some(new_dcid_seq);
8047
8048 self.ids.link_dcid_to_path_id(new_dcid_seq, pid)?;
8049
8050 trace!(
8051 "{} path ID {} changed DCID: old seq num {} new seq num {}",
8052 self.trace_id, pid, dcid_seq, new_dcid_seq,
8053 );
8054 } else {
8055 // We cannot use this path anymore for now.
8056 path.active_dcid_seq = None;
8057
8058 trace!(
8059 "{} path ID {} cannot be used; DCID seq num {} has been retired",
8060 self.trace_id, pid, dcid_seq,
8061 );
8062 }
8063 }
8064
8065 // Propagate error (if any) now...
8066 new_dcid_res?;
8067 },
8068
8069 frame::Frame::RetireConnectionId { seq_num } => {
8070 if self.ids.zero_length_scid() {
8071 return Err(Error::InvalidState);
8072 }
8073
8074 if let Some(pid) = self.ids.retire_scid(seq_num, &hdr.dcid)? {
8075 let path = self.paths.get_mut(pid)?;
8076
8077 // Maybe we already linked a new SCID to that path.
8078 if path.active_scid_seq == Some(seq_num) {
8079 // XXX: We do not remove unused paths now, we instead
8080 // wait until we need to maintain more paths than the
8081 // host is willing to.
8082 path.active_scid_seq = None;
8083 }
8084 }
8085 },
8086
8087 frame::Frame::PathChallenge { data } => {
8088 self.path_challenge_rx_count += 1;
8089
8090 self.paths
8091 .get_mut(recv_path_id)?
8092 .on_challenge_received(data);
8093 },
8094
8095 frame::Frame::PathResponse { data } => {
8096 self.paths.on_response_received(data)?;
8097 },
8098
8099 frame::Frame::ConnectionClose {
8100 error_code, reason, ..
8101 } => {
8102 self.peer_error = Some(ConnectionError {
8103 is_app: false,
8104 error_code,
8105 reason,
8106 });
8107
8108 let path = self.paths.get_active()?;
8109 self.draining_timer = Some(now + (path.recovery.pto() * 3));
8110 },
8111
8112 frame::Frame::ApplicationClose { error_code, reason } => {
8113 self.peer_error = Some(ConnectionError {
8114 is_app: true,
8115 error_code,
8116 reason,
8117 });
8118
8119 let path = self.paths.get_active()?;
8120 self.draining_timer = Some(now + (path.recovery.pto() * 3));
8121 },
8122
8123 frame::Frame::HandshakeDone => {
8124 if self.is_server {
8125 return Err(Error::InvalidPacket);
8126 }
8127
8128 self.peer_verified_initial_address = true;
8129
8130 self.handshake_confirmed = true;
8131
8132 // Once the handshake is confirmed, we can drop Handshake keys.
8133 self.drop_epoch_state(packet::Epoch::Handshake, now);
8134 },
8135
8136 frame::Frame::Datagram { data } => {
8137 // Close the connection if DATAGRAMs are not enabled.
8138 // quiche always advertises support for 64K sized DATAGRAM
8139 // frames, as recommended by the standard, so we don't need a
8140 // size check.
8141 if !self.dgram_enabled() {
8142 return Err(Error::InvalidState);
8143 }
8144
8145 // If recv queue is full, discard oldest
8146 if self.dgram_recv_queue.is_full() {
8147 self.dgram_recv_queue.pop();
8148 }
8149
8150 self.dgram_recv_queue.push(data)?;
8151
8152 self.dgram_recv_count = self.dgram_recv_count.saturating_add(1);
8153
8154 let path = self.paths.get_mut(recv_path_id)?;
8155 path.dgram_recv_count = path.dgram_recv_count.saturating_add(1);
8156 },
8157
8158 frame::Frame::DatagramHeader { .. } => unreachable!(),
8159 }
8160
8161 Ok(())
8162 }
8163
8164 /// Drops the keys and recovery state for the given epoch.
8165 fn drop_epoch_state(&mut self, epoch: packet::Epoch, now: Instant) {
8166 let crypto_ctx = &mut self.crypto_ctx[epoch];
8167 if crypto_ctx.crypto_open.is_none() {
8168 return;
8169 }
8170 crypto_ctx.clear();
8171 self.pkt_num_spaces[epoch].clear();
8172
8173 let handshake_status = self.handshake_status();
8174 for (_, p) in self.paths.iter_mut() {
8175 p.recovery
8176 .on_pkt_num_space_discarded(epoch, handshake_status, now);
8177 }
8178
8179 trace!("{} dropped epoch {} state", self.trace_id, epoch);
8180 }
8181
8182 /// Returns true if the connection-level flow control needs to be updated.
8183 ///
8184 /// This happens when the new max data limit is at least double the amount
8185 /// of data that can be received before blocking.
8186 fn should_update_max_data(&self) -> bool {
8187 self.flow_control.should_update_max_data()
8188 }
8189
8190 /// Returns the connection level flow control limit.
8191 fn max_rx_data(&self) -> u64 {
8192 self.flow_control.max_data()
8193 }
8194
8195 /// Returns true if the HANDSHAKE_DONE frame needs to be sent.
8196 fn should_send_handshake_done(&self) -> bool {
8197 self.is_established() && !self.handshake_done_sent && self.is_server
8198 }
8199
8200 /// Returns the idle timeout value.
8201 ///
8202 /// `None` is returned if both end-points disabled the idle timeout.
8203 fn idle_timeout(&self) -> Option<Duration> {
8204 // If the transport parameter is set to 0, then the respective endpoint
8205 // decided to disable the idle timeout. If both are disabled we should
8206 // not set any timeout.
8207 if self.local_transport_params.max_idle_timeout == 0 &&
8208 self.peer_transport_params.max_idle_timeout == 0
8209 {
8210 return None;
8211 }
8212
8213 // If the local endpoint or the peer disabled the idle timeout, use the
8214 // other peer's value, otherwise use the minimum of the two values.
8215 let idle_timeout = if self.local_transport_params.max_idle_timeout == 0 {
8216 self.peer_transport_params.max_idle_timeout
8217 } else if self.peer_transport_params.max_idle_timeout == 0 {
8218 self.local_transport_params.max_idle_timeout
8219 } else {
8220 cmp::min(
8221 self.local_transport_params.max_idle_timeout,
8222 self.peer_transport_params.max_idle_timeout,
8223 )
8224 };
8225
8226 let path_pto = match self.paths.get_active() {
8227 Ok(p) => p.recovery.pto(),
8228 Err(_) => Duration::ZERO,
8229 };
8230
8231 let idle_timeout = Duration::from_millis(idle_timeout);
8232 let idle_timeout = cmp::max(idle_timeout, 3 * path_pto);
8233
8234 Some(idle_timeout)
8235 }
8236
8237 /// Returns the connection's handshake status for use in loss recovery.
8238 fn handshake_status(&self) -> recovery::HandshakeStatus {
8239 recovery::HandshakeStatus {
8240 has_handshake_keys: self.crypto_ctx[packet::Epoch::Handshake]
8241 .has_keys(),
8242
8243 peer_verified_address: self.peer_verified_initial_address,
8244
8245 completed: self.is_established(),
8246 }
8247 }
8248
8249 /// Updates send capacity.
8250 fn update_tx_cap(&mut self) {
8251 let cwin_available = match self.paths.get_active() {
8252 Ok(p) => p.recovery.cwnd_available() as u64,
8253 Err(_) => 0,
8254 };
8255
8256 let cap =
8257 cmp::min(cwin_available, self.max_tx_data - self.tx_data) as usize;
8258 self.tx_cap = (cap as f64 * self.tx_cap_factor).ceil() as usize;
8259 }
8260
8261 fn delivery_rate_check_if_app_limited(&self) -> bool {
8262 // Enter the app-limited phase of delivery rate when these conditions
8263 // are met:
8264 //
8265 // - The remaining capacity is higher than available bytes in cwnd (there
8266 // is more room to send).
8267 // - New data since the last send() is smaller than available bytes in
8268 // cwnd (we queued less than what we can send).
8269 // - There is room to send more data in cwnd.
8270 //
8271 // In application-limited phases the transmission rate is limited by the
8272 // application rather than the congestion control algorithm.
8273 //
8274 // Note that this is equivalent to CheckIfApplicationLimited() from the
8275 // delivery rate draft. This is also separate from `recovery.app_limited`
8276 // and only applies to delivery rate calculation.
8277 let cwin_available = self
8278 .paths
8279 .iter()
8280 .filter(|&(_, p)| p.active())
8281 .map(|(_, p)| p.recovery.cwnd_available())
8282 .sum();
8283
8284 ((self.tx_buffered + self.dgram_send_queue_byte_size()) < cwin_available) &&
8285 (self.tx_data.saturating_sub(self.last_tx_data)) <
8286 cwin_available as u64 &&
8287 cwin_available > 0
8288 }
8289
8290 fn check_tx_buffered_invariant(&mut self) {
8291 // tx_buffered should track bytes queued in the stream buffers
8292 // and unacked retransmitable bytes in the network.
8293 // If tx_buffered > 0 mark the tx_buffered_state if there are no
8294 // flushable streams and there no inflight bytes.
8295 //
8296 // It is normal to have tx_buffered == 0 while there are inflight bytes
8297 // since not QUIC frames are retransmittable; inflight tracks all bytes
8298 // on the network which are subject to congestion control.
8299 if self.tx_buffered > 0 &&
8300 !self.streams.has_flushable() &&
8301 !self
8302 .paths
8303 .iter()
8304 .any(|(_, p)| p.recovery.bytes_in_flight() > 0)
8305 {
8306 self.tx_buffered_state = TxBufferTrackingState::Inconsistent;
8307 }
8308 }
8309
8310 fn set_initial_dcid(
8311 &mut self, cid: ConnectionId<'static>, reset_token: Option<u128>,
8312 path_id: usize,
8313 ) -> Result<()> {
8314 self.ids.set_initial_dcid(cid, reset_token, Some(path_id));
8315 self.paths.get_mut(path_id)?.active_dcid_seq = Some(0);
8316
8317 Ok(())
8318 }
8319
8320 /// Selects the path that the incoming packet belongs to, or creates a new
8321 /// one if no existing path matches.
8322 fn get_or_create_recv_path_id(
8323 &mut self, recv_pid: Option<usize>, dcid: &ConnectionId, buf_len: usize,
8324 info: &RecvInfo,
8325 ) -> Result<usize> {
8326 let ids = &mut self.ids;
8327
8328 let (in_scid_seq, mut in_scid_pid) =
8329 ids.find_scid_seq(dcid).ok_or(Error::InvalidState)?;
8330
8331 if let Some(recv_pid) = recv_pid {
8332 // If the path observes a change of SCID used, note it.
8333 let recv_path = self.paths.get_mut(recv_pid)?;
8334
8335 let cid_entry =
8336 recv_path.active_scid_seq.and_then(|v| ids.get_scid(v).ok());
8337
8338 if cid_entry.map(|e| &e.cid) != Some(dcid) {
8339 let incoming_cid_entry = ids.get_scid(in_scid_seq)?;
8340
8341 let prev_recv_pid =
8342 incoming_cid_entry.path_id.unwrap_or(recv_pid);
8343
8344 if prev_recv_pid != recv_pid {
8345 trace!(
8346 "{} peer reused CID {:?} from path {} on path {}",
8347 self.trace_id,
8348 dcid,
8349 prev_recv_pid,
8350 recv_pid
8351 );
8352
8353 // TODO: reset congestion control.
8354 }
8355
8356 trace!(
8357 "{} path ID {} now see SCID with seq num {}",
8358 self.trace_id,
8359 recv_pid,
8360 in_scid_seq
8361 );
8362
8363 recv_path.active_scid_seq = Some(in_scid_seq);
8364 ids.link_scid_to_path_id(in_scid_seq, recv_pid)?;
8365 }
8366
8367 return Ok(recv_pid);
8368 }
8369
8370 // This is a new 4-tuple. See if the CID has not been assigned on
8371 // another path.
8372
8373 // Ignore this step if are using zero-length SCID.
8374 if ids.zero_length_scid() {
8375 in_scid_pid = None;
8376 }
8377
8378 if let Some(in_scid_pid) = in_scid_pid {
8379 // This CID has been used by another path. If we have the
8380 // room to do so, create a new `Path` structure holding this
8381 // new 4-tuple. Otherwise, drop the packet.
8382 let old_path = self.paths.get_mut(in_scid_pid)?;
8383 let old_local_addr = old_path.local_addr();
8384 let old_peer_addr = old_path.peer_addr();
8385
8386 trace!(
8387 "{} reused CID seq {} of ({},{}) (path {}) on ({},{})",
8388 self.trace_id,
8389 in_scid_seq,
8390 old_local_addr,
8391 old_peer_addr,
8392 in_scid_pid,
8393 info.to,
8394 info.from
8395 );
8396
8397 // Notify the application.
8398 self.paths.notify_event(PathEvent::ReusedSourceConnectionId(
8399 in_scid_seq,
8400 (old_local_addr, old_peer_addr),
8401 (info.to, info.from),
8402 ));
8403 }
8404
8405 // This is a new path using an unassigned CID; create it!
8406 let mut path = path::Path::new(
8407 info.to,
8408 info.from,
8409 &self.recovery_config,
8410 self.path_challenge_recv_max_queue_len,
8411 false,
8412 None,
8413 );
8414
8415 path.max_send_bytes = buf_len * self.max_amplification_factor;
8416 path.active_scid_seq = Some(in_scid_seq);
8417
8418 // Automatically probes the new path.
8419 path.request_validation();
8420
8421 let pid = self.paths.insert_path(path, self.is_server)?;
8422
8423 // Do not record path reuse.
8424 if in_scid_pid.is_none() {
8425 ids.link_scid_to_path_id(in_scid_seq, pid)?;
8426 }
8427
8428 Ok(pid)
8429 }
8430
8431 /// Selects the path on which the next packet must be sent.
8432 fn get_send_path_id(
8433 &self, from: Option<SocketAddr>, to: Option<SocketAddr>,
8434 ) -> Result<usize> {
8435 // A probing packet must be sent, but only if the connection is fully
8436 // established.
8437 if self.is_established() {
8438 let mut probing = self
8439 .paths
8440 .iter()
8441 .filter(|(_, p)| from.is_none() || Some(p.local_addr()) == from)
8442 .filter(|(_, p)| to.is_none() || Some(p.peer_addr()) == to)
8443 .filter(|(_, p)| p.active_dcid_seq.is_some())
8444 .filter(|(_, p)| p.probing_required())
8445 .map(|(pid, _)| pid);
8446
8447 if let Some(pid) = probing.next() {
8448 return Ok(pid);
8449 }
8450 }
8451
8452 if let Some((pid, p)) = self.paths.get_active_with_pid() {
8453 if from.is_some() && Some(p.local_addr()) != from {
8454 return Err(Error::Done);
8455 }
8456
8457 if to.is_some() && Some(p.peer_addr()) != to {
8458 return Err(Error::Done);
8459 }
8460
8461 return Ok(pid);
8462 };
8463
8464 Err(Error::InvalidState)
8465 }
8466
8467 /// Sets the path with identifier 'path_id' to be active.
8468 fn set_active_path(&mut self, path_id: usize, now: Instant) -> Result<()> {
8469 if let Ok(old_active_path) = self.paths.get_active_mut() {
8470 for &e in packet::Epoch::epochs(
8471 packet::Epoch::Initial..=packet::Epoch::Application,
8472 ) {
8473 let (lost_packets, lost_bytes) = old_active_path
8474 .recovery
8475 .on_path_change(e, now, &self.trace_id);
8476
8477 self.lost_count += lost_packets;
8478 self.lost_bytes += lost_bytes as u64;
8479 }
8480 }
8481
8482 self.paths.set_active_path(path_id)
8483 }
8484
8485 /// Handles potential connection migration.
8486 fn on_peer_migrated(
8487 &mut self, new_pid: usize, disable_dcid_reuse: bool, now: Instant,
8488 ) -> Result<()> {
8489 let active_path_id = self.paths.get_active_path_id()?;
8490
8491 if active_path_id == new_pid {
8492 return Ok(());
8493 }
8494
8495 self.set_active_path(new_pid, now)?;
8496
8497 let no_spare_dcid =
8498 self.paths.get_mut(new_pid)?.active_dcid_seq.is_none();
8499
8500 if no_spare_dcid && !disable_dcid_reuse {
8501 self.paths.get_mut(new_pid)?.active_dcid_seq =
8502 self.paths.get_mut(active_path_id)?.active_dcid_seq;
8503 }
8504
8505 Ok(())
8506 }
8507
8508 /// Creates a new client-side path.
8509 fn create_path_on_client(
8510 &mut self, local_addr: SocketAddr, peer_addr: SocketAddr,
8511 ) -> Result<usize> {
8512 if self.is_server {
8513 return Err(Error::InvalidState);
8514 }
8515
8516 // If we use zero-length SCID and go over our local active CID limit,
8517 // the `insert_path()` call will raise an error.
8518 if !self.ids.zero_length_scid() && self.ids.available_scids() == 0 {
8519 return Err(Error::OutOfIdentifiers);
8520 }
8521
8522 // Do we have a spare DCID? If we are using zero-length DCID, just use
8523 // the default having sequence 0 (note that if we exceed our local CID
8524 // limit, the `insert_path()` call will raise an error.
8525 let dcid_seq = if self.ids.zero_length_dcid() {
8526 0
8527 } else {
8528 self.ids
8529 .lowest_available_dcid_seq()
8530 .ok_or(Error::OutOfIdentifiers)?
8531 };
8532
8533 let mut path = path::Path::new(
8534 local_addr,
8535 peer_addr,
8536 &self.recovery_config,
8537 self.path_challenge_recv_max_queue_len,
8538 false,
8539 None,
8540 );
8541 path.active_dcid_seq = Some(dcid_seq);
8542
8543 let pid = self
8544 .paths
8545 .insert_path(path, false)
8546 .map_err(|_| Error::OutOfIdentifiers)?;
8547 self.ids.link_dcid_to_path_id(dcid_seq, pid)?;
8548
8549 Ok(pid)
8550 }
8551
8552 // Marks the connection as closed and does any related tidyup.
8553 fn mark_closed(&mut self) {
8554 #[cfg(feature = "qlog")]
8555 {
8556 let cc = match (self.is_established(), self.timed_out, &self.peer_error, &self.local_error) {
8557 (false, _, _, _) => qlog::events::connectivity::ConnectionClosed {
8558 owner: Some(TransportOwner::Local),
8559 connection_code: None,
8560 application_code: None,
8561 internal_code: None,
8562 reason: Some("Failed to establish connection".to_string()),
8563 trigger: Some(qlog::events::connectivity::ConnectionClosedTrigger::HandshakeTimeout)
8564 },
8565
8566 (true, true, _, _) => qlog::events::connectivity::ConnectionClosed {
8567 owner: Some(TransportOwner::Local),
8568 connection_code: None,
8569 application_code: None,
8570 internal_code: None,
8571 reason: Some("Idle timeout".to_string()),
8572 trigger: Some(qlog::events::connectivity::ConnectionClosedTrigger::IdleTimeout)
8573 },
8574
8575 (true, false, Some(peer_error), None) => {
8576 let (connection_code, application_code, trigger) = if peer_error.is_app {
8577 (None, Some(qlog::events::ApplicationErrorCode::Value(peer_error.error_code)), None)
8578 } else {
8579 let trigger = if peer_error.error_code == WireErrorCode::NoError as u64 {
8580 Some(qlog::events::connectivity::ConnectionClosedTrigger::Clean)
8581 } else {
8582 Some(qlog::events::connectivity::ConnectionClosedTrigger::Error)
8583 };
8584
8585 (Some(qlog::events::ConnectionErrorCode::Value(peer_error.error_code)), None, trigger)
8586 };
8587
8588 qlog::events::connectivity::ConnectionClosed {
8589 owner: Some(TransportOwner::Remote),
8590 connection_code,
8591 application_code,
8592 internal_code: None,
8593 reason: Some(String::from_utf8_lossy(&peer_error.reason).to_string()),
8594 trigger,
8595 }
8596 },
8597
8598 (true, false, None, Some(local_error)) => {
8599 let (connection_code, application_code, trigger) = if local_error.is_app {
8600 (None, Some(qlog::events::ApplicationErrorCode::Value(local_error.error_code)), None)
8601 } else {
8602 let trigger = if local_error.error_code == WireErrorCode::NoError as u64 {
8603 Some(qlog::events::connectivity::ConnectionClosedTrigger::Clean)
8604 } else {
8605 Some(qlog::events::connectivity::ConnectionClosedTrigger::Error)
8606 };
8607
8608 (Some(qlog::events::ConnectionErrorCode::Value(local_error.error_code)), None, trigger)
8609 };
8610
8611 qlog::events::connectivity::ConnectionClosed {
8612 owner: Some(TransportOwner::Local),
8613 connection_code,
8614 application_code,
8615 internal_code: None,
8616 reason: Some(String::from_utf8_lossy(&local_error.reason).to_string()),
8617 trigger,
8618 }
8619 },
8620
8621 _ => qlog::events::connectivity::ConnectionClosed {
8622 owner: None,
8623 connection_code: None,
8624 application_code: None,
8625 internal_code: None,
8626 reason: None,
8627 trigger: None,
8628 },
8629 };
8630
8631 qlog_with_type!(QLOG_CONNECTION_CLOSED, self.qlog, q, {
8632 let ev_data = EventData::ConnectionClosed(cc);
8633
8634 q.add_event_data_now(ev_data).ok();
8635 });
8636 self.qlog.streamer = None;
8637 }
8638 self.closed = true;
8639 }
8640}
8641
8642#[cfg(feature = "boringssl-boring-crate")]
8643impl<F: BufFactory> AsMut<boring::ssl::SslRef> for Connection<F> {
8644 fn as_mut(&mut self) -> &mut boring::ssl::SslRef {
8645 self.handshake.ssl_mut()
8646 }
8647}
8648
8649/// Maps an `Error` to `Error::Done`, or itself.
8650///
8651/// When a received packet that hasn't yet been authenticated triggers a failure
8652/// it should, in most cases, be ignored, instead of raising a connection error,
8653/// to avoid potential man-in-the-middle and man-on-the-side attacks.
8654///
8655/// However, if no other packet was previously received, the connection should
8656/// indeed be closed as the received packet might just be network background
8657/// noise, and it shouldn't keep resources occupied indefinitely.
8658///
8659/// This function maps an error to `Error::Done` to ignore a packet failure
8660/// without aborting the connection, except when no other packet was previously
8661/// received, in which case the error itself is returned, but only on the
8662/// server-side as the client will already have armed the idle timer.
8663///
8664/// This must only be used for errors preceding packet authentication. Failures
8665/// happening after a packet has been authenticated should still cause the
8666/// connection to be aborted.
8667fn drop_pkt_on_err(
8668 e: Error, recv_count: usize, is_server: bool, trace_id: &str,
8669) -> Error {
8670 // On the server, if no other packet has been successfully processed, abort
8671 // the connection to avoid keeping the connection open when only junk is
8672 // received.
8673 if is_server && recv_count == 0 {
8674 return e;
8675 }
8676
8677 trace!("{trace_id} dropped invalid packet");
8678
8679 // Ignore other invalid packets that haven't been authenticated to prevent
8680 // man-in-the-middle and man-on-the-side attacks.
8681 Error::Done
8682}
8683
8684struct AddrTupleFmt(SocketAddr, SocketAddr);
8685
8686impl std::fmt::Display for AddrTupleFmt {
8687 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
8688 let AddrTupleFmt(src, dst) = &self;
8689
8690 if src.ip().is_unspecified() || dst.ip().is_unspecified() {
8691 return Ok(());
8692 }
8693
8694 f.write_fmt(format_args!("src:{src} dst:{dst}"))
8695 }
8696}
8697
8698/// Statistics about the connection.
8699///
8700/// A connection's statistics can be collected using the [`stats()`] method.
8701///
8702/// [`stats()`]: struct.Connection.html#method.stats
8703#[derive(Clone, Default)]
8704pub struct Stats {
8705 /// The number of QUIC packets received.
8706 pub recv: usize,
8707
8708 /// The number of QUIC packets sent.
8709 pub sent: usize,
8710
8711 /// The number of QUIC packets that were lost.
8712 pub lost: usize,
8713
8714 /// The number of QUIC packets that were marked as lost but later acked.
8715 pub spurious_lost: usize,
8716
8717 /// The number of sent QUIC packets with retransmitted data.
8718 pub retrans: usize,
8719
8720 /// The number of sent bytes.
8721 pub sent_bytes: u64,
8722
8723 /// The number of received bytes.
8724 pub recv_bytes: u64,
8725
8726 /// The number of bytes sent acked.
8727 pub acked_bytes: u64,
8728
8729 /// The number of bytes sent lost.
8730 pub lost_bytes: u64,
8731
8732 /// The number of stream bytes retransmitted.
8733 pub stream_retrans_bytes: u64,
8734
8735 /// The number of DATAGRAM frames received.
8736 pub dgram_recv: usize,
8737
8738 /// The number of DATAGRAM frames sent.
8739 pub dgram_sent: usize,
8740
8741 /// The number of known paths for the connection.
8742 pub paths_count: usize,
8743
8744 /// The number of streams reset by local.
8745 pub reset_stream_count_local: u64,
8746
8747 /// The number of streams stopped by local.
8748 pub stopped_stream_count_local: u64,
8749
8750 /// The number of streams reset by remote.
8751 pub reset_stream_count_remote: u64,
8752
8753 /// The number of streams stopped by remote.
8754 pub stopped_stream_count_remote: u64,
8755
8756 /// The number of DATA_BLOCKED frames sent due to hitting the connection
8757 /// flow control limit.
8758 pub data_blocked_sent_count: u64,
8759
8760 /// The number of STREAM_DATA_BLOCKED frames sent due to a stream hitting
8761 /// the stream flow control limit.
8762 pub stream_data_blocked_sent_count: u64,
8763
8764 /// The number of DATA_BLOCKED frames received from the remote.
8765 pub data_blocked_recv_count: u64,
8766
8767 /// The number of STREAM_DATA_BLOCKED frames received from the remote.
8768 pub stream_data_blocked_recv_count: u64,
8769
8770 /// The total number of PATH_CHALLENGE frames that were received.
8771 pub path_challenge_rx_count: u64,
8772
8773 /// Total duration during which this side of the connection was
8774 /// actively sending bytes or waiting for those bytes to be acked.
8775 pub bytes_in_flight_duration: Duration,
8776
8777 /// Health state of the connection's tx_buffered.
8778 pub tx_buffered_state: TxBufferTrackingState,
8779}
8780
8781impl std::fmt::Debug for Stats {
8782 #[inline]
8783 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
8784 write!(
8785 f,
8786 "recv={} sent={} lost={} retrans={}",
8787 self.recv, self.sent, self.lost, self.retrans,
8788 )?;
8789
8790 write!(
8791 f,
8792 " sent_bytes={} recv_bytes={} lost_bytes={}",
8793 self.sent_bytes, self.recv_bytes, self.lost_bytes,
8794 )?;
8795
8796 Ok(())
8797 }
8798}
8799
8800/// QUIC Unknown Transport Parameter.
8801///
8802/// A QUIC transport parameter that is not specifically recognized
8803/// by this implementation.
8804#[derive(Clone, Debug, PartialEq)]
8805pub struct UnknownTransportParameter<T> {
8806 /// The ID of the unknown transport parameter.
8807 pub id: u64,
8808
8809 /// Original data representing the value of the unknown transport parameter.
8810 pub value: T,
8811}
8812
8813impl<T> UnknownTransportParameter<T> {
8814 /// Checks whether an unknown Transport Parameter's ID is in the reserved
8815 /// space.
8816 ///
8817 /// See Section 18.1 in [RFC9000](https://datatracker.ietf.org/doc/html/rfc9000#name-reserved-transport-paramete).
8818 pub fn is_reserved(&self) -> bool {
8819 let n = (self.id - 27) / 31;
8820 self.id == 31 * n + 27
8821 }
8822}
8823
8824#[cfg(feature = "qlog")]
8825impl From<UnknownTransportParameter<Vec<u8>>>
8826 for qlog::events::quic::UnknownTransportParameter
8827{
8828 fn from(value: UnknownTransportParameter<Vec<u8>>) -> Self {
8829 Self {
8830 id: value.id,
8831 value: qlog::HexSlice::maybe_string(Some(value.value.as_slice()))
8832 .unwrap_or_default(),
8833 }
8834 }
8835}
8836
8837impl From<UnknownTransportParameter<&[u8]>>
8838 for UnknownTransportParameter<Vec<u8>>
8839{
8840 // When an instance of an UnknownTransportParameter is actually
8841 // stored in UnknownTransportParameters, then we make a copy
8842 // of the bytes if the source is an instance of an UnknownTransportParameter
8843 // whose value is not owned.
8844 fn from(value: UnknownTransportParameter<&[u8]>) -> Self {
8845 Self {
8846 id: value.id,
8847 value: value.value.to_vec(),
8848 }
8849 }
8850}
8851
8852/// Track unknown transport parameters, up to a limit.
8853#[derive(Clone, Debug, PartialEq, Default)]
8854pub struct UnknownTransportParameters {
8855 /// The space remaining for storing unknown transport parameters.
8856 pub capacity: usize,
8857 /// The unknown transport parameters.
8858 pub parameters: Vec<UnknownTransportParameter<Vec<u8>>>,
8859}
8860
8861impl UnknownTransportParameters {
8862 /// Pushes an unknown transport parameter into storage if there is space
8863 /// remaining.
8864 pub fn push(&mut self, new: UnknownTransportParameter<&[u8]>) -> Result<()> {
8865 let new_unknown_tp_size = new.value.len() + size_of::<u64>();
8866 if new_unknown_tp_size < self.capacity {
8867 self.capacity -= new_unknown_tp_size;
8868 self.parameters.push(new.into());
8869 Ok(())
8870 } else {
8871 Err(octets::BufferTooShortError.into())
8872 }
8873 }
8874}
8875
8876/// An Iterator over unknown transport parameters.
8877pub struct UnknownTransportParameterIterator<'a> {
8878 index: usize,
8879 parameters: &'a Vec<UnknownTransportParameter<Vec<u8>>>,
8880}
8881
8882impl<'a> IntoIterator for &'a UnknownTransportParameters {
8883 type IntoIter = UnknownTransportParameterIterator<'a>;
8884 type Item = &'a UnknownTransportParameter<Vec<u8>>;
8885
8886 fn into_iter(self) -> Self::IntoIter {
8887 UnknownTransportParameterIterator {
8888 index: 0,
8889 parameters: &self.parameters,
8890 }
8891 }
8892}
8893
8894impl<'a> Iterator for UnknownTransportParameterIterator<'a> {
8895 type Item = &'a UnknownTransportParameter<Vec<u8>>;
8896
8897 fn next(&mut self) -> Option<Self::Item> {
8898 let result = self.parameters.get(self.index);
8899 self.index += 1;
8900 result
8901 }
8902}
8903
8904/// QUIC Transport Parameters
8905#[derive(Clone, Debug, PartialEq)]
8906pub struct TransportParams {
8907 /// Value of Destination CID field from first Initial packet sent by client
8908 pub original_destination_connection_id: Option<ConnectionId<'static>>,
8909 /// The maximum idle timeout.
8910 pub max_idle_timeout: u64,
8911 /// Token used for verifying stateless resets
8912 pub stateless_reset_token: Option<u128>,
8913 /// The maximum UDP payload size.
8914 pub max_udp_payload_size: u64,
8915 /// The initial flow control maximum data for the connection.
8916 pub initial_max_data: u64,
8917 /// The initial flow control maximum data for local bidirectional streams.
8918 pub initial_max_stream_data_bidi_local: u64,
8919 /// The initial flow control maximum data for remote bidirectional streams.
8920 pub initial_max_stream_data_bidi_remote: u64,
8921 /// The initial flow control maximum data for unidirectional streams.
8922 pub initial_max_stream_data_uni: u64,
8923 /// The initial maximum bidirectional streams.
8924 pub initial_max_streams_bidi: u64,
8925 /// The initial maximum unidirectional streams.
8926 pub initial_max_streams_uni: u64,
8927 /// The ACK delay exponent.
8928 pub ack_delay_exponent: u64,
8929 /// The max ACK delay.
8930 pub max_ack_delay: u64,
8931 /// Whether active migration is disabled.
8932 pub disable_active_migration: bool,
8933 /// The active connection ID limit.
8934 pub active_conn_id_limit: u64,
8935 /// The value that the endpoint included in the Source CID field of a Retry
8936 /// Packet.
8937 pub initial_source_connection_id: Option<ConnectionId<'static>>,
8938 /// The value that the server included in the Source CID field of a Retry
8939 /// Packet.
8940 pub retry_source_connection_id: Option<ConnectionId<'static>>,
8941 /// DATAGRAM frame extension parameter, if any.
8942 pub max_datagram_frame_size: Option<u64>,
8943 /// Unknown peer transport parameters and values, if any.
8944 pub unknown_params: Option<UnknownTransportParameters>,
8945 // pub preferred_address: ...,
8946}
8947
8948impl Default for TransportParams {
8949 fn default() -> TransportParams {
8950 TransportParams {
8951 original_destination_connection_id: None,
8952 max_idle_timeout: 0,
8953 stateless_reset_token: None,
8954 max_udp_payload_size: 65527,
8955 initial_max_data: 0,
8956 initial_max_stream_data_bidi_local: 0,
8957 initial_max_stream_data_bidi_remote: 0,
8958 initial_max_stream_data_uni: 0,
8959 initial_max_streams_bidi: 0,
8960 initial_max_streams_uni: 0,
8961 ack_delay_exponent: 3,
8962 max_ack_delay: 25,
8963 disable_active_migration: false,
8964 active_conn_id_limit: 2,
8965 initial_source_connection_id: None,
8966 retry_source_connection_id: None,
8967 max_datagram_frame_size: None,
8968 unknown_params: Default::default(),
8969 }
8970 }
8971}
8972
8973impl TransportParams {
8974 fn decode(
8975 buf: &[u8], is_server: bool, unknown_size: Option<usize>,
8976 ) -> Result<TransportParams> {
8977 let mut params = octets::Octets::with_slice(buf);
8978 let mut seen_params = HashSet::new();
8979
8980 let mut tp = TransportParams::default();
8981
8982 if let Some(unknown_transport_param_tracking_size) = unknown_size {
8983 tp.unknown_params = Some(UnknownTransportParameters {
8984 capacity: unknown_transport_param_tracking_size,
8985 parameters: vec![],
8986 });
8987 }
8988
8989 while params.cap() > 0 {
8990 let id = params.get_varint()?;
8991
8992 if seen_params.contains(&id) {
8993 return Err(Error::InvalidTransportParam);
8994 }
8995 seen_params.insert(id);
8996
8997 let mut val = params.get_bytes_with_varint_length()?;
8998
8999 match id {
9000 0x0000 => {
9001 if is_server {
9002 return Err(Error::InvalidTransportParam);
9003 }
9004
9005 tp.original_destination_connection_id =
9006 Some(val.to_vec().into());
9007 },
9008
9009 0x0001 => {
9010 tp.max_idle_timeout = val.get_varint()?;
9011 },
9012
9013 0x0002 => {
9014 if is_server {
9015 return Err(Error::InvalidTransportParam);
9016 }
9017
9018 tp.stateless_reset_token = Some(u128::from_be_bytes(
9019 val.get_bytes(16)?
9020 .to_vec()
9021 .try_into()
9022 .map_err(|_| Error::BufferTooShort)?,
9023 ));
9024 },
9025
9026 0x0003 => {
9027 tp.max_udp_payload_size = val.get_varint()?;
9028
9029 if tp.max_udp_payload_size < 1200 {
9030 return Err(Error::InvalidTransportParam);
9031 }
9032 },
9033
9034 0x0004 => {
9035 tp.initial_max_data = val.get_varint()?;
9036 },
9037
9038 0x0005 => {
9039 tp.initial_max_stream_data_bidi_local = val.get_varint()?;
9040 },
9041
9042 0x0006 => {
9043 tp.initial_max_stream_data_bidi_remote = val.get_varint()?;
9044 },
9045
9046 0x0007 => {
9047 tp.initial_max_stream_data_uni = val.get_varint()?;
9048 },
9049
9050 0x0008 => {
9051 let max = val.get_varint()?;
9052
9053 if max > MAX_STREAM_ID {
9054 return Err(Error::InvalidTransportParam);
9055 }
9056
9057 tp.initial_max_streams_bidi = max;
9058 },
9059
9060 0x0009 => {
9061 let max = val.get_varint()?;
9062
9063 if max > MAX_STREAM_ID {
9064 return Err(Error::InvalidTransportParam);
9065 }
9066
9067 tp.initial_max_streams_uni = max;
9068 },
9069
9070 0x000a => {
9071 let ack_delay_exponent = val.get_varint()?;
9072
9073 if ack_delay_exponent > 20 {
9074 return Err(Error::InvalidTransportParam);
9075 }
9076
9077 tp.ack_delay_exponent = ack_delay_exponent;
9078 },
9079
9080 0x000b => {
9081 let max_ack_delay = val.get_varint()?;
9082
9083 if max_ack_delay >= 2_u64.pow(14) {
9084 return Err(Error::InvalidTransportParam);
9085 }
9086
9087 tp.max_ack_delay = max_ack_delay;
9088 },
9089
9090 0x000c => {
9091 tp.disable_active_migration = true;
9092 },
9093
9094 0x000d => {
9095 if is_server {
9096 return Err(Error::InvalidTransportParam);
9097 }
9098
9099 // TODO: decode preferred_address
9100 },
9101
9102 0x000e => {
9103 let limit = val.get_varint()?;
9104
9105 if limit < 2 {
9106 return Err(Error::InvalidTransportParam);
9107 }
9108
9109 tp.active_conn_id_limit = limit;
9110 },
9111
9112 0x000f => {
9113 tp.initial_source_connection_id = Some(val.to_vec().into());
9114 },
9115
9116 0x00010 => {
9117 if is_server {
9118 return Err(Error::InvalidTransportParam);
9119 }
9120
9121 tp.retry_source_connection_id = Some(val.to_vec().into());
9122 },
9123
9124 0x0020 => {
9125 tp.max_datagram_frame_size = Some(val.get_varint()?);
9126 },
9127
9128 // Track unknown transport parameters specially.
9129 unknown_tp_id => {
9130 if let Some(unknown_params) = &mut tp.unknown_params {
9131 // It is _not_ an error not to have space enough to track
9132 // an unknown parameter.
9133 let _ = unknown_params.push(UnknownTransportParameter {
9134 id: unknown_tp_id,
9135 value: val.buf(),
9136 });
9137 }
9138 },
9139 }
9140 }
9141
9142 Ok(tp)
9143 }
9144
9145 fn encode_param(
9146 b: &mut octets::OctetsMut, ty: u64, len: usize,
9147 ) -> Result<()> {
9148 b.put_varint(ty)?;
9149 b.put_varint(len as u64)?;
9150
9151 Ok(())
9152 }
9153
9154 fn encode<'a>(
9155 tp: &TransportParams, is_server: bool, out: &'a mut [u8],
9156 ) -> Result<&'a mut [u8]> {
9157 let mut b = octets::OctetsMut::with_slice(out);
9158
9159 if is_server {
9160 if let Some(ref odcid) = tp.original_destination_connection_id {
9161 TransportParams::encode_param(&mut b, 0x0000, odcid.len())?;
9162 b.put_bytes(odcid)?;
9163 }
9164 };
9165
9166 if tp.max_idle_timeout != 0 {
9167 assert!(tp.max_idle_timeout <= octets::MAX_VAR_INT);
9168 TransportParams::encode_param(
9169 &mut b,
9170 0x0001,
9171 octets::varint_len(tp.max_idle_timeout),
9172 )?;
9173 b.put_varint(tp.max_idle_timeout)?;
9174 }
9175
9176 if is_server {
9177 if let Some(ref token) = tp.stateless_reset_token {
9178 TransportParams::encode_param(&mut b, 0x0002, 16)?;
9179 b.put_bytes(&token.to_be_bytes())?;
9180 }
9181 }
9182
9183 if tp.max_udp_payload_size != 0 {
9184 assert!(tp.max_udp_payload_size <= octets::MAX_VAR_INT);
9185 TransportParams::encode_param(
9186 &mut b,
9187 0x0003,
9188 octets::varint_len(tp.max_udp_payload_size),
9189 )?;
9190 b.put_varint(tp.max_udp_payload_size)?;
9191 }
9192
9193 if tp.initial_max_data != 0 {
9194 assert!(tp.initial_max_data <= octets::MAX_VAR_INT);
9195 TransportParams::encode_param(
9196 &mut b,
9197 0x0004,
9198 octets::varint_len(tp.initial_max_data),
9199 )?;
9200 b.put_varint(tp.initial_max_data)?;
9201 }
9202
9203 if tp.initial_max_stream_data_bidi_local != 0 {
9204 assert!(tp.initial_max_stream_data_bidi_local <= octets::MAX_VAR_INT);
9205 TransportParams::encode_param(
9206 &mut b,
9207 0x0005,
9208 octets::varint_len(tp.initial_max_stream_data_bidi_local),
9209 )?;
9210 b.put_varint(tp.initial_max_stream_data_bidi_local)?;
9211 }
9212
9213 if tp.initial_max_stream_data_bidi_remote != 0 {
9214 assert!(
9215 tp.initial_max_stream_data_bidi_remote <= octets::MAX_VAR_INT
9216 );
9217 TransportParams::encode_param(
9218 &mut b,
9219 0x0006,
9220 octets::varint_len(tp.initial_max_stream_data_bidi_remote),
9221 )?;
9222 b.put_varint(tp.initial_max_stream_data_bidi_remote)?;
9223 }
9224
9225 if tp.initial_max_stream_data_uni != 0 {
9226 assert!(tp.initial_max_stream_data_uni <= octets::MAX_VAR_INT);
9227 TransportParams::encode_param(
9228 &mut b,
9229 0x0007,
9230 octets::varint_len(tp.initial_max_stream_data_uni),
9231 )?;
9232 b.put_varint(tp.initial_max_stream_data_uni)?;
9233 }
9234
9235 if tp.initial_max_streams_bidi != 0 {
9236 assert!(tp.initial_max_streams_bidi <= octets::MAX_VAR_INT);
9237 TransportParams::encode_param(
9238 &mut b,
9239 0x0008,
9240 octets::varint_len(tp.initial_max_streams_bidi),
9241 )?;
9242 b.put_varint(tp.initial_max_streams_bidi)?;
9243 }
9244
9245 if tp.initial_max_streams_uni != 0 {
9246 assert!(tp.initial_max_streams_uni <= octets::MAX_VAR_INT);
9247 TransportParams::encode_param(
9248 &mut b,
9249 0x0009,
9250 octets::varint_len(tp.initial_max_streams_uni),
9251 )?;
9252 b.put_varint(tp.initial_max_streams_uni)?;
9253 }
9254
9255 if tp.ack_delay_exponent != 0 {
9256 assert!(tp.ack_delay_exponent <= octets::MAX_VAR_INT);
9257 TransportParams::encode_param(
9258 &mut b,
9259 0x000a,
9260 octets::varint_len(tp.ack_delay_exponent),
9261 )?;
9262 b.put_varint(tp.ack_delay_exponent)?;
9263 }
9264
9265 if tp.max_ack_delay != 0 {
9266 assert!(tp.max_ack_delay <= octets::MAX_VAR_INT);
9267 TransportParams::encode_param(
9268 &mut b,
9269 0x000b,
9270 octets::varint_len(tp.max_ack_delay),
9271 )?;
9272 b.put_varint(tp.max_ack_delay)?;
9273 }
9274
9275 if tp.disable_active_migration {
9276 TransportParams::encode_param(&mut b, 0x000c, 0)?;
9277 }
9278
9279 // TODO: encode preferred_address
9280
9281 if tp.active_conn_id_limit != 2 {
9282 assert!(tp.active_conn_id_limit <= octets::MAX_VAR_INT);
9283 TransportParams::encode_param(
9284 &mut b,
9285 0x000e,
9286 octets::varint_len(tp.active_conn_id_limit),
9287 )?;
9288 b.put_varint(tp.active_conn_id_limit)?;
9289 }
9290
9291 if let Some(scid) = &tp.initial_source_connection_id {
9292 TransportParams::encode_param(&mut b, 0x000f, scid.len())?;
9293 b.put_bytes(scid)?;
9294 }
9295
9296 if is_server {
9297 if let Some(scid) = &tp.retry_source_connection_id {
9298 TransportParams::encode_param(&mut b, 0x0010, scid.len())?;
9299 b.put_bytes(scid)?;
9300 }
9301 }
9302
9303 if let Some(max_datagram_frame_size) = tp.max_datagram_frame_size {
9304 assert!(max_datagram_frame_size <= octets::MAX_VAR_INT);
9305 TransportParams::encode_param(
9306 &mut b,
9307 0x0020,
9308 octets::varint_len(max_datagram_frame_size),
9309 )?;
9310 b.put_varint(max_datagram_frame_size)?;
9311 }
9312
9313 let out_len = b.off();
9314
9315 Ok(&mut out[..out_len])
9316 }
9317
9318 /// Creates a qlog event for connection transport parameters and TLS fields
9319 #[cfg(feature = "qlog")]
9320 pub fn to_qlog(
9321 &self, owner: TransportOwner, cipher: Option<crypto::Algorithm>,
9322 ) -> EventData {
9323 let original_destination_connection_id = qlog::HexSlice::maybe_string(
9324 self.original_destination_connection_id.as_ref(),
9325 );
9326
9327 let stateless_reset_token = qlog::HexSlice::maybe_string(
9328 self.stateless_reset_token.map(|s| s.to_be_bytes()).as_ref(),
9329 );
9330
9331 let tls_cipher: Option<String> = cipher.map(|f| format!("{f:?}"));
9332
9333 EventData::TransportParametersSet(
9334 qlog::events::quic::TransportParametersSet {
9335 owner: Some(owner),
9336 tls_cipher,
9337 original_destination_connection_id,
9338 stateless_reset_token,
9339 disable_active_migration: Some(self.disable_active_migration),
9340 max_idle_timeout: Some(self.max_idle_timeout),
9341 max_udp_payload_size: Some(self.max_udp_payload_size as u32),
9342 ack_delay_exponent: Some(self.ack_delay_exponent as u16),
9343 max_ack_delay: Some(self.max_ack_delay as u16),
9344 active_connection_id_limit: Some(
9345 self.active_conn_id_limit as u32,
9346 ),
9347
9348 initial_max_data: Some(self.initial_max_data),
9349 initial_max_stream_data_bidi_local: Some(
9350 self.initial_max_stream_data_bidi_local,
9351 ),
9352 initial_max_stream_data_bidi_remote: Some(
9353 self.initial_max_stream_data_bidi_remote,
9354 ),
9355 initial_max_stream_data_uni: Some(
9356 self.initial_max_stream_data_uni,
9357 ),
9358 initial_max_streams_bidi: Some(self.initial_max_streams_bidi),
9359 initial_max_streams_uni: Some(self.initial_max_streams_uni),
9360
9361 unknown_parameters: self
9362 .unknown_params
9363 .as_ref()
9364 .map(|unknown_params| {
9365 unknown_params
9366 .into_iter()
9367 .cloned()
9368 .map(
9369 Into::<
9370 qlog::events::quic::UnknownTransportParameter,
9371 >::into,
9372 )
9373 .collect()
9374 })
9375 .unwrap_or_default(),
9376
9377 ..Default::default()
9378 },
9379 )
9380 }
9381}
9382
9383#[doc(hidden)]
9384pub mod test_utils;
9385
9386#[cfg(test)]
9387mod tests;
9388
9389pub use crate::packet::ConnectionId;
9390pub use crate::packet::Header;
9391pub use crate::packet::Type;
9392
9393pub use crate::path::PathEvent;
9394pub use crate::path::PathStats;
9395pub use crate::path::SocketAddrIter;
9396
9397pub use crate::recovery::BbrBwLoReductionStrategy;
9398pub use crate::recovery::BbrParams;
9399pub use crate::recovery::CongestionControlAlgorithm;
9400pub use crate::recovery::StartupExit;
9401pub use crate::recovery::StartupExitReason;
9402
9403pub use crate::stream::StreamIter;
9404
9405pub use crate::range_buf::BufFactory;
9406pub use crate::range_buf::BufSplit;
9407
9408pub use crate::error::ConnectionError;
9409pub use crate::error::Error;
9410pub use crate::error::Result;
9411pub use crate::error::WireErrorCode;
9412
9413mod cid;
9414mod crypto;
9415mod dgram;
9416mod error;
9417#[cfg(feature = "ffi")]
9418mod ffi;
9419mod flowcontrol;
9420mod frame;
9421pub mod h3;
9422mod minmax;
9423mod packet;
9424mod path;
9425mod pmtud;
9426mod rand;
9427mod range_buf;
9428mod ranges;
9429mod recovery;
9430mod stream;
9431mod tls;