1#![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
27mod cid_queue;
29pub mod coding;
30mod constant_time;
31mod range_set;
32pub mod transport_parameters;
33mod varint;
34
35pub use varint::{VarInt, VarIntBoundsExceeded};
36
37pub mod connection;
41pub mod config;
42pub mod frame;
43pub mod endpoint;
44pub mod packet;
45pub mod shared;
46pub mod transport_error;
47mod congestion;
49pub mod cid_generator;
50mod token;
51mod token_memory_cache;
52pub mod candidate_discovery;
53mod connection_establishment_simple;
54pub mod nat_traversal_api;
55
56pub mod transport;
58pub mod nat_traversal;
59pub mod discovery;
60pub mod crypto;
61pub mod api;
62
63pub mod quic_node;
65pub mod terminal_ui;
66pub mod workflow;
67pub mod monitoring;
68pub mod optimization;
69pub mod chat;
70pub mod stats_dashboard;
71pub mod auth;
72
73pub mod quinn_high_level;
75
76pub use quinn_high_level::{
78 Endpoint,
79 Connection as HighLevelConnection,
80 Connecting,
81 Accept,
82 RecvStream as HighLevelRecvStream,
83 SendStream as HighLevelSendStream,
84};
85
86pub use crypto::raw_public_keys::key_utils::{
88 generate_ed25519_keypair, derive_peer_id_from_public_key,
89 derive_peer_id_from_key_bytes, verify_peer_id,
90 public_key_to_bytes, public_key_from_bytes,
91};
92
93pub use connection::{
95 Connection, ConnectionError, ConnectionStats, Event,
96 RecvStream, SendStream, Streams, StreamEvent, SendDatagramError,
97 Chunk, Chunks, ClosedStream, FinishError, ReadError, ReadableError,
98 WriteError, Written, Datagrams,
99};
100pub use endpoint::{Endpoint as LowLevelEndpoint, ConnectionHandle, Incoming, AcceptError, ConnectError, DatagramEvent};
101pub use shared::{ConnectionId, EcnCodepoint, EndpointEvent};
102pub use transport_error::{Code as TransportErrorCode, Error as TransportError};
103pub use candidate_discovery::{
104 CandidateDiscoveryManager, DiscoveryConfig, DiscoveryEvent, DiscoveryError,
105 NetworkInterface, ValidatedCandidate,
106};
107pub use connection_establishment_simple::{
108 SimpleConnectionEstablishmentManager, SimpleEstablishmentConfig,
109 SimpleConnectionEvent,
110};
111pub use nat_traversal_api::{
112 NatTraversalEndpoint, NatTraversalConfig, EndpointRole, PeerId, BootstrapNode,
113 CandidateAddress, NatTraversalEvent, NatTraversalError, NatTraversalStatistics,
114};
115pub use connection::nat_traversal::{CandidateSource, CandidateState, NatTraversalRole};
116pub use quic_node::{QuicP2PNode, QuicNodeConfig, NodeStats as QuicNodeStats};
117
118#[cfg(fuzzing)]
119pub mod fuzzing;
120
121pub const DEFAULT_SUPPORTED_VERSIONS: &[u32] = &[
127 0x00000001, 0xff00_001d, ];
130
131#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
133#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
134pub enum Side {
135 Client = 0,
137 Server = 1,
139}
140
141impl Side {
142 #[inline]
143 pub fn is_client(self) -> bool {
145 self == Self::Client
146 }
147
148 #[inline]
149 pub fn is_server(self) -> bool {
151 self == Self::Server
152 }
153}
154
155impl ops::Not for Side {
156 type Output = Self;
157 fn not(self) -> Self {
158 match self {
159 Self::Client => Self::Server,
160 Self::Server => Self::Client,
161 }
162 }
163}
164
165#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
167#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
168pub enum Dir {
169 Bi = 0,
171 Uni = 1,
173}
174
175impl Dir {
176 fn iter() -> impl Iterator<Item = Self> {
177 [Self::Bi, Self::Uni].iter().cloned()
178 }
179}
180
181impl fmt::Display for Dir {
182 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
183 use Dir::*;
184 f.pad(match *self {
185 Bi => "bidirectional",
186 Uni => "unidirectional",
187 })
188 }
189}
190
191#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
193#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
194pub struct StreamId(u64);
195
196impl fmt::Display for StreamId {
197 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198 let initiator = match self.initiator() {
199 Side::Client => "client",
200 Side::Server => "server",
201 };
202 let dir = match self.dir() {
203 Dir::Uni => "uni",
204 Dir::Bi => "bi",
205 };
206 write!(
207 f,
208 "{} {}directional stream {}",
209 initiator,
210 dir,
211 self.index()
212 )
213 }
214}
215
216impl StreamId {
217 pub fn new(initiator: Side, dir: Dir, index: u64) -> Self {
219 Self((index << 2) | ((dir as u64) << 1) | initiator as u64)
220 }
221 pub fn initiator(self) -> Side {
223 if self.0 & 0x1 == 0 {
224 Side::Client
225 } else {
226 Side::Server
227 }
228 }
229 pub fn dir(self) -> Dir {
231 if self.0 & 0x2 == 0 { Dir::Bi } else { Dir::Uni }
232 }
233 pub fn index(self) -> u64 {
235 self.0 >> 2
236 }
237}
238
239impl From<StreamId> for VarInt {
240 fn from(x: StreamId) -> Self {
241 unsafe { Self::from_u64_unchecked(x.0) }
242 }
243}
244
245impl From<VarInt> for StreamId {
246 fn from(v: VarInt) -> Self {
247 Self(v.0)
248 }
249}
250
251impl From<StreamId> for u64 {
252 fn from(x: StreamId) -> Self {
253 x.0
254 }
255}
256
257impl coding::Codec for StreamId {
258 fn decode<B: bytes::Buf>(buf: &mut B) -> coding::Result<Self> {
259 VarInt::decode(buf).map(|x| Self(x.into_inner()))
260 }
261 fn encode<B: bytes::BufMut>(&self, buf: &mut B) {
262 VarInt::from_u64(self.0).unwrap().encode(buf);
263 }
264}
265
266#[derive(Debug)]
268#[must_use]
269pub struct Transmit {
270 pub destination: SocketAddr,
272 pub ecn: Option<EcnCodepoint>,
274 pub size: usize,
276 pub segment_size: Option<usize>,
279 pub src_ip: Option<IpAddr>,
281}
282
283#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
285pub(crate) use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
286#[cfg(all(target_family = "wasm", target_os = "unknown"))]
287pub(crate) use web_time::{Duration, Instant, SystemTime, UNIX_EPOCH};
288
289pub(crate) const LOC_CID_COUNT: u64 = 8;
295pub(crate) const RESET_TOKEN_SIZE: usize = 16;
296pub(crate) const MAX_CID_SIZE: usize = 20;
297pub(crate) const MIN_INITIAL_SIZE: u16 = 1200;
298pub(crate) const INITIAL_MTU: u16 = 1200;
300pub(crate) const MAX_UDP_PAYLOAD: u16 = 65527;
301pub(crate) const TIMER_GRANULARITY: Duration = Duration::from_millis(1);
302pub(crate) const MAX_STREAM_COUNT: u64 = 1 << 60;
304
305pub(crate) use token::{ResetToken, TokenStore, TokenLog, NoneTokenLog};
307pub(crate) use token_memory_cache::TokenMemoryCache;
308pub(crate) use frame::Frame;
309pub use config::{EndpointConfig, TransportConfig, ServerConfig, AckFrequencyConfig, MtuDiscoveryConfig, ClientConfig};
310pub use cid_generator::RandomConnectionIdGenerator;