1#![cfg_attr(not(fuzzing), warn(missing_docs))]
16#![allow(clippy::too_many_arguments)]
18#![warn(unreachable_pub)]
19#![warn(clippy::use_self)]
20
21use std::{
22 fmt,
23 net::{IpAddr, SocketAddr},
24 ops,
25};
26
27mod cid_queue;
28pub mod coding;
29mod constant_time;
30mod range_set;
31#[cfg(all(test, feature = "rustls", any(feature = "aws-lc-rs", feature = "ring")))]
32mod tests;
33pub mod transport_parameters;
34mod varint;
35
36pub use varint::{VarInt, VarIntBoundsExceeded};
37
38#[cfg(feature = "bloom")]
39mod bloom_token_log;
40#[cfg(feature = "bloom")]
41pub use bloom_token_log::BloomTokenLog;
42
43pub(crate) mod connection;
44pub use crate::connection::{
45 Chunk, Chunks, ClosePathError, ClosedPath, ClosedStream, Connection, ConnectionError,
46 ConnectionStats, Datagrams, Event, FinishError, FrameStats, MultipathNotNegotiated,
47 NetworkChangeHint, PathAbandonReason, PathError, PathEvent, PathId, PathStats, PathStatus,
48 ReadError, ReadableError, RecvStream, RttEstimator, SendDatagramError, SendStream,
49 SetPathStatusError, ShouldTransmit, StreamEvent, Streams, UdpStats, WriteError,
50};
51#[cfg(test)]
52use test_strategy::Arbitrary;
53
54#[cfg(feature = "rustls")]
55pub use rustls;
56
57mod config;
58pub use config::{
59 AckFrequencyConfig, ClientConfig, ConfigError, EndpointConfig, IdleTimeout, MtuDiscoveryConfig,
60 ServerConfig, StdSystemTime, TimeSource, TransportConfig, ValidationTokenConfig,
61};
62#[cfg(feature = "qlog")]
63pub use config::{QlogConfig, QlogFactory, QlogFileFactory};
64
65pub mod crypto;
66
67mod frame;
68pub use crate::frame::{
69 ApplicationClose, ConnectionClose, Datagram, DatagramInfo, FrameType, InvalidFrameId,
70 MaybeFrame, StreamInfo,
71};
72use crate::{
73 coding::{Decodable, Encodable},
74 frame::Frame,
75};
76
77mod endpoint;
78pub use crate::endpoint::{
79 AcceptError, ConnectError, ConnectionHandle, DatagramEvent, DecryptedInitial, Endpoint,
80 Incoming, IncomingAlpns, RetryError,
81};
82
83mod packet;
84pub use packet::{
85 ConnectionIdParser, FixedLengthConnectionIdParser, LongType, PacketDecodeError, PartialDecode,
86 ProtectedHeader, ProtectedInitialHeader,
87};
88
89mod shared;
90pub use crate::shared::{ConnectionEvent, ConnectionId, EcnCodepoint, EndpointEvent};
91
92mod transport_error;
93pub use crate::transport_error::{Code as TransportErrorCode, Error as TransportError};
94
95pub mod congestion;
96
97mod cid_generator;
98pub use crate::cid_generator::{
99 ConnectionIdGenerator, HashedConnectionIdGenerator, InvalidCid, RandomConnectionIdGenerator,
100};
101
102mod token;
103use token::ResetToken;
104pub use token::{NoneTokenLog, NoneTokenStore, TokenLog, TokenReuseError, TokenStore};
105
106mod address_discovery;
107
108mod token_memory_cache;
109pub use token_memory_cache::TokenMemoryCache;
110
111pub mod n0_nat_traversal;
112
113#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
115pub(crate) use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
116#[cfg(all(target_family = "wasm", target_os = "unknown"))]
117pub(crate) use web_time::{Duration, Instant, SystemTime, UNIX_EPOCH};
118
119#[cfg(feature = "bench")]
120pub mod bench_exports {
121 pub use crate::connection::send_buffer::send_buffer_benches;
123}
124
125#[cfg(fuzzing)]
126pub mod fuzzing {
127 pub use crate::connection::{Retransmits, State as ConnectionState, StreamsState};
128 pub use crate::frame::ResetStream;
129 pub use crate::packet::PartialDecode;
130 pub use crate::transport_parameters::TransportParameters;
131 pub use bytes::{BufMut, BytesMut};
132
133 #[cfg(feature = "arbitrary")]
134 use arbitrary::{Arbitrary, Result, Unstructured};
135
136 #[cfg(feature = "arbitrary")]
137 impl<'arbitrary> Arbitrary<'arbitrary> for TransportParameters {
138 fn arbitrary(u: &mut Unstructured<'arbitrary>) -> Result<Self> {
139 Ok(Self {
140 initial_max_streams_bidi: u.arbitrary()?,
141 initial_max_streams_uni: u.arbitrary()?,
142 ack_delay_exponent: u.arbitrary()?,
143 max_udp_payload_size: u.arbitrary()?,
144 ..Self::default()
145 })
146 }
147 }
148
149 #[derive(Debug)]
150 pub struct PacketParams {
151 pub local_cid_len: usize,
152 pub buf: BytesMut,
153 pub grease_quic_bit: bool,
154 }
155
156 #[cfg(feature = "arbitrary")]
157 impl<'arbitrary> Arbitrary<'arbitrary> for PacketParams {
158 fn arbitrary(u: &mut Unstructured<'arbitrary>) -> Result<Self> {
159 let local_cid_len: usize = u.int_in_range(0..=crate::MAX_CID_SIZE)?;
160 let bytes: Vec<u8> = Vec::arbitrary(u)?;
161 let mut buf = BytesMut::new();
162 buf.put_slice(&bytes[..]);
163 Ok(Self {
164 local_cid_len,
165 buf,
166 grease_quic_bit: bool::arbitrary(u)?,
167 })
168 }
169 }
170}
171
172pub const DEFAULT_SUPPORTED_VERSIONS: &[u32] = &[
174 0x00000001,
175 0xff00_001d,
176 0xff00_001e,
177 0xff00_001f,
178 0xff00_0020,
179 0xff00_0021,
180 0xff00_0022,
181];
182
183#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
185#[cfg_attr(test, derive(Arbitrary))]
186#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
187pub enum Side {
188 Client = 0,
190 Server = 1,
192}
193
194impl Side {
195 #[inline]
196 pub fn is_client(self) -> bool {
198 self == Self::Client
199 }
200
201 #[inline]
202 pub fn is_server(self) -> bool {
204 self == Self::Server
205 }
206}
207
208impl ops::Not for Side {
209 type Output = Self;
210 fn not(self) -> Self {
211 match self {
212 Self::Client => Self::Server,
213 Self::Server => Self::Client,
214 }
215 }
216}
217
218#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
220#[cfg_attr(test, derive(Arbitrary))]
221#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
222pub enum Dir {
223 Bi = 0,
225 Uni = 1,
227}
228
229impl Dir {
230 fn iter() -> impl Iterator<Item = Self> {
231 [Self::Bi, Self::Uni].iter().cloned()
232 }
233}
234
235impl fmt::Display for Dir {
236 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
237 use Dir::*;
238 f.pad(match *self {
239 Bi => "bidirectional",
240 Uni => "unidirectional",
241 })
242 }
243}
244
245#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
247#[cfg_attr(test, derive(Arbitrary))]
248pub struct StreamId(#[cfg_attr(test, strategy(crate::varint::varint_u64()))] u64);
249
250impl fmt::Display for StreamId {
251 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
252 let initiator = match self.initiator() {
253 Side::Client => "client",
254 Side::Server => "server",
255 };
256 let dir = match self.dir() {
257 Dir::Uni => "uni",
258 Dir::Bi => "bi",
259 };
260 write!(
261 f,
262 "{} {}directional stream {}",
263 initiator,
264 dir,
265 self.index()
266 )
267 }
268}
269
270impl StreamId {
271 pub fn new(initiator: Side, dir: Dir, index: u64) -> Self {
273 Self((index << 2) | ((dir as u64) << 1) | initiator as u64)
274 }
275 pub fn initiator(self) -> Side {
277 if self.0 & 0x1 == 0 {
278 Side::Client
279 } else {
280 Side::Server
281 }
282 }
283 pub fn dir(self) -> Dir {
285 if self.0 & 0x2 == 0 { Dir::Bi } else { Dir::Uni }
286 }
287 pub fn index(self) -> u64 {
289 self.0 >> 2
290 }
291}
292
293impl From<StreamId> for VarInt {
294 fn from(x: StreamId) -> Self {
295 unsafe { Self::from_u64_unchecked(x.0) }
296 }
297}
298
299impl From<VarInt> for StreamId {
300 fn from(v: VarInt) -> Self {
301 Self(v.0)
302 }
303}
304
305impl From<StreamId> for u64 {
306 fn from(x: StreamId) -> Self {
307 x.0
308 }
309}
310
311impl Decodable for StreamId {
312 fn decode<B: bytes::Buf>(buf: &mut B) -> coding::Result<Self> {
313 VarInt::decode(buf).map(|x| Self(x.into_inner()))
314 }
315}
316
317impl Encodable for StreamId {
318 fn encode<B: bytes::BufMut>(&self, buf: &mut B) {
319 VarInt::from_u64(self.0).unwrap().encode(buf);
320 }
321}
322
323#[cfg(feature = "arbitrary")]
324impl<'arbitrary> arbitrary::Arbitrary<'arbitrary> for StreamId {
325 fn arbitrary(u: &mut arbitrary::Unstructured<'arbitrary>) -> arbitrary::Result<Self> {
326 Ok(VarInt::arbitrary(u)?.into())
327 }
328}
329
330#[derive(Debug)]
332#[must_use]
333pub struct Transmit {
334 pub destination: SocketAddr,
336 pub ecn: Option<EcnCodepoint>,
338 pub size: usize,
340 pub segment_size: Option<usize>,
343 pub src_ip: Option<IpAddr>,
345}
346
347const LOCAL_CID_COUNT: u64 = 12;
353const RESET_TOKEN_SIZE: usize = 16;
354const MAX_CID_SIZE: usize = 20;
355const MIN_INITIAL_SIZE: u16 = 1200;
356const INITIAL_MTU: u16 = 1200;
358const MAX_UDP_PAYLOAD: u16 = 65527;
359const TIMER_GRANULARITY: Duration = Duration::from_millis(1);
360const MAX_STREAM_COUNT: u64 = 1 << 60;
362
363#[derive(Hash, Eq, PartialEq, Copy, Clone)]
371pub struct FourTuple {
372 remote: SocketAddr,
374 local_ip: Option<IpAddr>,
380}
381
382impl FourTuple {
383 pub fn new(mut remote: SocketAddr, local_ip: Option<IpAddr>) -> Self {
385 if let SocketAddr::V6(socket_addr) = &mut remote {
386 socket_addr.set_flowinfo(0);
394
395 let requires_scope_id =
398 socket_addr.ip().is_unicast_link_local() || socket_addr.ip().is_multicast();
399 if !requires_scope_id {
400 socket_addr.set_scope_id(0);
404 }
405 }
406
407 Self { remote, local_ip }
408 }
409
410 pub fn from_remote(remote: SocketAddr) -> Self {
412 Self::new(remote, None)
413 }
414
415 pub fn remote(&self) -> SocketAddr {
417 self.remote
418 }
419
420 pub fn local_ip(&self) -> Option<IpAddr> {
422 self.local_ip
423 }
424
425 pub(crate) fn is_probably_same_path(&self, other: &Self) -> bool {
436 self.remote == other.remote && (self.local_ip.is_none() || self.local_ip == other.local_ip)
437 }
438
439 pub(crate) fn update_local_if_same_remote(&mut self, other: &Self) -> bool {
446 if self.remote != other.remote {
447 return false;
448 }
449 if self.local_ip.is_some() && self.local_ip != other.local_ip {
450 return false;
451 }
452 self.local_ip = other.local_ip;
453 true
454 }
455}
456
457impl fmt::Display for FourTuple {
458 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
459 f.write_str("(local: ")?;
460 if let Some(local_ip) = &self.local_ip {
461 local_ip.fmt(f)?;
462 f.write_str(", ")?;
463 } else {
464 f.write_str("<unspecified>, ")?;
465 }
466 f.write_str("remote: ")?;
467 self.remote.fmt(f)?;
468 f.write_str(")")
469 }
470}
471
472impl fmt::Debug for FourTuple {
473 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
474 fmt::Display::fmt(&self, f)
475 }
476}
477
478impl From<SocketAddr> for FourTuple {
480 fn from(value: SocketAddr) -> Self {
481 Self::from_remote(value)
482 }
483}