1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//! QUIC transport protocol support for Tokio
//!
//! [QUIC](https://en.wikipedia.org/wiki/QUIC) is a modern transport protocol addressing
//! shortcomings of TCP, such as head-of-line blocking, poor security, slow handshakes, and
//! inefficient congestion control. This crate provides a portable userspace implementation. It
//! builds on top of quinn-proto, which implements protocol logic independent of any particular
//! runtime.
//!
//! The entry point of this crate is the [`Endpoint`](struct.Endpoint.html).
//!
#![cfg_attr(
    feature = "rustls",
    doc = "```no_run
# use futures::TryFutureExt;
let mut builder = quinn::Endpoint::builder();
// ... configure builder ...
// Ensure you're inside a tokio runtime context
let (endpoint, _) = builder.bind(&\"[::]:0\".parse().unwrap()).unwrap();
// ... use endpoint ...
```"
)]
//! # About QUIC
//!
//! A QUIC connection is an association between two endpoints. The endpoint which initiates the
//! connection is termed the client, and the endpoint which accepts it is termed the server. A
//! single endpoint may function as both client and server for different connections, for example
//! in a peer-to-peer application. To communicate application data, each endpoint may open streams
//! up to a limit dictated by its peer. Typically, that limit is increased as old streams are
//! finished.
//!
//! Streams may be unidirectional or bidirectional, and are cheap to create and disposable. For
//! example, a traditionally datagram-oriented application could use a new stream for every
//! message it wants to send, no longer needing to worry about MTUs. Bidirectional streams behave
//! much like a traditional TCP connection, and are useful for sending messages that have an
//! immediate response, such as an HTTP request. Stream data is delivered reliably, and there is no
//! ordering enforced between data on different streams.
//!
//! By avoiding head-of-line blocking and providing unified congestion control across all streams
//! of a connection, QUIC is able to provide higher throughput and lower latency than one or
//! multiple TCP connections between the same two hosts, while providing more useful behavior than
//! raw UDP sockets.
//!
//! Quinn also exposes unreliable datagrams, which are a low-level primitive preferred when
//! automatic fragmentation and retransmission of certain data is not desired.
//!
//! QUIC uses encryption and identity verification built directly on TLS 1.3. Just as with a TLS
//! server, it is useful for a QUIC server to be identified by a certificate signed by a trusted
//! authority. If this is infeasible--for example, if servers are short-lived or not associated
//! with a domain name--then as with TLS, self-signed certificates can be used to provide
//! encryption alone.
#![warn(missing_docs)]

mod broadcast;
mod builders;
mod connection;
mod endpoint;
mod platform;
mod streams;
mod udp;

pub use proto::{
    crypto, ApplicationClose, Certificate, CertificateChain, ConnectError, ConnectionClose,
    ConnectionError, ParseError, PrivateKey, Transmit, TransportConfig, VarInt,
};

pub use crate::builders::EndpointError;
pub use crate::connection::{SendDatagramError, ZeroRttAccepted};
pub use crate::streams::{ReadError, ReadExactError, ReadToEndError, WriteError};

/// Types that are generic over the crypto protocol implementation
pub mod generic {
    pub use crate::builders::{ClientConfigBuilder, EndpointBuilder, ServerConfigBuilder};
    pub use crate::connection::{
        Connecting, Connection, Datagrams, IncomingBiStreams, IncomingUniStreams, NewConnection,
        OpenBi, OpenUni,
    };
    pub use crate::endpoint::{Endpoint, Incoming};
    pub use crate::streams::{Read, ReadExact, ReadToEnd, RecvStream, SendStream};
    pub use proto::generic::{ClientConfig, ServerConfig};
}

#[cfg(feature = "rustls")]
mod rustls_impls {
    use crate::generic;
    use proto::crypto::rustls::TlsSession;

    /// A `ClientConfig` using rustls for the cryptography protocol
    pub type ClientConfig = generic::ClientConfig<TlsSession>;
    /// A `ServerConfig` using rustls for the cryptography protocol
    pub type ServerConfig = generic::ServerConfig<TlsSession>;

    /// A `ClientConfigBuilder` using rustls for the cryptography protocol
    pub type ClientConfigBuilder = generic::ClientConfigBuilder<TlsSession>;
    /// An `EndpointBuilder` using rustls for the cryptography protocol
    pub type EndpointBuilder = generic::EndpointBuilder<TlsSession>;
    /// A `ServerConfigBuilder` using rustls for the cryptography protocol
    pub type ServerConfigBuilder = generic::ServerConfigBuilder<TlsSession>;

    /// A `Connecting` using rustls for the cryptography protocol
    pub type Connecting = generic::Connecting<TlsSession>;
    /// A `Connection` using rustls for the cryptography protocol
    pub type Connection = generic::Connection<TlsSession>;
    /// A `Datagrams` using rustls for the cryptography protocol
    pub type Datagrams = generic::Datagrams<TlsSession>;
    /// An `IncomingBiStreams` using rustls for the cryptography protocol
    pub type IncomingBiStreams = generic::IncomingBiStreams<TlsSession>;
    /// An `IncomingUniStreams` using rustls for the cryptography protocol
    pub type IncomingUniStreams = generic::IncomingUniStreams<TlsSession>;
    /// A `NewConnection` using rustls for the cryptography protocol
    pub type NewConnection = generic::NewConnection<TlsSession>;
    /// An `OpenBi` using rustls for the cryptography protocol
    pub type OpenBi = generic::OpenBi<TlsSession>;
    /// An `OpenUni` using rustls for the cryptography protocol
    pub type OpenUni = generic::OpenUni<TlsSession>;

    /// An `Endpoint` using rustls for the cryptography protocol
    pub type Endpoint = generic::Endpoint<TlsSession>;
    /// An `Incoming` using rustls for the cryptography protocol
    pub type Incoming = generic::Incoming<TlsSession>;

    /// A `Read` using rustls for the cryptography protocol
    pub type Read<'a> = generic::Read<'a, TlsSession>;
    /// A `ReadExact` using rustls for the cryptography protocol
    pub type ReadExact<'a> = generic::ReadExact<'a, TlsSession>;
    /// A `ReadToEnd` using rustls for the cryptography protocol
    pub type ReadToEnd = generic::ReadToEnd<TlsSession>;
    /// A `RecvStream` using rustls for the cryptography protocol
    pub type RecvStream = generic::RecvStream<TlsSession>;
    /// A `SendStream` using rustls for the cryptography protocol
    pub type SendStream = generic::SendStream<TlsSession>;
}

#[cfg(feature = "rustls")]
pub use rustls_impls::*;

#[cfg(test)]
mod tests;

#[derive(Debug)]
enum ConnectionEvent {
    Close {
        error_code: VarInt,
        reason: bytes::Bytes,
    },
    Proto(proto::ConnectionEvent),
}

#[derive(Debug)]
enum EndpointEvent {
    Proto(proto::EndpointEvent),
    Transmit(proto::Transmit),
}

/// Maximum number of send/recv calls to make before moving on to other processing
///
/// This helps ensure we don't starve anything when the CPU is slower than the link. Value selected
/// more or less arbitrarily.
const IO_LOOP_BOUND: usize = 10;