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;
69pub use crate::frame::{ApplicationClose, ConnectionClose, Datagram, FrameType};
70use crate::{
71 coding::{Decodable, Encodable},
72 frame::Frame,
73};
74
75mod endpoint;
76pub use crate::endpoint::{
77 AcceptError, ConnectError, ConnectionHandle, DatagramEvent, Endpoint, Incoming, RetryError,
78};
79
80mod packet;
81pub use packet::{
82 ConnectionIdParser, FixedLengthConnectionIdParser, LongType, PacketDecodeError, PartialDecode,
83 ProtectedHeader, ProtectedInitialHeader,
84};
85
86mod shared;
87pub use crate::shared::{ConnectionEvent, ConnectionId, EcnCodepoint, EndpointEvent};
88
89mod transport_error;
90pub use crate::transport_error::{Code as TransportErrorCode, Error as TransportError};
91
92pub mod congestion;
93
94mod cid_generator;
95pub use crate::cid_generator::{
96 ConnectionIdGenerator, HashedConnectionIdGenerator, InvalidCid, RandomConnectionIdGenerator,
97};
98
99mod token;
100use token::ResetToken;
101pub use token::{NoneTokenLog, NoneTokenStore, TokenLog, TokenReuseError, TokenStore};
102
103mod address_discovery;
104
105mod token_memory_cache;
106pub use token_memory_cache::TokenMemoryCache;
107
108pub mod iroh_hp;
109
110#[cfg(feature = "arbitrary")]
111use arbitrary::Arbitrary;
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))]
185#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
186pub enum Side {
187 Client = 0,
189 Server = 1,
191}
192
193impl Side {
194 #[inline]
195 pub fn is_client(self) -> bool {
197 self == Self::Client
198 }
199
200 #[inline]
201 pub fn is_server(self) -> bool {
203 self == Self::Server
204 }
205}
206
207impl ops::Not for Side {
208 type Output = Self;
209 fn not(self) -> Self {
210 match self {
211 Self::Client => Self::Server,
212 Self::Server => Self::Client,
213 }
214 }
215}
216
217#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
219#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
220pub enum Dir {
221 Bi = 0,
223 Uni = 1,
225}
226
227impl Dir {
228 fn iter() -> impl Iterator<Item = Self> {
229 [Self::Bi, Self::Uni].iter().cloned()
230 }
231}
232
233impl fmt::Display for Dir {
234 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
235 use Dir::*;
236 f.pad(match *self {
237 Bi => "bidirectional",
238 Uni => "unidirectional",
239 })
240 }
241}
242
243#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
245#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
246pub struct StreamId(u64);
247
248impl fmt::Display for StreamId {
249 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
250 let initiator = match self.initiator() {
251 Side::Client => "client",
252 Side::Server => "server",
253 };
254 let dir = match self.dir() {
255 Dir::Uni => "uni",
256 Dir::Bi => "bi",
257 };
258 write!(
259 f,
260 "{} {}directional stream {}",
261 initiator,
262 dir,
263 self.index()
264 )
265 }
266}
267
268impl StreamId {
269 pub fn new(initiator: Side, dir: Dir, index: u64) -> Self {
271 Self((index << 2) | ((dir as u64) << 1) | initiator as u64)
272 }
273 pub fn initiator(self) -> Side {
275 if self.0 & 0x1 == 0 {
276 Side::Client
277 } else {
278 Side::Server
279 }
280 }
281 pub fn dir(self) -> Dir {
283 if self.0 & 0x2 == 0 { Dir::Bi } else { Dir::Uni }
284 }
285 pub fn index(self) -> u64 {
287 self.0 >> 2
288 }
289}
290
291impl From<StreamId> for VarInt {
292 fn from(x: StreamId) -> Self {
293 unsafe { Self::from_u64_unchecked(x.0) }
294 }
295}
296
297impl From<VarInt> for StreamId {
298 fn from(v: VarInt) -> Self {
299 Self(v.0)
300 }
301}
302
303impl From<StreamId> for u64 {
304 fn from(x: StreamId) -> Self {
305 x.0
306 }
307}
308
309impl Decodable for StreamId {
310 fn decode<B: bytes::Buf>(buf: &mut B) -> coding::Result<Self> {
311 VarInt::decode(buf).map(|x| Self(x.into_inner()))
312 }
313}
314impl Encodable for StreamId {
315 fn encode<B: bytes::BufMut>(&self, buf: &mut B) {
316 VarInt::from_u64(self.0).unwrap().encode(buf);
317 }
318}
319
320#[derive(Debug)]
322#[must_use]
323pub struct Transmit {
324 pub destination: SocketAddr,
326 pub ecn: Option<EcnCodepoint>,
328 pub size: usize,
330 pub segment_size: Option<usize>,
333 pub src_ip: Option<IpAddr>,
335}
336
337const LOC_CID_COUNT: u64 = 12;
343const RESET_TOKEN_SIZE: usize = 16;
344const MAX_CID_SIZE: usize = 20;
345const MIN_INITIAL_SIZE: u16 = 1200;
346const INITIAL_MTU: u16 = 1200;
348const MAX_UDP_PAYLOAD: u16 = 65527;
349const TIMER_GRANULARITY: Duration = Duration::from_millis(1);
350const MAX_STREAM_COUNT: u64 = 1 << 60;