1#![allow(elided_lifetimes_in_paths)]
3#![allow(missing_debug_implementations)]
4#![allow(missing_docs)]
19#![allow(unreachable_pub)]
20#![allow(clippy::cognitive_complexity)]
21#![allow(clippy::too_many_arguments)]
22#![allow(clippy::use_self)]
23#![allow(dead_code)]
31#![allow(clippy::field_reassign_with_default)]
32#![allow(clippy::module_inception)]
33#![allow(clippy::useless_vec)]
34#![allow(private_interfaces)]
35#![allow(clippy::upper_case_acronyms)]
36#![allow(clippy::type_complexity)]
37#![allow(clippy::manual_clamp)]
38#![allow(clippy::needless_range_loop)]
39#![allow(clippy::borrowed_box)]
40#![allow(clippy::manual_strip)]
41#![allow(clippy::if_same_then_else)]
42#![allow(clippy::ptr_arg)]
43#![allow(clippy::incompatible_msrv)]
44#![allow(clippy::await_holding_lock)]
45#![allow(clippy::single_match)]
46#![allow(clippy::must_use_candidate)]
47#![allow(clippy::let_underscore_must_use)]
48#![allow(clippy::let_underscore_untyped)]
49#![allow(clippy::large_enum_variant)]
50#![allow(clippy::too_many_lines)]
51#![allow(clippy::result_large_err)]
52#![allow(clippy::enum_glob_use)]
53#![allow(clippy::match_like_matches_macro)]
54#![allow(clippy::struct_field_names)]
55#![allow(clippy::cast_precision_loss)]
56#![allow(clippy::cast_sign_loss)]
57#![allow(clippy::cast_possible_wrap)]
58#![allow(clippy::cast_possible_truncation)]
59#![allow(clippy::unnecessary_wraps)]
60#![allow(clippy::doc_markdown)]
61#![allow(clippy::module_name_repetitions)]
62#![allow(clippy::items_after_statements)]
63#![allow(clippy::missing_panics_doc)]
64#![allow(clippy::missing_errors_doc)]
65#![allow(clippy::similar_names)]
66#![allow(clippy::new_without_default)]
67#![allow(clippy::unwrap_or_default)]
68#![allow(clippy::uninlined_format_args)]
69#![allow(clippy::redundant_field_names)]
70#![allow(clippy::redundant_closure_for_method_calls)]
71#![allow(clippy::redundant_pattern_matching)]
72#![allow(clippy::option_if_let_else)]
73#![allow(clippy::trivially_copy_pass_by_ref)]
74#![allow(clippy::len_without_is_empty)]
75#![allow(clippy::explicit_auto_deref)]
76#![allow(clippy::blocks_in_conditions)]
77#![allow(clippy::collapsible_else_if)]
78#![allow(clippy::collapsible_if)]
79#![allow(clippy::unnecessary_cast)]
80#![allow(clippy::needless_bool)]
81#![allow(clippy::needless_borrow)]
82#![allow(clippy::redundant_static_lifetimes)]
83#![allow(clippy::match_ref_pats)]
84#![allow(clippy::should_implement_trait)]
85#![allow(clippy::wildcard_imports)]
86#![allow(unused_must_use)]
87#![allow(improper_ctypes)]
88#![allow(improper_ctypes_definitions)]
89#![allow(non_upper_case_globals)]
90#![allow(clippy::wrong_self_convention)]
91#![allow(clippy::vec_init_then_push)]
92#![allow(clippy::format_in_format_args)]
93#![allow(clippy::from_over_into)]
94#![allow(clippy::useless_conversion)]
95#![allow(clippy::never_loop)]
96#![allow(dropping_references)]
97#![allow(non_snake_case)]
98#![allow(clippy::unnecessary_literal_unwrap)]
99#![allow(clippy::assertions_on_constants)]
100#![allow(unused_imports)]
101
102use std::{
103 fmt,
104 net::{IpAddr, SocketAddr},
105 ops,
106};
107
108mod cid_queue;
110pub mod coding;
111mod constant_time;
112mod range_set;
113pub mod transport_parameters;
114mod varint;
115
116pub use varint::{VarInt, VarIntBoundsExceeded};
117
118pub mod config;
123pub mod connection;
125pub mod endpoint;
127pub mod frame;
129pub mod packet;
131pub mod shared;
133pub mod transport_error;
135pub mod candidate_discovery;
138pub mod cid_generator;
140mod congestion;
141mod protocol_violations;
142#[cfg(test)]
143mod protocol_violations_tests;
144
145mod connection_establishment_simple;
147pub mod nat_traversal_api;
149mod token;
150mod token_memory_cache;
151pub mod tracing;
153
154pub mod api;
157pub mod crypto;
159pub mod discovery;
161pub mod nat_traversal;
163pub mod transport;
165
166pub mod auth;
169pub mod chat;
171pub mod optimization;
173pub mod quic_node;
175pub mod stats_dashboard;
177pub mod terminal_ui;
179
180pub mod compliance_validator;
183
184pub mod logging;
187
188pub mod metrics;
190
191pub mod relay;
193
194pub mod high_level;
196
197pub use high_level::{
199 Accept, Connecting, Connection as HighLevelConnection, Endpoint,
200 RecvStream as HighLevelRecvStream, SendStream as HighLevelSendStream,
201};
202
203pub use crypto::raw_public_keys::key_utils::{
205 derive_peer_id_from_key_bytes, derive_peer_id_from_public_key, generate_ed25519_keypair,
206 public_key_from_bytes, public_key_to_bytes, verify_peer_id,
207};
208
209pub use candidate_discovery::{
211 CandidateDiscoveryManager, DiscoveryConfig, DiscoveryError, DiscoveryEvent, NetworkInterface,
212 ValidatedCandidate,
213};
214pub use connection::nat_traversal::{CandidateSource, CandidateState, NatTraversalRole};
215pub use connection::{
216 Chunk, Chunks, ClosedStream, Connection, ConnectionError, ConnectionStats, Datagrams, Event,
217 FinishError, ReadError, ReadableError, RecvStream, SendDatagramError, SendStream, StreamEvent,
218 Streams, WriteError, Written,
219};
220pub use connection_establishment_simple::{
221 SimpleConnectionEstablishmentManager, SimpleConnectionEvent, SimpleEstablishmentConfig,
222};
223pub use endpoint::{
224 AcceptError, ConnectError, ConnectionHandle, DatagramEvent, Endpoint as LowLevelEndpoint,
225 Incoming,
226};
227pub use nat_traversal_api::{
228 BootstrapNode, CandidateAddress, EndpointRole, NatTraversalConfig, NatTraversalEndpoint,
229 NatTraversalError, NatTraversalEvent, NatTraversalStatistics, PeerId,
230};
231pub use quic_node::{NodeStats as QuicNodeStats, QuicNodeConfig, QuicP2PNode};
232pub use relay::{
233 AuthToken, RelayAction, RelayAuthenticator, RelayConnection, RelayConnectionConfig,
234 RelayError, RelayEvent, RelayResult, SessionId, SessionManager, SessionState,
235};
236pub use shared::{ConnectionId, EcnCodepoint, EndpointEvent};
237pub use transport_error::{Code as TransportErrorCode, Error as TransportError};
238
239pub const DEFAULT_SUPPORTED_VERSIONS: &[u32] = &[
248 0x00000001, 0xff00_001d, ];
251
252#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
254#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
255pub enum Side {
256 Client = 0,
258 Server = 1,
260}
261
262impl Side {
263 #[inline]
264 pub fn is_client(self) -> bool {
266 self == Self::Client
267 }
268
269 #[inline]
270 pub fn is_server(self) -> bool {
272 self == Self::Server
273 }
274}
275
276impl ops::Not for Side {
277 type Output = Self;
278 fn not(self) -> Self {
279 match self {
280 Self::Client => Self::Server,
281 Self::Server => Self::Client,
282 }
283 }
284}
285
286#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
288#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
289pub enum Dir {
290 Bi = 0,
292 Uni = 1,
294}
295
296impl Dir {
297 fn iter() -> impl Iterator<Item = Self> {
298 [Self::Bi, Self::Uni].iter().cloned()
299 }
300}
301
302impl fmt::Display for Dir {
303 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
304 use Dir::*;
305 f.pad(match *self {
306 Bi => "bidirectional",
307 Uni => "unidirectional",
308 })
309 }
310}
311
312#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
314#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
315pub struct StreamId(u64);
316
317impl fmt::Display for StreamId {
318 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
319 let initiator = match self.initiator() {
320 Side::Client => "client",
321 Side::Server => "server",
322 };
323 let dir = match self.dir() {
324 Dir::Uni => "uni",
325 Dir::Bi => "bi",
326 };
327 write!(
328 f,
329 "{} {}directional stream {}",
330 initiator,
331 dir,
332 self.index()
333 )
334 }
335}
336
337impl StreamId {
338 pub fn new(initiator: Side, dir: Dir, index: u64) -> Self {
340 Self((index << 2) | ((dir as u64) << 1) | initiator as u64)
341 }
342 pub fn initiator(self) -> Side {
344 if self.0 & 0x1 == 0 {
345 Side::Client
346 } else {
347 Side::Server
348 }
349 }
350 pub fn dir(self) -> Dir {
352 if self.0 & 0x2 == 0 { Dir::Bi } else { Dir::Uni }
353 }
354 pub fn index(self) -> u64 {
356 self.0 >> 2
357 }
358}
359
360impl From<StreamId> for VarInt {
361 fn from(x: StreamId) -> Self {
362 unsafe { Self::from_u64_unchecked(x.0) }
363 }
364}
365
366impl From<VarInt> for StreamId {
367 fn from(v: VarInt) -> Self {
368 Self(v.0)
369 }
370}
371
372impl From<StreamId> for u64 {
373 fn from(x: StreamId) -> Self {
374 x.0
375 }
376}
377
378impl coding::Codec for StreamId {
379 fn decode<B: bytes::Buf>(buf: &mut B) -> coding::Result<Self> {
380 VarInt::decode(buf).map(|x| Self(x.into_inner()))
381 }
382 fn encode<B: bytes::BufMut>(&self, buf: &mut B) {
383 VarInt::from_u64(self.0).unwrap().encode(buf);
384 }
385}
386
387#[derive(Debug)]
389#[must_use]
390pub struct Transmit {
391 pub destination: SocketAddr,
393 pub ecn: Option<EcnCodepoint>,
395 pub size: usize,
397 pub segment_size: Option<usize>,
400 pub src_ip: Option<IpAddr>,
402}
403
404#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
406pub(crate) use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
407#[cfg(all(target_family = "wasm", target_os = "unknown"))]
408pub(crate) use web_time::{Duration, Instant, SystemTime, UNIX_EPOCH};
409
410pub(crate) const LOC_CID_COUNT: u64 = 8;
416pub(crate) const RESET_TOKEN_SIZE: usize = 16;
417pub(crate) const MAX_CID_SIZE: usize = 20;
418pub(crate) const MIN_INITIAL_SIZE: u16 = 1200;
419pub(crate) const INITIAL_MTU: u16 = 1200;
421pub(crate) const MAX_UDP_PAYLOAD: u16 = 65527;
422pub(crate) const TIMER_GRANULARITY: Duration = Duration::from_millis(1);
423pub(crate) const MAX_STREAM_COUNT: u64 = 1 << 60;
425
426pub use cid_generator::RandomConnectionIdGenerator;
428pub use config::{
429 AckFrequencyConfig, ClientConfig, EndpointConfig, MtuDiscoveryConfig, ServerConfig,
430 TransportConfig,
431};
432
433pub use crypto::pqc::{
435 HybridKem, HybridPreference, HybridSignature, MlDsa65, MlKem768, PqcConfig, PqcConfigBuilder,
436 PqcError, PqcMode, PqcResult,
437};
438pub(crate) use frame::Frame;
439pub(crate) use token::{NoneTokenLog, ResetToken, TokenLog, TokenStore};
440pub(crate) use token_memory_cache::TokenMemoryCache;