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