ant_quic/
lib.rs

1//! ant-quic: QUIC transport protocol with advanced NAT traversal for P2P networks
2//!
3//! This library provides a clean, modular implementation of QUIC-native NAT traversal
4//! using raw public keys for authentication. It is designed to be minimal, focused,
5//! and highly testable, with exceptional cross-platform support.
6//!
7//! The library is organized into the following main modules:
8//! - `transport`: Core QUIC transport functionality
9//! - `nat_traversal`: QUIC-native NAT traversal protocol
10//! - `discovery`: Platform-specific network interface discovery
11//! - `crypto`: Raw public key authentication
12//! - `api`: High-level P2P networking API
13
14#![cfg_attr(not(fuzzing), warn(missing_docs))]
15#![cfg_attr(test, allow(dead_code))]
16#![warn(unreachable_pub)]
17#![allow(clippy::cognitive_complexity)]
18#![allow(clippy::too_many_arguments)]
19#![warn(clippy::use_self)]
20
21use std::{
22    fmt,
23    net::{IpAddr, SocketAddr},
24    ops,
25};
26
27// Core modules
28mod cid_queue;
29pub mod coding;
30mod constant_time;
31mod range_set;
32pub mod transport_parameters;
33mod varint;
34
35pub use varint::{VarInt, VarIntBoundsExceeded};
36
37// Removed optional bloom module
38
39// Core implementation modules
40pub mod config;
41pub mod connection;
42pub mod endpoint;
43pub mod frame;
44pub mod packet;
45pub mod shared;
46pub mod transport_error;
47// Simplified congestion control
48pub mod candidate_discovery;
49pub mod cid_generator;
50mod congestion;
51
52// Zero-cost tracing system
53pub mod tracing;
54mod connection_establishment_simple;
55pub mod nat_traversal_api;
56mod token;
57mod token_memory_cache;
58
59// Public modules with new structure
60pub mod api;
61pub mod crypto;
62pub mod discovery;
63pub mod nat_traversal;
64pub mod transport;
65
66// Additional modules
67pub mod auth;
68pub mod chat;
69pub mod optimization;
70pub mod quic_node;
71pub mod stats_dashboard;
72pub mod terminal_ui;
73
74// High-level async API modules (ported from quinn crate)
75pub mod quinn_high_level;
76
77// Re-export high-level API types for easier usage
78pub use quinn_high_level::{
79    Accept, Connecting, Connection as HighLevelConnection, Endpoint,
80    RecvStream as HighLevelRecvStream, SendStream as HighLevelSendStream,
81};
82
83// Re-export crypto utilities for peer ID management
84pub use crypto::raw_public_keys::key_utils::{
85    derive_peer_id_from_key_bytes, derive_peer_id_from_public_key, generate_ed25519_keypair,
86    public_key_from_bytes, public_key_to_bytes, verify_peer_id,
87};
88
89// Re-export key types for backward compatibility
90pub use candidate_discovery::{
91    CandidateDiscoveryManager, DiscoveryConfig, DiscoveryError, DiscoveryEvent, NetworkInterface,
92    ValidatedCandidate,
93};
94pub use connection::nat_traversal::{CandidateSource, CandidateState, NatTraversalRole};
95pub use connection::{
96    Chunk, Chunks, ClosedStream, Connection, ConnectionError, ConnectionStats, Datagrams, Event,
97    FinishError, ReadError, ReadableError, RecvStream, SendDatagramError, SendStream, StreamEvent,
98    Streams, WriteError, Written,
99};
100pub use connection_establishment_simple::{
101    SimpleConnectionEstablishmentManager, SimpleConnectionEvent, SimpleEstablishmentConfig,
102};
103pub use endpoint::{
104    AcceptError, ConnectError, ConnectionHandle, DatagramEvent, Endpoint as LowLevelEndpoint,
105    Incoming,
106};
107pub use nat_traversal_api::{
108    BootstrapNode, CandidateAddress, EndpointRole, NatTraversalConfig, NatTraversalEndpoint,
109    NatTraversalError, NatTraversalEvent, NatTraversalStatistics, PeerId,
110};
111pub use quic_node::{NodeStats as QuicNodeStats, QuicNodeConfig, QuicP2PNode};
112pub use shared::{ConnectionId, EcnCodepoint, EndpointEvent};
113pub use transport_error::{Code as TransportErrorCode, Error as TransportError};
114
115// #[cfg(fuzzing)]
116// pub mod fuzzing; // Module not implemented yet
117
118/// The QUIC protocol version implemented.
119///
120/// Simplified to include only the essential versions:
121/// - 0x00000001: QUIC v1 (RFC 9000)
122/// - 0xff00_001d: Draft 29
123pub const DEFAULT_SUPPORTED_VERSIONS: &[u32] = &[
124    0x00000001,  // QUIC v1 (RFC 9000)
125    0xff00_001d, // Draft 29
126];
127
128/// Whether an endpoint was the initiator of a connection
129#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
130#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
131pub enum Side {
132    /// The initiator of a connection
133    Client = 0,
134    /// The acceptor of a connection
135    Server = 1,
136}
137
138impl Side {
139    #[inline]
140    /// Shorthand for `self == Side::Client`
141    pub fn is_client(self) -> bool {
142        self == Self::Client
143    }
144
145    #[inline]
146    /// Shorthand for `self == Side::Server`
147    pub fn is_server(self) -> bool {
148        self == Self::Server
149    }
150}
151
152impl ops::Not for Side {
153    type Output = Self;
154    fn not(self) -> Self {
155        match self {
156            Self::Client => Self::Server,
157            Self::Server => Self::Client,
158        }
159    }
160}
161
162/// Whether a stream communicates data in both directions or only from the initiator
163#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
164#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
165pub enum Dir {
166    /// Data flows in both directions
167    Bi = 0,
168    /// Data flows only from the stream's initiator
169    Uni = 1,
170}
171
172impl Dir {
173    fn iter() -> impl Iterator<Item = Self> {
174        [Self::Bi, Self::Uni].iter().cloned()
175    }
176}
177
178impl fmt::Display for Dir {
179    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180        use Dir::*;
181        f.pad(match *self {
182            Bi => "bidirectional",
183            Uni => "unidirectional",
184        })
185    }
186}
187
188/// Identifier for a stream within a particular connection
189#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
190#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
191pub struct StreamId(u64);
192
193impl fmt::Display for StreamId {
194    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195        let initiator = match self.initiator() {
196            Side::Client => "client",
197            Side::Server => "server",
198        };
199        let dir = match self.dir() {
200            Dir::Uni => "uni",
201            Dir::Bi => "bi",
202        };
203        write!(
204            f,
205            "{} {}directional stream {}",
206            initiator,
207            dir,
208            self.index()
209        )
210    }
211}
212
213impl StreamId {
214    /// Create a new StreamId
215    pub fn new(initiator: Side, dir: Dir, index: u64) -> Self {
216        Self((index << 2) | ((dir as u64) << 1) | initiator as u64)
217    }
218    /// Which side of a connection initiated the stream
219    pub fn initiator(self) -> Side {
220        if self.0 & 0x1 == 0 {
221            Side::Client
222        } else {
223            Side::Server
224        }
225    }
226    /// Which directions data flows in
227    pub fn dir(self) -> Dir {
228        if self.0 & 0x2 == 0 { Dir::Bi } else { Dir::Uni }
229    }
230    /// Distinguishes streams of the same initiator and directionality
231    pub fn index(self) -> u64 {
232        self.0 >> 2
233    }
234}
235
236impl From<StreamId> for VarInt {
237    fn from(x: StreamId) -> Self {
238        unsafe { Self::from_u64_unchecked(x.0) }
239    }
240}
241
242impl From<VarInt> for StreamId {
243    fn from(v: VarInt) -> Self {
244        Self(v.0)
245    }
246}
247
248impl From<StreamId> for u64 {
249    fn from(x: StreamId) -> Self {
250        x.0
251    }
252}
253
254impl coding::Codec for StreamId {
255    fn decode<B: bytes::Buf>(buf: &mut B) -> coding::Result<Self> {
256        VarInt::decode(buf).map(|x| Self(x.into_inner()))
257    }
258    fn encode<B: bytes::BufMut>(&self, buf: &mut B) {
259        VarInt::from_u64(self.0).unwrap().encode(buf);
260    }
261}
262
263/// An outgoing packet
264#[derive(Debug)]
265#[must_use]
266pub struct Transmit {
267    /// The socket this datagram should be sent to
268    pub destination: SocketAddr,
269    /// Explicit congestion notification bits to set on the packet
270    pub ecn: Option<EcnCodepoint>,
271    /// Amount of data written to the caller-supplied buffer
272    pub size: usize,
273    /// The segment size if this transmission contains multiple datagrams.
274    /// This is `None` if the transmit only contains a single datagram
275    pub segment_size: Option<usize>,
276    /// Optional source IP address for the datagram
277    pub src_ip: Option<IpAddr>,
278}
279
280// Deal with time
281#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
282pub(crate) use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
283#[cfg(all(target_family = "wasm", target_os = "unknown"))]
284pub(crate) use web_time::{Duration, Instant, SystemTime, UNIX_EPOCH};
285
286//
287// Useful internal constants
288//
289
290/// The maximum number of CIDs we bother to issue per connection
291pub(crate) const LOC_CID_COUNT: u64 = 8;
292pub(crate) const RESET_TOKEN_SIZE: usize = 16;
293pub(crate) const MAX_CID_SIZE: usize = 20;
294pub(crate) const MIN_INITIAL_SIZE: u16 = 1200;
295/// <https://www.rfc-editor.org/rfc/rfc9000.html#name-datagram-size>
296pub(crate) const INITIAL_MTU: u16 = 1200;
297pub(crate) const MAX_UDP_PAYLOAD: u16 = 65527;
298pub(crate) const TIMER_GRANULARITY: Duration = Duration::from_millis(1);
299/// Maximum number of streams that can be tracked per connection
300pub(crate) const MAX_STREAM_COUNT: u64 = 1 << 60;
301
302// Internal type re-exports for crate modules
303pub use cid_generator::RandomConnectionIdGenerator;
304pub use config::{
305    AckFrequencyConfig, ClientConfig, EndpointConfig, MtuDiscoveryConfig, ServerConfig,
306    TransportConfig,
307};
308pub(crate) use frame::Frame;
309pub(crate) use token::{NoneTokenLog, ResetToken, TokenLog, TokenStore};
310pub(crate) use token_memory_cache::TokenMemoryCache;