ant_quic/
lib.rs

1//! ant-quic: QUIC transport protocol with advanced NAT traversal for P2P networks
2#![allow(elided_lifetimes_in_paths)]
3#![allow(missing_debug_implementations)]
4//!
5//! This library provides a clean, modular implementation of QUIC-native NAT traversal
6//! using raw public keys for authentication. It is designed to be minimal, focused,
7//! and highly testable, with exceptional cross-platform support.
8//!
9//! The library is organized into the following main modules:
10//! - `transport`: Core QUIC transport functionality
11//! - `nat_traversal`: QUIC-native NAT traversal protocol
12//! - `discovery`: Platform-specific network interface discovery
13//! - `crypto`: Raw public key authentication
14//! - `api`: High-level P2P networking API
15
16// TODO: Re-enable after fixing all missing documentation
17// #![cfg_attr(not(fuzzing), warn(missing_docs))]
18#![allow(missing_docs)]
19#![allow(unreachable_pub)]
20#![allow(clippy::cognitive_complexity)]
21#![allow(clippy::too_many_arguments)]
22#![allow(clippy::use_self)]
23// FIXME: Temporary allows to get CI passing quickly
24// These should be gradually removed as the codebase is cleaned up
25// Priority items to fix:
26// 1. Re-enable missing_docs and document all public items
27// 2. Fix dead_code warnings by removing unused code
28// 3. Fix clippy style issues (field names, formatting, etc)
29// 4. Enable proper error handling instead of allowing unused_must_use
30#![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
108// Core modules
109mod cid_queue;
110pub mod coding;
111mod constant_time;
112mod range_set;
113pub mod transport_parameters;
114mod varint;
115
116pub use varint::{VarInt, VarIntBoundsExceeded};
117
118// Removed optional bloom module
119
120// Core implementation modules
121/// Configuration structures and validation
122pub mod config;
123/// QUIC connection state machine and management
124pub mod connection;
125/// QUIC endpoint for accepting and initiating connections
126pub mod endpoint;
127/// QUIC frame types and encoding/decoding
128pub mod frame;
129/// QUIC packet structures and processing
130pub mod packet;
131/// Shared types and utilities
132pub mod shared;
133/// Transport error types and codes
134pub mod transport_error;
135// Simplified congestion control
136/// Network candidate discovery and management
137pub mod candidate_discovery;
138/// Connection ID generation strategies
139pub mod cid_generator;
140mod congestion;
141mod protocol_violations;
142#[cfg(test)]
143mod protocol_violations_tests;
144
145// Zero-cost tracing system
146mod connection_establishment_simple;
147/// High-level NAT traversal API
148pub mod nat_traversal_api;
149mod token;
150mod token_memory_cache;
151/// Zero-cost tracing and event logging system
152pub mod tracing;
153
154// Public modules with new structure
155/// High-level API for QUIC operations
156pub mod api;
157/// Cryptographic operations and raw public key support
158pub mod crypto;
159/// Platform-specific network interface discovery
160pub mod discovery;
161/// NAT traversal protocol implementation
162pub mod nat_traversal;
163/// Transport-level protocol implementation
164pub mod transport;
165
166// Additional modules
167/// Peer authentication system
168pub mod auth;
169/// Secure chat protocol implementation
170pub mod chat;
171/// Performance optimization utilities
172pub mod optimization;
173/// High-level QUIC P2P node implementation
174pub mod quic_node;
175/// Real-time statistics dashboard
176pub mod stats_dashboard;
177/// Terminal user interface components
178pub mod terminal_ui;
179
180// Compliance validation framework
181/// IETF compliance validation tools
182pub mod compliance_validator;
183
184// Comprehensive logging system
185/// Structured logging and diagnostics
186pub mod logging;
187
188// High-level async API modules (ported from quinn crate)
189pub mod high_level;
190
191// Re-export high-level API types for easier usage
192pub use high_level::{
193    Accept, Connecting, Connection as HighLevelConnection, Endpoint,
194    RecvStream as HighLevelRecvStream, SendStream as HighLevelSendStream,
195};
196
197// Re-export crypto utilities for peer ID management
198pub use crypto::raw_public_keys::key_utils::{
199    derive_peer_id_from_key_bytes, derive_peer_id_from_public_key, generate_ed25519_keypair,
200    public_key_from_bytes, public_key_to_bytes, verify_peer_id,
201};
202
203// Re-export key types for backward compatibility
204pub use candidate_discovery::{
205    CandidateDiscoveryManager, DiscoveryConfig, DiscoveryError, DiscoveryEvent, NetworkInterface,
206    ValidatedCandidate,
207};
208pub use connection::nat_traversal::{CandidateSource, CandidateState, NatTraversalRole};
209pub use connection::{
210    Chunk, Chunks, ClosedStream, Connection, ConnectionError, ConnectionStats, Datagrams, Event,
211    FinishError, ReadError, ReadableError, RecvStream, SendDatagramError, SendStream, StreamEvent,
212    Streams, WriteError, Written,
213};
214pub use connection_establishment_simple::{
215    SimpleConnectionEstablishmentManager, SimpleConnectionEvent, SimpleEstablishmentConfig,
216};
217pub use endpoint::{
218    AcceptError, ConnectError, ConnectionHandle, DatagramEvent, Endpoint as LowLevelEndpoint,
219    Incoming,
220};
221pub use nat_traversal_api::{
222    BootstrapNode, CandidateAddress, EndpointRole, NatTraversalConfig, NatTraversalEndpoint,
223    NatTraversalError, NatTraversalEvent, NatTraversalStatistics, PeerId,
224};
225pub use quic_node::{NodeStats as QuicNodeStats, QuicNodeConfig, QuicP2PNode};
226pub use shared::{ConnectionId, EcnCodepoint, EndpointEvent};
227pub use transport_error::{Code as TransportErrorCode, Error as TransportError};
228
229// #[cfg(fuzzing)]
230// pub mod fuzzing; // Module not implemented yet
231
232/// The QUIC protocol version implemented.
233///
234/// Simplified to include only the essential versions:
235/// - 0x00000001: QUIC v1 (RFC 9000)
236/// - 0xff00_001d: Draft 29
237pub const DEFAULT_SUPPORTED_VERSIONS: &[u32] = &[
238    0x00000001,  // QUIC v1 (RFC 9000)
239    0xff00_001d, // Draft 29
240];
241
242/// Whether an endpoint was the initiator of a connection
243#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
244#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
245pub enum Side {
246    /// The initiator of a connection
247    Client = 0,
248    /// The acceptor of a connection
249    Server = 1,
250}
251
252impl Side {
253    #[inline]
254    /// Shorthand for `self == Side::Client`
255    pub fn is_client(self) -> bool {
256        self == Self::Client
257    }
258
259    #[inline]
260    /// Shorthand for `self == Side::Server`
261    pub fn is_server(self) -> bool {
262        self == Self::Server
263    }
264}
265
266impl ops::Not for Side {
267    type Output = Self;
268    fn not(self) -> Self {
269        match self {
270            Self::Client => Self::Server,
271            Self::Server => Self::Client,
272        }
273    }
274}
275
276/// Whether a stream communicates data in both directions or only from the initiator
277#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
278#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
279pub enum Dir {
280    /// Data flows in both directions
281    Bi = 0,
282    /// Data flows only from the stream's initiator
283    Uni = 1,
284}
285
286impl Dir {
287    fn iter() -> impl Iterator<Item = Self> {
288        [Self::Bi, Self::Uni].iter().cloned()
289    }
290}
291
292impl fmt::Display for Dir {
293    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
294        use Dir::*;
295        f.pad(match *self {
296            Bi => "bidirectional",
297            Uni => "unidirectional",
298        })
299    }
300}
301
302/// Identifier for a stream within a particular connection
303#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
304#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
305pub struct StreamId(u64);
306
307impl fmt::Display for StreamId {
308    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
309        let initiator = match self.initiator() {
310            Side::Client => "client",
311            Side::Server => "server",
312        };
313        let dir = match self.dir() {
314            Dir::Uni => "uni",
315            Dir::Bi => "bi",
316        };
317        write!(
318            f,
319            "{} {}directional stream {}",
320            initiator,
321            dir,
322            self.index()
323        )
324    }
325}
326
327impl StreamId {
328    /// Create a new StreamId
329    pub fn new(initiator: Side, dir: Dir, index: u64) -> Self {
330        Self((index << 2) | ((dir as u64) << 1) | initiator as u64)
331    }
332    /// Which side of a connection initiated the stream
333    pub fn initiator(self) -> Side {
334        if self.0 & 0x1 == 0 {
335            Side::Client
336        } else {
337            Side::Server
338        }
339    }
340    /// Which directions data flows in
341    pub fn dir(self) -> Dir {
342        if self.0 & 0x2 == 0 { Dir::Bi } else { Dir::Uni }
343    }
344    /// Distinguishes streams of the same initiator and directionality
345    pub fn index(self) -> u64 {
346        self.0 >> 2
347    }
348}
349
350impl From<StreamId> for VarInt {
351    fn from(x: StreamId) -> Self {
352        unsafe { Self::from_u64_unchecked(x.0) }
353    }
354}
355
356impl From<VarInt> for StreamId {
357    fn from(v: VarInt) -> Self {
358        Self(v.0)
359    }
360}
361
362impl From<StreamId> for u64 {
363    fn from(x: StreamId) -> Self {
364        x.0
365    }
366}
367
368impl coding::Codec for StreamId {
369    fn decode<B: bytes::Buf>(buf: &mut B) -> coding::Result<Self> {
370        VarInt::decode(buf).map(|x| Self(x.into_inner()))
371    }
372    fn encode<B: bytes::BufMut>(&self, buf: &mut B) {
373        VarInt::from_u64(self.0).unwrap().encode(buf);
374    }
375}
376
377/// An outgoing packet
378#[derive(Debug)]
379#[must_use]
380pub struct Transmit {
381    /// The socket this datagram should be sent to
382    pub destination: SocketAddr,
383    /// Explicit congestion notification bits to set on the packet
384    pub ecn: Option<EcnCodepoint>,
385    /// Amount of data written to the caller-supplied buffer
386    pub size: usize,
387    /// The segment size if this transmission contains multiple datagrams.
388    /// This is `None` if the transmit only contains a single datagram
389    pub segment_size: Option<usize>,
390    /// Optional source IP address for the datagram
391    pub src_ip: Option<IpAddr>,
392}
393
394// Deal with time
395#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
396pub(crate) use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
397#[cfg(all(target_family = "wasm", target_os = "unknown"))]
398pub(crate) use web_time::{Duration, Instant, SystemTime, UNIX_EPOCH};
399
400//
401// Useful internal constants
402//
403
404/// The maximum number of CIDs we bother to issue per connection
405pub(crate) const LOC_CID_COUNT: u64 = 8;
406pub(crate) const RESET_TOKEN_SIZE: usize = 16;
407pub(crate) const MAX_CID_SIZE: usize = 20;
408pub(crate) const MIN_INITIAL_SIZE: u16 = 1200;
409/// <https://www.rfc-editor.org/rfc/rfc9000.html#name-datagram-size>
410pub(crate) const INITIAL_MTU: u16 = 1200;
411pub(crate) const MAX_UDP_PAYLOAD: u16 = 65527;
412pub(crate) const TIMER_GRANULARITY: Duration = Duration::from_millis(1);
413/// Maximum number of streams that can be tracked per connection
414pub(crate) const MAX_STREAM_COUNT: u64 = 1 << 60;
415
416// Internal type re-exports for crate modules
417pub use cid_generator::RandomConnectionIdGenerator;
418pub use config::{
419    AckFrequencyConfig, ClientConfig, EndpointConfig, MtuDiscoveryConfig, ServerConfig,
420    TransportConfig,
421};
422pub(crate) use frame::Frame;
423pub(crate) use token::{NoneTokenLog, ResetToken, TokenLog, TokenStore};
424pub(crate) use token_memory_cache::TokenMemoryCache;