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