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