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, PathError, PathEvent, PathId,
48 PathStats, PathStatus, ReadError, ReadableError, RecvStream, RttEstimator, SendDatagramError,
49 SendStream, SetPathStatusError, ShouldTransmit, StreamEvent, Streams, UdpStats, WriteError,
50 Written,
51};
52
53#[cfg(feature = "rustls")]
54pub use rustls;
55
56mod config;
57#[cfg(doc)]
58pub use config::DEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED;
59pub use config::{
60 AckFrequencyConfig, ClientConfig, ConfigError, EndpointConfig, IdleTimeout, MtuDiscoveryConfig,
61 ServerConfig, StdSystemTime, TimeSource, TransportConfig, ValidationTokenConfig,
62};
63#[cfg(feature = "qlog")]
64pub use config::{QlogConfig, QlogFactory, QlogFileFactory};
65
66pub mod crypto;
67
68mod frame;
69use crate::frame::Frame;
70pub use crate::frame::{ApplicationClose, ConnectionClose, Datagram, FrameType};
71
72mod endpoint;
73pub use crate::endpoint::{
74 AcceptError, ConnectError, ConnectionHandle, DatagramEvent, Endpoint, Incoming, RetryError,
75};
76
77mod packet;
78pub use packet::{
79 ConnectionIdParser, FixedLengthConnectionIdParser, LongType, PacketDecodeError, PartialDecode,
80 ProtectedHeader, ProtectedInitialHeader,
81};
82
83mod shared;
84pub use crate::shared::{ConnectionEvent, ConnectionId, EcnCodepoint, EndpointEvent};
85
86mod transport_error;
87pub use crate::transport_error::{Code as TransportErrorCode, Error as TransportError};
88
89pub mod congestion;
90
91mod cid_generator;
92pub use crate::cid_generator::{
93 ConnectionIdGenerator, HashedConnectionIdGenerator, InvalidCid, RandomConnectionIdGenerator,
94};
95
96mod token;
97use token::ResetToken;
98pub use token::{NoneTokenLog, NoneTokenStore, TokenLog, TokenReuseError, TokenStore};
99
100mod address_discovery;
101
102mod token_memory_cache;
103pub use token_memory_cache::TokenMemoryCache;
104
105pub mod iroh_hp;
106
107#[cfg(feature = "arbitrary")]
108use arbitrary::Arbitrary;
109
110#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
112pub(crate) use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
113#[cfg(all(target_family = "wasm", target_os = "unknown"))]
114pub(crate) use web_time::{Duration, Instant, SystemTime, UNIX_EPOCH};
115
116#[cfg(feature = "bench")]
117pub mod bench_exports {
118 pub use crate::connection::send_buffer::send_buffer_benches;
120}
121
122#[cfg(fuzzing)]
123pub mod fuzzing {
124 pub use crate::connection::{Retransmits, State as ConnectionState, StreamsState};
125 pub use crate::frame::ResetStream;
126 pub use crate::packet::PartialDecode;
127 pub use crate::transport_parameters::TransportParameters;
128 pub use bytes::{BufMut, BytesMut};
129
130 #[cfg(feature = "arbitrary")]
131 use arbitrary::{Arbitrary, Result, Unstructured};
132
133 #[cfg(feature = "arbitrary")]
134 impl<'arbitrary> Arbitrary<'arbitrary> for TransportParameters {
135 fn arbitrary(u: &mut Unstructured<'arbitrary>) -> Result<Self> {
136 Ok(Self {
137 initial_max_streams_bidi: u.arbitrary()?,
138 initial_max_streams_uni: u.arbitrary()?,
139 ack_delay_exponent: u.arbitrary()?,
140 max_udp_payload_size: u.arbitrary()?,
141 ..Self::default()
142 })
143 }
144 }
145
146 #[derive(Debug)]
147 pub struct PacketParams {
148 pub local_cid_len: usize,
149 pub buf: BytesMut,
150 pub grease_quic_bit: bool,
151 }
152
153 #[cfg(feature = "arbitrary")]
154 impl<'arbitrary> Arbitrary<'arbitrary> for PacketParams {
155 fn arbitrary(u: &mut Unstructured<'arbitrary>) -> Result<Self> {
156 let local_cid_len: usize = u.int_in_range(0..=crate::MAX_CID_SIZE)?;
157 let bytes: Vec<u8> = Vec::arbitrary(u)?;
158 let mut buf = BytesMut::new();
159 buf.put_slice(&bytes[..]);
160 Ok(Self {
161 local_cid_len,
162 buf,
163 grease_quic_bit: bool::arbitrary(u)?,
164 })
165 }
166 }
167}
168
169pub const DEFAULT_SUPPORTED_VERSIONS: &[u32] = &[
171 0x00000001,
172 0xff00_001d,
173 0xff00_001e,
174 0xff00_001f,
175 0xff00_0020,
176 0xff00_0021,
177 0xff00_0022,
178];
179
180#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
182#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
183pub enum Side {
184 Client = 0,
186 Server = 1,
188}
189
190impl Side {
191 #[inline]
192 pub fn is_client(self) -> bool {
194 self == Self::Client
195 }
196
197 #[inline]
198 pub fn is_server(self) -> bool {
200 self == Self::Server
201 }
202}
203
204impl ops::Not for Side {
205 type Output = Self;
206 fn not(self) -> Self {
207 match self {
208 Self::Client => Self::Server,
209 Self::Server => Self::Client,
210 }
211 }
212}
213
214#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
216#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
217pub enum Dir {
218 Bi = 0,
220 Uni = 1,
222}
223
224impl Dir {
225 fn iter() -> impl Iterator<Item = Self> {
226 [Self::Bi, Self::Uni].iter().cloned()
227 }
228}
229
230impl fmt::Display for Dir {
231 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
232 use Dir::*;
233 f.pad(match *self {
234 Bi => "bidirectional",
235 Uni => "unidirectional",
236 })
237 }
238}
239
240#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
242#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
243pub struct StreamId(u64);
244
245impl fmt::Display for StreamId {
246 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
247 let initiator = match self.initiator() {
248 Side::Client => "client",
249 Side::Server => "server",
250 };
251 let dir = match self.dir() {
252 Dir::Uni => "uni",
253 Dir::Bi => "bi",
254 };
255 write!(
256 f,
257 "{} {}directional stream {}",
258 initiator,
259 dir,
260 self.index()
261 )
262 }
263}
264
265impl StreamId {
266 pub fn new(initiator: Side, dir: Dir, index: u64) -> Self {
268 Self((index << 2) | ((dir as u64) << 1) | initiator as u64)
269 }
270 pub fn initiator(self) -> Side {
272 if self.0 & 0x1 == 0 {
273 Side::Client
274 } else {
275 Side::Server
276 }
277 }
278 pub fn dir(self) -> Dir {
280 if self.0 & 0x2 == 0 { Dir::Bi } else { Dir::Uni }
281 }
282 pub fn index(self) -> u64 {
284 self.0 >> 2
285 }
286}
287
288impl From<StreamId> for VarInt {
289 fn from(x: StreamId) -> Self {
290 unsafe { Self::from_u64_unchecked(x.0) }
291 }
292}
293
294impl From<VarInt> for StreamId {
295 fn from(v: VarInt) -> Self {
296 Self(v.0)
297 }
298}
299
300impl From<StreamId> for u64 {
301 fn from(x: StreamId) -> Self {
302 x.0
303 }
304}
305
306impl coding::Codec for StreamId {
307 fn decode<B: bytes::Buf>(buf: &mut B) -> coding::Result<Self> {
308 VarInt::decode(buf).map(|x| Self(x.into_inner()))
309 }
310 fn encode<B: bytes::BufMut>(&self, buf: &mut B) {
311 VarInt::from_u64(self.0).unwrap().encode(buf);
312 }
313}
314
315#[derive(Debug)]
317#[must_use]
318pub struct Transmit {
319 pub destination: SocketAddr,
321 pub ecn: Option<EcnCodepoint>,
323 pub size: usize,
325 pub segment_size: Option<usize>,
328 pub src_ip: Option<IpAddr>,
330}
331
332const LOC_CID_COUNT: u64 = 12;
338const RESET_TOKEN_SIZE: usize = 16;
339const MAX_CID_SIZE: usize = 20;
340const MIN_INITIAL_SIZE: u16 = 1200;
341const INITIAL_MTU: u16 = 1200;
343const MAX_UDP_PAYLOAD: u16 = 65527;
344const TIMER_GRANULARITY: Duration = Duration::from_millis(1);
345const MAX_STREAM_COUNT: u64 = 1 << 60;