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