1#![allow(elided_lifetimes_in_paths)]
10#![allow(missing_debug_implementations)]
11#![allow(clippy::manual_is_multiple_of)]
12#![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#![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
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 connection_strategy;
140
141pub mod happy_eyeballs;
143
144pub mod discovery_trait;
146
147pub mod structured_events;
149
150pub mod node;
161
162pub mod node_config;
164
165pub mod node_status;
167
168pub mod node_event;
170
171pub mod config;
174pub mod connection;
176pub mod endpoint;
178pub mod frame;
180pub mod packet;
182pub mod shared;
184pub mod transport_error;
186pub mod candidate_discovery;
189pub mod cid_generator;
191mod congestion;
192
193pub mod nat_traversal_api;
196mod token;
197mod token_memory_cache;
198pub mod tracing;
200
201pub mod constrained;
204pub mod crypto;
206pub mod discovery;
208pub mod nat_traversal;
210pub mod transport;
212
213pub mod connection_router;
215
216pub mod chat;
220
221pub mod p2p_endpoint;
230
231pub mod unified_config;
236
237pub mod stats_dashboard;
239pub mod terminal_ui;
241
242pub mod compliance_validator;
245
246pub mod logging;
249
250pub mod metrics;
252
253pub mod relay;
255
256pub mod masque;
258
259pub mod trust;
261
262pub mod token_v2;
264
265pub mod high_level;
267
268pub use high_level::{
270 Accept, Connecting, Connection as HighLevelConnection, Endpoint,
271 RecvStream as HighLevelRecvStream, SendStream as HighLevelSendStream,
272};
273
274pub mod link_transport;
276mod link_transport_impl;
277
278pub use link_transport::{
280 BoxFuture, BoxStream, BoxedHandler, Capabilities, ConnectionStats as LinkConnectionStats,
281 DisconnectReason as LinkDisconnectReason, Incoming as LinkIncoming, LinkConn, LinkError,
282 LinkEvent, LinkRecvStream, LinkResult, LinkSendStream, LinkTransport, NatHint, ProtocolHandler,
283 ProtocolHandlerExt, ProtocolId, StreamFilter, StreamType, StreamTypeFamily,
284};
285pub use link_transport_impl::{
286 P2pLinkConn, P2pLinkTransport, P2pRecvStream, P2pSendStream, SharedTransport,
287};
288
289pub mod bootstrap_cache;
291pub use bootstrap_cache::{
292 BootstrapCache, BootstrapCacheConfig, BootstrapCacheConfigBuilder, CacheEvent, CacheStats,
293 CachedPeer, ConnectionOutcome, ConnectionStats as CacheConnectionStats,
294 NatType as CacheNatType, PeerCapabilities, PeerSource, QualityWeights, SelectionStrategy,
295};
296
297pub mod host_identity;
299pub use host_identity::{EndpointKeyPolicy, HostIdentity, HostKeyStorage, StorageError};
300
301pub use crypto::raw_public_keys::key_utils::{
303 ML_DSA_65_PUBLIC_KEY_SIZE, ML_DSA_65_SECRET_KEY_SIZE, MlDsaPublicKey, MlDsaSecretKey,
304 fingerprint_public_key, fingerprint_public_key_bytes, generate_ml_dsa_keypair,
305};
306
307pub use candidate_discovery::{
309 CandidateDiscoveryManager, DiscoveryConfig, DiscoveryError, DiscoveryEvent, NetworkInterface,
310 ValidatedCandidate,
311};
312pub use connection::nat_traversal::{CandidateSource, CandidateState};
314pub use connection::{
315 Chunk, Chunks, ClosedStream, Connection, ConnectionError, ConnectionStats, DatagramDropStats,
316 Datagrams, Event, FinishError, ReadError, ReadableError, RecvStream, SendDatagramError,
317 SendStream, StreamEvent, Streams, WriteError, Written,
318};
319pub use endpoint::{
320 AcceptError, ConnectError, ConnectionHandle, DatagramEvent, Endpoint as LowLevelEndpoint,
321 Incoming,
322};
323pub use nat_traversal_api::{
324 BootstrapNode, CandidateAddress, NatTraversalConfig, NatTraversalEndpoint, NatTraversalError,
325 NatTraversalEvent, NatTraversalStatistics,
326};
327
328pub use node::{Node, NodeError};
334
335pub use node_config::{NodeConfig, NodeConfigBuilder};
337
338pub use node_status::{NatType, NodeStatus};
340
341pub use node_event::{DisconnectReason as NodeDisconnectReason, NodeEvent, TraversalMethod};
343
344pub use p2p_endpoint::{
350 ConnectionMetrics, DisconnectReason, EndpointError, EndpointStats, P2pEndpoint, P2pEvent,
351 PeerConnection, TraversalPhase,
352};
353
354pub use unified_config::{ConfigError, MtuConfig, NatConfig, P2pConfig, P2pConfigBuilder};
356
357pub use connection_strategy::{
359 AttemptedMethod, ConnectionAttemptError, ConnectionMethod, ConnectionStage, ConnectionStrategy,
360 StrategyConfig,
361};
362
363pub use relay::{
364 AuthToken,
365 MasqueRelayClient,
367 MasqueRelayConfig,
368 MasqueRelayServer,
369 MasqueRelayStats,
370 MigrationConfig,
371 MigrationCoordinator,
372 MigrationState,
373 RelayAuthenticator,
374 RelayError,
375 RelayManager,
376 RelayManagerConfig,
377 RelayResult,
378 RelaySession,
379 RelaySessionConfig,
380 RelaySessionState,
381 RelayStatisticsCollector,
382};
383pub use shared::{ConnectionId, EcnCodepoint, EndpointEvent};
384pub use transport_error::{Code as TransportErrorCode, Error as TransportError};
385
386pub use transport::{
388 BandwidthClass, InboundDatagram, LinkQuality, LoRaParams, ProtocolEngine, ProviderError,
389 TransportAddr, TransportCapabilities, TransportCapabilitiesBuilder, TransportDiagnostics,
390 TransportProvider, TransportRegistry, TransportStats, TransportType, UdpTransport,
391};
392
393#[cfg(feature = "ble")]
394pub use transport::BleTransport;
395
396pub use connection_router::{
398 ConnectionRouter, RoutedConnection, RouterConfig, RouterError, RouterStats,
399};
400
401pub const DEFAULT_SUPPORTED_VERSIONS: &[u32] = &[
410 0x00000001, 0xff00_001d, ];
413
414#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
416#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
417pub enum Side {
418 Client = 0,
420 Server = 1,
422}
423
424impl Side {
425 #[inline]
426 pub fn is_client(self) -> bool {
428 self == Self::Client
429 }
430
431 #[inline]
432 pub fn is_server(self) -> bool {
434 self == Self::Server
435 }
436}
437
438impl ops::Not for Side {
439 type Output = Self;
440 fn not(self) -> Self {
441 match self {
442 Self::Client => Self::Server,
443 Self::Server => Self::Client,
444 }
445 }
446}
447
448#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
450#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
451pub enum Dir {
452 Bi = 0,
454 Uni = 1,
456}
457
458impl Dir {
459 fn iter() -> impl Iterator<Item = Self> {
460 [Self::Bi, Self::Uni].iter().cloned()
461 }
462}
463
464impl fmt::Display for Dir {
465 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
466 use Dir::*;
467 f.pad(match *self {
468 Bi => "bidirectional",
469 Uni => "unidirectional",
470 })
471 }
472}
473
474#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
476#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
477pub struct StreamId(u64);
478
479impl fmt::Display for StreamId {
480 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
481 let initiator = match self.initiator() {
482 Side::Client => "client",
483 Side::Server => "server",
484 };
485 let dir = match self.dir() {
486 Dir::Uni => "uni",
487 Dir::Bi => "bi",
488 };
489 write!(
490 f,
491 "{} {}directional stream {}",
492 initiator,
493 dir,
494 self.index()
495 )
496 }
497}
498
499impl StreamId {
500 pub fn new(initiator: Side, dir: Dir, index: u64) -> Self {
502 Self((index << 2) | ((dir as u64) << 1) | initiator as u64)
503 }
504 pub fn initiator(self) -> Side {
506 if self.0 & 0x1 == 0 {
507 Side::Client
508 } else {
509 Side::Server
510 }
511 }
512 pub fn dir(self) -> Dir {
514 if self.0 & 0x2 == 0 { Dir::Bi } else { Dir::Uni }
515 }
516 pub fn index(self) -> u64 {
518 self.0 >> 2
519 }
520}
521
522impl From<StreamId> for VarInt {
523 fn from(x: StreamId) -> Self {
524 unsafe { Self::from_u64_unchecked(x.0) }
525 }
526}
527
528impl From<VarInt> for StreamId {
529 fn from(v: VarInt) -> Self {
530 Self(v.0)
531 }
532}
533
534impl From<StreamId> for u64 {
535 fn from(x: StreamId) -> Self {
536 x.0
537 }
538}
539
540impl coding::Codec for StreamId {
541 fn decode<B: bytes::Buf>(buf: &mut B) -> coding::Result<Self> {
542 VarInt::decode(buf).map(|x| Self(x.into_inner()))
543 }
544 fn encode<B: bytes::BufMut>(&self, buf: &mut B) {
545 match VarInt::from_u64(self.0) {
547 Ok(varint) => varint.encode(buf),
548 Err(_) => {
549 VarInt::MAX.encode(buf);
551 }
552 }
553 }
554}
555
556#[derive(Debug)]
558#[must_use]
559pub struct Transmit {
560 pub destination: SocketAddr,
562 pub ecn: Option<EcnCodepoint>,
564 pub size: usize,
566 pub segment_size: Option<usize>,
569 pub src_ip: Option<IpAddr>,
571}
572
573#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
575pub(crate) use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
576#[cfg(all(target_family = "wasm", target_os = "unknown"))]
577pub(crate) use web_time::{Duration, Instant, SystemTime, UNIX_EPOCH};
578
579pub const SHUTDOWN_DRAIN_TIMEOUT: Duration = Duration::from_secs(5);
587
588pub(crate) const LOC_CID_COUNT: u64 = 8;
590pub(crate) const RESET_TOKEN_SIZE: usize = 16;
591pub(crate) const MAX_CID_SIZE: usize = 20;
592pub(crate) const MIN_INITIAL_SIZE: u16 = 1200;
593pub(crate) const INITIAL_MTU: u16 = 1200;
595pub(crate) const MAX_UDP_PAYLOAD: u16 = 65527;
596pub(crate) const TIMER_GRANULARITY: Duration = Duration::from_millis(1);
597pub(crate) const MAX_STREAM_COUNT: u64 = 1 << 60;
599
600pub use cid_generator::RandomConnectionIdGenerator;
602pub use config::{
603 AckFrequencyConfig, ClientConfig, EndpointConfig, MtuDiscoveryConfig, ServerConfig,
604 TransportConfig,
605};
606
607pub use crypto::pqc::{MlDsa65, MlKem768, PqcConfig, PqcConfigBuilder, PqcError, PqcResult};
610pub(crate) use frame::Frame;
611pub use token::TokenStore;
612pub(crate) use token::{NoneTokenLog, ResetToken, TokenLog};
613pub(crate) use token_memory_cache::TokenMemoryCache;