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