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