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