kvarn_quinn/lib.rs
1//! QUIC transport protocol implementation
2//!
3//! [QUIC](https://en.wikipedia.org/wiki/QUIC) is a modern transport protocol addressing
4//! shortcomings of TCP, such as head-of-line blocking, poor security, slow handshakes, and
5//! inefficient congestion control. This crate provides a portable userspace implementation. It
6//! builds on top of quinn-proto, which implements protocol logic independent of any particular
7//! runtime.
8//!
9//! The entry point of this crate is the [`Endpoint`].
10//!
11//! # About QUIC
12//!
13//! A QUIC connection is an association between two endpoints. The endpoint which initiates the
14//! connection is termed the client, and the endpoint which accepts it is termed the server. A
15//! single endpoint may function as both client and server for different connections, for example
16//! in a peer-to-peer application. To communicate application data, each endpoint may open streams
17//! up to a limit dictated by its peer. Typically, that limit is increased as old streams are
18//! finished.
19//!
20//! Streams may be unidirectional or bidirectional, and are cheap to create and disposable. For
21//! example, a traditionally datagram-oriented application could use a new stream for every
22//! message it wants to send, no longer needing to worry about MTUs. Bidirectional streams behave
23//! much like a traditional TCP connection, and are useful for sending messages that have an
24//! immediate response, such as an HTTP request. Stream data is delivered reliably, and there is no
25//! ordering enforced between data on different streams.
26//!
27//! By avoiding head-of-line blocking and providing unified congestion control across all streams
28//! of a connection, QUIC is able to provide higher throughput and lower latency than one or
29//! multiple TCP connections between the same two hosts, while providing more useful behavior than
30//! raw UDP sockets.
31//!
32//! Quinn also exposes unreliable datagrams, which are a low-level primitive preferred when
33//! automatic fragmentation and retransmission of certain data is not desired.
34//!
35//! QUIC uses encryption and identity verification built directly on TLS 1.3. Just as with a TLS
36//! server, it is useful for a QUIC server to be identified by a certificate signed by a trusted
37//! authority. If this is infeasible--for example, if servers are short-lived or not associated
38//! with a domain name--then as with TLS, self-signed certificates can be used to provide
39//! encryption alone.
40#![warn(missing_docs)]
41#![warn(unreachable_pub)]
42#![warn(clippy::use_self)]
43
44use std::time::Duration;
45
46macro_rules! ready {
47 ($e:expr $(,)?) => {
48 match $e {
49 std::task::Poll::Ready(t) => t,
50 std::task::Poll::Pending => return std::task::Poll::Pending,
51 }
52 };
53}
54
55mod connection;
56mod endpoint;
57mod mutex;
58mod recv_stream;
59mod runtime;
60mod send_stream;
61mod work_limiter;
62
63use bytes::Bytes;
64pub use proto::{
65 congestion, crypto, AckFrequencyConfig, ApplicationClose, Chunk, ClientConfig, ConfigError,
66 ConnectError, ConnectionClose, ConnectionError, EndpointConfig, IdleTimeout,
67 MtuDiscoveryConfig, ServerConfig, StreamId, Transmit, TransportConfig, VarInt,
68};
69#[cfg(feature = "tls-rustls")]
70pub use rustls;
71pub use udp;
72
73pub use crate::connection::{
74 AcceptBi, AcceptUni, Connecting, Connection, OpenBi, OpenUni, ReadDatagram, SendDatagramError,
75 UnknownStream, ZeroRttAccepted,
76};
77pub use crate::endpoint::{Accept, Endpoint};
78pub use crate::recv_stream::{ReadError, ReadExactError, ReadToEndError, RecvStream};
79#[cfg(feature = "runtime-async-std")]
80pub use crate::runtime::AsyncStdRuntime;
81#[cfg(feature = "runtime-smol")]
82pub use crate::runtime::SmolRuntime;
83#[cfg(feature = "runtime-tokio")]
84pub use crate::runtime::TokioRuntime;
85pub use crate::runtime::{default_runtime, AsyncTimer, AsyncUdpSocket, Runtime};
86pub use crate::send_stream::{SendStream, StoppedError, WriteError};
87
88#[cfg(test)]
89mod tests;
90
91#[derive(Debug)]
92enum ConnectionEvent {
93 Close {
94 error_code: VarInt,
95 reason: bytes::Bytes,
96 },
97 Proto(proto::ConnectionEvent),
98 Ping,
99}
100
101#[derive(Debug)]
102enum EndpointEvent {
103 Proto(proto::EndpointEvent),
104 Transmit(proto::Transmit, Bytes),
105}
106
107/// Maximum number of datagrams processed in send/recv calls to make before moving on to other processing
108///
109/// This helps ensure we don't starve anything when the CPU is slower than the link.
110/// Value is selected by picking a low number which didn't degrade throughput in benchmarks.
111const IO_LOOP_BOUND: usize = 160;
112
113/// The maximum amount of time that should be spent in `recvmsg()` calls per endpoint iteration
114///
115/// 50us are chosen so that an endpoint iteration with a 50us sendmsg limit blocks
116/// the runtime for a maximum of about 100us.
117/// Going much lower does not yield any noticeable difference, since a single `recvmmsg`
118/// batch of size 32 was observed to take 30us on some systems.
119const RECV_TIME_BOUND: Duration = Duration::from_micros(50);
120
121/// The maximum amount of time that should be spent in `sendmsg()` calls per endpoint iteration
122const SEND_TIME_BOUND: Duration = Duration::from_micros(50);
123
124/// The maximum size of content length of packets in the outgoing transmit queue. Transmit packets
125/// generated from the endpoint (retry or initial close) can be dropped when this limit is being execeeded.
126/// Chose to represent 100 MB of data.
127const MAX_TRANSMIT_QUEUE_CONTENTS_LEN: usize = 100_000_000;