Skip to main content

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#![allow(clippy::manual_is_multiple_of)]
12//!
13//! This library provides a clean, modular implementation of QUIC-native NAT traversal
14//! using raw public keys for authentication. It is designed to be minimal, focused,
15//! and highly testable, with exceptional cross-platform support.
16//!
17//! The library is organized into the following main modules:
18//! - `transport`: Core QUIC transport functionality
19//! - `nat_traversal`: QUIC-native NAT traversal protocol
20//! - `discovery`: Platform-specific network interface discovery
21//! - `crypto`: Raw public key authentication
22//! - `trust`: Trust management with TOFU pinning and channel binding
23
24// Documentation warnings enabled - all public APIs must be documented
25#![cfg_attr(not(fuzzing), warn(missing_docs))]
26#![allow(unreachable_pub)]
27#![allow(clippy::cognitive_complexity)]
28#![allow(clippy::too_many_arguments)]
29#![allow(clippy::use_self)]
30// Dead code warnings enabled - remove unused code
31#![warn(dead_code)]
32#![allow(clippy::field_reassign_with_default)]
33#![allow(clippy::module_inception)]
34#![allow(clippy::useless_vec)]
35#![allow(private_interfaces)]
36#![allow(clippy::upper_case_acronyms)]
37#![allow(clippy::type_complexity)]
38#![allow(clippy::manual_clamp)]
39#![allow(clippy::needless_range_loop)]
40#![allow(clippy::borrowed_box)]
41#![allow(clippy::manual_strip)]
42#![allow(clippy::if_same_then_else)]
43#![allow(clippy::ptr_arg)]
44#![allow(clippy::incompatible_msrv)]
45#![allow(clippy::await_holding_lock)]
46#![allow(clippy::single_match)]
47#![allow(clippy::must_use_candidate)]
48#![allow(clippy::let_underscore_must_use)]
49#![allow(clippy::let_underscore_untyped)]
50#![allow(clippy::large_enum_variant)]
51#![allow(clippy::too_many_lines)]
52#![allow(clippy::result_large_err)]
53#![allow(clippy::enum_glob_use)]
54#![allow(clippy::match_like_matches_macro)]
55#![allow(clippy::struct_field_names)]
56#![allow(clippy::cast_precision_loss)]
57#![allow(clippy::cast_sign_loss)]
58#![allow(clippy::cast_possible_wrap)]
59#![allow(clippy::cast_possible_truncation)]
60#![allow(clippy::unnecessary_wraps)]
61#![allow(clippy::doc_markdown)]
62#![allow(clippy::module_name_repetitions)]
63#![allow(clippy::items_after_statements)]
64#![allow(clippy::missing_panics_doc)]
65#![allow(clippy::missing_errors_doc)]
66#![allow(clippy::similar_names)]
67#![allow(clippy::new_without_default)]
68#![allow(clippy::unwrap_or_default)]
69#![allow(clippy::uninlined_format_args)]
70#![allow(clippy::redundant_field_names)]
71#![allow(clippy::redundant_closure_for_method_calls)]
72#![allow(clippy::redundant_pattern_matching)]
73#![allow(clippy::option_if_let_else)]
74#![allow(clippy::trivially_copy_pass_by_ref)]
75#![allow(clippy::len_without_is_empty)]
76#![allow(clippy::explicit_auto_deref)]
77#![allow(clippy::blocks_in_conditions)]
78#![allow(clippy::collapsible_else_if)]
79#![allow(clippy::collapsible_if)]
80#![allow(clippy::unnecessary_cast)]
81#![allow(clippy::needless_bool)]
82#![allow(clippy::needless_borrow)]
83#![allow(clippy::redundant_static_lifetimes)]
84#![allow(clippy::match_ref_pats)]
85#![allow(clippy::should_implement_trait)]
86#![allow(clippy::wildcard_imports)]
87#![warn(unused_must_use)]
88#![allow(improper_ctypes)]
89#![allow(improper_ctypes_definitions)]
90#![allow(non_upper_case_globals)]
91#![allow(clippy::wrong_self_convention)]
92#![allow(clippy::vec_init_then_push)]
93#![allow(clippy::format_in_format_args)]
94#![allow(clippy::from_over_into)]
95#![allow(clippy::useless_conversion)]
96#![allow(clippy::never_loop)]
97#![allow(dropping_references)]
98#![allow(non_snake_case)]
99#![allow(clippy::unnecessary_literal_unwrap)]
100#![allow(clippy::assertions_on_constants)]
101
102use std::{
103    fmt,
104    net::{IpAddr, SocketAddr},
105    ops,
106};
107
108// Core modules
109mod ack_frame;
110mod cid_queue;
111pub mod coding;
112mod constant_time;
113mod range_set;
114pub mod transport_parameters;
115mod varint;
116
117pub use varint::{VarInt, VarIntBoundsExceeded};
118
119// Removed optional bloom module
120
121/// Bounded pending data buffer with TTL expiration
122pub mod bounded_pending_buffer;
123
124/// Process-global diagnostics surfaces (X0X-0043 GSO bundle counters etc.).
125pub mod diagnostics;
126
127/// RTT-based path selection with hysteresis
128pub mod path_selection;
129
130/// Coordinated shutdown for endpoints
131pub mod shutdown;
132
133/// Watchable state pattern for reactive observation
134pub mod watchable;
135
136/// Fair polling for multiple transports
137pub mod fair_polling;
138
139/// Graceful transport degradation
140pub mod transport_resilience;
141
142/// Connection strategy state machine for progressive NAT traversal fallback
143pub mod connection_strategy;
144
145/// RFC 8305 Happy Eyeballs v2 for parallel IPv4/IPv6 connection racing
146pub mod happy_eyeballs;
147
148/// Standardized error handling patterns
149pub mod error_handling;
150
151/// Discovery trait for stream composition
152pub mod discovery_trait;
153
154/// Structured event logging for observability
155pub mod structured_events;
156
157// ============================================================================
158// SIMPLE API - Zero Configuration P2P
159// ============================================================================
160
161/// Zero-configuration P2P node - THE PRIMARY API
162///
163/// Use [`Node`] for the simplest possible P2P experience:
164/// ```rust,ignore
165/// let node = Node::new().await?;
166/// ```
167pub mod node;
168
169/// Minimal configuration for zero-config P2P nodes
170pub mod node_config;
171
172/// Consolidated node status for observability
173pub mod node_status;
174
175mod coordinator_control;
176/// Circuit-breaker for NAT traversal coordinators.
177pub(crate) mod coordinator_health;
178/// First-party mDNS discovery state and query types
179pub mod mdns;
180/// Unified events for P2P nodes
181pub mod node_event;
182mod peer_directory;
183mod port_mapping;
184
185/// Reachability scope and traversal metadata shared across APIs
186pub mod reachability;
187
188// Core implementation modules
189/// Configuration structures and validation
190pub mod config;
191/// QUIC connection state machine and management
192pub mod connection;
193/// QUIC endpoint for accepting and initiating connections
194pub mod endpoint;
195/// QUIC frame types and encoding/decoding
196pub mod frame;
197/// QUIC packet structures and processing
198pub mod packet;
199/// Read-only path handles and path identifiers
200pub mod path;
201/// Shared types and utilities
202pub mod shared;
203/// Transport error types and codes
204pub mod transport_error;
205// Simplified congestion control
206/// Network candidate discovery and management
207pub mod candidate_discovery;
208/// Connection ID generation strategies
209pub mod cid_generator;
210mod congestion;
211
212// Zero-cost tracing system
213/// High-level NAT traversal API
214pub mod nat_traversal_api;
215mod token;
216mod token_memory_cache;
217/// Zero-cost tracing and event logging system
218pub mod tracing;
219
220// Public modules with new structure
221/// Constrained protocol engine for low-bandwidth transports (BLE, LoRa)
222pub mod constrained;
223/// Cryptographic operations and raw public key support
224pub mod crypto;
225/// Platform-specific network interface discovery
226pub mod discovery;
227
228// X0X-0038: re-export the AddressLookup trait + filter trait + registry from
229// the discovery module so callers can write `use ant_quic::AddressLookup;`.
230pub use discovery::{
231    AddrFilter, AddressLookup, BootstrapCacheLookup, CompositeFilter, DedupFilter,
232    DropLoopbackFilter, DropUnspecifiedFilter, HardcodedLookup, LookupError, LookupRegistry,
233    MdnsLookup, ParallelLookupStream, PassThroughFilter, PreferIpv6Filter,
234};
235/// NAT traversal protocol implementation
236pub mod nat_traversal;
237/// Transport-level protocol implementation
238pub mod transport;
239
240/// Connection router for automatic protocol engine selection (QUIC vs Constrained)
241pub mod connection_router;
242
243// Additional modules
244// v0.2: auth module removed - TLS handles peer authentication via ML-DSA-65
245/// Secure chat protocol implementation
246pub mod chat;
247
248// ============================================================================
249// P2P API
250// ============================================================================
251
252/// Lifecycle close-reason helpers shared by the transport and P2P layers.
253mod connection_lifecycle;
254
255/// P2P endpoint - the primary API for ant-quic
256///
257/// This module provides the main API for P2P networking with NAT traversal,
258/// connection management, and secure communication.
259pub mod p2p_endpoint;
260
261/// P2P configuration system
262///
263/// This module provides `P2pConfig` with builder pattern support for
264/// configuring endpoints, NAT traversal, MTU, PQC, and other settings.
265pub mod unified_config;
266
267/// Real-time statistics dashboard
268pub mod stats_dashboard;
269/// Terminal user interface components
270pub mod terminal_ui;
271
272// Compliance validation framework
273/// IETF compliance validation tools
274pub mod compliance_validator;
275
276// Comprehensive logging system
277/// Structured logging and diagnostics
278pub mod logging;
279
280/// Metrics collection and export system (basic metrics always available)
281pub mod metrics;
282
283/// TURN-style relay protocol for NAT traversal fallback
284pub mod relay;
285
286/// MASQUE CONNECT-UDP Bind protocol for fully connectable P2P nodes
287pub mod masque;
288
289/// Transport trust module (TOFU, rotations, channel binding surfaces)
290pub mod trust;
291
292/// Address-validation tokens bound to (PeerId||CID||nonce)
293pub mod token_v2;
294
295// High-level async API modules (ported from quinn crate)
296pub mod high_level;
297
298// Re-export high-level API types for easier usage
299pub use high_level::{
300    Accept, Connecting, Connection as HighLevelConnection, Endpoint,
301    RecvStream as HighLevelRecvStream, SendStream as HighLevelSendStream, WeakConnectionHandle,
302};
303pub use path::{Path, PathId, WeakPathHandle};
304
305// Link transport abstraction layer for overlay networks
306pub mod link_transport;
307mod link_transport_impl;
308
309// Re-export link transport types
310pub use link_transport::{
311    BoxFuture, BoxStream, BoxedHandler, Capabilities, ConnectionStats as LinkConnectionStats,
312    DisconnectReason as LinkDisconnectReason, Incoming as LinkIncoming, LinkConn, LinkError,
313    LinkEvent, LinkRecvStream, LinkResult, LinkSendStream, LinkTransport, NatHint, ProtocolHandler,
314    ProtocolHandlerExt, ProtocolId, StreamFilter, StreamType, StreamTypeFamily,
315};
316pub use link_transport_impl::{
317    P2pLinkConn, P2pLinkTransport, P2pRecvStream, P2pSendStream, SharedTransport,
318};
319
320// Bootstrap cache for peer persistence and quality-based selection
321pub mod bootstrap_cache;
322pub use bootstrap_cache::{
323    BootstrapCache, BootstrapCacheConfig, BootstrapCacheConfigBuilder, CacheEvent, CacheStats,
324    CachedPeer, ConnectionOutcome, ConnectionStats as CacheConnectionStats,
325    NatType as CacheNatType, PeerCapabilities, PeerSource, QualityWeights, SelectionStrategy,
326};
327
328// Host identity for local-only HostKey management (ADR-007)
329pub mod host_identity;
330pub use host_identity::{EndpointKeyPolicy, HostIdentity, HostKeyStorage, StorageError};
331
332// Re-export crypto utilities for peer ID management (v0.2: Pure PQC with ML-DSA-65)
333pub use crypto::raw_public_keys::key_utils::{
334    ML_DSA_65_PUBLIC_KEY_SIZE, ML_DSA_65_SECRET_KEY_SIZE, MlDsaPublicKey, MlDsaSecretKey,
335    derive_peer_id_from_key_bytes, derive_peer_id_from_public_key, generate_ml_dsa_keypair,
336    verify_peer_id,
337};
338
339// Re-export key types for backward compatibility
340pub use candidate_discovery::{
341    CandidateDiscoveryManager, DiscoveryConfig, DiscoveryError, DiscoveryEvent, NetworkInterface,
342    ValidatedCandidate,
343};
344// v0.13.0: NatTraversalRole removed - all nodes are symmetric P2P nodes
345pub use connection::nat_traversal::{CandidateSource, CandidateState};
346pub use connection::{
347    Chunk, Chunks, ClosedStream, Connection, ConnectionError, ConnectionStats, DatagramDropStats,
348    Datagrams, Event, FinishError, PathStats, ReadError, ReadableError, RecvStream,
349    SendDatagramError, SendStream, StreamEvent, Streams, WriteError, Written,
350};
351pub use coordinator_control::RejectionReason;
352pub use endpoint::{
353    AcceptError, ConnectError, ConnectionHandle, DatagramEvent, Endpoint as LowLevelEndpoint,
354    Incoming,
355};
356pub use nat_traversal_api::{
357    BootstrapNode, CandidateAddress, NatTraversalConfig, NatTraversalEndpoint, NatTraversalError,
358    NatTraversalEvent, NatTraversalStatistics, PeerId, TraversalDeadlineKind,
359    TraversalFailureReason,
360};
361pub use reachability::{ReachabilityScope, TraversalMethod};
362
363// ============================================================================
364// SIMPLE API EXPORTS - Zero Configuration P2P (RECOMMENDED)
365// ============================================================================
366
367/// Zero-configuration P2P node - THE PRIMARY API
368pub use node::{Node, NodeError};
369
370/// Minimal configuration for zero-config P2P nodes
371pub use node_config::{NodeConfig, NodeConfigBuilder};
372
373/// Consolidated node status for observability
374pub use node_status::{NatType, NodeStatus};
375
376/// Unified events for P2P nodes
377pub use node_event::{DisconnectReason as NodeDisconnectReason, NodeEvent};
378
379// ============================================================================
380// P2P API EXPORTS (for advanced use)
381// ============================================================================
382
383/// P2P endpoint - for advanced use, prefer Node for most applications
384pub use ack_frame::ReceiveRejectReason;
385pub use connection_lifecycle::ConnectionCloseReason;
386pub use diagnostics::{GsoDiagnostics, GsoDiagnosticsSnapshot};
387pub use p2p_endpoint::{
388    AckDiagnosticsSnapshot, AckOutcomeCounters, AckPeerDiagnosticsSnapshot,
389    AckStageDiagnosticsSnapshot, AckStageLatencySnapshot, ConnectionHealth, ConnectionMetrics,
390    ConnectionTransportStats, DataChannelDiagnosticsSnapshot, DirectPathStatus,
391    DirectPathUnavailableReason, DisconnectReason, EndpointError, EndpointStats, P2pEndpoint,
392    P2pEvent, PeerConnection, PeerLifecycleEvent, TraversalPhase,
393};
394
395/// P2P configuration with builder pattern
396pub use unified_config::{
397    ConfigError, MtuConfig, NatConfig, P2pConfig, P2pConfigBuilder, PortMappingConfig,
398};
399
400/// Connection strategy for progressive NAT traversal fallback
401pub use connection_strategy::{
402    AttemptedMethod, ConnectionAttemptError, ConnectionMethod, ConnectionStage, ConnectionStrategy,
403    StrategyConfig,
404};
405
406pub use relay::{
407    AuthToken,
408    // MASQUE types re-exported from relay module
409    MasqueRelayClient,
410    MasqueRelayConfig,
411    MasqueRelayServer,
412    MasqueRelayStats,
413    MigrationConfig,
414    MigrationCoordinator,
415    MigrationState,
416    RelayAuthenticator,
417    RelayError,
418    RelayManager,
419    RelayManagerConfig,
420    RelayResult,
421    RelaySession,
422    RelaySessionConfig,
423    RelaySessionState,
424    RelayStatisticsCollector,
425};
426pub use shared::{ConnectionId, EcnCodepoint, EndpointEvent};
427pub use transport_error::{Code as TransportErrorCode, Error as TransportError};
428
429// Re-export transport abstraction types
430pub use transport::{
431    BandwidthClass, InboundDatagram, LinkQuality, LoRaParams, ProtocolEngine, ProviderError,
432    TransportAddr, TransportCapabilities, TransportCapabilitiesBuilder, TransportDiagnostics,
433    TransportProvider, TransportRegistry, TransportStats, TransportType, UdpTransport,
434};
435
436#[cfg(feature = "ble")]
437pub use transport::BleTransport;
438
439// Re-export connection router types for automatic protocol engine selection
440pub use connection_router::{
441    ConnectionRouter, RoutedConnection, RouterConfig, RouterError, RouterStats,
442};
443
444// #[cfg(fuzzing)]
445// pub mod fuzzing; // Module not implemented yet
446
447/// The QUIC protocol version implemented.
448///
449/// Simplified to include only the essential versions:
450/// - 0x00000001: QUIC v1 (RFC 9000)
451/// - 0xff00_001d: Draft 29
452pub const DEFAULT_SUPPORTED_VERSIONS: &[u32] = &[
453    0x00000001,  // QUIC v1 (RFC 9000)
454    0xff00_001d, // Draft 29
455];
456
457/// Whether an endpoint was the initiator of a connection
458#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
459#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
460pub enum Side {
461    /// The initiator of a connection
462    Client = 0,
463    /// The acceptor of a connection
464    Server = 1,
465}
466
467impl Side {
468    #[inline]
469    /// Shorthand for `self == Side::Client`
470    pub fn is_client(self) -> bool {
471        self == Self::Client
472    }
473
474    #[inline]
475    /// Shorthand for `self == Side::Server`
476    pub fn is_server(self) -> bool {
477        self == Self::Server
478    }
479}
480
481impl ops::Not for Side {
482    type Output = Self;
483    fn not(self) -> Self {
484        match self {
485            Self::Client => Self::Server,
486            Self::Server => Self::Client,
487        }
488    }
489}
490
491/// Whether a stream communicates data in both directions or only from the initiator
492#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
493#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
494pub enum Dir {
495    /// Data flows in both directions
496    Bi = 0,
497    /// Data flows only from the stream's initiator
498    Uni = 1,
499}
500
501impl Dir {
502    fn iter() -> impl Iterator<Item = Self> {
503        [Self::Bi, Self::Uni].iter().cloned()
504    }
505}
506
507impl fmt::Display for Dir {
508    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
509        use Dir::*;
510        f.pad(match *self {
511            Bi => "bidirectional",
512            Uni => "unidirectional",
513        })
514    }
515}
516
517/// Identifier for a stream within a particular connection
518#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
519#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
520pub struct StreamId(u64);
521
522impl fmt::Display for StreamId {
523    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
524        let initiator = match self.initiator() {
525            Side::Client => "client",
526            Side::Server => "server",
527        };
528        let dir = match self.dir() {
529            Dir::Uni => "uni",
530            Dir::Bi => "bi",
531        };
532        write!(
533            f,
534            "{} {}directional stream {}",
535            initiator,
536            dir,
537            self.index()
538        )
539    }
540}
541
542impl StreamId {
543    const MAX_INDEX: u64 = VarInt::MAX.into_inner() >> 2;
544
545    /// Create a new StreamId if it fits in QUIC's variable-length integer range.
546    pub fn try_new(initiator: Side, dir: Dir, index: u64) -> Result<Self, VarIntBoundsExceeded> {
547        if index > Self::MAX_INDEX {
548            return Err(VarIntBoundsExceeded);
549        }
550        let raw = (index << 2) | ((dir as u64) << 1) | initiator as u64;
551        VarInt::from_u64(raw).map(|_| Self(raw))
552    }
553
554    /// Create a new StreamId from trusted internal stream accounting.
555    pub(crate) fn new(initiator: Side, dir: Dir, index: u64) -> Self {
556        Self((index << 2) | ((dir as u64) << 1) | initiator as u64)
557    }
558    /// Which side of a connection initiated the stream
559    pub fn initiator(self) -> Side {
560        if self.0 & 0x1 == 0 {
561            Side::Client
562        } else {
563            Side::Server
564        }
565    }
566    /// Which directions data flows in
567    pub fn dir(self) -> Dir {
568        if self.0 & 0x2 == 0 { Dir::Bi } else { Dir::Uni }
569    }
570    /// Distinguishes streams of the same initiator and directionality
571    pub fn index(self) -> u64 {
572        self.0 >> 2
573    }
574}
575
576impl From<StreamId> for VarInt {
577    fn from(x: StreamId) -> Self {
578        // StreamId values enter through VarInt decoding, checked public construction,
579        // or trusted internal stream accounting bounded by MAX_STREAM_COUNT.
580        unsafe { Self::from_u64_unchecked(x.0) }
581    }
582}
583
584impl From<VarInt> for StreamId {
585    fn from(v: VarInt) -> Self {
586        Self(v.0)
587    }
588}
589
590impl From<StreamId> for u64 {
591    fn from(x: StreamId) -> Self {
592        x.0
593    }
594}
595
596impl coding::Codec for StreamId {
597    fn decode<B: bytes::Buf>(buf: &mut B) -> coding::Result<Self> {
598        VarInt::decode(buf).map(|x| Self(x.into_inner()))
599    }
600    fn encode<B: bytes::BufMut>(&self, buf: &mut B) {
601        VarInt::from(*self).encode(buf);
602    }
603}
604
605#[cfg(test)]
606mod stream_id_tests {
607    use super::{Dir, Side, StreamId, VarInt};
608
609    #[test]
610    fn try_new_accepts_largest_valid_stream_index() {
611        let stream_id = StreamId::try_new(Side::Server, Dir::Uni, StreamId::MAX_INDEX);
612        assert!(stream_id.is_ok());
613    }
614
615    #[test]
616    fn try_new_rejects_stream_index_outside_varint_range() {
617        let invalid_index = StreamId::MAX_INDEX + 1;
618        let stream_id = StreamId::try_new(Side::Client, Dir::Bi, invalid_index);
619        assert!(stream_id.is_err());
620    }
621
622    #[test]
623    fn try_new_rejects_index_that_would_alias_after_shift() {
624        let stream_id = StreamId::try_new(Side::Client, Dir::Bi, 1_u64 << 63);
625        assert!(stream_id.is_err());
626    }
627
628    #[test]
629    fn valid_stream_id_converts_to_varint() {
630        let stream_id = StreamId::try_new(Side::Client, Dir::Uni, 7);
631        assert!(stream_id.is_ok());
632        let Ok(stream_id) = stream_id else {
633            return;
634        };
635        let varint = VarInt::from(stream_id);
636        assert_eq!(varint.into_inner(), u64::from(stream_id));
637    }
638}
639
640/// An outgoing packet
641#[derive(Debug)]
642#[must_use]
643pub struct Transmit {
644    /// The socket this datagram should be sent to
645    pub destination: SocketAddr,
646    /// Explicit congestion notification bits to set on the packet
647    pub ecn: Option<EcnCodepoint>,
648    /// Amount of data written to the caller-supplied buffer
649    pub size: usize,
650    /// The segment size if this transmission contains multiple datagrams.
651    /// This is `None` if the transmit only contains a single datagram
652    pub segment_size: Option<usize>,
653    /// Optional source IP address for the datagram
654    pub src_ip: Option<IpAddr>,
655}
656
657// Deal with time
658#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
659pub(crate) use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
660#[cfg(all(target_family = "wasm", target_os = "unknown"))]
661pub(crate) use web_time::{Duration, Instant, SystemTime, UNIX_EPOCH};
662
663//
664// Useful internal constants
665//
666
667/// Maximum time to wait for QUIC connections and tasks to drain during shutdown.
668///
669/// Used by both `P2pEndpoint` and `NatTraversalEndpoint` to bound graceful-shutdown waits.
670pub const SHUTDOWN_DRAIN_TIMEOUT: Duration = Duration::from_secs(5);
671
672/// The maximum number of CIDs we bother to issue per connection
673pub(crate) const LOC_CID_COUNT: u64 = 8;
674pub(crate) const RESET_TOKEN_SIZE: usize = 16;
675pub(crate) const MAX_CID_SIZE: usize = 20;
676pub(crate) const MIN_INITIAL_SIZE: u16 = 1200;
677/// <https://www.rfc-editor.org/rfc/rfc9000.html#name-datagram-size>
678pub(crate) const INITIAL_MTU: u16 = 1200;
679pub(crate) const MAX_UDP_PAYLOAD: u16 = 65527;
680pub(crate) const TIMER_GRANULARITY: Duration = Duration::from_millis(1);
681/// Maximum number of streams that can be tracked per connection
682pub(crate) const MAX_STREAM_COUNT: u64 = 1 << 60;
683
684// Internal type re-exports for crate modules
685pub use cid_generator::RandomConnectionIdGenerator;
686pub use config::{
687    AckFrequencyConfig, ClientConfig, EndpointConfig, MtuDiscoveryConfig, ServerConfig,
688    TransportConfig,
689};
690
691// Post-Quantum Cryptography (PQC) re-exports - always available
692// v0.2: Pure PQC only - HybridKem and HybridSignature removed
693pub use crypto::pqc::{MlDsa65, MlKem768, PqcConfig, PqcConfigBuilder, PqcError, PqcResult};
694pub(crate) use frame::Frame;
695pub use token::TokenStore;
696pub(crate) use token::{NoneTokenLog, ResetToken, TokenLog};
697pub(crate) use token_memory_cache::TokenMemoryCache;