ant_quic/
lib.rs

1// Copyright 2024 Saorsa Labs Ltd.
2//
3// This Saorsa Network Software is licensed under the General Public License (GPL), version 3.
4// Please see the file LICENSE-GPL, or visit <http://www.gnu.org/licenses/> for the full text.
5//
6// Full details available at https://saorsalabs.com/licenses
7
8//! ant-quic: QUIC transport protocol with advanced NAT traversal for P2P networks
9#![allow(elided_lifetimes_in_paths)]
10#![allow(missing_debug_implementations)]
11//!
12//! This library provides a clean, modular implementation of QUIC-native NAT traversal
13//! using raw public keys for authentication. It is designed to be minimal, focused,
14//! and highly testable, with exceptional cross-platform support.
15//!
16//! The library is organized into the following main modules:
17//! - `transport`: Core QUIC transport functionality
18//! - `nat_traversal`: QUIC-native NAT traversal protocol
19//! - `discovery`: Platform-specific network interface discovery
20//! - `crypto`: Raw public key authentication
21//! - `trust`: Trust management with TOFU pinning and channel binding
22
23// Documentation warnings enabled - all public APIs must be documented
24#![cfg_attr(not(fuzzing), warn(missing_docs))]
25#![allow(unreachable_pub)]
26#![allow(clippy::cognitive_complexity)]
27#![allow(clippy::too_many_arguments)]
28#![allow(clippy::use_self)]
29// Dead code warnings enabled - remove unused code
30#![warn(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#![warn(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/// Bounded pending data buffer with TTL expiration
121pub mod bounded_pending_buffer;
122
123/// RTT-based path selection with hysteresis
124pub mod path_selection;
125
126/// Coordinated shutdown for endpoints
127pub mod shutdown;
128
129/// Watchable state pattern for reactive observation
130pub mod watchable;
131
132/// Fair polling for multiple transports
133pub mod fair_polling;
134
135/// Graceful transport degradation
136pub mod transport_resilience;
137
138/// Discovery trait for stream composition
139pub mod discovery_trait;
140
141/// Structured event logging for observability
142pub mod structured_events;
143
144// ============================================================================
145// SIMPLE API - Zero Configuration P2P
146// ============================================================================
147
148/// Zero-configuration P2P node - THE PRIMARY API
149///
150/// Use [`Node`] for the simplest possible P2P experience:
151/// ```rust,ignore
152/// let node = Node::new().await?;
153/// ```
154pub mod node;
155
156/// Minimal configuration for zero-config P2P nodes
157pub mod node_config;
158
159/// Consolidated node status for observability
160pub mod node_status;
161
162/// Unified events for P2P nodes
163pub mod node_event;
164
165// Core implementation modules
166/// Configuration structures and validation
167pub mod config;
168/// QUIC connection state machine and management
169pub mod connection;
170/// QUIC endpoint for accepting and initiating connections
171pub mod endpoint;
172/// QUIC frame types and encoding/decoding
173pub mod frame;
174/// QUIC packet structures and processing
175pub mod packet;
176/// Shared types and utilities
177pub mod shared;
178/// Transport error types and codes
179pub mod transport_error;
180// Simplified congestion control
181/// Network candidate discovery and management
182pub mod candidate_discovery;
183/// Connection ID generation strategies
184pub mod cid_generator;
185mod congestion;
186mod protocol_violations;
187#[cfg(test)]
188mod protocol_violations_tests;
189
190// Zero-cost tracing system
191/// High-level NAT traversal API
192pub mod nat_traversal_api;
193mod token;
194mod token_memory_cache;
195/// Zero-cost tracing and event logging system
196pub mod tracing;
197
198// Public modules with new structure
199/// Cryptographic operations and raw public key support
200pub mod crypto;
201/// Platform-specific network interface discovery
202pub mod discovery;
203/// NAT traversal protocol implementation
204pub mod nat_traversal;
205/// Transport-level protocol implementation
206pub mod transport;
207
208// Additional modules
209// v0.2: auth module removed - TLS handles peer authentication via ML-DSA-65
210/// Secure chat protocol implementation
211pub mod chat;
212// Performance optimization utilities are deprecated; remove module to eliminate dead code
213// pub mod optimization;
214
215// ============================================================================
216// P2P API
217// ============================================================================
218
219/// P2P endpoint - the primary API for ant-quic
220///
221/// This module provides the main API for P2P networking with NAT traversal,
222/// connection management, and secure communication.
223pub mod p2p_endpoint;
224
225/// P2P configuration system
226///
227/// This module provides `P2pConfig` with builder pattern support for
228/// configuring endpoints, NAT traversal, MTU, PQC, and other settings.
229pub mod unified_config;
230
231/// Real-time statistics dashboard
232pub mod stats_dashboard;
233/// Terminal user interface components
234pub mod terminal_ui;
235
236// Compliance validation framework
237/// IETF compliance validation tools
238pub mod compliance_validator;
239
240// Comprehensive logging system
241/// Structured logging and diagnostics
242pub mod logging;
243
244/// Metrics collection and export system (basic metrics always available)
245pub mod metrics;
246
247/// TURN-style relay protocol for NAT traversal fallback
248pub mod relay;
249
250/// MASQUE CONNECT-UDP Bind protocol for fully connectable P2P nodes
251pub mod masque;
252
253/// Transport trust module (TOFU, rotations, channel binding surfaces)
254pub mod trust;
255
256/// Address-validation tokens bound to (PeerId||CID||nonce)
257#[cfg(feature = "aws-lc-rs")]
258pub mod token_v2;
259
260// High-level async API modules (ported from quinn crate)
261pub mod high_level;
262
263// Re-export high-level API types for easier usage
264pub use high_level::{
265    Accept, Connecting, Connection as HighLevelConnection, Endpoint,
266    RecvStream as HighLevelRecvStream, SendStream as HighLevelSendStream,
267};
268
269// Link transport abstraction layer for overlay networks
270pub mod link_transport;
271mod link_transport_impl;
272
273// Re-export link transport types
274pub use link_transport::{
275    BoxFuture, BoxStream, Capabilities, ConnectionStats as LinkConnectionStats,
276    DisconnectReason as LinkDisconnectReason, Incoming as LinkIncoming, LinkConn, LinkError,
277    LinkEvent, LinkRecvStream, LinkResult, LinkSendStream, LinkTransport, NatHint, ProtocolId,
278};
279pub use link_transport_impl::{P2pLinkConn, P2pLinkTransport, P2pRecvStream, P2pSendStream};
280
281// Re-export crypto utilities for peer ID management (v0.2: Pure PQC with ML-DSA-65)
282pub use crypto::raw_public_keys::key_utils::{
283    ML_DSA_65_PUBLIC_KEY_SIZE, ML_DSA_65_SECRET_KEY_SIZE, MlDsaPublicKey, MlDsaSecretKey,
284    derive_peer_id_from_key_bytes, derive_peer_id_from_public_key, generate_ml_dsa_keypair,
285    verify_peer_id,
286};
287
288// Re-export key types for backward compatibility
289pub use candidate_discovery::{
290    CandidateDiscoveryManager, DiscoveryConfig, DiscoveryError, DiscoveryEvent, NetworkInterface,
291    ValidatedCandidate,
292};
293// v0.13.0: NatTraversalRole removed - all nodes are symmetric P2P nodes
294pub use connection::nat_traversal::{CandidateSource, CandidateState};
295pub use connection::{
296    Chunk, Chunks, ClosedStream, Connection, ConnectionError, ConnectionStats, Datagrams, Event,
297    FinishError, ReadError, ReadableError, RecvStream, SendDatagramError, SendStream, StreamEvent,
298    Streams, WriteError, Written,
299};
300pub use endpoint::{
301    AcceptError, ConnectError, ConnectionHandle, DatagramEvent, Endpoint as LowLevelEndpoint,
302    Incoming,
303};
304pub use nat_traversal_api::{
305    BootstrapNode, CandidateAddress, NatTraversalConfig, NatTraversalEndpoint, NatTraversalError,
306    NatTraversalEvent, NatTraversalStatistics, PeerId,
307};
308
309// ============================================================================
310// SIMPLE API EXPORTS - Zero Configuration P2P (RECOMMENDED)
311// ============================================================================
312
313/// Zero-configuration P2P node - THE PRIMARY API
314pub use node::{Node, NodeError};
315
316/// Minimal configuration for zero-config P2P nodes
317pub use node_config::{NodeConfig, NodeConfigBuilder};
318
319/// Consolidated node status for observability
320pub use node_status::{NatType, NodeStatus};
321
322/// Unified events for P2P nodes
323pub use node_event::{DisconnectReason as NodeDisconnectReason, NodeEvent, TraversalMethod};
324
325// ============================================================================
326// P2P API EXPORTS (for advanced use)
327// ============================================================================
328
329/// P2P endpoint - for advanced use, prefer Node for most applications
330pub use p2p_endpoint::{
331    ConnectionMetrics, DisconnectReason, EndpointError, EndpointStats, P2pEndpoint, P2pEvent,
332    PeerConnection, TraversalPhase,
333};
334
335/// P2P configuration with builder pattern
336pub use unified_config::{ConfigError, MtuConfig, NatConfig, P2pConfig, P2pConfigBuilder};
337
338pub use relay::{
339    AuthToken, RelayAction, RelayAuthenticator, RelayConnection, RelayConnectionConfig, RelayError,
340    RelayEvent, RelayResult, SessionId, SessionManager, SessionState,
341};
342pub use shared::{ConnectionId, EcnCodepoint, EndpointEvent};
343pub use transport_error::{Code as TransportErrorCode, Error as TransportError};
344
345// #[cfg(fuzzing)]
346// pub mod fuzzing; // Module not implemented yet
347
348/// The QUIC protocol version implemented.
349///
350/// Simplified to include only the essential versions:
351/// - 0x00000001: QUIC v1 (RFC 9000)
352/// - 0xff00_001d: Draft 29
353pub const DEFAULT_SUPPORTED_VERSIONS: &[u32] = &[
354    0x00000001,  // QUIC v1 (RFC 9000)
355    0xff00_001d, // Draft 29
356];
357
358/// Whether an endpoint was the initiator of a connection
359#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
360#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
361pub enum Side {
362    /// The initiator of a connection
363    Client = 0,
364    /// The acceptor of a connection
365    Server = 1,
366}
367
368impl Side {
369    #[inline]
370    /// Shorthand for `self == Side::Client`
371    pub fn is_client(self) -> bool {
372        self == Self::Client
373    }
374
375    #[inline]
376    /// Shorthand for `self == Side::Server`
377    pub fn is_server(self) -> bool {
378        self == Self::Server
379    }
380}
381
382impl ops::Not for Side {
383    type Output = Self;
384    fn not(self) -> Self {
385        match self {
386            Self::Client => Self::Server,
387            Self::Server => Self::Client,
388        }
389    }
390}
391
392/// Whether a stream communicates data in both directions or only from the initiator
393#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
394#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
395pub enum Dir {
396    /// Data flows in both directions
397    Bi = 0,
398    /// Data flows only from the stream's initiator
399    Uni = 1,
400}
401
402impl Dir {
403    fn iter() -> impl Iterator<Item = Self> {
404        [Self::Bi, Self::Uni].iter().cloned()
405    }
406}
407
408impl fmt::Display for Dir {
409    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
410        use Dir::*;
411        f.pad(match *self {
412            Bi => "bidirectional",
413            Uni => "unidirectional",
414        })
415    }
416}
417
418/// Identifier for a stream within a particular connection
419#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
420#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
421pub struct StreamId(u64);
422
423impl fmt::Display for StreamId {
424    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
425        let initiator = match self.initiator() {
426            Side::Client => "client",
427            Side::Server => "server",
428        };
429        let dir = match self.dir() {
430            Dir::Uni => "uni",
431            Dir::Bi => "bi",
432        };
433        write!(
434            f,
435            "{} {}directional stream {}",
436            initiator,
437            dir,
438            self.index()
439        )
440    }
441}
442
443impl StreamId {
444    /// Create a new StreamId
445    pub fn new(initiator: Side, dir: Dir, index: u64) -> Self {
446        Self((index << 2) | ((dir as u64) << 1) | initiator as u64)
447    }
448    /// Which side of a connection initiated the stream
449    pub fn initiator(self) -> Side {
450        if self.0 & 0x1 == 0 {
451            Side::Client
452        } else {
453            Side::Server
454        }
455    }
456    /// Which directions data flows in
457    pub fn dir(self) -> Dir {
458        if self.0 & 0x2 == 0 { Dir::Bi } else { Dir::Uni }
459    }
460    /// Distinguishes streams of the same initiator and directionality
461    pub fn index(self) -> u64 {
462        self.0 >> 2
463    }
464}
465
466impl From<StreamId> for VarInt {
467    fn from(x: StreamId) -> Self {
468        unsafe { Self::from_u64_unchecked(x.0) }
469    }
470}
471
472impl From<VarInt> for StreamId {
473    fn from(v: VarInt) -> Self {
474        Self(v.0)
475    }
476}
477
478impl From<StreamId> for u64 {
479    fn from(x: StreamId) -> Self {
480        x.0
481    }
482}
483
484impl coding::Codec for StreamId {
485    fn decode<B: bytes::Buf>(buf: &mut B) -> coding::Result<Self> {
486        VarInt::decode(buf).map(|x| Self(x.into_inner()))
487    }
488    fn encode<B: bytes::BufMut>(&self, buf: &mut B) {
489        // StreamId values should always be valid VarInt values, but handle the error case
490        match VarInt::from_u64(self.0) {
491            Ok(varint) => varint.encode(buf),
492            Err(_) => {
493                // This should never happen for valid StreamIds, but use a safe fallback
494                VarInt::MAX.encode(buf);
495            }
496        }
497    }
498}
499
500/// An outgoing packet
501#[derive(Debug)]
502#[must_use]
503pub struct Transmit {
504    /// The socket this datagram should be sent to
505    pub destination: SocketAddr,
506    /// Explicit congestion notification bits to set on the packet
507    pub ecn: Option<EcnCodepoint>,
508    /// Amount of data written to the caller-supplied buffer
509    pub size: usize,
510    /// The segment size if this transmission contains multiple datagrams.
511    /// This is `None` if the transmit only contains a single datagram
512    pub segment_size: Option<usize>,
513    /// Optional source IP address for the datagram
514    pub src_ip: Option<IpAddr>,
515}
516
517// Deal with time
518#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
519pub(crate) use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
520#[cfg(all(target_family = "wasm", target_os = "unknown"))]
521pub(crate) use web_time::{Duration, Instant, SystemTime, UNIX_EPOCH};
522
523//
524// Useful internal constants
525//
526
527/// The maximum number of CIDs we bother to issue per connection
528pub(crate) const LOC_CID_COUNT: u64 = 8;
529pub(crate) const RESET_TOKEN_SIZE: usize = 16;
530pub(crate) const MAX_CID_SIZE: usize = 20;
531pub(crate) const MIN_INITIAL_SIZE: u16 = 1200;
532/// <https://www.rfc-editor.org/rfc/rfc9000.html#name-datagram-size>
533pub(crate) const INITIAL_MTU: u16 = 1200;
534pub(crate) const MAX_UDP_PAYLOAD: u16 = 65527;
535pub(crate) const TIMER_GRANULARITY: Duration = Duration::from_millis(1);
536/// Maximum number of streams that can be tracked per connection
537pub(crate) const MAX_STREAM_COUNT: u64 = 1 << 60;
538
539// Internal type re-exports for crate modules
540pub use cid_generator::RandomConnectionIdGenerator;
541pub use config::{
542    AckFrequencyConfig, ClientConfig, EndpointConfig, MtuDiscoveryConfig, ServerConfig,
543    TransportConfig,
544};
545
546// Post-Quantum Cryptography (PQC) re-exports - always available
547// v0.2: Pure PQC only - HybridKem and HybridSignature removed
548pub use crypto::pqc::{MlDsa65, MlKem768, PqcConfig, PqcConfigBuilder, PqcError, PqcResult};
549pub(crate) use frame::Frame;
550pub use token::TokenStore;
551pub(crate) use token::{NoneTokenLog, ResetToken, TokenLog};
552pub(crate) use token_memory_cache::TokenMemoryCache;