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