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