1#![allow(elided_lifetimes_in_paths)]
10#![allow(missing_debug_implementations)]
11#![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#![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
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 bounded_pending_buffer;
122
123pub mod path_selection;
125
126pub mod shutdown;
128
129pub mod watchable;
131
132pub mod fair_polling;
134
135pub mod transport_resilience;
137
138pub mod discovery_trait;
140
141pub mod structured_events;
143
144pub mod node;
155
156pub mod node_config;
158
159pub mod node_status;
161
162pub mod node_event;
164
165pub mod config;
168pub mod connection;
170pub mod endpoint;
172pub mod frame;
174pub mod packet;
176pub mod shared;
178pub mod transport_error;
180pub mod candidate_discovery;
183pub mod cid_generator;
185mod congestion;
186mod protocol_violations;
187#[cfg(test)]
188mod protocol_violations_tests;
189
190pub mod nat_traversal_api;
193mod token;
194mod token_memory_cache;
195pub mod tracing;
197
198pub mod crypto;
201pub mod discovery;
203pub mod nat_traversal;
205pub mod transport;
207
208pub mod chat;
212pub mod p2p_endpoint;
224
225pub mod unified_config;
230
231pub mod stats_dashboard;
233pub mod terminal_ui;
235
236pub mod compliance_validator;
239
240pub mod logging;
243
244pub mod metrics;
246
247pub mod relay;
249
250pub mod masque;
252
253pub mod trust;
255
256#[cfg(feature = "aws-lc-rs")]
258pub mod token_v2;
259
260pub mod high_level;
262
263pub use high_level::{
265 Accept, Connecting, Connection as HighLevelConnection, Endpoint,
266 RecvStream as HighLevelRecvStream, SendStream as HighLevelSendStream,
267};
268
269pub mod link_transport;
271mod link_transport_impl;
272
273pub 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
281pub mod bootstrap_cache;
283pub use bootstrap_cache::{
284 BootstrapCache, BootstrapCacheConfig, BootstrapCacheConfigBuilder, CacheEvent, CacheStats,
285 CachedPeer, ConnectionOutcome, ConnectionStats as CacheConnectionStats,
286 NatType as CacheNatType, PeerCapabilities, PeerSource, QualityWeights, SelectionStrategy,
287};
288
289pub use crypto::raw_public_keys::key_utils::{
291 ML_DSA_65_PUBLIC_KEY_SIZE, ML_DSA_65_SECRET_KEY_SIZE, MlDsaPublicKey, MlDsaSecretKey,
292 derive_peer_id_from_key_bytes, derive_peer_id_from_public_key, generate_ml_dsa_keypair,
293 verify_peer_id,
294};
295
296pub use candidate_discovery::{
298 CandidateDiscoveryManager, DiscoveryConfig, DiscoveryError, DiscoveryEvent, NetworkInterface,
299 ValidatedCandidate,
300};
301pub use connection::nat_traversal::{CandidateSource, CandidateState};
303pub use connection::{
304 Chunk, Chunks, ClosedStream, Connection, ConnectionError, ConnectionStats, Datagrams, Event,
305 FinishError, ReadError, ReadableError, RecvStream, SendDatagramError, SendStream, StreamEvent,
306 Streams, WriteError, Written,
307};
308pub use endpoint::{
309 AcceptError, ConnectError, ConnectionHandle, DatagramEvent, Endpoint as LowLevelEndpoint,
310 Incoming,
311};
312pub use nat_traversal_api::{
313 BootstrapNode, CandidateAddress, NatTraversalConfig, NatTraversalEndpoint, NatTraversalError,
314 NatTraversalEvent, NatTraversalStatistics, PeerId,
315};
316
317pub use node::{Node, NodeError};
323
324pub use node_config::{NodeConfig, NodeConfigBuilder};
326
327pub use node_status::{NatType, NodeStatus};
329
330pub use node_event::{DisconnectReason as NodeDisconnectReason, NodeEvent, TraversalMethod};
332
333pub use p2p_endpoint::{
339 ConnectionMetrics, DisconnectReason, EndpointError, EndpointStats, P2pEndpoint, P2pEvent,
340 PeerConnection, TraversalPhase,
341};
342
343pub use unified_config::{ConfigError, MtuConfig, NatConfig, P2pConfig, P2pConfigBuilder};
345
346pub use relay::{
347 AuthToken,
348 MasqueRelayClient,
350 MasqueRelayConfig,
351 MasqueRelayServer,
352 MasqueRelayStats,
353 MigrationConfig,
354 MigrationCoordinator,
355 MigrationState,
356 RelayAuthenticator,
357 RelayError,
358 RelayManager,
359 RelayManagerConfig,
360 RelayResult,
361 RelaySession,
362 RelaySessionConfig,
363 RelaySessionState,
364 RelayStatisticsCollector,
365};
366pub use shared::{ConnectionId, EcnCodepoint, EndpointEvent};
367pub use transport_error::{Code as TransportErrorCode, Error as TransportError};
368
369pub const DEFAULT_SUPPORTED_VERSIONS: &[u32] = &[
378 0x00000001, 0xff00_001d, ];
381
382#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
384#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
385pub enum Side {
386 Client = 0,
388 Server = 1,
390}
391
392impl Side {
393 #[inline]
394 pub fn is_client(self) -> bool {
396 self == Self::Client
397 }
398
399 #[inline]
400 pub fn is_server(self) -> bool {
402 self == Self::Server
403 }
404}
405
406impl ops::Not for Side {
407 type Output = Self;
408 fn not(self) -> Self {
409 match self {
410 Self::Client => Self::Server,
411 Self::Server => Self::Client,
412 }
413 }
414}
415
416#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
418#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
419pub enum Dir {
420 Bi = 0,
422 Uni = 1,
424}
425
426impl Dir {
427 fn iter() -> impl Iterator<Item = Self> {
428 [Self::Bi, Self::Uni].iter().cloned()
429 }
430}
431
432impl fmt::Display for Dir {
433 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
434 use Dir::*;
435 f.pad(match *self {
436 Bi => "bidirectional",
437 Uni => "unidirectional",
438 })
439 }
440}
441
442#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
444#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
445pub struct StreamId(u64);
446
447impl fmt::Display for StreamId {
448 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
449 let initiator = match self.initiator() {
450 Side::Client => "client",
451 Side::Server => "server",
452 };
453 let dir = match self.dir() {
454 Dir::Uni => "uni",
455 Dir::Bi => "bi",
456 };
457 write!(
458 f,
459 "{} {}directional stream {}",
460 initiator,
461 dir,
462 self.index()
463 )
464 }
465}
466
467impl StreamId {
468 pub fn new(initiator: Side, dir: Dir, index: u64) -> Self {
470 Self((index << 2) | ((dir as u64) << 1) | initiator as u64)
471 }
472 pub fn initiator(self) -> Side {
474 if self.0 & 0x1 == 0 {
475 Side::Client
476 } else {
477 Side::Server
478 }
479 }
480 pub fn dir(self) -> Dir {
482 if self.0 & 0x2 == 0 { Dir::Bi } else { Dir::Uni }
483 }
484 pub fn index(self) -> u64 {
486 self.0 >> 2
487 }
488}
489
490impl From<StreamId> for VarInt {
491 fn from(x: StreamId) -> Self {
492 unsafe { Self::from_u64_unchecked(x.0) }
493 }
494}
495
496impl From<VarInt> for StreamId {
497 fn from(v: VarInt) -> Self {
498 Self(v.0)
499 }
500}
501
502impl From<StreamId> for u64 {
503 fn from(x: StreamId) -> Self {
504 x.0
505 }
506}
507
508impl coding::Codec for StreamId {
509 fn decode<B: bytes::Buf>(buf: &mut B) -> coding::Result<Self> {
510 VarInt::decode(buf).map(|x| Self(x.into_inner()))
511 }
512 fn encode<B: bytes::BufMut>(&self, buf: &mut B) {
513 match VarInt::from_u64(self.0) {
515 Ok(varint) => varint.encode(buf),
516 Err(_) => {
517 VarInt::MAX.encode(buf);
519 }
520 }
521 }
522}
523
524#[derive(Debug)]
526#[must_use]
527pub struct Transmit {
528 pub destination: SocketAddr,
530 pub ecn: Option<EcnCodepoint>,
532 pub size: usize,
534 pub segment_size: Option<usize>,
537 pub src_ip: Option<IpAddr>,
539}
540
541#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
543pub(crate) use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
544#[cfg(all(target_family = "wasm", target_os = "unknown"))]
545pub(crate) use web_time::{Duration, Instant, SystemTime, UNIX_EPOCH};
546
547pub(crate) const LOC_CID_COUNT: u64 = 8;
553pub(crate) const RESET_TOKEN_SIZE: usize = 16;
554pub(crate) const MAX_CID_SIZE: usize = 20;
555pub(crate) const MIN_INITIAL_SIZE: u16 = 1200;
556pub(crate) const INITIAL_MTU: u16 = 1200;
558pub(crate) const MAX_UDP_PAYLOAD: u16 = 65527;
559pub(crate) const TIMER_GRANULARITY: Duration = Duration::from_millis(1);
560pub(crate) const MAX_STREAM_COUNT: u64 = 1 << 60;
562
563pub use cid_generator::RandomConnectionIdGenerator;
565pub use config::{
566 AckFrequencyConfig, ClientConfig, EndpointConfig, MtuDiscoveryConfig, ServerConfig,
567 TransportConfig,
568};
569
570pub use crypto::pqc::{MlDsa65, MlKem768, PqcConfig, PqcConfigBuilder, PqcError, PqcResult};
573pub(crate) use frame::Frame;
574pub use token::TokenStore;
575pub(crate) use token::{NoneTokenLog, ResetToken, TokenLog};
576pub(crate) use token_memory_cache::TokenMemoryCache;