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