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