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