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