Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1661 bug fix raw diff viewer #6

Draft
wants to merge 43 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
90118e7
perf: change throughput units from MiB/s into Mb/s.
stormshield-damiend Apr 18, 2024
85351bc
proto: remove the Side argument from ServerConfig::initial_keys()
djc Jan 20, 2024
b61d9ec
proto: rename InvalidDnsName to InvalidServerName
djc Mar 26, 2024
e28b29f
quinn: add bounds in dyn Error types
djc Apr 21, 2024
07e4281
proto: deduplicate rustls ClientConfig setup
djc Mar 28, 2024
285e1b6
proto: add test helpers for custom ALPN crypto configs
djc Apr 5, 2024
ae82c38
quinn: use ClientConfig helper for tests
djc Apr 5, 2024
7687540
quinn: inline single-use helper function
djc Apr 5, 2024
f0d1a45
perf: hoist config construction out of conditionals
djc Apr 5, 2024
a85a4c1
Update rustls to 0.23 and ring to 0.17
djc Dec 4, 2023
3be1ab5
Upgrade to rcgen 0.13
djc Apr 1, 2024
e6d4897
proto: validate ClientConfig crypto provider
djc Mar 26, 2024
ce13559
proto: validate ServerConfig crypto provider
gabrik Apr 5, 2024
9ce24f9
Refuse incoming connections after endpoint is closed
Ralith Apr 20, 2024
040f6d7
Forbid new outgoing connections on closed endpoints
Ralith Apr 20, 2024
b570714
ci: pass codecov token explicitly
djc Apr 22, 2024
5eae60d
Factor out receive state
nemethf Apr 20, 2024
ca8189a
Lift work limiter start/end out of receive logic
nemethf Apr 20, 2024
42381f4
Introduce struct for poll_socket's return value
Ralith Apr 23, 2024
bacff26
Socket rebind: drain old socket
nemethf Apr 20, 2024
5beaf01
quinn: allow rebinding an abstract socket
djc Apr 23, 2024
7c982a3
Derive retry token keys from retry source CIDs
Ralith Mar 23, 2024
b07370a
Store client address explicitly in the retry token
Ralith Mar 23, 2024
5f63104
Accept connections with unrecognized address validation tokens
Ralith Mar 23, 2024
5507c6b
Fold redundant `use` blocks
Ralith Dec 19, 2023
ef73b2d
Lift udp_transmit helper out of endpoint.rs
Ralith Dec 19, 2023
de7d334
Replace AsyncUdpSocket::poll_send with try_send and poller object
Ralith Dec 20, 2023
3a62a9e
Update connection sockets on rebind
Ralith Dec 19, 2023
fe1643d
Transmit directly from connection tasks
Ralith Dec 19, 2023
426c1d2
Remove newly superfluous quinn::EndpointEvent
Ralith Apr 7, 2024
3adf533
Reduce rightward drift
Ralith Dec 19, 2023
7727989
Don't reallocate send buffer for every batch of transmits
Ralith Dec 19, 2023
9860617
Annotate client/server tasks in rebind_recv test
Ralith Dec 19, 2023
d075733
Don't buffer endpoint-generated datagrams
Ralith Dec 19, 2023
0722280
Fix bitrotted fallback UDP backend
Ralith Dec 21, 2023
ee08826
Drop sendmmsg support
Ralith Dec 21, 2023
5613a45
Transmit borrowed UDP payloads
Ralith Dec 21, 2023
375445d
Fix incorrect size in split_transmit
Ralith Apr 7, 2024
46ac7d7
Replace BytesMut transmit buffers with Vec
Ralith Dec 21, 2023
76b9099
Remove badges from metadata
djc Apr 26, 2024
af30cbd
Add references to OpenCollective
djc Apr 26, 2024
7877462
proto: Factor out DatagramConnectionEvent
gretchenfrage Apr 26, 2024
b76f7a7
Fix race condition between 0-RTT and Incoming
gretchenfrage Apr 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
open_collective: quinn-rs
1 change: 1 addition & 0 deletions .github/workflows/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ jobs:
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: lcov.info
fail_ci_if_error: true
12 changes: 5 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE-MIT)
[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE-APACHE)

Quinn is a pure-rust, async-compatible implementation of the IETF [QUIC][quic] transport protocol.
Quinn is a pure-Rust, async-compatible implementation of the IETF [QUIC][quic] transport protocol.
The project was founded by [Dirkjan Ochtman](https://github.com/djc) and
[Benjamin Saunders](https://github.com/Ralith) as a side project in 2018, and has seen more than
30 releases since then. If you're using Quinn in a commercial setting, please consider
[sponsoring](https://opencollective.com/quinn-rs) the project.

## Features

Expand Down Expand Up @@ -108,12 +112,6 @@ the variable.
The minimum supported Rust version for published releases of our
crates will always be at least 6 months old at the time of release.

## Authors

* **Dirkjan Ochtman** - *Project owner & founder*
* **Benjamin Saunders** - *Project owner & founder*
* **Jean-Christophe Begue** - *Project collaborator, author of the HTTP/3 Implementation*

[quic]: https://quicwg.github.io/
[issues]: https://github.com/djc/quinn/issues
[rustls]: https://github.com/ctz/rustls
Expand Down
4 changes: 2 additions & 2 deletions bench/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ anyhow = "1.0.22"
bytes = "1"
hdrhistogram = { version = "7.2", default-features = false }
quinn = { path = "../quinn" }
rcgen = "0.12.0"
rustls = { version = "0.21.0", default-features = false, features = ["quic"] }
rcgen = "0.13"
rustls = { version = "0.23", default-features = false, features = ["ring", "std"] }
clap = { version = "4", features = ["derive"] }
tokio = { version = "1.0.1", features = ["rt", "sync"] }
tracing = "0.1.10"
Expand Down
9 changes: 5 additions & 4 deletions bench/src/bin/bulk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::{

use anyhow::{Context, Result};
use clap::Parser;
use rustls::pki_types::{CertificateDer, PrivatePkcs8KeyDer};
use tokio::sync::Semaphore;
use tracing::{info, trace};

Expand All @@ -21,14 +22,14 @@ fn main() {
configure_tracing_subscriber();

let cert = rcgen::generate_simple_self_signed(vec!["localhost".into()]).unwrap();
let key = rustls::PrivateKey(cert.serialize_private_key_der());
let cert = rustls::Certificate(cert.serialize_der().unwrap());
let key = PrivatePkcs8KeyDer::from(cert.key_pair.serialize_der());
let cert = CertificateDer::from(cert.cert);

let server_span = tracing::error_span!("server");
let runtime = rt();
let (server_addr, endpoint) = {
let _guard = server_span.enter();
server_endpoint(&runtime, cert.clone(), key, &opt)
server_endpoint(&runtime, cert.clone(), key.into(), &opt)
};

let server_thread = std::thread::spawn(move || {
Expand Down Expand Up @@ -111,7 +112,7 @@ async fn server(endpoint: quinn::Endpoint, opt: Opt) -> Result<()> {

async fn client(
server_addr: SocketAddr,
server_cert: rustls::Certificate,
server_cert: CertificateDer<'static>,
opt: Opt,
) -> Result<ClientStats> {
let (endpoint, connection) = connect_client(server_addr, server_cert, opt).await?;
Expand Down
34 changes: 22 additions & 12 deletions bench/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ use std::{
use anyhow::{Context, Result};
use bytes::Bytes;
use clap::Parser;
use rustls::RootCertStore;
use quinn::crypto::rustls::QuicClientConfig;
use rustls::{
pki_types::{CertificateDer, PrivateKeyDer},
RootCertStore,
};
use tokio::runtime::{Builder, Runtime};
use tracing::trace;

Expand All @@ -27,8 +31,8 @@ pub fn configure_tracing_subscriber() {
/// Creates a server endpoint which runs on the given runtime
pub fn server_endpoint(
rt: &tokio::runtime::Runtime,
cert: rustls::Certificate,
key: rustls::PrivateKey,
cert: CertificateDer<'static>,
key: PrivateKeyDer<'static>,
opt: &Opt,
) -> (SocketAddr, quinn::Endpoint) {
let cert_chain = vec![cert];
Expand All @@ -50,23 +54,28 @@ pub fn server_endpoint(
/// Create a client endpoint and client connection
pub async fn connect_client(
server_addr: SocketAddr,
server_cert: rustls::Certificate,
server_cert: CertificateDer<'_>,
opt: Opt,
) -> Result<(quinn::Endpoint, quinn::Connection)> {
let endpoint =
quinn::Endpoint::client(SocketAddr::new(IpAddr::V6(Ipv6Addr::LOCALHOST), 0)).unwrap();

let mut roots = RootCertStore::empty();
roots.add(&server_cert)?;
let crypto = rustls::ClientConfig::builder()
.with_cipher_suites(&[opt.cipher.as_rustls()])
.with_safe_default_kx_groups()
roots.add(server_cert)?;

let default_provider = rustls::crypto::ring::default_provider();
let provider = rustls::crypto::CryptoProvider {
cipher_suites: vec![opt.cipher.as_rustls()],
..default_provider
};

let crypto = rustls::ClientConfig::builder_with_provider(provider.into())
.with_protocol_versions(&[&rustls::version::TLS13])
.unwrap()
.with_root_certificates(roots)
.with_no_client_auth();

let mut client_config = quinn::ClientConfig::new(Arc::new(crypto));
let mut client_config = quinn::ClientConfig::new(Arc::new(QuicClientConfig::try_from(crypto)?));
client_config.transport_config(Arc::new(transport_config(&opt)));

let connection = endpoint
Expand Down Expand Up @@ -223,10 +232,11 @@ pub enum CipherSuite {

impl CipherSuite {
pub fn as_rustls(self) -> rustls::SupportedCipherSuite {
use rustls::crypto::ring::cipher_suite;
match self {
CipherSuite::Aes128 => rustls::cipher_suite::TLS13_AES_128_GCM_SHA256,
CipherSuite::Aes256 => rustls::cipher_suite::TLS13_AES_256_GCM_SHA384,
CipherSuite::Chacha20 => rustls::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256,
CipherSuite::Aes128 => cipher_suite::TLS13_AES_128_GCM_SHA256,
CipherSuite::Aes256 => cipher_suite::TLS13_AES_256_GCM_SHA384,
CipherSuite::Chacha20 => cipher_suite::TLS13_CHACHA20_POLY1305_SHA256,
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions perf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ anyhow = "1.0.22"
hdrhistogram = { version = "7.2", default-features = false }
quinn = { path = "../quinn" }
quinn-proto = { path = "../quinn-proto" }
rcgen = "0.12.0"
rustls = { version = "0.21.0", default-features = false, features = ["dangerous_configuration"] }
rustls-pemfile = "1.0.0"
rcgen = "0.13"
rustls = { version = "0.23", default-features = false, features = ["ring", "std"] }
rustls-pemfile = "2"
serde = { version = "1.0", features = ["derive"], optional = true }
serde_json = { version = "1.0", optional = true }
socket2 = "0.5"
Expand Down
86 changes: 62 additions & 24 deletions perf/src/bin/perf_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use std::{
use anyhow::{Context, Result};
use bytes::Bytes;
use clap::Parser;
use quinn::TokioRuntime;
use quinn::{crypto::rustls::QuicClientConfig, TokioRuntime};
use rustls::pki_types::{CertificateDer, ServerName, UnixTime};
use tokio::sync::Semaphore;
use tracing::{debug, error, info};

Expand Down Expand Up @@ -115,12 +116,17 @@ async fn run(opt: Opt) -> Result<()> {

let endpoint = quinn::Endpoint::new(Default::default(), None, socket, Arc::new(TokioRuntime))?;

let mut crypto = rustls::ClientConfig::builder()
.with_cipher_suites(perf::PERF_CIPHER_SUITES)
.with_safe_default_kx_groups()
let default_provider = rustls::crypto::ring::default_provider();
let provider = Arc::new(rustls::crypto::CryptoProvider {
cipher_suites: perf::PERF_CIPHER_SUITES.into(),
..default_provider
});

let mut crypto = rustls::ClientConfig::builder_with_provider(provider.clone())
.with_protocol_versions(&[&rustls::version::TLS13])
.unwrap()
.with_custom_certificate_verifier(SkipServerVerification::new())
.dangerous()
.with_custom_certificate_verifier(SkipServerVerification::new(provider))
.with_no_client_auth();
crypto.alpn_protocols = vec![b"perf".to_vec()];

Expand All @@ -131,17 +137,17 @@ async fn run(opt: Opt) -> Result<()> {
let mut transport = quinn::TransportConfig::default();
transport.initial_mtu(opt.initial_mtu);

let mut cfg = if opt.no_protection {
quinn::ClientConfig::new(Arc::new(NoProtectionClientConfig::new(Arc::new(crypto))))
} else {
quinn::ClientConfig::new(Arc::new(crypto))
};
cfg.transport_config(Arc::new(transport));
let crypto = Arc::new(QuicClientConfig::try_from(crypto)?);
let mut config = quinn::ClientConfig::new(match opt.no_protection {
true => Arc::new(NoProtectionClientConfig::new(crypto)),
false => crypto,
});
config.transport_config(Arc::new(transport));

let stream_stats = OpenStreamStats::default();

let connection = endpoint
.connect_with(cfg, addr, host_name)?
.connect_with(config, addr, host_name)?
.await
.context("connecting")?;

Expand Down Expand Up @@ -355,24 +361,56 @@ async fn request_bi(
Ok(())
}

struct SkipServerVerification;
#[derive(Debug)]
struct SkipServerVerification(Arc<rustls::crypto::CryptoProvider>);

impl SkipServerVerification {
fn new() -> Arc<Self> {
Arc::new(Self)
fn new(provider: Arc<rustls::crypto::CryptoProvider>) -> Arc<Self> {
Arc::new(Self(provider))
}
}

impl rustls::client::ServerCertVerifier for SkipServerVerification {
impl rustls::client::danger::ServerCertVerifier for SkipServerVerification {
fn verify_server_cert(
&self,
_end_entity: &rustls::Certificate,
_intermediates: &[rustls::Certificate],
_server_name: &rustls::ServerName,
_scts: &mut dyn Iterator<Item = &[u8]>,
_ocsp_response: &[u8],
_now: std::time::SystemTime,
) -> Result<rustls::client::ServerCertVerified, rustls::Error> {
Ok(rustls::client::ServerCertVerified::assertion())
_end_entity: &CertificateDer<'_>,
_intermediates: &[CertificateDer<'_>],
_server_name: &ServerName<'_>,
_ocsp: &[u8],
_now: UnixTime,
) -> Result<rustls::client::danger::ServerCertVerified, rustls::Error> {
Ok(rustls::client::danger::ServerCertVerified::assertion())
}

fn verify_tls12_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &rustls::DigitallySignedStruct,
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
rustls::crypto::verify_tls12_signature(
message,
cert,
dss,
&self.0.signature_verification_algorithms,
)
}

fn verify_tls13_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &rustls::DigitallySignedStruct,
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
rustls::crypto::verify_tls13_signature(
message,
cert,
dss,
&self.0.signature_verification_algorithms,
)
}

fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
self.0.signature_verification_algorithms.supported_schemes()
}
}
48 changes: 26 additions & 22 deletions perf/src/bin/perf_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ use std::{fs, net::SocketAddr, path::PathBuf, sync::Arc, time::Duration};
use anyhow::{Context, Result};
use bytes::Bytes;
use clap::Parser;
use quinn::TokioRuntime;
use quinn::{crypto::rustls::QuicServerConfig, TokioRuntime};
use rustls::pki_types::{CertificateDer, PrivatePkcs8KeyDer};
use tracing::{debug, error, info};

use perf::{bind_socket, noprotection::NoProtectionServerConfig};
use perf::{bind_socket, noprotection::NoProtectionServerConfig, PERF_CIPHER_SUITES};

#[derive(Parser)]
#[clap(name = "server")]
Expand Down Expand Up @@ -56,30 +57,33 @@ async fn run(opt: Opt) -> Result<()> {
(Some(key), Some(cert)) => {
let key = fs::read(key).context("reading key")?;
let cert = fs::read(cert).expect("reading cert");

let mut certs = Vec::new();
for cert in rustls_pemfile::certs(&mut cert.as_ref()).context("parsing cert")? {
certs.push(rustls::Certificate(cert));
}

(rustls::PrivateKey(key), certs)
(
PrivatePkcs8KeyDer::from(key),
rustls_pemfile::certs(&mut cert.as_ref())
.collect::<Result<_, _>>()
.context("parsing cert")?,
)
}
_ => {
let cert = rcgen::generate_simple_self_signed(vec!["localhost".into()]).unwrap();
(
rustls::PrivateKey(cert.serialize_private_key_der()),
vec![rustls::Certificate(cert.serialize_der().unwrap())],
PrivatePkcs8KeyDer::from(cert.key_pair.serialize_der()),
vec![CertificateDer::from(cert.cert)],
)
}
};

let mut crypto = rustls::ServerConfig::builder()
.with_cipher_suites(perf::PERF_CIPHER_SUITES)
.with_safe_default_kx_groups()
let default_provider = rustls::crypto::ring::default_provider();
let provider = rustls::crypto::CryptoProvider {
cipher_suites: PERF_CIPHER_SUITES.into(),
..default_provider
};

let mut crypto = rustls::ServerConfig::builder_with_provider(provider.into())
.with_protocol_versions(&[&rustls::version::TLS13])
.unwrap()
.with_no_client_auth()
.with_single_cert(cert, key)
.with_single_cert(cert, key.into())
.unwrap();
crypto.alpn_protocols = vec![b"perf".to_vec()];

Expand All @@ -90,18 +94,18 @@ async fn run(opt: Opt) -> Result<()> {
let mut transport = quinn::TransportConfig::default();
transport.initial_mtu(opt.initial_mtu);

let mut server_config = if opt.no_protection {
quinn::ServerConfig::with_crypto(Arc::new(NoProtectionServerConfig::new(Arc::new(crypto))))
} else {
quinn::ServerConfig::with_crypto(Arc::new(crypto))
};
server_config.transport_config(Arc::new(transport));
let crypto = Arc::new(QuicServerConfig::try_from(crypto)?);
let mut config = quinn::ServerConfig::with_crypto(match opt.no_protection {
true => Arc::new(NoProtectionServerConfig::new(crypto)),
false => crypto,
});
config.transport_config(Arc::new(transport));

let socket = bind_socket(opt.listen, opt.send_buffer_size, opt.recv_buffer_size)?;

let endpoint = quinn::Endpoint::new(
Default::default(),
Some(server_config),
Some(config),
socket,
Arc::new(TokioRuntime),
)
Expand Down
7 changes: 4 additions & 3 deletions perf/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::net::SocketAddr;

use anyhow::{Context, Result};
use rustls::crypto::ring::cipher_suite;
use socket2::{Domain, Protocol, Socket, Type};
use tracing::warn;

Expand Down Expand Up @@ -51,7 +52,7 @@ pub fn bind_socket(
}

pub static PERF_CIPHER_SUITES: &[rustls::SupportedCipherSuite] = &[
rustls::cipher_suite::TLS13_AES_128_GCM_SHA256,
rustls::cipher_suite::TLS13_AES_256_GCM_SHA384,
rustls::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256,
cipher_suite::TLS13_AES_128_GCM_SHA256,
cipher_suite::TLS13_AES_256_GCM_SHA384,
cipher_suite::TLS13_CHACHA20_POLY1305_SHA256,
];
Loading