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