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