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