зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1911792 - update neqo to v0.8.2 r=kershaw,necko-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D218637
This commit is contained in:
Родитель
ef3fe58632
Коммит
2217e98397
|
@ -85,9 +85,9 @@ git = "https://github.com/mozilla/mp4parse-rust"
|
|||
rev = "a138e40ec1c603615873e524b5b22e11c0ec4820"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/mozilla/neqo?tag=v0.8.1"]
|
||||
[source."git+https://github.com/mozilla/neqo?tag=v0.8.2"]
|
||||
git = "https://github.com/mozilla/neqo"
|
||||
tag = "v0.8.1"
|
||||
tag = "v0.8.2"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/servo/unicode-bidi?rev=ca612daf1c08c53abe07327cb3e6ef6e0a760f0c"]
|
||||
|
|
|
@ -4043,8 +4043,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "neqo-bin"
|
||||
version = "0.8.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.8.1#f0bffce01be53309a9cc93dc344141f57918cb3b"
|
||||
version = "0.8.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.8.2#b7e17668eb8f2fb13c1d945a9a7f79bd31257eb8"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"clap-verbosity-flag",
|
||||
|
@ -4065,8 +4065,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "neqo-common"
|
||||
version = "0.8.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.8.1#f0bffce01be53309a9cc93dc344141f57918cb3b"
|
||||
version = "0.8.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.8.2#b7e17668eb8f2fb13c1d945a9a7f79bd31257eb8"
|
||||
dependencies = [
|
||||
"enum-map",
|
||||
"env_logger",
|
||||
|
@ -4078,8 +4078,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "neqo-crypto"
|
||||
version = "0.8.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.8.1#f0bffce01be53309a9cc93dc344141f57918cb3b"
|
||||
version = "0.8.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.8.2#b7e17668eb8f2fb13c1d945a9a7f79bd31257eb8"
|
||||
dependencies = [
|
||||
"bindgen 0.69.4",
|
||||
"log",
|
||||
|
@ -4093,8 +4093,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "neqo-http3"
|
||||
version = "0.8.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.8.1#f0bffce01be53309a9cc93dc344141f57918cb3b"
|
||||
version = "0.8.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.8.2#b7e17668eb8f2fb13c1d945a9a7f79bd31257eb8"
|
||||
dependencies = [
|
||||
"enumset",
|
||||
"log",
|
||||
|
@ -4109,8 +4109,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "neqo-qpack"
|
||||
version = "0.8.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.8.1#f0bffce01be53309a9cc93dc344141f57918cb3b"
|
||||
version = "0.8.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.8.2#b7e17668eb8f2fb13c1d945a9a7f79bd31257eb8"
|
||||
dependencies = [
|
||||
"log",
|
||||
"neqo-common",
|
||||
|
@ -4121,8 +4121,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "neqo-transport"
|
||||
version = "0.8.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.8.1#f0bffce01be53309a9cc93dc344141f57918cb3b"
|
||||
version = "0.8.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.8.2#b7e17668eb8f2fb13c1d945a9a7f79bd31257eb8"
|
||||
dependencies = [
|
||||
"enum-map",
|
||||
"indexmap 2.2.6",
|
||||
|
@ -4136,8 +4136,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "neqo-udp"
|
||||
version = "0.8.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.8.1#f0bffce01be53309a9cc93dc344141f57918cb3b"
|
||||
version = "0.8.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.8.2#b7e17668eb8f2fb13c1d945a9a7f79bd31257eb8"
|
||||
dependencies = [
|
||||
"log",
|
||||
"neqo-common",
|
||||
|
@ -4808,6 +4808,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"once_cell",
|
||||
"socket2 0.5.7",
|
||||
"windows-sys",
|
||||
|
|
|
@ -13570,11 +13570,6 @@
|
|||
# tracked in https://github.com/quinn-rs/quinn/issues/1947.
|
||||
#if defined(ANDROID) && !defined(HAVE_64BIT_BUILD)
|
||||
value: true
|
||||
# Always use NSPR on Windows. Windows is failing with a zero-size read. Future
|
||||
# fix and further details tracked in
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=1911658.
|
||||
#elif defined(XP_WIN)
|
||||
value: true
|
||||
#else
|
||||
value: @IS_NOT_NIGHTLY_BUILD@
|
||||
#endif
|
||||
|
|
|
@ -9,11 +9,11 @@ license = "MPL-2.0"
|
|||
name = "neqo_glue"
|
||||
|
||||
[dependencies]
|
||||
neqo-udp = { tag = "v0.8.1", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-http3 = { tag = "v0.8.1", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-transport = { tag = "v0.8.1", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-common = { tag = "v0.8.1", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-qpack = { tag = "v0.8.1", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-udp = { tag = "v0.8.2", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-http3 = { tag = "v0.8.2", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-transport = { tag = "v0.8.2", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-common = { tag = "v0.8.2", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-qpack = { tag = "v0.8.2", git = "https://github.com/mozilla/neqo" }
|
||||
nserror = { path = "../../../xpcom/rust/nserror" }
|
||||
nsstring = { path = "../../../xpcom/rust/nsstring" }
|
||||
xpcom = { path = "../../../xpcom/rust/xpcom" }
|
||||
|
@ -28,7 +28,7 @@ uuid = { version = "1.0", features = ["v4"] }
|
|||
winapi = {version = "0.3", features = ["ws2def"] }
|
||||
|
||||
[dependencies.neqo-crypto]
|
||||
tag = "v0.8.1"
|
||||
tag = "v0.8.2"
|
||||
git = "https://github.com/mozilla/neqo"
|
||||
default-features = false
|
||||
features = ["gecko"]
|
||||
|
|
|
@ -1479,14 +1479,11 @@ pub extern "C" fn neqo_http3conn_peer_certificate_info(
|
|||
conn: &mut NeqoHttp3Conn,
|
||||
neqo_certs_info: &mut NeqoCertificateInfo,
|
||||
) -> nsresult {
|
||||
let mut certs_info = match conn.conn.peer_certificate() {
|
||||
Some(certs) => certs,
|
||||
None => return NS_ERROR_NOT_AVAILABLE,
|
||||
let Some(certs_info) = conn.conn.peer_certificate() else {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
};
|
||||
|
||||
neqo_certs_info.certs = certs_info
|
||||
.map(|cert| cert.iter().cloned().collect())
|
||||
.collect();
|
||||
neqo_certs_info.certs = certs_info.iter().map(ThinVec::from).collect();
|
||||
|
||||
match &mut certs_info.stapled_ocsp_responses() {
|
||||
Some(ocsp_val) => {
|
||||
|
|
|
@ -6,11 +6,11 @@ edition = "2018"
|
|||
license = "MPL-2.0"
|
||||
|
||||
[dependencies]
|
||||
neqo-bin = { tag = "v0.8.1", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-transport = { tag = "v0.8.1", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-common = { tag = "v0.8.1", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-http3 = { tag = "v0.8.1", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-qpack = { tag = "v0.8.1", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-bin = { tag = "v0.8.2", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-transport = { tag = "v0.8.2", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-common = { tag = "v0.8.2", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-http3 = { tag = "v0.8.2", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-qpack = { tag = "v0.8.2", git = "https://github.com/mozilla/neqo" }
|
||||
log = "0.4.0"
|
||||
base64 = "0.21"
|
||||
cfg-if = "1.0"
|
||||
|
@ -20,7 +20,7 @@ tokio = { version = "1", features = ["rt-multi-thread"] }
|
|||
mozilla-central-workspace-hack = { version = "0.1", features = ["http3server"], optional = true }
|
||||
|
||||
[dependencies.neqo-crypto]
|
||||
tag = "v0.8.1"
|
||||
tag = "v0.8.2"
|
||||
git = "https://github.com/mozilla/neqo"
|
||||
default-features = false
|
||||
features = ["gecko"]
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"5c8f1c82accd7dbe47dd53838f165d72009d8718e98fce6bef4757d3c8836ab0","benches/main.rs":"5209cbf879c3e0672e5c2f6f60b70643c4a28fbecdc56c182d7437a2f91740dd","src/bin/client.rs":"db77efd75dc0745b6dd983ab8fa3bc8f5f9111967f0d90d23cb19140a940246d","src/bin/server.rs":"2f7ab3c7a98117bd162e6fd07abef1d21791d1bb240db3aae61afa6ff72df83a","src/client/http09.rs":"868a55062e864e7c290e345e3049afbd49796ec3655259a681457540efa3650f","src/client/http3.rs":"cf6dc5ec2cf8eeb673410f499daa15ec55ed64bf3d51da718659f284e7984f25","src/client/mod.rs":"3bf40a6dcc5fde24c823f55ee9d34a2e7d96d2d19980b234d3ec22e33771c14c","src/lib.rs":"e41fe10d5f45b4472ca97a8be531a6b959ec47f094cf2fad3f4f50954ce09046","src/server/http09.rs":"7b0b0459d2b71ecb1d4c93177304a8b7dc0a74dc4cb0a9875df18295ab04b271","src/server/http3.rs":"9d5361a724be1d0e234bbc4b3893a8830825e5886a24a40b96e3f87f35c7b968","src/server/mod.rs":"91f8cd6278c42eef20b6e16f3d903705073d741093bcdf161b58c01914aca2de","src/udp.rs":"74004ac193cca4b7f3f31ecedb975d901ae1e25a8644dc4deedbfbc97d4a2d17"},"package":null}
|
||||
{"files":{"Cargo.toml":"a35a84144abc70ceec5017089f31a5c7ed6fd5d38073e2ba1648dbedbd3d4d0e","benches/main.rs":"aa39bf1f08863e3bace034a991c60a4723f1a7d30b3fc1d1f8c4d7f73bc748c3","src/bin/client.rs":"db77efd75dc0745b6dd983ab8fa3bc8f5f9111967f0d90d23cb19140a940246d","src/bin/server.rs":"2f7ab3c7a98117bd162e6fd07abef1d21791d1bb240db3aae61afa6ff72df83a","src/client/http09.rs":"868a55062e864e7c290e345e3049afbd49796ec3655259a681457540efa3650f","src/client/http3.rs":"7ffba6396ab5875cda5f3ab092d4cc34ab16adad30277b017bc667086d374d18","src/client/mod.rs":"3bf40a6dcc5fde24c823f55ee9d34a2e7d96d2d19980b234d3ec22e33771c14c","src/lib.rs":"e41fe10d5f45b4472ca97a8be531a6b959ec47f094cf2fad3f4f50954ce09046","src/server/http09.rs":"7b0b0459d2b71ecb1d4c93177304a8b7dc0a74dc4cb0a9875df18295ab04b271","src/server/http3.rs":"9d5361a724be1d0e234bbc4b3893a8830825e5886a24a40b96e3f87f35c7b968","src/server/mod.rs":"91f8cd6278c42eef20b6e16f3d903705073d741093bcdf161b58c01914aca2de","src/udp.rs":"81391238621282fae1efc4e5b28be7226733e1bfef7e790f21fb23395cb738bc"},"package":null}
|
|
@ -13,7 +13,7 @@
|
|||
edition = "2021"
|
||||
rust-version = "1.76.0"
|
||||
name = "neqo-bin"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
authors = ["The Neqo Authors <necko@mozilla.com>"]
|
||||
description = "A basic QUIC HTTP/0.9 and HTTP/3 client and server."
|
||||
homepage = "https://github.com/mozilla/neqo/"
|
||||
|
@ -101,7 +101,8 @@ version = "0.13"
|
|||
default-features = false
|
||||
|
||||
[dependencies.quinn-udp]
|
||||
version = "0.5.0"
|
||||
version = "0.5.4"
|
||||
features = ["direct-log"]
|
||||
default-features = false
|
||||
|
||||
[dependencies.regex]
|
||||
|
|
|
@ -13,7 +13,6 @@ use tokio::runtime::Runtime;
|
|||
struct Benchmark {
|
||||
name: String,
|
||||
requests: Vec<u64>,
|
||||
sample_size: Option<usize>,
|
||||
}
|
||||
|
||||
fn transfer(c: &mut Criterion) {
|
||||
|
@ -22,25 +21,18 @@ fn transfer(c: &mut Criterion) {
|
|||
|
||||
let done_sender = spawn_server();
|
||||
|
||||
for Benchmark {
|
||||
name,
|
||||
requests,
|
||||
sample_size,
|
||||
} in [
|
||||
for Benchmark { name, requests } in [
|
||||
Benchmark {
|
||||
name: "1-conn/1-100mb-resp (aka. Download)".to_string(),
|
||||
requests: vec![100 * 1024 * 1024],
|
||||
sample_size: Some(10),
|
||||
},
|
||||
Benchmark {
|
||||
name: "1-conn/10_000-parallel-1b-resp (aka. RPS)".to_string(),
|
||||
requests: vec![1; 10_000],
|
||||
sample_size: None,
|
||||
},
|
||||
Benchmark {
|
||||
name: "1-conn/1-1b-resp (aka. HPS)".to_string(),
|
||||
requests: vec![1; 1],
|
||||
sample_size: None,
|
||||
},
|
||||
] {
|
||||
let mut group = c.benchmark_group(name);
|
||||
|
@ -50,9 +42,6 @@ fn transfer(c: &mut Criterion) {
|
|||
} else {
|
||||
Throughput::Elements(requests.len() as u64)
|
||||
});
|
||||
if let Some(size) = sample_size {
|
||||
group.sample_size(size);
|
||||
}
|
||||
group.bench_function("client", |b| {
|
||||
b.to_async(Runtime::new().unwrap()).iter_batched(
|
||||
|| client::client(client::Args::new(&requests)),
|
||||
|
|
|
@ -30,11 +30,7 @@ use url::Url;
|
|||
use super::{get_output_file, qlog_new, Args, CloseState, Res};
|
||||
|
||||
pub struct Handler<'a> {
|
||||
#[allow(
|
||||
unknown_lints,
|
||||
clippy::struct_field_names,
|
||||
clippy::redundant_field_names
|
||||
)]
|
||||
#[allow(clippy::struct_field_names)]
|
||||
url_handler: UrlHandler<'a>,
|
||||
token: Option<ResumptionToken>,
|
||||
output_read_data: bool,
|
||||
|
|
|
@ -57,7 +57,7 @@ impl Socket {
|
|||
pub fn recv(&self, local_address: &SocketAddr) -> Result<Vec<Datagram>, io::Error> {
|
||||
self.inner
|
||||
.try_io(tokio::io::Interest::READABLE, || {
|
||||
neqo_udp::recv_inner(local_address, &self.state, (&self.inner).into())
|
||||
neqo_udp::recv_inner(local_address, &self.state, &self.inner)
|
||||
})
|
||||
.or_else(|e| {
|
||||
if e.kind() == io::ErrorKind::WouldBlock {
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"6474d7f764179fabd82c4b8f7b8ea95c7a538035adb968301a077613478c664e","build.rs":"306b2f909a25ae38daf5404a4e128d2a94e8975b70870864c2a71cafec9717c7","src/codec.rs":"30a5045a351dc4eee960d8ffc8ec275f1806d70f3805cd8bdbcfe63dee0cc0b1","src/datagram.rs":"2acecfcbecfbb767ea920e3b22388e67b31fcda776cae5b2d7ecbc67dd9febf7","src/event.rs":"106ca6c4afb107fa49a1bc72f5eb4ae95f4baa1ba19736aa38c8ba973774c160","src/fuzz.rs":"1ca74a34bdc97fedecf8a63c4a13cc487d1b2212398fb76f67792c822002138d","src/header.rs":"480a7848466249a78acddbf0bc0b4a096189abc14a89ad1a0943be571add2c2b","src/hrtime.rs":"9c60f13ae9429a9ddb318502b52eba2225e1dbd77637442a0048fb4b0f7acccd","src/incrdecoder.rs":"5c45034e61e75c76d2bca8b075c3e7a3cdd8af8c82b67c76283a2b08ab11846b","src/lib.rs":"2381fc00127a7eaf2265c3a13dc1e1d5843e048f3a8a1c97f1e6621c038de380","src/log.rs":"6ed99e15707c4256ae793011ed2f4b33aa81fed70205aaf5f8d3cd11ad451cf0","src/qlog.rs":"1cee4ff3bc9bf735a1bb913e1515ef240a70326a34c56a6ce89de02bc9f3459c","src/tos.rs":"28fd9acfce06f68ac6691efd2609618850182f77ef3717ce2db07bfac19a9396","tests/log.rs":"a11e21fb570258ca93bb40e3923817d381e1e605accbc3aed1df5a0a9918b41d"},"package":null}
|
||||
{"files":{"Cargo.toml":"0393214662d5143db3f4c167c862ca3174738cbd3e1d6b4cf2773df25c91d273","build.rs":"306b2f909a25ae38daf5404a4e128d2a94e8975b70870864c2a71cafec9717c7","src/codec.rs":"549ee76e90898d37102bd4eabfce69a98aaec6862785eaeb4c9af57b7a36a655","src/datagram.rs":"2acecfcbecfbb767ea920e3b22388e67b31fcda776cae5b2d7ecbc67dd9febf7","src/event.rs":"106ca6c4afb107fa49a1bc72f5eb4ae95f4baa1ba19736aa38c8ba973774c160","src/fuzz.rs":"1ca74a34bdc97fedecf8a63c4a13cc487d1b2212398fb76f67792c822002138d","src/header.rs":"480a7848466249a78acddbf0bc0b4a096189abc14a89ad1a0943be571add2c2b","src/hrtime.rs":"93a544743f3994e5d4c494b313a9532ab5bd23541ff63a747cb377ad6d5edc72","src/incrdecoder.rs":"5c45034e61e75c76d2bca8b075c3e7a3cdd8af8c82b67c76283a2b08ab11846b","src/lib.rs":"2381fc00127a7eaf2265c3a13dc1e1d5843e048f3a8a1c97f1e6621c038de380","src/log.rs":"6ed99e15707c4256ae793011ed2f4b33aa81fed70205aaf5f8d3cd11ad451cf0","src/qlog.rs":"1cee4ff3bc9bf735a1bb913e1515ef240a70326a34c56a6ce89de02bc9f3459c","src/tos.rs":"28fd9acfce06f68ac6691efd2609618850182f77ef3717ce2db07bfac19a9396","tests/log.rs":"a11e21fb570258ca93bb40e3923817d381e1e605accbc3aed1df5a0a9918b41d"},"package":null}
|
|
@ -13,7 +13,7 @@
|
|||
edition = "2021"
|
||||
rust-version = "1.76.0"
|
||||
name = "neqo-common"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
authors = ["The Neqo Authors <necko@mozilla.com>"]
|
||||
description = "Neqo, the Mozilla implementation of QUIC in Rust."
|
||||
homepage = "https://github.com/mozilla/neqo/"
|
||||
|
|
|
@ -304,7 +304,6 @@ impl Encoder {
|
|||
/// # Panics
|
||||
///
|
||||
/// When `n` is outside the range `1..=8`.
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
pub fn encode_uint<T: Into<u64>>(&mut self, n: usize, v: T) -> &mut Self {
|
||||
let v = v.into();
|
||||
assert!(n > 0 && n <= 8);
|
||||
|
@ -374,7 +373,6 @@ impl Encoder {
|
|||
/// # Panics
|
||||
///
|
||||
/// When `f()` writes more than 2^62 bytes.
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
pub fn encode_vvec_with<F: FnOnce(&mut Self)>(&mut self, f: F) -> &mut Self {
|
||||
let start = self.buf.len();
|
||||
// Optimize for short buffers, reserve a single byte for the length.
|
||||
|
|
|
@ -287,37 +287,37 @@ impl Time {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::unused_self)] // Only on some platforms is it unused.
|
||||
#[allow(clippy::missing_const_for_fn)] // Only const on some platforms where the function is empty.
|
||||
#[cfg(target_os = "macos")]
|
||||
fn start(&self) {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
if let Some(p) = self.active {
|
||||
mac::set_realtime(p.scaled(self.scale));
|
||||
} else {
|
||||
mac::set_thread_policy(self.deflt);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if let Some(p) = self.active {
|
||||
_ = unsafe { timeBeginPeriod(p.as_uint()) };
|
||||
}
|
||||
if let Some(p) = self.active {
|
||||
mac::set_realtime(p.scaled(self.scale));
|
||||
} else {
|
||||
mac::set_thread_policy(self.deflt);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::unused_self)] // Only on some platforms is it unused.
|
||||
#[allow(clippy::missing_const_for_fn)] // Only const on some platforms where the function is empty.
|
||||
#[cfg(target_os = "windows")]
|
||||
fn start(&self) {
|
||||
if let Some(p) = self.active {
|
||||
_ = unsafe { timeBeginPeriod(p.as_uint()) };
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(not(target_os = "macos"), not(target_os = "windows")))]
|
||||
#[allow(clippy::unused_self)]
|
||||
const fn start(&self) {}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn stop(&self) {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if let Some(p) = self.active {
|
||||
_ = unsafe { timeEndPeriod(p.as_uint()) };
|
||||
}
|
||||
if let Some(p) = self.active {
|
||||
_ = unsafe { timeEndPeriod(p.as_uint()) };
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[allow(clippy::unused_self)]
|
||||
const fn stop(&self) {}
|
||||
|
||||
fn update(&mut self) {
|
||||
let next = self.periods.min();
|
||||
if next != self.active {
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"c666fb16006b6fab5594d6631e107b4faedc360f737e838e775cbe64c1b6e1e5","bindings/bindings.toml":"56921b753535f899b8095df3e8af04b1dc2213c4808dfb39734a3c554454d01d","bindings/nspr_err.h":"2d5205d017b536c2d838bcf9bc4ec79f96dd50e7bb9b73892328781f1ee6629d","bindings/nspr_error.h":"e41c03c77b8c22046f8618832c9569fbcc7b26d8b9bbc35eea7168f35e346889","bindings/nspr_io.h":"085b289849ef0e77f88512a27b4d9bdc28252bd4d39c6a17303204e46ef45f72","bindings/nspr_time.h":"2e637fd338a5cf0fd3fb0070a47f474a34c2a7f4447f31b6875f5a9928d0a261","bindings/nss_ciphers.h":"95ec6344a607558b3c5ba8510f463b6295f3a2fb3f538a01410531045a5f62d1","bindings/nss_init.h":"ef49045063782fb612aff459172cc6a89340f15005808608ade5320ca9974310","bindings/nss_p11.h":"0b81e64fe6db49b2ecff94edd850be111ef99ec11220e88ceb1c67be90143a78","bindings/nss_secerr.h":"713e8368bdae5159af7893cfa517dabfe5103cede051dee9c9557c850a2defc6","bindings/nss_ssl.h":"af222fb957b989e392e762fa2125c82608a0053aff4fb97e556691646c88c335","bindings/nss_sslerr.h":"24b97f092183d8486f774cdaef5030d0249221c78343570d83a4ee5b594210ae","bindings/nss_sslopt.h":"b7807eb7abdad14db6ad7bc51048a46b065a0ea65a4508c95a12ce90e59d1eea","build.rs":"51cfa35860a4c1a0f16e3fc2e2540b02cd9bdf1598f0ca65b74cf4c02fca5be3","min_version.txt":"7e98f86c69cddb4f65cf96a6de1f4297e3ce224a4c4628609e29042b6c4dcfb9","src/aead.rs":"8fc9307ad6ca9651bfaf29cc2bc5144c5c573be90ef7e0e11405a04256f8e077","src/aead_null.rs":"81163fafef59bd2800bd0a078d53d0f05ee114f0e22165717823a5ff1cb908af","src/agent.rs":"51acad973ae4ab01de056bf7df2e884003fbeffb7c93eaf838019160b4bf8427","src/agentio.rs":"f7d5105845fa9fc9d1bfbd9bfeefd4fb10986e8bdf760d442cb2be230de6575e","src/auth.rs":"ced1a18f691894984244088020ea25dc1ee678603317f0c7dfc8b8842fa750b4","src/cert.rs":"0ea1f458342fe1f1f4a300dd85783bd47539bac3bc05d52ee9c23191e3f59488","src/constants.rs":"f5c779db128a8b0607841ca18c376971017eb327e102e5e6959a7d8effe4b3a6","src/ech.rs":"9d322fcc01c0886f1dfe9bb6273cb9f88a746452ac9a802761b1816a05930c1f","src/err.rs":"6fcceee509fd8f6b321745f962f2de957b10ceb1f408a93657a23f63b4ab72d2","src/exp.rs":"d953873e87430b1c84d4a83c8eb3815041f5585b210bbaf59ae2c4d0057f5edd","src/ext.rs":"cbf7d9f5ecabf4b8c9efd6c334637ab1596ec5266d38ab8d2d6ceae305283deb","src/hkdf.rs":"8745ba761be821c1819cedf6dfd91f8b3148c6718053a4a74f33eb50c7d0cc40","src/hp.rs":"a169745d505a233f52abed09576d76d0e803205c929b74e83ba4e66dc14105fa","src/lib.rs":"1f2c171e76f353c99cebe66f9812d3021ab2914eb015fed6a07409b7cfa426e6","src/min_version.rs":"c6e1f98b9f56db0622ac38c1be131c55acf4a0f09ed0d6283f4d6308e2d1301a","src/p11.rs":"32606dc2c8f861d4bc4b17b7dfb178049f1e64fe330d7624070d8a1d08dd675f","src/prio.rs":"e5e169296c0ac69919c59fb6c1f8bd6bf079452eaa13d75da0edd41d435d3f6f","src/replay.rs":"96b7af8eff9e14313e79303092018b12e8834f780c96b8e247c497fdc680c696","src/result.rs":"0587cbb6aace71a7f9765ef7c01dcd9f73a49dcc6331e1d8fe4de2aef6ca65b6","src/secrets.rs":"4ffaa66f25df47dadf042063bff5953effa7bf2f4920cafe827757d6a659cb58","src/selfencrypt.rs":"018c2dacabd3e463fdadd5707715b23c26c261c4c7d86e66c62f0acec986cad9","src/ssl.rs":"170933713f82511eff2846da18f7e651e12a4ed95281aee0df85d11634c1ea97","src/time.rs":"6e239ea1e4c54fae8df02cf847a8dfdbf5beff421596c34a1f297513e4d87453","tests/aead.rs":"e36ae77802df1ea6d17cfd1bd2178a3706089577d6fd1554ca86e748b8b235b9","tests/agent.rs":"824735f88e487a3748200844e9481e81a72163ad74d82faa9aa16594d9b9bb25","tests/ext.rs":"57af4e2df211fa8afdb73125d4344ef5c70c1ea4579107c3e6f5746308ee3e7b","tests/handshake.rs":"538c9241c4e3a65d4e66be70ec8faa02cb7ddc2b43362cb051fbb83b9c213a51","tests/hkdf.rs":"1d2098dc8398395864baf13e4886cfd1da6d36118727c3b264f457ee3da6b048","tests/hp.rs":"ccda23018dac70b3ff3742afcb0fbae0735be9aeb36644a4ae2b1d7c9126801c","tests/init.rs":"3e15150c4b324c06ca5e8935618e4008da53dc0ef4b69325d150831e87dc0b63","tests/selfencrypt.rs":"8d10840b41629bf449a6b3a551377315e8a05ca26c6b041548748196652c5909"},"package":null}
|
||||
{"files":{"Cargo.toml":"652b2c877cd7b9fb9d00ecb9dfead065c9b578d6d294f1f7b89dfdc2b887a3eb","bindings/bindings.toml":"0e06a03035a90ec5f823b30c8b78ec010a332ae0e5ed0c953da2e4c406451793","bindings/nspr_err.h":"2d5205d017b536c2d838bcf9bc4ec79f96dd50e7bb9b73892328781f1ee6629d","bindings/nspr_error.h":"e41c03c77b8c22046f8618832c9569fbcc7b26d8b9bbc35eea7168f35e346889","bindings/nspr_io.h":"085b289849ef0e77f88512a27b4d9bdc28252bd4d39c6a17303204e46ef45f72","bindings/nspr_time.h":"2e637fd338a5cf0fd3fb0070a47f474a34c2a7f4447f31b6875f5a9928d0a261","bindings/nss_ciphers.h":"95ec6344a607558b3c5ba8510f463b6295f3a2fb3f538a01410531045a5f62d1","bindings/nss_init.h":"ef49045063782fb612aff459172cc6a89340f15005808608ade5320ca9974310","bindings/nss_p11.h":"0b81e64fe6db49b2ecff94edd850be111ef99ec11220e88ceb1c67be90143a78","bindings/nss_secerr.h":"713e8368bdae5159af7893cfa517dabfe5103cede051dee9c9557c850a2defc6","bindings/nss_ssl.h":"af222fb957b989e392e762fa2125c82608a0053aff4fb97e556691646c88c335","bindings/nss_sslerr.h":"24b97f092183d8486f774cdaef5030d0249221c78343570d83a4ee5b594210ae","bindings/nss_sslopt.h":"b7807eb7abdad14db6ad7bc51048a46b065a0ea65a4508c95a12ce90e59d1eea","build.rs":"51cfa35860a4c1a0f16e3fc2e2540b02cd9bdf1598f0ca65b74cf4c02fca5be3","min_version.txt":"94ebbba5fc5de230ca467b7e316e9202e4a86c603b3a629cffd647859f48b730","src/aead.rs":"6410bcbe717a6b9ea6f11209b0888033358113ebc05b8a95cec1980d1360be4d","src/aead_null.rs":"81163fafef59bd2800bd0a078d53d0f05ee114f0e22165717823a5ff1cb908af","src/agent.rs":"607f8a648b2099e81750d3d4076a8ca485c79603011d6b0fb2a515aac400c514","src/agentio.rs":"22e63d5efefbff41113cf002a75bb08f15228cb83e9e2cba65eb6da52dad0264","src/auth.rs":"ced1a18f691894984244088020ea25dc1ee678603317f0c7dfc8b8842fa750b4","src/cert.rs":"8e75e69ec3544474b21f8915a7559463889c2f608b201dee274a8d701880950e","src/constants.rs":"f5c779db128a8b0607841ca18c376971017eb327e102e5e6959a7d8effe4b3a6","src/ech.rs":"75dd192423e8996d9061da5e9c20d30bff5153b9344132eda4fe321c4c141870","src/err.rs":"2366501e0b48933a6a2e1c5b934aa55108c093729c84878b45e1e012e4e45d51","src/exp.rs":"d953873e87430b1c84d4a83c8eb3815041f5585b210bbaf59ae2c4d0057f5edd","src/ext.rs":"cbf7d9f5ecabf4b8c9efd6c334637ab1596ec5266d38ab8d2d6ceae305283deb","src/hkdf.rs":"8745ba761be821c1819cedf6dfd91f8b3148c6718053a4a74f33eb50c7d0cc40","src/hp.rs":"510a4a7f278203aa306ead05608f99397edc3806dc22b0af9e28c665b43ae56c","src/lib.rs":"db01ac68d002055bf12d940442c9b9195cc1331bb779571794eae6dc1223eef6","src/min_version.rs":"c6e1f98b9f56db0622ac38c1be131c55acf4a0f09ed0d6283f4d6308e2d1301a","src/p11.rs":"375397b18fcdf36dcdd22c164c8572dd83caf01b8d0065be3029444b197e1464","src/prio.rs":"5cf0105e78b1db43c65283208174abc3714a41dbb4d5cd80ac547a5a5a7c627c","src/replay.rs":"ad5be8e5d20cde477e7fa734000d880bc36d8288d4689e57332f212f65dde716","src/result.rs":"0587cbb6aace71a7f9765ef7c01dcd9f73a49dcc6331e1d8fe4de2aef6ca65b6","src/secrets.rs":"2c47935c5b8c42363897881eaa0c171e84cf031e57a6e1387b99327080e8dd60","src/selfencrypt.rs":"018c2dacabd3e463fdadd5707715b23c26c261c4c7d86e66c62f0acec986cad9","src/ssl.rs":"59bafcaed7caa66fe448339a1f75ce807ef92fc28247709df4f8058499b0787e","src/time.rs":"ade63a72ae90796d7fcccadbb15efc4594fcdb68913a914a657d4556fde88f62","tests/aead.rs":"e36ae77802df1ea6d17cfd1bd2178a3706089577d6fd1554ca86e748b8b235b9","tests/agent.rs":"cbd0011f1d33281883a45d433228221062424c94e86decade5697731c08a1c52","tests/ext.rs":"57af4e2df211fa8afdb73125d4344ef5c70c1ea4579107c3e6f5746308ee3e7b","tests/handshake.rs":"aa904736d36cc5d5cc0c4f6053b529987f33f944a73411bf08e01d30c4867186","tests/hkdf.rs":"1d2098dc8398395864baf13e4886cfd1da6d36118727c3b264f457ee3da6b048","tests/hp.rs":"ccda23018dac70b3ff3742afcb0fbae0735be9aeb36644a4ae2b1d7c9126801c","tests/init.rs":"3e15150c4b324c06ca5e8935618e4008da53dc0ef4b69325d150831e87dc0b63","tests/selfencrypt.rs":"8d10840b41629bf449a6b3a551377315e8a05ca26c6b041548748196652c5909"},"package":null}
|
|
@ -13,7 +13,7 @@
|
|||
edition = "2021"
|
||||
rust-version = "1.76.0"
|
||||
name = "neqo-crypto"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
authors = ["The Neqo Authors <necko@mozilla.com>"]
|
||||
description = "Neqo, the Mozilla implementation of QUIC in Rust."
|
||||
homepage = "https://github.com/mozilla/neqo/"
|
||||
|
|
|
@ -45,7 +45,6 @@ functions = [
|
|||
"SSL_OptionSet",
|
||||
"SSL_OptionGetDefault",
|
||||
"SSL_PeerCertificate",
|
||||
"SSL_PeerCertificateChain",
|
||||
"SSL_PeerSignedCertTimestamps",
|
||||
"SSL_PeerStapledOCSPResponses",
|
||||
"SSL_ResetHandshake",
|
||||
|
@ -137,8 +136,6 @@ variables = [
|
|||
|
||||
[nss_p11]
|
||||
types = [
|
||||
"CERTCertList",
|
||||
"CERTCertListNode",
|
||||
"CK_CHACHA20_PARAMS",
|
||||
"CK_ATTRIBUTE_TYPE",
|
||||
"CK_FLAGS",
|
||||
|
@ -151,7 +148,6 @@ types = [
|
|||
]
|
||||
functions = [
|
||||
"CERT_DestroyCertificate",
|
||||
"CERT_DestroyCertList",
|
||||
"CERT_GetCertificateDer",
|
||||
"NSS_SetAlgorithmPolicy",
|
||||
"PK11_CipherOp",
|
||||
|
@ -173,6 +169,7 @@ functions = [
|
|||
"PK11_ImportDataKey",
|
||||
"PK11_ReadRawAttribute",
|
||||
"PK11_ReferenceSymKey",
|
||||
"SECITEM_FreeArray",
|
||||
"SECITEM_FreeItem",
|
||||
"SECKEY_CopyPrivateKey",
|
||||
"SECKEY_CopyPublicKey",
|
||||
|
|
|
@ -1 +1 @@
|
|||
3.98
|
||||
3.103
|
||||
|
|
|
@ -69,7 +69,6 @@ impl RealAead {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
#[allow(clippy::unused_self)]
|
||||
pub const fn expansion(&self) -> usize {
|
||||
16
|
||||
}
|
||||
|
|
|
@ -748,7 +748,7 @@ impl SecretAgent {
|
|||
/// # Panics
|
||||
///
|
||||
/// If setup fails.
|
||||
#[allow(unknown_lints, clippy::branches_sharing_code)]
|
||||
#[allow(clippy::branches_sharing_code)]
|
||||
pub fn close(&mut self) {
|
||||
// It should be safe to close multiple times.
|
||||
if self.fd.is_null() {
|
||||
|
@ -833,12 +833,7 @@ impl ResumptionToken {
|
|||
|
||||
/// A TLS Client.
|
||||
#[derive(Debug)]
|
||||
#[allow(
|
||||
renamed_and_removed_lints,
|
||||
clippy::box_vec,
|
||||
unknown_lints,
|
||||
clippy::box_collection
|
||||
)] // We need the Box.
|
||||
#[allow(clippy::box_collection)] // We need the Box.
|
||||
pub struct Client {
|
||||
agent: SecretAgent,
|
||||
|
||||
|
|
|
@ -87,7 +87,6 @@ impl RecordList {
|
|||
self.records.push(Record::new(epoch, ct, data));
|
||||
}
|
||||
|
||||
#[allow(clippy::unused_self)]
|
||||
unsafe extern "C" fn ingest(
|
||||
_fd: *mut ssl::PRFileDesc,
|
||||
epoch: ssl::PRUint16,
|
||||
|
@ -220,7 +219,6 @@ impl AgentIo {
|
|||
}
|
||||
|
||||
unsafe fn borrow(fd: &mut PrFd) -> &mut Self {
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
(**fd).secret.cast::<Self>().as_mut().unwrap()
|
||||
}
|
||||
|
||||
|
|
|
@ -4,23 +4,23 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::ptr::{addr_of, NonNull};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use neqo_common::qerror;
|
||||
|
||||
use crate::{
|
||||
err::secstatus_to_res,
|
||||
null_safe_slice,
|
||||
p11::{CERTCertListNode, CERT_GetCertificateDer, CertList, Item, SECItem, SECItemArray},
|
||||
ssl::{
|
||||
PRFileDesc, SSL_PeerCertificateChain, SSL_PeerSignedCertTimestamps,
|
||||
SSL_PeerStapledOCSPResponses,
|
||||
},
|
||||
experimental_api, null_safe_slice,
|
||||
p11::{ItemArray, ItemArrayIterator, SECItem, SECItemArray},
|
||||
ssl::{PRFileDesc, SSL_PeerSignedCertTimestamps, SSL_PeerStapledOCSPResponses},
|
||||
};
|
||||
|
||||
experimental_api!(SSL_PeerCertificateChainDER(
|
||||
fd: *mut PRFileDesc,
|
||||
out: *mut *mut SECItemArray,
|
||||
));
|
||||
|
||||
pub struct CertificateInfo {
|
||||
certs: CertList,
|
||||
cursor: *const CERTCertListNode,
|
||||
certs: ItemArray,
|
||||
/// `stapled_ocsp_responses` and `signed_cert_timestamp` are properties
|
||||
/// associated with each of the certificates. Right now, NSS only
|
||||
/// reports the value for the end-entity certificate (the first).
|
||||
|
@ -28,12 +28,14 @@ pub struct CertificateInfo {
|
|||
signed_cert_timestamp: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
fn peer_certificate_chain(fd: *mut PRFileDesc) -> Option<(CertList, *const CERTCertListNode)> {
|
||||
let chain = unsafe { SSL_PeerCertificateChain(fd) };
|
||||
CertList::from_ptr(chain.cast()).ok().map(|certs| {
|
||||
let cursor = CertificateInfo::head(&certs);
|
||||
(certs, cursor)
|
||||
})
|
||||
fn peer_certificate_chain(fd: *mut PRFileDesc) -> Option<ItemArray> {
|
||||
let mut chain_ptr: *mut SECItemArray = std::ptr::null_mut();
|
||||
let rv = unsafe { SSL_PeerCertificateChainDER(fd, &mut chain_ptr) };
|
||||
if rv.is_ok() {
|
||||
ItemArray::from_ptr(chain_ptr).ok()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// As explained in rfc6961, an OCSPResponseList can have at most
|
||||
|
@ -72,32 +74,26 @@ fn signed_cert_timestamp(fd: *mut PRFileDesc) -> Option<Vec<u8>> {
|
|||
|
||||
impl CertificateInfo {
|
||||
pub(crate) fn new(fd: *mut PRFileDesc) -> Option<Self> {
|
||||
peer_certificate_chain(fd).map(|(certs, cursor)| Self {
|
||||
peer_certificate_chain(fd).map(|certs| Self {
|
||||
certs,
|
||||
cursor,
|
||||
stapled_ocsp_responses: stapled_ocsp_responses(fd),
|
||||
signed_cert_timestamp: signed_cert_timestamp(fd),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn head(certs: &CertList) -> *const CERTCertListNode {
|
||||
// Three stars: one for the reference, one for the wrapper, one to deference the pointer.
|
||||
unsafe { addr_of!((***certs).list).cast() }
|
||||
impl CertificateInfo {
|
||||
#[must_use]
|
||||
pub fn iter(&self) -> ItemArrayIterator<'_> {
|
||||
self.certs.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for &'a mut CertificateInfo {
|
||||
impl<'a> IntoIterator for &'a CertificateInfo {
|
||||
type IntoIter = ItemArrayIterator<'a>;
|
||||
type Item = &'a [u8];
|
||||
fn next(&mut self) -> Option<&'a [u8]> {
|
||||
self.cursor = unsafe { *self.cursor }.links.next.cast();
|
||||
if self.cursor == CertificateInfo::head(&self.certs) {
|
||||
return None;
|
||||
}
|
||||
let mut item = Item::make_empty();
|
||||
let cert = unsafe { *self.cursor }.cert;
|
||||
secstatus_to_res(unsafe { CERT_GetCertificateDer(cert, &mut item) })
|
||||
.expect("getting DER from certificate should work");
|
||||
Some(unsafe { null_safe_slice(item.data, item.len) })
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -102,8 +102,8 @@ pub fn generate_keys() -> Res<(PrivateKey, PublicKey)> {
|
|||
let oid = unsafe { oid_data.as_ref() }.ok_or(Error::InternalError)?;
|
||||
let oid_slc = unsafe { null_safe_slice(oid.oid.data, oid.oid.len) };
|
||||
let mut params: Vec<u8> = Vec::with_capacity(oid_slc.len() + 2);
|
||||
params.push(u8::try_from(p11::SEC_ASN1_OBJECT_ID).unwrap());
|
||||
params.push(u8::try_from(oid.oid.len).unwrap());
|
||||
params.push(u8::try_from(p11::SEC_ASN1_OBJECT_ID)?);
|
||||
params.push(u8::try_from(oid.oid.len)?);
|
||||
params.extend_from_slice(oid_slc);
|
||||
|
||||
let mut public_ptr: *mut SECKEYPublicKey = null_mut();
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
// except according to those terms.
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![allow(clippy::upper_case_acronyms)]
|
||||
|
||||
use std::{os::raw::c_char, str::Utf8Error};
|
||||
|
||||
|
|
|
@ -68,7 +68,6 @@ impl HpKey {
|
|||
/// # Panics
|
||||
///
|
||||
/// When `cipher` is not known to this code.
|
||||
#[allow(clippy::cast_sign_loss)] // Cast for PK11_GetBlockSize is safe.
|
||||
pub fn extract(version: Version, cipher: Cipher, prk: &SymKey, label: &str) -> Res<Self> {
|
||||
const ZERO: &[u8] = &[0; 12];
|
||||
|
||||
|
@ -119,7 +118,7 @@ impl HpKey {
|
|||
|
||||
debug_assert_eq!(
|
||||
res.block_size(),
|
||||
usize::try_from(unsafe { PK11_GetBlockSize(mech, null_mut()) }).unwrap()
|
||||
usize::try_from(unsafe { PK11_GetBlockSize(mech, null_mut()) })?
|
||||
);
|
||||
Ok(res)
|
||||
}
|
||||
|
@ -155,10 +154,10 @@ impl HpKey {
|
|||
&mut output_len,
|
||||
c_int::try_from(output.len())?,
|
||||
sample[..Self::SAMPLE_SIZE].as_ptr().cast(),
|
||||
c_int::try_from(Self::SAMPLE_SIZE).unwrap(),
|
||||
c_int::try_from(Self::SAMPLE_SIZE)?,
|
||||
)
|
||||
})?;
|
||||
debug_assert_eq!(usize::try_from(output_len).unwrap(), output.len());
|
||||
debug_assert_eq!(usize::try_from(output_len)?, output.len());
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
|
@ -183,7 +182,7 @@ impl HpKey {
|
|||
c_uint::try_from(Self::SAMPLE_SIZE)?,
|
||||
)
|
||||
})?;
|
||||
debug_assert_eq!(usize::try_from(output_len).unwrap(), output.len());
|
||||
debug_assert_eq!(usize::try_from(output_len)?, output.len());
|
||||
Ok(output)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,10 +61,9 @@ pub use self::{
|
|||
|
||||
mod min_version;
|
||||
use min_version::MINIMUM_NSS_VERSION;
|
||||
use neqo_common::qerror;
|
||||
|
||||
#[allow(non_upper_case_globals, clippy::redundant_static_lifetimes)]
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
#[allow(unknown_lints, clippy::borrow_as_ptr)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
mod nss {
|
||||
include!(concat!(env!("OUT_DIR"), "/nss_init.rs"));
|
||||
}
|
||||
|
@ -96,13 +95,13 @@ fn already_initialized() -> bool {
|
|||
unsafe { nss::NSS_IsInitialized() != 0 }
|
||||
}
|
||||
|
||||
fn version_check() {
|
||||
let min_ver = CString::new(MINIMUM_NSS_VERSION).unwrap();
|
||||
assert_ne!(
|
||||
unsafe { nss::NSS_VersionCheck(min_ver.as_ptr()) },
|
||||
0,
|
||||
"Minimum NSS version of {MINIMUM_NSS_VERSION} not supported",
|
||||
);
|
||||
fn version_check() -> Res<()> {
|
||||
let min_ver = CString::new(MINIMUM_NSS_VERSION)?;
|
||||
if unsafe { nss::NSS_VersionCheck(min_ver.as_ptr()) } == 0 {
|
||||
qerror!("Minimum NSS version of {MINIMUM_NSS_VERSION} not supported");
|
||||
return Err(Error::UnsupportedVersion);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Initialize NSS. This only executes the initialization routines once, so if there is any chance
|
||||
|
@ -115,7 +114,7 @@ pub fn init() -> Res<()> {
|
|||
// Set time zero.
|
||||
time::init();
|
||||
let res = INITIALIZED.get_or_init(|| {
|
||||
version_check();
|
||||
version_check()?;
|
||||
if already_initialized() {
|
||||
return Ok(NssLoaded::External);
|
||||
}
|
||||
|
@ -154,7 +153,7 @@ fn enable_ssl_trace() -> Res<()> {
|
|||
pub fn init_db<P: Into<PathBuf>>(dir: P) -> Res<()> {
|
||||
time::init();
|
||||
let res = INITIALIZED.get_or_init(|| {
|
||||
version_check();
|
||||
version_check()?;
|
||||
if already_initialized() {
|
||||
return Ok(NssLoaded::External);
|
||||
}
|
||||
|
@ -215,16 +214,15 @@ pub fn assert_initialized() {
|
|||
/// # Safety
|
||||
/// The caller must adhere to the safety constraints of `std::slice::from_raw_parts`,
|
||||
/// except that this will accept a null value for `data`.
|
||||
unsafe fn null_safe_slice<'a, T>(data: *const u8, len: T) -> &'a [u8]
|
||||
unsafe fn null_safe_slice<'a, T, L>(data: *const T, len: L) -> &'a [T]
|
||||
where
|
||||
usize: TryFrom<T>,
|
||||
usize: TryFrom<L>,
|
||||
{
|
||||
if data.is_null() {
|
||||
let len = usize::try_from(len).unwrap_or_else(|_| panic!("null_safe_slice: size overflow"));
|
||||
if data.is_null() || len == 0 {
|
||||
&[]
|
||||
} else if let Ok(len) = usize::try_from(len) {
|
||||
} else {
|
||||
#[allow(clippy::disallowed_methods)]
|
||||
std::slice::from_raw_parts(data, len)
|
||||
} else {
|
||||
panic!("null_safe_slice: size overflow");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ use std::{
|
|||
ops::{Deref, DerefMut},
|
||||
os::raw::c_uint,
|
||||
ptr::null_mut,
|
||||
slice::Iter as SliceIter,
|
||||
};
|
||||
|
||||
use neqo_common::hex_with_len;
|
||||
|
@ -24,9 +25,7 @@ use crate::{
|
|||
null_safe_slice,
|
||||
};
|
||||
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
#[allow(clippy::unreadable_literal)]
|
||||
#[allow(unknown_lints, clippy::borrow_as_ptr)]
|
||||
mod nss_p11 {
|
||||
include!(concat!(env!("OUT_DIR"), "/nss_p11.rs"));
|
||||
}
|
||||
|
@ -70,16 +69,14 @@ macro_rules! scoped_ptr {
|
|||
}
|
||||
|
||||
impl Drop for $scoped {
|
||||
#[allow(unused_must_use)]
|
||||
fn drop(&mut self) {
|
||||
unsafe { $dtor(self.ptr) };
|
||||
unsafe { _ = $dtor(self.ptr) };
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
scoped_ptr!(Certificate, CERTCertificate, CERT_DestroyCertificate);
|
||||
scoped_ptr!(CertList, CERTCertList, CERT_DestroyCertList);
|
||||
scoped_ptr!(PublicKey, SECKEYPublicKey, SECKEY_DestroyPublicKey);
|
||||
|
||||
impl PublicKey {
|
||||
|
@ -100,10 +97,10 @@ impl PublicKey {
|
|||
**self,
|
||||
buf.as_mut_ptr(),
|
||||
&mut len,
|
||||
c_uint::try_from(buf.len()).unwrap(),
|
||||
c_uint::try_from(buf.len())?,
|
||||
)
|
||||
})?;
|
||||
buf.truncate(usize::try_from(len).unwrap());
|
||||
buf.truncate(usize::try_from(len)?);
|
||||
Ok(buf)
|
||||
}
|
||||
}
|
||||
|
@ -240,6 +237,12 @@ unsafe fn destroy_secitem(item: *mut SECItem) {
|
|||
}
|
||||
scoped_ptr!(Item, SECItem, destroy_secitem);
|
||||
|
||||
impl AsRef<[u8]> for SECItem {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
unsafe { null_safe_slice(self.data, self.len) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Item {
|
||||
/// Create a wrapper for a slice of this object.
|
||||
/// Creating this object is technically safe, but using it is extremely dangerous.
|
||||
|
@ -290,6 +293,38 @@ impl Item {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe fn destroy_secitem_array(array: *mut SECItemArray) {
|
||||
SECITEM_FreeArray(array, PRBool::from(true));
|
||||
}
|
||||
scoped_ptr!(ItemArray, SECItemArray, destroy_secitem_array);
|
||||
|
||||
impl<'a> IntoIterator for &'a ItemArray {
|
||||
type Item = &'a [u8];
|
||||
type IntoIter = ItemArrayIterator<'a>;
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
Self::IntoIter {
|
||||
iter: AsRef::<[SECItem]>::as_ref(self).iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[SECItem]> for ItemArray {
|
||||
fn as_ref(&self) -> &[SECItem] {
|
||||
unsafe { null_safe_slice((*self.ptr).items, (*self.ptr).len) }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ItemArrayIterator<'a> {
|
||||
iter: SliceIter<'a, SECItem>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for ItemArrayIterator<'a> {
|
||||
type Item = &'a [u8];
|
||||
fn next(&mut self) -> Option<&'a [u8]> {
|
||||
self.iter.next().map(AsRef::<[u8]>::as_ref)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "disable-random")]
|
||||
thread_local! {
|
||||
static CURRENT_VALUE: std::cell::Cell<u8> = const { std::cell::Cell::new(0) };
|
||||
|
|
|
@ -4,16 +4,12 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(clippy::upper_case_acronyms)]
|
||||
#![allow(
|
||||
dead_code,
|
||||
non_upper_case_globals,
|
||||
non_snake_case,
|
||||
clippy::cognitive_complexity,
|
||||
clippy::empty_enum,
|
||||
clippy::too_many_lines,
|
||||
unknown_lints,
|
||||
clippy::borrow_as_ptr
|
||||
clippy::too_many_lines
|
||||
)]
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/nspr_io.rs"));
|
||||
|
|
|
@ -18,8 +18,6 @@ use crate::{
|
|||
};
|
||||
|
||||
// This is an opaque struct in NSS.
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
#[allow(clippy::empty_enum)]
|
||||
pub enum SSLAntiReplayContext {}
|
||||
|
||||
experimental_api!(SSL_CreateAntiReplayContext(
|
||||
|
|
|
@ -70,7 +70,6 @@ pub struct Secrets {
|
|||
}
|
||||
|
||||
impl Secrets {
|
||||
#[allow(clippy::unused_self)]
|
||||
unsafe extern "C" fn secret_available(
|
||||
_fd: *mut PRFileDesc,
|
||||
epoch: u16,
|
||||
|
|
|
@ -8,11 +8,8 @@
|
|||
dead_code,
|
||||
non_upper_case_globals,
|
||||
non_snake_case,
|
||||
clippy::cognitive_complexity,
|
||||
clippy::too_many_lines,
|
||||
clippy::upper_case_acronyms,
|
||||
unknown_lints,
|
||||
clippy::borrow_as_ptr
|
||||
clippy::cognitive_complexity
|
||||
)]
|
||||
|
||||
use std::os::raw::{c_uint, c_void};
|
||||
|
@ -28,9 +25,7 @@ mod SSLOption {
|
|||
}
|
||||
|
||||
// I clearly don't understand how bindgen operates.
|
||||
#[allow(clippy::empty_enum)]
|
||||
pub enum PLArenaPool {}
|
||||
#[allow(clippy::empty_enum)]
|
||||
pub enum PRFileDesc {}
|
||||
|
||||
// Remap some constants.
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(clippy::upper_case_acronyms)]
|
||||
|
||||
use std::{
|
||||
ops::Deref,
|
||||
os::raw::c_void,
|
||||
|
|
|
@ -129,8 +129,8 @@ fn raw() {
|
|||
assert!(server.state().is_connected());
|
||||
|
||||
// The client should have one certificate for the server.
|
||||
let mut certs = client.peer_certificate().unwrap();
|
||||
assert_eq!(1, certs.count());
|
||||
let certs = client.peer_certificate().unwrap();
|
||||
assert_eq!(1, certs.into_iter().count());
|
||||
|
||||
// The server shouldn't have a client certificate.
|
||||
assert!(server.peer_certificate().is_none());
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
// except according to those terms.
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![allow(clippy::missing_panics_doc)]
|
||||
#![allow(clippy::missing_errors_doc)]
|
||||
|
||||
use std::{mem, time::Instant};
|
||||
|
||||
|
@ -18,6 +16,8 @@ use neqo_crypto::{
|
|||
use test_fixture::{anti_replay, fixture_init, now};
|
||||
|
||||
/// Consume records until the handshake state changes.
|
||||
#[allow(clippy::missing_panics_doc)]
|
||||
#[allow(clippy::missing_errors_doc)]
|
||||
pub fn forward_records(
|
||||
now: Instant,
|
||||
agent: &mut SecretAgent,
|
||||
|
@ -65,6 +65,7 @@ fn handshake(now: Instant, client: &mut SecretAgent, server: &mut SecretAgent) {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::missing_panics_doc)]
|
||||
pub fn connect_at(now: Instant, client: &mut SecretAgent, server: &mut SecretAgent) {
|
||||
handshake(now, client, server);
|
||||
qinfo!("client: {:?}", client.state());
|
||||
|
@ -77,6 +78,7 @@ pub fn connect(client: &mut SecretAgent, server: &mut SecretAgent) {
|
|||
connect_at(now(), client, server);
|
||||
}
|
||||
|
||||
#[allow(clippy::missing_panics_doc)]
|
||||
pub fn connect_fail(client: &mut SecretAgent, server: &mut SecretAgent) {
|
||||
handshake(now(), client, server);
|
||||
assert!(!client.state().is_connected());
|
||||
|
@ -131,6 +133,7 @@ fn zero_rtt_setup(mode: Resumption, client: &Client, server: &mut Server) -> Opt
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::missing_panics_doc)]
|
||||
#[must_use]
|
||||
pub fn resumption_setup(mode: Resumption) -> (Option<AntiReplay>, ResumptionToken) {
|
||||
fixture_init();
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"173c2046a37c37c60d1a72799c3df3b278a76883caff7126ebf133849a4281c0","src/buffered_send_stream.rs":"dfb248c66ea65418b0c7798c2ecaa3ed70ef1af818ef58d53ef742b3445077b7","src/client_events.rs":"77fedca72ce54956eaba3fb7103085d196a631b764662584ea2629224c5c234e","src/conn_params.rs":"7f0df52bceda1923aef2b7c5c64a532f49ea083ea45e3dcd5bd4b03031b89643","src/connection.rs":"4a56ee7b7643f718318f138fd3d5235795cb0be9d2ae073959b43c2096b01b41","src/connection_client.rs":"8917faadc002d1ce35caec163422944fded670be4d6c5aad4cfe521a70a4dd52","src/connection_server.rs":"02fda7595a33c57d0b3ccede51a1e7a8c9073e1ec107ca1b56c56f1728db2318","src/control_stream_local.rs":"20917762c7e7c1112c56abf1cbaf0ad7f0eab97d8db9a3b10ff524315a235670","src/control_stream_remote.rs":"babad4b42274ea32936aa6a11fcb910d5d4a17c00db26cffd60545358207db86","src/features/extended_connect/mod.rs":"1def634e4d3547cc273fd862f3b22bbd22e94e03a402d1e2672c4b6b5061cd5e","src/features/extended_connect/tests/mod.rs":"fd6aee37243713e80fc526552f21f0222338cec9890409b6575a2a637b17ec1f","src/features/extended_connect/tests/webtransport/datagrams.rs":"51d6f3828c44b438eb1776e8dcce531af520f28bc0d715807d3f53a0eaa071d1","src/features/extended_connect/tests/webtransport/mod.rs":"27f77213414089148e94067bfc54133945a971fd7ddd6936bbfeabb9badc7e67","src/features/extended_connect/tests/webtransport/negotiation.rs":"a22094dbaf0754d39ac8ac08fce1ae34ace108220b696c7d618567df56cddeec","src/features/extended_connect/tests/webtransport/sessions.rs":"cf8aa14087cc3ff42657d86ecacbd51bc182357fdcbd10f57d32784abb415a12","src/features/extended_connect/tests/webtransport/streams.rs":"4c136855292d5ba5169f41c18beea13e7f1e014a0acb13c565c872d3a80d6377","src/features/extended_connect/webtransport_session.rs":"da0b99092d8af8d4f7699c8d45e2e4057f4de38d6fa99e27e3a7feffa569374f","src/features/extended_connect/webtransport_streams.rs":"9855d77705acb7d21566333c4b297816e363be2ade14b8685fd1df4a4861cf74","src/features/mod.rs":"89056df3a868cb0037963c942fc27093cc16d84538ffca2d4759f9a6a6c74c7f","src/frames/hframe.rs":"72349bf4e9dd5c57dc5443bb9aa079887e2742dc08d77ea55567e3b09e0de4d8","src/frames/mod.rs":"0e6d49888d723b2c2c73df11020ceb88d9f062e9d4dc436eb38173e0b772d905","src/frames/reader.rs":"8c7ea836a466410bd3c98848b4852945ae30e1306f73290c401c686998bde16d","src/frames/tests/hframe.rs":"01ec74eb3eb25d95042aa0263f9267f89535e6b7b8c1161fab4ba9ee5352d4a7","src/frames/tests/mod.rs":"a07b99a7ebc0771630a7b360679a5b8d568bb5ad2f1ec92e7f5afe6644c6800e","src/frames/tests/reader.rs":"6c5aaa9bf6becaf1892fda5d6d42c5e650f65d1a1a0fb4ccba9f5a6618a77ced","src/frames/tests/wtframe.rs":"589ebe1e62ce4da63b37b7d22cde7ba572ddbf29336fdcdbbcd0a745f79dacd8","src/frames/wtframe.rs":"ad6dd63c54a0305c045cd983d5889ae86a5a1afe1e7c13e1c169de9af440759e","src/headers_checks.rs":"be0f0109298dcc3a40350b7c0950076ddfe20617d195b305e3ffc8582557ab18","src/lib.rs":"54e9f5e9d37dc9b6bd6d1390edd91b4041699035419bdf7d44f18173e6be51cb","src/priority.rs":"946307329f31819d969093406ae5448f7923343ccc112221ea6eedf86cf447dc","src/push_controller.rs":"53f72e8043505f85cba0f9c16b4a5ce14d6668b030d773067bc88b2a10bdd25b","src/qlog.rs":"db5f2dd6566d44b4f0541f75266b417b558c09e62141f056885cb8c66478a932","src/qpack_decoder_receiver.rs":"eb06c4be59da567fef70c20daa2c0f165c768131165479a210e69659f168b88f","src/qpack_encoder_receiver.rs":"831f3da9ec17966286786ba3f2c723395a132e65d6a33b4ec341fe7640c1a53d","src/recv_message.rs":"c3acf0544680f88ccd3500e6bea949c1bb43e2fb0a8922edc8f837d0166c89f8","src/request_target.rs":"9720b9f87d66a7c2301bba7de5a5a9300f547613a63153a4d35c7a7506a59b31","src/send_message.rs":"be4e9f64db2c25eb7176b84695e608e768115d62e615d389a33d26f7cd5b0c6c","src/server.rs":"ff1aa32155da19d37df1a9303abe0b0f641b6ff8ef45d76d7aab94eb78472475","src/server_connection_events.rs":"1396baab265a814045ccfe63d637a4fdc32a667b5eb2925fa4951f5c3078fb20","src/server_events.rs":"02fc8c0711efd758fb1ddee27d257c12ed35e2a989e7bf3de44bd662dc8234e3","src/settings.rs":"d0f8c546e70161422a029a40564b9e9b953fe671c60835196b16f3364779eaf9","src/stream_type_reader.rs":"89e1a625bc0b7d7ad9d9bd4d82ad1d330fe7f5115e2c4f4ee6790b20b2e9acec","tests/httpconn.rs":"b29f3b1f6214586c472b1302a5111fc9ae549161b7ef41cacece10c4837a3401","tests/priority.rs":"364754507873298612ad12e8d1d106d26d993712142d0be4cbf056da5338854c","tests/send_message.rs":"cdf7028eb64f8f3778c3bbb2a10e9482c4e995e9e1813143ccd83ec96b2d4b6a","tests/webtransport.rs":"02b81be0a20252a8bb0796b5287e426c1af5ddaf5a47d68aa9165393cba83c45"},"package":null}
|
||||
{"files":{"Cargo.toml":"d1a77c96f99b33741e667343b225c969c746e9e093173bea6514515398ae68ad","src/buffered_send_stream.rs":"dfb248c66ea65418b0c7798c2ecaa3ed70ef1af818ef58d53ef742b3445077b7","src/client_events.rs":"77fedca72ce54956eaba3fb7103085d196a631b764662584ea2629224c5c234e","src/conn_params.rs":"7f0df52bceda1923aef2b7c5c64a532f49ea083ea45e3dcd5bd4b03031b89643","src/connection.rs":"0d7b2e529839fe6c6f7bcb6117dc8734f0dc5cce1dfb3e2541c9710488e1b753","src/connection_client.rs":"8d6d1518bee62519911dd2571e97d463d9e05cb13ec55bc1cf6f6712c920972e","src/connection_server.rs":"02fda7595a33c57d0b3ccede51a1e7a8c9073e1ec107ca1b56c56f1728db2318","src/control_stream_local.rs":"20917762c7e7c1112c56abf1cbaf0ad7f0eab97d8db9a3b10ff524315a235670","src/control_stream_remote.rs":"3729f67aa0681b1dbd4147063890f8440f27d82454776500ae964a17cda4d6b5","src/features/extended_connect/mod.rs":"cbeb2294eaf34f08a2c0d0fe4d3473aea9c65df6faaec9dc3ed29dcb577b1c3f","src/features/extended_connect/tests/mod.rs":"fd6aee37243713e80fc526552f21f0222338cec9890409b6575a2a637b17ec1f","src/features/extended_connect/tests/webtransport/datagrams.rs":"51d6f3828c44b438eb1776e8dcce531af520f28bc0d715807d3f53a0eaa071d1","src/features/extended_connect/tests/webtransport/mod.rs":"27f77213414089148e94067bfc54133945a971fd7ddd6936bbfeabb9badc7e67","src/features/extended_connect/tests/webtransport/negotiation.rs":"a22094dbaf0754d39ac8ac08fce1ae34ace108220b696c7d618567df56cddeec","src/features/extended_connect/tests/webtransport/sessions.rs":"cf8aa14087cc3ff42657d86ecacbd51bc182357fdcbd10f57d32784abb415a12","src/features/extended_connect/tests/webtransport/streams.rs":"4c136855292d5ba5169f41c18beea13e7f1e014a0acb13c565c872d3a80d6377","src/features/extended_connect/webtransport_session.rs":"da0b99092d8af8d4f7699c8d45e2e4057f4de38d6fa99e27e3a7feffa569374f","src/features/extended_connect/webtransport_streams.rs":"9855d77705acb7d21566333c4b297816e363be2ade14b8685fd1df4a4861cf74","src/features/mod.rs":"89056df3a868cb0037963c942fc27093cc16d84538ffca2d4759f9a6a6c74c7f","src/frames/hframe.rs":"72349bf4e9dd5c57dc5443bb9aa079887e2742dc08d77ea55567e3b09e0de4d8","src/frames/mod.rs":"0e6d49888d723b2c2c73df11020ceb88d9f062e9d4dc436eb38173e0b772d905","src/frames/reader.rs":"8c7ea836a466410bd3c98848b4852945ae30e1306f73290c401c686998bde16d","src/frames/tests/hframe.rs":"53941fd7656f5e424d499278e6d9ba93ce716f219e86fe6fa08c058ea92f8d7b","src/frames/tests/mod.rs":"c6bbf85fbc6cb9adf6115d315f0564317eefd83ff3177c93050844ad77f6e694","src/frames/tests/reader.rs":"9ee0d9cdd87b98da2b94e577bbcc2bfde6d72be5177bf02364188935f79cb36a","src/frames/tests/wtframe.rs":"c6598d24f5e12972f02de6e1394362671633982db637a07e1c0bb9b56d93ea2a","src/frames/wtframe.rs":"ad6dd63c54a0305c045cd983d5889ae86a5a1afe1e7c13e1c169de9af440759e","src/headers_checks.rs":"69964deb121721be01df7174c177543c161389295ce1450d348369279e312ba4","src/lib.rs":"3fb980eee46bee8dcb97ad9d55014555d8994a7a2d040ca223f2d28fe7d923ef","src/priority.rs":"946307329f31819d969093406ae5448f7923343ccc112221ea6eedf86cf447dc","src/push_controller.rs":"53f72e8043505f85cba0f9c16b4a5ce14d6668b030d773067bc88b2a10bdd25b","src/qlog.rs":"db5f2dd6566d44b4f0541f75266b417b558c09e62141f056885cb8c66478a932","src/qpack_decoder_receiver.rs":"eb06c4be59da567fef70c20daa2c0f165c768131165479a210e69659f168b88f","src/qpack_encoder_receiver.rs":"831f3da9ec17966286786ba3f2c723395a132e65d6a33b4ec341fe7640c1a53d","src/recv_message.rs":"c3acf0544680f88ccd3500e6bea949c1bb43e2fb0a8922edc8f837d0166c89f8","src/request_target.rs":"9720b9f87d66a7c2301bba7de5a5a9300f547613a63153a4d35c7a7506a59b31","src/send_message.rs":"be4e9f64db2c25eb7176b84695e608e768115d62e615d389a33d26f7cd5b0c6c","src/server.rs":"8d48376abf36d036f51a84cddcc3d5acd56786b181fba0e24449e1417b030d63","src/server_connection_events.rs":"1396baab265a814045ccfe63d637a4fdc32a667b5eb2925fa4951f5c3078fb20","src/server_events.rs":"02fc8c0711efd758fb1ddee27d257c12ed35e2a989e7bf3de44bd662dc8234e3","src/settings.rs":"d0f8c546e70161422a029a40564b9e9b953fe671c60835196b16f3364779eaf9","src/stream_type_reader.rs":"0bc91ee4c2a516053cd2b55a60f9bd8e62008cde94274e281224cdffe352a907","tests/httpconn.rs":"87c32197258711d916cace23ed850c5bf0198f5e32756c68a32d91206b6e6db8","tests/priority.rs":"364754507873298612ad12e8d1d106d26d993712142d0be4cbf056da5338854c","tests/send_message.rs":"cdf7028eb64f8f3778c3bbb2a10e9482c4e995e9e1813143ccd83ec96b2d4b6a","tests/webtransport.rs":"02b81be0a20252a8bb0796b5287e426c1af5ddaf5a47d68aa9165393cba83c45"},"package":null}
|
|
@ -13,7 +13,7 @@
|
|||
edition = "2021"
|
||||
rust-version = "1.76.0"
|
||||
name = "neqo-http3"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
authors = ["The Neqo Authors <necko@mozilla.com>"]
|
||||
description = "Neqo, the Mozilla implementation of QUIC in Rust."
|
||||
homepage = "https://github.com/mozilla/neqo/"
|
||||
|
|
|
@ -467,7 +467,6 @@ impl Http3Connection {
|
|||
|
||||
/// The function calls `receive` for a stream. It also deals with the outcome of a read by
|
||||
/// calling `handle_stream_manipulation_output`.
|
||||
#[allow(clippy::option_if_let_else)] // False positive as borrow scope isn't lexical here.
|
||||
fn stream_receive(&mut self, conn: &mut Connection, stream_id: StreamId) -> Res<ReceiveOutput> {
|
||||
qtrace!([self], "Readable stream {}.", stream_id);
|
||||
|
||||
|
|
|
@ -2127,14 +2127,14 @@ mod tests {
|
|||
|
||||
// Client: Test receiving a new control stream and a SETTINGS frame.
|
||||
#[test]
|
||||
fn test_client_connect_and_exchange_qpack_and_control_streams() {
|
||||
fn client_connect_and_exchange_qpack_and_control_streams() {
|
||||
mem::drop(connect());
|
||||
}
|
||||
|
||||
// Client: Test that the connection will be closed if control stream
|
||||
// has been closed.
|
||||
#[test]
|
||||
fn test_client_close_control_stream() {
|
||||
fn client_close_control_stream() {
|
||||
let (mut client, mut server) = connect();
|
||||
server
|
||||
.conn
|
||||
|
@ -2148,7 +2148,7 @@ mod tests {
|
|||
// Client: Test that the connection will be closed if the local control stream
|
||||
// has been reset.
|
||||
#[test]
|
||||
fn test_client_reset_control_stream() {
|
||||
fn client_reset_control_stream() {
|
||||
let (mut client, mut server) = connect();
|
||||
server
|
||||
.conn
|
||||
|
@ -2162,7 +2162,7 @@ mod tests {
|
|||
// Client: Test that the connection will be closed if the server side encoder stream
|
||||
// has been reset.
|
||||
#[test]
|
||||
fn test_client_reset_server_side_encoder_stream() {
|
||||
fn client_reset_server_side_encoder_stream() {
|
||||
let (mut client, mut server) = connect();
|
||||
server
|
||||
.conn
|
||||
|
@ -2176,7 +2176,7 @@ mod tests {
|
|||
// Client: Test that the connection will be closed if the server side decoder stream
|
||||
// has been reset.
|
||||
#[test]
|
||||
fn test_client_reset_server_side_decoder_stream() {
|
||||
fn client_reset_server_side_decoder_stream() {
|
||||
let (mut client, mut server) = connect();
|
||||
server
|
||||
.conn
|
||||
|
@ -2190,7 +2190,7 @@ mod tests {
|
|||
// Client: Test that the connection will be closed if the local control stream
|
||||
// has received a stop_sending.
|
||||
#[test]
|
||||
fn test_client_stop_sending_control_stream() {
|
||||
fn client_stop_sending_control_stream() {
|
||||
let (mut client, mut server) = connect();
|
||||
server
|
||||
.conn
|
||||
|
@ -2204,7 +2204,7 @@ mod tests {
|
|||
// Client: Test that the connection will be closed if the client side encoder stream
|
||||
// has received a stop_sending.
|
||||
#[test]
|
||||
fn test_client_stop_sending_encoder_stream() {
|
||||
fn client_stop_sending_encoder_stream() {
|
||||
let (mut client, mut server) = connect();
|
||||
server
|
||||
.conn
|
||||
|
@ -2218,7 +2218,7 @@ mod tests {
|
|||
// Client: Test that the connection will be closed if the client side decoder stream
|
||||
// has received a stop_sending.
|
||||
#[test]
|
||||
fn test_client_stop_sending_decoder_stream() {
|
||||
fn client_stop_sending_decoder_stream() {
|
||||
let (mut client, mut server) = connect();
|
||||
server
|
||||
.conn
|
||||
|
@ -2232,7 +2232,7 @@ mod tests {
|
|||
// Client: test missing SETTINGS frame
|
||||
// (the first frame sent is a garbage frame).
|
||||
#[test]
|
||||
fn test_client_missing_settings() {
|
||||
fn client_missing_settings() {
|
||||
let (mut client, mut server) = connect_only_transport();
|
||||
// Create server control stream.
|
||||
let control_stream = server.conn.stream_create(StreamType::UniDi).unwrap();
|
||||
|
@ -2249,7 +2249,7 @@ mod tests {
|
|||
// Client: receiving SETTINGS frame twice causes connection close
|
||||
// with error HTTP_UNEXPECTED_FRAME.
|
||||
#[test]
|
||||
fn test_client_receive_settings_twice() {
|
||||
fn client_receive_settings_twice() {
|
||||
let (mut client, mut server) = connect();
|
||||
// send the second SETTINGS frame.
|
||||
let sent = server.conn.stream_send(
|
||||
|
@ -2279,30 +2279,30 @@ mod tests {
|
|||
|
||||
// send DATA frame on a cortrol stream
|
||||
#[test]
|
||||
fn test_data_frame_on_control_stream() {
|
||||
fn data_frame_on_control_stream() {
|
||||
test_wrong_frame_on_control_stream(&[0x0, 0x2, 0x1, 0x2]);
|
||||
}
|
||||
|
||||
// send HEADERS frame on a cortrol stream
|
||||
#[test]
|
||||
fn test_headers_frame_on_control_stream() {
|
||||
fn headers_frame_on_control_stream() {
|
||||
test_wrong_frame_on_control_stream(&[0x1, 0x2, 0x1, 0x2]);
|
||||
}
|
||||
|
||||
// send PUSH_PROMISE frame on a cortrol stream
|
||||
#[test]
|
||||
fn test_push_promise_frame_on_control_stream() {
|
||||
fn push_promise_frame_on_control_stream() {
|
||||
test_wrong_frame_on_control_stream(&[0x5, 0x2, 0x1, 0x2]);
|
||||
}
|
||||
|
||||
// send PRIORITY_UPDATE frame on a control stream to the client
|
||||
#[test]
|
||||
fn test_priority_update_request_on_control_stream() {
|
||||
fn priority_update_request_on_control_stream() {
|
||||
test_wrong_frame_on_control_stream(&[0x80, 0x0f, 0x07, 0x00, 0x01, 0x03]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_priority_update_push_on_control_stream() {
|
||||
fn priority_update_push_on_control_stream() {
|
||||
test_wrong_frame_on_control_stream(&[0x80, 0x0f, 0x07, 0x01, 0x01, 0x03]);
|
||||
}
|
||||
|
||||
|
@ -2328,50 +2328,50 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_cancel_push_frame_on_push_stream() {
|
||||
fn cancel_push_frame_on_push_stream() {
|
||||
test_wrong_frame_on_push_stream(&[0x3, 0x1, 0x5]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_settings_frame_on_push_stream() {
|
||||
fn settings_frame_on_push_stream() {
|
||||
test_wrong_frame_on_push_stream(&[0x4, 0x4, 0x6, 0x4, 0x8, 0x4]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_push_promise_frame_on_push_stream() {
|
||||
fn push_promise_frame_on_push_stream() {
|
||||
test_wrong_frame_on_push_stream(&[0x5, 0x2, 0x1, 0x2]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_priority_update_request_on_push_stream() {
|
||||
fn priority_update_request_on_push_stream() {
|
||||
test_wrong_frame_on_push_stream(&[0x80, 0x0f, 0x07, 0x00, 0x01, 0x03]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_priority_update_push_on_push_stream() {
|
||||
fn priority_update_push_on_push_stream() {
|
||||
test_wrong_frame_on_push_stream(&[0x80, 0x0f, 0x07, 0x01, 0x01, 0x03]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_goaway_frame_on_push_stream() {
|
||||
fn goaway_frame_on_push_stream() {
|
||||
test_wrong_frame_on_push_stream(&[0x7, 0x1, 0x5]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_max_push_id_frame_on_push_stream() {
|
||||
fn max_push_id_frame_on_push_stream() {
|
||||
test_wrong_frame_on_push_stream(&[0xd, 0x1, 0x5]);
|
||||
}
|
||||
|
||||
// send DATA frame before a header frame
|
||||
#[test]
|
||||
fn test_data_frame_on_push_stream() {
|
||||
fn data_frame_on_push_stream() {
|
||||
test_wrong_frame_on_push_stream(&[0x0, 0x2, 0x1, 0x2]);
|
||||
}
|
||||
|
||||
// Client: receive unknown stream type
|
||||
// This function also tests getting stream id that does not fit into a single byte.
|
||||
#[test]
|
||||
fn test_client_received_unknown_stream() {
|
||||
fn client_received_unknown_stream() {
|
||||
let (mut client, mut server) = connect();
|
||||
|
||||
// create a stream with unknown type.
|
||||
|
@ -2416,38 +2416,38 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_cancel_push_frame_on_request_stream() {
|
||||
fn cancel_push_frame_on_request_stream() {
|
||||
test_wrong_frame_on_request_stream(&[0x3, 0x1, 0x5]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_settings_frame_on_request_stream() {
|
||||
fn settings_frame_on_request_stream() {
|
||||
test_wrong_frame_on_request_stream(&[0x4, 0x4, 0x6, 0x4, 0x8, 0x4]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_goaway_frame_on_request_stream() {
|
||||
fn goaway_frame_on_request_stream() {
|
||||
test_wrong_frame_on_request_stream(&[0x7, 0x1, 0x5]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_max_push_id_frame_on_request_stream() {
|
||||
fn max_push_id_frame_on_request_stream() {
|
||||
test_wrong_frame_on_request_stream(&[0xd, 0x1, 0x5]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_priority_update_request_on_request_stream() {
|
||||
fn priority_update_request_on_request_stream() {
|
||||
test_wrong_frame_on_request_stream(&[0x80, 0x0f, 0x07, 0x00, 0x01, 0x03]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_priority_update_push_on_request_stream() {
|
||||
fn priority_update_push_on_request_stream() {
|
||||
test_wrong_frame_on_request_stream(&[0x80, 0x0f, 0x07, 0x01, 0x01, 0x03]);
|
||||
}
|
||||
|
||||
// Test reading of a slowly streamed frame. bytes are received one by one
|
||||
#[test]
|
||||
fn test_frame_reading() {
|
||||
fn frame_reading() {
|
||||
let (mut client, mut server) = connect_only_transport();
|
||||
|
||||
// create a control stream.
|
||||
|
@ -2801,7 +2801,6 @@ mod tests {
|
|||
|
||||
// Send 2 data frames so that the second one cannot fit into the send_buf and it is only
|
||||
// partialy sent. We check that the sent data is correct.
|
||||
#[allow(clippy::useless_vec)]
|
||||
fn fetch_with_two_data_frames(
|
||||
first_frame: &[u8],
|
||||
expected_first_data_frame_header: &[u8],
|
||||
|
@ -2952,7 +2951,7 @@ mod tests {
|
|||
|
||||
// Test receiving STOP_SENDING with the HttpNoError error code.
|
||||
#[test]
|
||||
fn test_stop_sending_early_response() {
|
||||
fn stop_sending_early_response() {
|
||||
// Connect exchange headers and send a request. Also check if the correct header frame has
|
||||
// been sent.
|
||||
let (mut client, mut server, request_stream_id) = connect_and_send_request(false);
|
||||
|
@ -3030,7 +3029,7 @@ mod tests {
|
|||
|
||||
// Server sends stop sending and reset.
|
||||
#[test]
|
||||
fn test_stop_sending_other_error_with_reset() {
|
||||
fn stop_sending_other_error_with_reset() {
|
||||
// Connect exchange headers and send a request. Also check if the correct header frame has
|
||||
// been sent.
|
||||
let (mut client, mut server, request_stream_id) = connect_and_send_request(false);
|
||||
|
@ -3094,7 +3093,7 @@ mod tests {
|
|||
|
||||
// Server sends stop sending with RequestRejected, but it does not send reset.
|
||||
#[test]
|
||||
fn test_stop_sending_other_error_wo_reset() {
|
||||
fn stop_sending_other_error_wo_reset() {
|
||||
// Connect exchange headers and send a request. Also check if the correct header frame has
|
||||
// been sent.
|
||||
let (mut client, mut server, request_stream_id) = connect_and_send_request(false);
|
||||
|
@ -3142,7 +3141,7 @@ mod tests {
|
|||
// Server sends stop sending and reset. We have some events for that stream already
|
||||
// in client.events. The events will be removed.
|
||||
#[test]
|
||||
fn test_stop_sending_and_reset_other_error_with_events() {
|
||||
fn stop_sending_and_reset_other_error_with_events() {
|
||||
// Connect exchange headers and send a request. Also check if the correct header frame has
|
||||
// been sent.
|
||||
let (mut client, mut server, request_stream_id) = connect_and_send_request(false);
|
||||
|
@ -3216,7 +3215,7 @@ mod tests {
|
|||
// We have some events for that stream already in the client.events.
|
||||
// The events will be removed.
|
||||
#[test]
|
||||
fn test_stop_sending_other_error_with_events() {
|
||||
fn stop_sending_other_error_with_events() {
|
||||
// Connect exchange headers and send a request. Also check if the correct header frame has
|
||||
// been sent.
|
||||
let (mut client, mut server, request_stream_id) = connect_and_send_request(false);
|
||||
|
@ -3280,7 +3279,7 @@ mod tests {
|
|||
|
||||
// Server sends a reset. We will close sending side as well.
|
||||
#[test]
|
||||
fn test_reset_wo_stop_sending() {
|
||||
fn reset_wo_stop_sending() {
|
||||
// Connect exchange headers and send a request. Also check if the correct header frame has
|
||||
// been sent.
|
||||
let (mut client, mut server, request_stream_id) = connect_and_send_request(false);
|
||||
|
@ -3357,24 +3356,24 @@ mod tests {
|
|||
|
||||
// Incomplete DATA frame
|
||||
#[test]
|
||||
fn test_incomplet_data_frame() {
|
||||
fn incomplet_data_frame() {
|
||||
test_incomplet_frame(&HTTP_RESPONSE_2[..12], &Error::HttpFrame);
|
||||
}
|
||||
|
||||
// Incomplete HEADERS frame
|
||||
#[test]
|
||||
fn test_incomplet_headers_frame() {
|
||||
fn incomplet_headers_frame() {
|
||||
test_incomplet_frame(&HTTP_RESPONSE_2[..7], &Error::HttpFrame);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_incomplet_unknown_frame() {
|
||||
fn incomplet_unknown_frame() {
|
||||
test_incomplet_frame(&[0x21], &Error::HttpFrame);
|
||||
}
|
||||
|
||||
// test goaway
|
||||
#[test]
|
||||
fn test_goaway() {
|
||||
fn goaway() {
|
||||
let (mut client, mut server) = connect();
|
||||
let request_stream_id_1 = make_request(&mut client, false, &[]);
|
||||
assert_eq!(request_stream_id_1, 0);
|
||||
|
@ -3596,7 +3595,7 @@ mod tests {
|
|||
|
||||
// Close stream before headers.
|
||||
#[test]
|
||||
fn test_stream_fin_wo_headers() {
|
||||
fn stream_fin_wo_headers() {
|
||||
let (mut client, mut server, request_stream_id) = connect_and_send_request(true);
|
||||
// send fin before sending any data.
|
||||
server.conn.stream_close_send(request_stream_id).unwrap();
|
||||
|
@ -3625,7 +3624,7 @@ mod tests {
|
|||
|
||||
// Close stream imemediately after headers.
|
||||
#[test]
|
||||
fn test_stream_fin_after_headers() {
|
||||
fn stream_fin_after_headers() {
|
||||
let (mut client, mut server, request_stream_id) = connect_and_send_request(true);
|
||||
|
||||
server_send_response_and_exchange_packet(
|
||||
|
@ -3664,7 +3663,7 @@ mod tests {
|
|||
// Send headers, read headers and than close stream.
|
||||
// We should get HeaderReady and a DataReadable
|
||||
#[test]
|
||||
fn test_stream_fin_after_headers_are_read_wo_data_frame() {
|
||||
fn stream_fin_after_headers_are_read_wo_data_frame() {
|
||||
let (mut client, mut server, request_stream_id) = connect_and_send_request(true);
|
||||
// Send some good data wo fin
|
||||
server_send_response_and_exchange_packet(
|
||||
|
@ -3730,7 +3729,7 @@ mod tests {
|
|||
|
||||
// Send headers and an empty data frame, then close the stream.
|
||||
#[test]
|
||||
fn test_stream_fin_after_headers_and_a_empty_data_frame() {
|
||||
fn stream_fin_after_headers_and_a_empty_data_frame() {
|
||||
let (mut client, mut server, request_stream_id) = connect_and_send_request(true);
|
||||
|
||||
// Send headers.
|
||||
|
@ -3783,7 +3782,7 @@ mod tests {
|
|||
// Send headers and an empty data frame. Read headers and then close the stream.
|
||||
// We should get a HeaderReady without fin and a DataReadable wo data and with fin.
|
||||
#[test]
|
||||
fn test_stream_fin_after_headers_an_empty_data_frame_are_read() {
|
||||
fn stream_fin_after_headers_an_empty_data_frame_are_read() {
|
||||
let (mut client, mut server, request_stream_id) = connect_and_send_request(true);
|
||||
// Send some good data wo fin
|
||||
// Send headers.
|
||||
|
@ -3854,7 +3853,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_stream_fin_after_a_data_frame() {
|
||||
fn stream_fin_after_a_data_frame() {
|
||||
let (mut client, mut server, request_stream_id) = connect_and_send_request(true);
|
||||
// Send some good data wo fin
|
||||
server_send_response_and_exchange_packet(
|
||||
|
@ -3919,7 +3918,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiple_data_frames() {
|
||||
fn multiple_data_frames() {
|
||||
let (mut client, mut server, request_stream_id) = connect_and_send_request(true);
|
||||
|
||||
// Send two data frames with fin
|
||||
|
@ -3955,7 +3954,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_receive_grease_before_response() {
|
||||
fn receive_grease_before_response() {
|
||||
// Construct an unknown frame.
|
||||
const UNKNOWN_FRAME_LEN: usize = 832;
|
||||
|
||||
|
@ -4000,7 +3999,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_frames_header_blocked() {
|
||||
fn read_frames_header_blocked() {
|
||||
let (mut client, mut server, request_stream_id) = connect_and_send_request(true);
|
||||
|
||||
setup_server_side_encoder(&mut client, &mut server);
|
||||
|
@ -4069,7 +4068,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_frames_header_blocked_with_fin_after_headers() {
|
||||
fn read_frames_header_blocked_with_fin_after_headers() {
|
||||
let (mut hconn, mut server, request_stream_id) = connect_and_send_request(true);
|
||||
|
||||
setup_server_side_encoder(&mut hconn, &mut server);
|
||||
|
@ -4632,7 +4631,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_trailers_with_fin_after_headers() {
|
||||
fn trailers_with_fin_after_headers() {
|
||||
// Make a new connection.
|
||||
let (mut client, mut server, request_stream_id) = connect_and_send_request(true);
|
||||
|
||||
|
@ -4693,7 +4692,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_trailers_with_later_fin_after_headers() {
|
||||
fn trailers_with_later_fin_after_headers() {
|
||||
// Make a new connection.
|
||||
let (mut client, mut server, request_stream_id) = connect_and_send_request(true);
|
||||
|
||||
|
@ -4763,7 +4762,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_data_after_trailers_after_headers() {
|
||||
fn data_after_trailers_after_headers() {
|
||||
// Make a new connection.
|
||||
let (mut client, mut server, request_stream_id) = connect_and_send_request(true);
|
||||
|
||||
|
@ -5557,7 +5556,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_max_push_id_frame_update_is_sent() {
|
||||
fn max_push_id_frame_update_is_sent() {
|
||||
const MAX_PUSH_ID_FRAME: &[u8] = &[0xd, 0x1, 0x8];
|
||||
|
||||
// Connect and send a request
|
||||
|
|
|
@ -63,7 +63,6 @@ impl RecvStream for ControlStreamRemote {
|
|||
Err(Error::HttpClosedCriticalStream)
|
||||
}
|
||||
|
||||
#[allow(clippy::vec_init_then_push)] // Clippy fail.
|
||||
fn receive(&mut self, conn: &mut Connection) -> Res<(ReceiveOutput, bool)> {
|
||||
let mut control_frames = Vec::new();
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(clippy::module_name_repetitions)]
|
||||
|
||||
pub(crate) mod webtransport_session;
|
||||
pub(crate) mod webtransport_streams;
|
||||
|
||||
|
|
|
@ -16,13 +16,13 @@ use crate::{
|
|||
};
|
||||
|
||||
#[test]
|
||||
fn test_data_frame() {
|
||||
fn data_frame() {
|
||||
let f = HFrame::Data { len: 3 };
|
||||
enc_dec_hframe(&f, "0003010203", 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_headers_frame() {
|
||||
fn headers_frame() {
|
||||
let f = HFrame::Headers {
|
||||
header_block: vec![0x01, 0x02, 0x03],
|
||||
};
|
||||
|
@ -30,13 +30,13 @@ fn test_headers_frame() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_cancel_push_frame4() {
|
||||
fn cancel_push_frame4() {
|
||||
let f = HFrame::CancelPush { push_id: 5 };
|
||||
enc_dec_hframe(&f, "030105", 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_settings_frame4() {
|
||||
fn settings_frame4() {
|
||||
let f = HFrame::Settings {
|
||||
settings: HSettings::new(&[HSetting::new(HSettingType::MaxHeaderListSize, 4)]),
|
||||
};
|
||||
|
@ -44,7 +44,7 @@ fn test_settings_frame4() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_push_promise_frame4() {
|
||||
fn push_promise_frame4() {
|
||||
let f = HFrame::PushPromise {
|
||||
push_id: 4,
|
||||
header_block: vec![0x61, 0x62, 0x63, 0x64],
|
||||
|
@ -53,7 +53,7 @@ fn test_push_promise_frame4() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_goaway_frame4() {
|
||||
fn goaway_frame4() {
|
||||
let f = HFrame::Goaway {
|
||||
stream_id: StreamId::new(5),
|
||||
};
|
||||
|
@ -80,7 +80,7 @@ fn grease() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_priority_update_request_default() {
|
||||
fn priority_update_request_default() {
|
||||
let f = HFrame::PriorityUpdateRequest {
|
||||
element_id: 6,
|
||||
priority: Priority::default(),
|
||||
|
@ -89,7 +89,7 @@ fn test_priority_update_request_default() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_priority_update_request_incremental_default() {
|
||||
fn priority_update_request_incremental_default() {
|
||||
let f = HFrame::PriorityUpdateRequest {
|
||||
element_id: 7,
|
||||
priority: Priority::new(6, false),
|
||||
|
@ -98,7 +98,7 @@ fn test_priority_update_request_incremental_default() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_priority_update_request_urgency_default() {
|
||||
fn priority_update_request_urgency_default() {
|
||||
let f = HFrame::PriorityUpdateRequest {
|
||||
element_id: 8,
|
||||
priority: Priority::new(3, true),
|
||||
|
@ -107,7 +107,7 @@ fn test_priority_update_request_urgency_default() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_priority_update_push_default() {
|
||||
fn priority_update_push_default() {
|
||||
let f = HFrame::PriorityUpdatePush {
|
||||
element_id: 10,
|
||||
priority: Priority::default(),
|
||||
|
|
|
@ -15,7 +15,6 @@ use crate::frames::{
|
|||
reader::FrameDecoder, FrameReader, HFrame, StreamReaderConnectionWrapper, WebTransportFrame,
|
||||
};
|
||||
|
||||
#[allow(clippy::many_single_char_names)]
|
||||
pub fn enc_dec<T: FrameDecoder<T>>(d: &Encoder, st: &str, remaining: usize) -> T {
|
||||
// For data, headers and push_promise we do not read all bytes from the buffer
|
||||
let d2 = Encoder::from_hex(st);
|
||||
|
|
|
@ -55,7 +55,7 @@ impl FrameReaderTest {
|
|||
|
||||
// Test receiving byte by byte for a SETTINGS frame.
|
||||
#[test]
|
||||
fn test_frame_reading_with_stream_settings1() {
|
||||
fn frame_reading_with_stream_settings1() {
|
||||
let mut fr = FrameReaderTest::new();
|
||||
|
||||
// Send and read settings frame 040406040804
|
||||
|
@ -77,7 +77,7 @@ fn test_frame_reading_with_stream_settings1() {
|
|||
|
||||
// Test receiving byte by byte for a SETTINGS frame with larger varints
|
||||
#[test]
|
||||
fn test_frame_reading_with_stream_settings2() {
|
||||
fn frame_reading_with_stream_settings2() {
|
||||
let mut fr = FrameReaderTest::new();
|
||||
|
||||
// Read settings frame 400406064004084100
|
||||
|
@ -97,7 +97,7 @@ fn test_frame_reading_with_stream_settings2() {
|
|||
|
||||
// Test receiving byte by byte for a PUSH_PROMISE frame.
|
||||
#[test]
|
||||
fn test_frame_reading_with_stream_push_promise() {
|
||||
fn frame_reading_with_stream_push_promise() {
|
||||
let mut fr = FrameReaderTest::new();
|
||||
|
||||
// Read push-promise frame 05054101010203
|
||||
|
@ -121,7 +121,7 @@ fn test_frame_reading_with_stream_push_promise() {
|
|||
|
||||
// Test DATA
|
||||
#[test]
|
||||
fn test_frame_reading_with_stream_data() {
|
||||
fn frame_reading_with_stream_data() {
|
||||
let mut fr = FrameReaderTest::new();
|
||||
|
||||
// Read data frame 0003010203
|
||||
|
@ -137,7 +137,7 @@ fn test_frame_reading_with_stream_data() {
|
|||
|
||||
// Test an unknown frame
|
||||
#[test]
|
||||
fn test_unknown_frame() {
|
||||
fn unknown_frame() {
|
||||
// Construct an unknown frame.
|
||||
const UNKNOWN_FRAME_LEN: usize = 832;
|
||||
|
||||
|
@ -162,7 +162,7 @@ fn test_unknown_frame() {
|
|||
|
||||
// Test receiving byte by byte for a WT_FRAME_CLOSE_SESSION frame.
|
||||
#[test]
|
||||
fn test_frame_reading_with_stream_wt_close_session() {
|
||||
fn frame_reading_with_stream_wt_close_session() {
|
||||
let mut fr = FrameReaderTest::new();
|
||||
|
||||
// Read CloseSession frame 6843090000000548656c6c6f
|
||||
|
@ -181,7 +181,7 @@ fn test_frame_reading_with_stream_wt_close_session() {
|
|||
|
||||
// Test an unknown frame for WebTransportFrames.
|
||||
#[test]
|
||||
fn test_unknown_wt_frame() {
|
||||
fn unknown_wt_frame() {
|
||||
// Construct an unknown frame.
|
||||
const UNKNOWN_FRAME_LEN: usize = 832;
|
||||
|
||||
|
@ -268,7 +268,7 @@ fn test_reading_frame<T: FrameDecoder<T> + PartialEq + Debug>(
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_complete_and_incomplete_unknown_frame() {
|
||||
fn complete_and_incomplete_unknown_frame() {
|
||||
// Construct an unknown frame.
|
||||
const UNKNOWN_FRAME_LEN: usize = 832;
|
||||
let mut enc = Encoder::with_capacity(UNKNOWN_FRAME_LEN + 4);
|
||||
|
@ -377,7 +377,7 @@ fn test_complete_and_incomplete_frame<T: FrameDecoder<T> + PartialEq + Debug>(
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_complete_and_incomplete_frames() {
|
||||
fn complete_and_incomplete_frames() {
|
||||
const FRAME_LEN: usize = 10;
|
||||
const HEADER_BLOCK: &[u8] = &[0x01, 0x02, 0x03, 0x04];
|
||||
|
||||
|
@ -460,7 +460,7 @@ fn test_complete_and_incomplete_frames() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_complete_and_incomplete_wt_frames() {
|
||||
fn complete_and_incomplete_wt_frames() {
|
||||
// H3_FRAME_TYPE_MAX_PUSH_ID
|
||||
let f = WebTransportFrame::CloseSession {
|
||||
error: 5,
|
||||
|
@ -474,7 +474,7 @@ fn test_complete_and_incomplete_wt_frames() {
|
|||
|
||||
// Test closing a stream before any frame is sent should not cause an error.
|
||||
#[test]
|
||||
fn test_frame_reading_when_stream_is_closed_before_sending_data() {
|
||||
fn frame_reading_when_stream_is_closed_before_sending_data() {
|
||||
let mut fr = FrameReaderTest::new();
|
||||
|
||||
fr.conn_s.stream_send(fr.stream_id, &[0x00]).unwrap();
|
||||
|
@ -497,7 +497,7 @@ fn test_frame_reading_when_stream_is_closed_before_sending_data() {
|
|||
// Test closing a stream before any frame is sent should not cause an error.
|
||||
// This is the same as the previous just for WebTransportFrame.
|
||||
#[test]
|
||||
fn test_wt_frame_reading_when_stream_is_closed_before_sending_data() {
|
||||
fn wt_frame_reading_when_stream_is_closed_before_sending_data() {
|
||||
let mut fr = FrameReaderTest::new();
|
||||
|
||||
fr.conn_s.stream_send(fr.stream_id, &[0x00]).unwrap();
|
||||
|
|
|
@ -8,7 +8,7 @@ use super::enc_dec_wtframe;
|
|||
use crate::frames::WebTransportFrame;
|
||||
|
||||
#[test]
|
||||
fn test_wt_close_session() {
|
||||
fn wt_close_session() {
|
||||
let f = WebTransportFrame::CloseSession {
|
||||
error: 5,
|
||||
message: "Hello".to_string(),
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(clippy::unused_unit)] // see https://github.com/Lymia/enumset/issues/44
|
||||
|
||||
use enumset::{enum_set, EnumSet, EnumSetType};
|
||||
use neqo_common::Header;
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(clippy::module_name_repetitions)] // This lint doesn't work here.
|
||||
|
||||
/*!
|
||||
|
||||
# The HTTP/3 protocol
|
||||
|
|
|
@ -500,7 +500,7 @@ mod tests {
|
|||
// Test http3 connection inintialization.
|
||||
// The server will open the control and qpack streams and send SETTINGS frame.
|
||||
#[test]
|
||||
fn test_server_connect() {
|
||||
fn server_connect() {
|
||||
mem::drop(connect_and_receive_settings());
|
||||
}
|
||||
|
||||
|
@ -573,14 +573,14 @@ mod tests {
|
|||
|
||||
// Server: Test receiving a new control stream and a SETTINGS frame.
|
||||
#[test]
|
||||
fn test_server_receive_control_frame() {
|
||||
fn server_receive_control_frame() {
|
||||
mem::drop(connect());
|
||||
}
|
||||
|
||||
// Server: Test that the connection will be closed if control stream
|
||||
// has been closed.
|
||||
#[test]
|
||||
fn test_server_close_control_stream() {
|
||||
fn server_close_control_stream() {
|
||||
let (mut hconn, mut peer_conn) = connect();
|
||||
let control = peer_conn.control_stream_id;
|
||||
peer_conn.stream_close_send(control).unwrap();
|
||||
|
@ -592,7 +592,7 @@ mod tests {
|
|||
// Server: test missing SETTINGS frame
|
||||
// (the first frame sent is a MAX_PUSH_ID frame).
|
||||
#[test]
|
||||
fn test_server_missing_settings() {
|
||||
fn server_missing_settings() {
|
||||
let (mut hconn, mut neqo_trans_conn) = connect_and_receive_settings();
|
||||
// Create client control stream.
|
||||
let control_stream = neqo_trans_conn.stream_create(StreamType::UniDi).unwrap();
|
||||
|
@ -607,7 +607,7 @@ mod tests {
|
|||
// Server: receiving SETTINGS frame twice causes connection close
|
||||
// with error HTTP_UNEXPECTED_FRAME.
|
||||
#[test]
|
||||
fn test_server_receive_settings_twice() {
|
||||
fn server_receive_settings_twice() {
|
||||
let (mut hconn, mut peer_conn) = connect();
|
||||
// send the second SETTINGS frame.
|
||||
peer_conn.control_send(&[0x4, 0x6, 0x1, 0x40, 0x64, 0x7, 0x40, 0x64]);
|
||||
|
@ -637,28 +637,28 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_priority_update_valid_id_0() {
|
||||
fn priority_update_valid_id_0() {
|
||||
// Client-Initiated, Bidirectional
|
||||
priority_update_check_id(StreamId::new(0), true);
|
||||
}
|
||||
#[test]
|
||||
fn test_priority_update_invalid_id_1() {
|
||||
fn priority_update_invalid_id_1() {
|
||||
// Server-Initiated, Bidirectional
|
||||
priority_update_check_id(StreamId::new(1), false);
|
||||
}
|
||||
#[test]
|
||||
fn test_priority_update_invalid_id_2() {
|
||||
fn priority_update_invalid_id_2() {
|
||||
// Client-Initiated, Unidirectional
|
||||
priority_update_check_id(StreamId::new(2), false);
|
||||
}
|
||||
#[test]
|
||||
fn test_priority_update_invalid_id_3() {
|
||||
fn priority_update_invalid_id_3() {
|
||||
// Server-Initiated, Unidirectional
|
||||
priority_update_check_id(StreamId::new(3), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_priority_update_invalid_large_id() {
|
||||
fn priority_update_invalid_large_id() {
|
||||
// Server-Initiated, Unidirectional (divisible by 4)
|
||||
priority_update_check_id(StreamId::new(1_000_000_000), false);
|
||||
}
|
||||
|
@ -676,26 +676,26 @@ mod tests {
|
|||
|
||||
// send DATA frame on a control stream
|
||||
#[test]
|
||||
fn test_server_data_frame_on_control_stream() {
|
||||
fn server_data_frame_on_control_stream() {
|
||||
test_wrong_frame_on_control_stream(&[0x0, 0x2, 0x1, 0x2]);
|
||||
}
|
||||
|
||||
// send HEADERS frame on a cortrol stream
|
||||
#[test]
|
||||
fn test_server_headers_frame_on_control_stream() {
|
||||
fn server_headers_frame_on_control_stream() {
|
||||
test_wrong_frame_on_control_stream(&[0x1, 0x2, 0x1, 0x2]);
|
||||
}
|
||||
|
||||
// send PUSH_PROMISE frame on a cortrol stream
|
||||
#[test]
|
||||
fn test_server_push_promise_frame_on_control_stream() {
|
||||
fn server_push_promise_frame_on_control_stream() {
|
||||
test_wrong_frame_on_control_stream(&[0x5, 0x2, 0x1, 0x2]);
|
||||
}
|
||||
|
||||
// Server: receive unknown stream type
|
||||
// also test getting stream id that does not fit into a single byte.
|
||||
#[test]
|
||||
fn test_server_received_unknown_stream() {
|
||||
fn server_received_unknown_stream() {
|
||||
let (mut hconn, mut peer_conn) = connect();
|
||||
|
||||
// create a stream with unknown type.
|
||||
|
@ -728,7 +728,7 @@ mod tests {
|
|||
|
||||
// Server: receiving a push stream on a server should cause WrongStreamDirection
|
||||
#[test]
|
||||
fn test_server_received_push_stream() {
|
||||
fn server_received_push_stream() {
|
||||
let (mut hconn, mut peer_conn) = connect();
|
||||
|
||||
// create a push stream.
|
||||
|
@ -742,7 +742,7 @@ mod tests {
|
|||
|
||||
/// Test reading of a slowly streamed frame. bytes are received one by one
|
||||
#[test]
|
||||
fn test_server_frame_reading() {
|
||||
fn server_frame_reading() {
|
||||
let (mut hconn, mut peer_conn) = connect_and_receive_settings();
|
||||
|
||||
// create a control stream.
|
||||
|
@ -865,23 +865,23 @@ mod tests {
|
|||
|
||||
// Incomplete DATA frame
|
||||
#[test]
|
||||
fn test_server_incomplete_data_frame() {
|
||||
fn server_incomplete_data_frame() {
|
||||
test_incomplete_frame(&REQUEST_WITH_BODY[..22]);
|
||||
}
|
||||
|
||||
// Incomplete HEADERS frame
|
||||
#[test]
|
||||
fn test_server_incomplete_headers_frame() {
|
||||
fn server_incomplete_headers_frame() {
|
||||
test_incomplete_frame(&REQUEST_WITH_BODY[..10]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_server_incomplete_unknown_frame() {
|
||||
fn server_incomplete_unknown_frame() {
|
||||
test_incomplete_frame(&[0x21]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_server_request_with_body() {
|
||||
fn server_request_with_body() {
|
||||
let (mut hconn, mut peer_conn) = connect();
|
||||
|
||||
let stream_id = peer_conn.stream_create(StreamType::BiDi).unwrap();
|
||||
|
@ -926,7 +926,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_server_request_with_body_send_stop_sending() {
|
||||
fn server_request_with_body_send_stop_sending() {
|
||||
let (mut hconn, mut peer_conn) = connect();
|
||||
|
||||
let stream_id = peer_conn.stream_create(StreamType::BiDi).unwrap();
|
||||
|
@ -1003,7 +1003,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_server_request_with_body_server_reset() {
|
||||
fn server_request_with_body_server_reset() {
|
||||
let (mut hconn, mut peer_conn) = connect();
|
||||
|
||||
let request_stream_id = peer_conn.stream_create(StreamType::BiDi).unwrap();
|
||||
|
@ -1072,7 +1072,7 @@ mod tests {
|
|||
// Server: Test that the connection will be closed if the local control stream
|
||||
// has been reset.
|
||||
#[test]
|
||||
fn test_server_reset_control_stream() {
|
||||
fn server_reset_control_stream() {
|
||||
let (mut hconn, mut peer_conn) = connect();
|
||||
peer_conn
|
||||
.stream_reset_send(CLIENT_SIDE_CONTROL_STREAM_ID, Error::HttpNoError.code())
|
||||
|
@ -1085,7 +1085,7 @@ mod tests {
|
|||
// Server: Test that the connection will be closed if the client side encoder stream
|
||||
// has been reset.
|
||||
#[test]
|
||||
fn test_server_reset_client_side_encoder_stream() {
|
||||
fn server_reset_client_side_encoder_stream() {
|
||||
let (mut hconn, mut peer_conn) = connect();
|
||||
peer_conn
|
||||
.stream_reset_send(CLIENT_SIDE_ENCODER_STREAM_ID, Error::HttpNoError.code())
|
||||
|
@ -1098,7 +1098,7 @@ mod tests {
|
|||
// Server: Test that the connection will be closed if the client side decoder stream
|
||||
// has been reset.
|
||||
#[test]
|
||||
fn test_server_reset_client_side_decoder_stream() {
|
||||
fn server_reset_client_side_decoder_stream() {
|
||||
let (mut hconn, mut peer_conn) = connect();
|
||||
peer_conn
|
||||
.stream_reset_send(CLIENT_SIDE_DECODER_STREAM_ID, Error::HttpNoError.code())
|
||||
|
@ -1111,7 +1111,7 @@ mod tests {
|
|||
// Server: Test that the connection will be closed if the local control stream
|
||||
// has received a stop_sending.
|
||||
#[test]
|
||||
fn test_client_stop_sending_control_stream() {
|
||||
fn client_stop_sending_control_stream() {
|
||||
let (mut hconn, mut peer_conn) = connect();
|
||||
|
||||
peer_conn
|
||||
|
@ -1125,7 +1125,7 @@ mod tests {
|
|||
// Server: Test that the connection will be closed if the server side encoder stream
|
||||
// has received a stop_sending.
|
||||
#[test]
|
||||
fn test_server_stop_sending_encoder_stream() {
|
||||
fn server_stop_sending_encoder_stream() {
|
||||
let (mut hconn, mut peer_conn) = connect();
|
||||
peer_conn
|
||||
.stream_stop_sending(SERVER_SIDE_ENCODER_STREAM_ID, Error::HttpNoError.code())
|
||||
|
@ -1138,7 +1138,7 @@ mod tests {
|
|||
// Server: Test that the connection will be closed if the server side decoder stream
|
||||
// has received a stop_sending.
|
||||
#[test]
|
||||
fn test_server_stop_sending_decoder_stream() {
|
||||
fn server_stop_sending_decoder_stream() {
|
||||
let (mut hconn, mut peer_conn) = connect();
|
||||
peer_conn
|
||||
.stream_stop_sending(SERVER_SIDE_DECODER_STREAM_ID, Error::HttpNoError.code())
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(clippy::module_name_repetitions)]
|
||||
|
||||
use neqo_common::{qtrace, Decoder, IncrementalDecoderUint, Role};
|
||||
use neqo_qpack::{decoder::QPACK_UNI_STREAM_TYPE_DECODER, encoder::QPACK_UNI_STREAM_TYPE_ENCODER};
|
||||
use neqo_transport::{Connection, StreamId, StreamType};
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(unused_assignments)]
|
||||
|
||||
use std::{
|
||||
mem,
|
||||
time::{Duration, Instant},
|
||||
|
@ -168,12 +166,12 @@ fn exchange_packets(client: &mut Http3Client, server: &mut Http3Server, out_ex:
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_connect() {
|
||||
fn simple_connect() {
|
||||
let (_hconn_c, _hconn_s, _d) = connect();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fetch() {
|
||||
fn fetch() {
|
||||
let (mut hconn_c, mut hconn_s, dgram) = connect();
|
||||
|
||||
qtrace!("-----client");
|
||||
|
@ -203,7 +201,7 @@ fn test_fetch() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_103_response() {
|
||||
fn response_103() {
|
||||
let (mut hconn_c, mut hconn_s, dgram) = connect();
|
||||
|
||||
let req = hconn_c
|
||||
|
@ -249,7 +247,7 @@ fn test_103_response() {
|
|||
/// [`neqo_transport::SendStream::set_writable_event_low_watermark`].
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
#[test]
|
||||
fn test_data_writable_events_low_watermark() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn data_writable_events_low_watermark() -> Result<(), Box<dyn std::error::Error>> {
|
||||
const STREAM_LIMIT: u64 = 5000;
|
||||
const DATA_FRAME_HEADER_SIZE: usize = 3;
|
||||
|
||||
|
@ -323,7 +321,7 @@ fn test_data_writable_events_low_watermark() -> Result<(), Box<dyn std::error::E
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_data_writable_events() {
|
||||
fn data_writable_events() {
|
||||
const STREAM_LIMIT: u64 = 5000;
|
||||
const DATA_AMOUNT: usize = 10000;
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"5179aa8414e078471cfdc7318b7bb36161fef0f74939b7b871f7e451b18e772c","src/decoder.rs":"510f1b597e1b1a05aa8e835ca6cfa8ae8450cc81ea947edf3ee5568c378ee797","src/decoder_instructions.rs":"87cabf7b19e7c66736fb38b5c037d21d1b3c14a816f1a663c523a679cff1ef82","src/encoder.rs":"4453eca4dbdcf21e8b8c847c86ba1dc3455985d461efa024319da39719cde6be","src/encoder_instructions.rs":"e4bae7510f5bea691e8089581d26128a34b733a85d4277d9eb47f16838a01b5e","src/header_block.rs":"b89c508d85622716f9b82b951767c70b0ff1bda21aaeb66f9b4a59e2252ba9af","src/huffman.rs":"4bafbcb6db099e6c18c480d4d5eb98669957aed2102c4f1bdf8f0e928c723e65","src/huffman_decode_helper.rs":"9ce470e318b3664f58aa109bed483ab15bfd9e0b17d261ea2b609668a42a9d80","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"f9bad0fe7643c618d034c4941ebd30ad5f6015b8b87b484b0ea79681d13d8b49","src/prefix.rs":"5ef50ae0cef68097a3061c9c38fb264e7a14a5658d35591687d1165a4219bc18","src/qlog.rs":"fbd96ef7d21db2bae19b8e379995544e8cf123e8e5129c1500ace2773acf5649","src/qpack_send_buf.rs":"e207e464b3063421b984ffb7eb4c7f90142e763e5f8c7e0d5aa1bd3614e9d6bd","src/reader.rs":"c23214ba190c7a59e416eaffac612ff8c2043c3a84e884fb10ae3bc112d884a5","src/static_table.rs":"6e5ec26e2b6bd63375d2d77e72748151d430d1629a8e497ec0d0ea21c078524a","src/stats.rs":"624dfa3b40858c304097bb0ce5b1be1bb4d7916b1abfc222f1aa705907009730","src/table.rs":"2d2c9e6070a1e90048a4ad7c8279f9e1ce7615b44d7d8145fb0f140e554f5ca2"},"package":null}
|
||||
{"files":{"Cargo.toml":"1eb162284c8ff5989adbd8dc2cb5e740163af130288c09471406549861b67703","src/decoder.rs":"ed2d6fa29e8726429aabb84e65f5d8025b320c0219b442b47c38903728ba3b2d","src/decoder_instructions.rs":"7e23ad00bcc6a1f0ee9af6c3d7f5ec5fcf11e9bc6cd895e125e3392c34b309e0","src/encoder.rs":"ebc9e82e5ad6b31be46ab876965d0e9dc710c4c5db084a631f384185b56cab36","src/encoder_instructions.rs":"5afc60ecc5b65f5b1908cff7eb3b7394c5c36cebe8ebfcdefbf792c827799390","src/header_block.rs":"1ea71fe2f588a0f96e39fd3a3157c66cc0ed2794f14c6f01b4a3069a43f7997b","src/huffman.rs":"6976f1b4d3e5ef849a6b080cfb2e8804bf01cfe3b9bd9e3994a319d5405cd8f3","src/huffman_decode_helper.rs":"9ce470e318b3664f58aa109bed483ab15bfd9e0b17d261ea2b609668a42a9d80","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"f9bad0fe7643c618d034c4941ebd30ad5f6015b8b87b484b0ea79681d13d8b49","src/prefix.rs":"d9ad12838d61b38dc2300948e3da01fd65371215edde1c370cf54ccd87d64d46","src/qlog.rs":"fbd96ef7d21db2bae19b8e379995544e8cf123e8e5129c1500ace2773acf5649","src/qpack_send_buf.rs":"48f8d0e011e0fb8e4bd0774279d3465e2be01fd9480eaf374ae2adada6be430d","src/reader.rs":"c23214ba190c7a59e416eaffac612ff8c2043c3a84e884fb10ae3bc112d884a5","src/static_table.rs":"6e5ec26e2b6bd63375d2d77e72748151d430d1629a8e497ec0d0ea21c078524a","src/stats.rs":"624dfa3b40858c304097bb0ce5b1be1bb4d7916b1abfc222f1aa705907009730","src/table.rs":"2d2c9e6070a1e90048a4ad7c8279f9e1ce7615b44d7d8145fb0f140e554f5ca2"},"package":null}
|
|
@ -13,7 +13,7 @@
|
|||
edition = "2021"
|
||||
rust-version = "1.76.0"
|
||||
name = "neqo-qpack"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
authors = ["The Neqo Authors <necko@mozilla.com>"]
|
||||
description = "Neqo, the Mozilla implementation of QUIC in Rust."
|
||||
homepage = "https://github.com/mozilla/neqo/"
|
||||
|
|
|
@ -396,7 +396,7 @@ mod tests {
|
|||
|
||||
// test insert_with_name_ref which fails because there is not enough space in the table
|
||||
#[test]
|
||||
fn test_recv_insert_with_name_ref_1() {
|
||||
fn recv_insert_with_name_ref_1() {
|
||||
test_instruction(
|
||||
0,
|
||||
&[0xc4, 0x04, 0x31, 0x32, 0x33, 0x34],
|
||||
|
@ -408,7 +408,7 @@ mod tests {
|
|||
|
||||
// test insert_name_ref that succeeds
|
||||
#[test]
|
||||
fn test_recv_insert_with_name_ref_2() {
|
||||
fn recv_insert_with_name_ref_2() {
|
||||
test_instruction(
|
||||
100,
|
||||
&[0xc4, 0x04, 0x31, 0x32, 0x33, 0x34],
|
||||
|
@ -420,7 +420,7 @@ mod tests {
|
|||
|
||||
// test insert with name literal - succeeds
|
||||
#[test]
|
||||
fn test_recv_insert_with_name_litarel_2() {
|
||||
fn recv_insert_with_name_litarel_2() {
|
||||
test_instruction(
|
||||
200,
|
||||
&[
|
||||
|
@ -434,12 +434,12 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_recv_change_capacity() {
|
||||
fn recv_change_capacity() {
|
||||
test_instruction(0, &[0x3f, 0xa9, 0x01], &Ok(()), &[0x03], 200);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_recv_change_capacity_too_big() {
|
||||
fn recv_change_capacity_too_big() {
|
||||
test_instruction(
|
||||
0,
|
||||
&[0x3f, 0xf1, 0x02],
|
||||
|
@ -452,7 +452,7 @@ mod tests {
|
|||
// this test tests header decoding, the header acks command and the insert count increment
|
||||
// command.
|
||||
#[test]
|
||||
fn test_duplicate() {
|
||||
fn duplicate() {
|
||||
let mut decoder = connect();
|
||||
|
||||
assert!(decoder.decoder.set_capacity(100).is_ok());
|
||||
|
@ -480,7 +480,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_incr_encode_header_ack_some() {
|
||||
fn encode_incr_encode_header_ack_some() {
|
||||
// 1. Decoder receives an instruction (header and value both as literal)
|
||||
// 2. Decoder process the instruction and sends an increment instruction.
|
||||
// 3. Decoder receives another two instruction (header and value both as literal) and a
|
||||
|
@ -517,7 +517,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_incr_encode_header_ack_all() {
|
||||
fn encode_incr_encode_header_ack_all() {
|
||||
// 1. Decoder receives an instruction (header and value both as literal)
|
||||
// 2. Decoder process the instruction and sends an increment instruction.
|
||||
// 3. Decoder receives another instruction (header and value both as literal) and a header
|
||||
|
@ -553,7 +553,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_header_ack_all() {
|
||||
fn header_ack_all() {
|
||||
// Send two instructions to insert values into the dynamic table and then send a header
|
||||
// that references them both. The result should be only a header acknowledgement.
|
||||
let headers = vec![
|
||||
|
@ -579,7 +579,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_header_ack_and_incr_instruction() {
|
||||
fn header_ack_and_incr_instruction() {
|
||||
// Send two instructions to insert values into the dynamic table and then send a header
|
||||
// that references only the first. The result should be a header acknowledgement and a
|
||||
// increment instruction.
|
||||
|
@ -603,7 +603,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_header_block_decoder() {
|
||||
fn header_block_decoder() {
|
||||
let test_cases: [TestElement; 6] = [
|
||||
// test a header with ref to static - encode_indexed
|
||||
TestElement {
|
||||
|
@ -684,7 +684,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_header_block_decoder_huffman() {
|
||||
fn header_block_decoder_huffman() {
|
||||
let test_cases: [TestElement; 6] = [
|
||||
// test a header with ref to static - encode_indexed
|
||||
TestElement {
|
||||
|
@ -763,7 +763,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_subtract_overflow_in_header_ack() {
|
||||
fn subtract_overflow_in_header_ack() {
|
||||
const HEADER_BLOCK_1: &[u8] = &[0x03, 0x81, 0x10, 0x11];
|
||||
const ENCODER_INST: &[u8] = &[
|
||||
0x4a, 0x6d, 0x79, 0x2d, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x61, 0x09, 0x6d, 0x79,
|
||||
|
@ -795,7 +795,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_base_larger_than_entry_count() {
|
||||
fn base_larger_than_entry_count() {
|
||||
// Test for issue https://github.com/mozilla/neqo/issues/533
|
||||
// Send instruction that inserts 2 fields into the dynamic table and send a header that
|
||||
// uses base larger than 2.
|
||||
|
|
|
@ -158,7 +158,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_encoding_decoding_instructions() {
|
||||
fn encoding_decoding_instructions() {
|
||||
test_encoding_decoding(DecoderInstruction::InsertCountIncrement { increment: 1 });
|
||||
test_encoding_decoding(DecoderInstruction::InsertCountIncrement { increment: 10_000 });
|
||||
|
||||
|
@ -197,7 +197,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_encoding_decoding_instructions_slow_reader() {
|
||||
fn encoding_decoding_instructions_slow_reader() {
|
||||
test_encoding_decoding_slow_reader(DecoderInstruction::InsertCountIncrement {
|
||||
increment: 10_000,
|
||||
});
|
||||
|
@ -210,7 +210,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_decoding_error() {
|
||||
fn decoding_error() {
|
||||
let mut test_receiver: TestReceiver = TestReceiver::default();
|
||||
// InsertCountIncrement with overflow
|
||||
test_receiver.write(&[
|
||||
|
|
|
@ -677,7 +677,7 @@ mod tests {
|
|||
|
||||
// test insert_with_name_literal which fails because there is not enough space in the table
|
||||
#[test]
|
||||
fn test_insert_with_name_literal_1() {
|
||||
fn insert_with_name_literal_1() {
|
||||
let mut encoder = connect(false);
|
||||
|
||||
// insert "content-length: 1234
|
||||
|
@ -691,7 +691,7 @@ mod tests {
|
|||
|
||||
// test insert_with_name_literal - succeeds
|
||||
#[test]
|
||||
fn test_insert_with_name_literal_2() {
|
||||
fn insert_with_name_literal_2() {
|
||||
let mut encoder = connect(false);
|
||||
|
||||
assert!(encoder.encoder.set_max_capacity(200).is_ok());
|
||||
|
@ -708,7 +708,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_change_capacity() {
|
||||
fn change_capacity() {
|
||||
let mut encoder = connect(false);
|
||||
|
||||
assert!(encoder.encoder.set_max_capacity(200).is_ok());
|
||||
|
@ -722,7 +722,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_header_block_encoder_non() {
|
||||
fn header_block_encoder_non() {
|
||||
let test_cases: [TestElement; 6] = [
|
||||
// test a header with ref to static - encode_indexed
|
||||
TestElement {
|
||||
|
@ -798,7 +798,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_header_block_encoder_huffman() {
|
||||
fn header_block_encoder_huffman() {
|
||||
let test_cases: [TestElement; 6] = [
|
||||
// test a header with ref to static - encode_indexed
|
||||
TestElement {
|
||||
|
@ -873,7 +873,7 @@ mod tests {
|
|||
|
||||
// Test inserts block on waiting for an insert count increment.
|
||||
#[test]
|
||||
fn test_insertion_blocked_on_insert_count_feedback() {
|
||||
fn insertion_blocked_on_insert_count_feedback() {
|
||||
let mut encoder = connect(false);
|
||||
|
||||
encoder.encoder.set_max_capacity(60).unwrap();
|
||||
|
@ -968,12 +968,12 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_header_ack() {
|
||||
fn header_ack() {
|
||||
test_insertion_blocked_on_waiting_for_header_ack_or_stream_cancel(0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stream_canceled() {
|
||||
fn stream_canceled() {
|
||||
test_insertion_blocked_on_waiting_for_header_ack_or_stream_cancel(1);
|
||||
}
|
||||
|
||||
|
@ -1595,7 +1595,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_do_not_evict_entry_that_are_referred_only_by_the_same_header_blocked_encoding() {
|
||||
fn do_not_evict_entry_that_are_referred_only_by_the_same_header_blocked_encoding() {
|
||||
let mut encoder = connect(false);
|
||||
|
||||
encoder.encoder.set_max_blocked_streams(20).unwrap();
|
||||
|
@ -1639,7 +1639,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_streams_cancel_cleans_up_unacked_header_blocks() {
|
||||
fn streams_cancel_cleans_up_unacked_header_blocks() {
|
||||
let mut encoder = connect(false);
|
||||
|
||||
encoder.encoder.set_max_blocked_streams(10).unwrap();
|
||||
|
|
|
@ -285,7 +285,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_encoding_decoding_instructions() {
|
||||
fn encoding_decoding_instructions() {
|
||||
test_encoding_decoding(&EncoderInstruction::Capacity { value: 1 }, false);
|
||||
test_encoding_decoding(&EncoderInstruction::Capacity { value: 10_000 }, false);
|
||||
|
||||
|
@ -386,7 +386,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_encoding_decoding_instructions_slow_reader() {
|
||||
fn encoding_decoding_instructions_slow_reader() {
|
||||
test_encoding_decoding_slow_reader(&EncoderInstruction::Capacity { value: 1 }, false);
|
||||
test_encoding_decoding_slow_reader(&EncoderInstruction::Capacity { value: 10_000 }, false);
|
||||
|
||||
|
@ -468,7 +468,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_decoding_error() {
|
||||
fn decoding_error() {
|
||||
let mut test_receiver: TestReceiver = TestReceiver::default();
|
||||
// EncoderInstruction::Capacity with overflow
|
||||
test_receiver.write(&[
|
||||
|
|
|
@ -612,7 +612,7 @@ mod tests {
|
|||
const LITERAL_VALUE: &str = "custom-key";
|
||||
|
||||
#[test]
|
||||
fn test_encode_indexed_static() {
|
||||
fn encode_indexed_static() {
|
||||
for (index, result, _, _) in INDEX_STATIC_TEST {
|
||||
let mut encoded_h = HeaderEncoder::new(0, true, 1000);
|
||||
encoded_h.encode_indexed_static(*index);
|
||||
|
@ -622,7 +622,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_indexed_dynamic() {
|
||||
fn encode_indexed_dynamic() {
|
||||
for (index, result, _, _) in INDEX_DYNAMIC_TEST {
|
||||
let mut encoded_h = HeaderEncoder::new(66, true, 1000);
|
||||
encoded_h.encode_indexed_dynamic(*index);
|
||||
|
@ -632,7 +632,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_indexed_dynamic_post() {
|
||||
fn encode_indexed_dynamic_post() {
|
||||
for (index, result, _, _) in INDEX_DYNAMIC_POST_TEST {
|
||||
let mut encoded_h = HeaderEncoder::new(0, true, 1000);
|
||||
encoded_h.encode_indexed_dynamic(*index);
|
||||
|
@ -642,7 +642,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_literal_with_name_ref_static() {
|
||||
fn encode_literal_with_name_ref_static() {
|
||||
for (index, result, _, _) in NAME_REF_STATIC {
|
||||
let mut encoded_h = HeaderEncoder::new(0, false, 1000);
|
||||
encoded_h.encode_literal_with_name_ref(true, *index, VALUE);
|
||||
|
@ -652,7 +652,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_literal_with_name_ref_dynamic() {
|
||||
fn encode_literal_with_name_ref_dynamic() {
|
||||
for (index, result, _, _) in NAME_REF_DYNAMIC {
|
||||
let mut encoded_h = HeaderEncoder::new(66, false, 1000);
|
||||
encoded_h.encode_literal_with_name_ref(false, *index, VALUE);
|
||||
|
@ -662,7 +662,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_literal_with_name_ref_dynamic_post() {
|
||||
fn encode_literal_with_name_ref_dynamic_post() {
|
||||
for (index, result, _, _) in NAME_REF_DYNAMIC_POST {
|
||||
let mut encoded_h = HeaderEncoder::new(0, false, 1000);
|
||||
encoded_h.encode_literal_with_name_ref(false, *index, VALUE);
|
||||
|
@ -672,7 +672,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_literal_with_name_ref_dynamic_huffman() {
|
||||
fn encode_literal_with_name_ref_dynamic_huffman() {
|
||||
for (index, result, _, _) in NAME_REF_DYNAMIC_HUFFMAN {
|
||||
let mut encoded_h = HeaderEncoder::new(66, true, 1000);
|
||||
encoded_h.encode_literal_with_name_ref(false, *index, VALUE);
|
||||
|
@ -681,7 +681,7 @@ mod tests {
|
|||
}
|
||||
}
|
||||
#[test]
|
||||
fn test_encode_literal_with_literal() {
|
||||
fn encode_literal_with_literal() {
|
||||
let mut encoded_h = HeaderEncoder::new(66, false, 1000);
|
||||
encoded_h.encode_literal_with_name_literal(VALUE, VALUE);
|
||||
encoded_h.encode_header_block_prefix();
|
||||
|
|
|
@ -237,7 +237,7 @@ mod tests {
|
|||
const WRONG_END: &[u8] = &[0xa8, 0xeb, 0x10, 0x64, 0x9c, 0xaf];
|
||||
|
||||
#[test]
|
||||
fn test_encoder() {
|
||||
fn encoder() {
|
||||
for e in TEST_CASES {
|
||||
let out = encode_huffman(e.val);
|
||||
assert_eq!(out[..], *e.res);
|
||||
|
@ -245,7 +245,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_decoder() {
|
||||
fn decoder() {
|
||||
for e in TEST_CASES {
|
||||
let res = decode_huffman(e.res);
|
||||
assert!(res.is_ok());
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Prefix {
|
||||
#[allow(unknown_lints)] // available with Rust v1.75
|
||||
#[allow(clippy::struct_field_names)]
|
||||
prefix: u8,
|
||||
len: u8,
|
||||
|
|
|
@ -108,21 +108,21 @@ mod tests {
|
|||
use super::{Prefix, QpackData};
|
||||
|
||||
#[test]
|
||||
fn test_encode_prefixed_encoded_int_1() {
|
||||
fn encode_prefixed_encoded_int_1() {
|
||||
let mut d = QpackData::default();
|
||||
d.encode_prefixed_encoded_int(Prefix::new(0xC0, 2), 5);
|
||||
assert_eq!(d[..], [0xc5]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_prefixed_encoded_int_2() {
|
||||
fn encode_prefixed_encoded_int_2() {
|
||||
let mut d = QpackData::default();
|
||||
d.encode_prefixed_encoded_int(Prefix::new(0xC0, 2), 65);
|
||||
assert_eq!(d[..], [0xff, 0x02]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_prefixed_encoded_int_3() {
|
||||
fn encode_prefixed_encoded_int_3() {
|
||||
let mut d = QpackData::default();
|
||||
d.encode_prefixed_encoded_int(Prefix::new(0xC0, 2), 100_000);
|
||||
assert_eq!(d[..], [0xff, 0xe1, 0x8c, 0x06]);
|
||||
|
@ -146,14 +146,14 @@ mod tests {
|
|||
const LITERAL_HUFFMAN: &[u8] = &[0xe8, 0x25, 0xa8, 0x49, 0xe9, 0x5b, 0xa9, 0x7d, 0x7f];
|
||||
|
||||
#[test]
|
||||
fn test_encode_literal() {
|
||||
fn encode_literal() {
|
||||
let mut d = QpackData::default();
|
||||
d.encode_literal(false, Prefix::new(0xC0, 2), VALUE);
|
||||
assert_eq!(&&d[..], &LITERAL);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_literal_huffman() {
|
||||
fn encode_literal_huffman() {
|
||||
let mut d = QpackData::default();
|
||||
d.encode_literal(true, Prefix::new(0xC0, 2), VALUE);
|
||||
assert_eq!(&&d[..], &LITERAL_HUFFMAN);
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -13,7 +13,7 @@
|
|||
edition = "2021"
|
||||
rust-version = "1.76.0"
|
||||
name = "neqo-transport"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
authors = ["The Neqo Authors <necko@mozilla.com>"]
|
||||
description = "Neqo, the Mozilla implementation of QUIC in Rust."
|
||||
homepage = "https://github.com/mozilla/neqo/"
|
||||
|
|
|
@ -6,11 +6,12 @@
|
|||
|
||||
use std::time::Duration;
|
||||
|
||||
use criterion::{criterion_group, criterion_main, BatchSize::SmallInput, Criterion, Throughput};
|
||||
use criterion::{criterion_group, criterion_main, BatchSize::SmallInput, Criterion};
|
||||
use neqo_transport::{ConnectionParameters, State};
|
||||
use test_fixture::{
|
||||
boxed,
|
||||
sim::{
|
||||
connection::{ConnectionNode, ReceiveData, SendData},
|
||||
connection::{ConnectionNode, ReachState, ReceiveData, SendData},
|
||||
network::{Delay, TailDrop},
|
||||
Simulator,
|
||||
},
|
||||
|
@ -21,47 +22,54 @@ const JITTER: Duration = Duration::from_millis(10);
|
|||
const TRANSFER_AMOUNT: usize = 1 << 22; // 4Mbyte
|
||||
|
||||
fn benchmark_transfer(c: &mut Criterion, label: &str, seed: &Option<impl AsRef<str>>) {
|
||||
let mut group = c.benchmark_group("transfer");
|
||||
group.throughput(Throughput::Bytes(u64::try_from(TRANSFER_AMOUNT).unwrap()));
|
||||
group.noise_threshold(0.03);
|
||||
group.bench_function(label, |b| {
|
||||
b.iter_batched(
|
||||
|| {
|
||||
let nodes = boxed![
|
||||
ConnectionNode::default_client(boxed![SendData::new(TRANSFER_AMOUNT)]),
|
||||
TailDrop::dsl_uplink(),
|
||||
Delay::new(ZERO..JITTER),
|
||||
ConnectionNode::default_server(boxed![ReceiveData::new(TRANSFER_AMOUNT)]),
|
||||
TailDrop::dsl_downlink(),
|
||||
Delay::new(ZERO..JITTER),
|
||||
];
|
||||
let mut sim = Simulator::new(label, nodes);
|
||||
if let Some(seed) = &seed {
|
||||
sim.seed_str(seed);
|
||||
}
|
||||
sim.setup()
|
||||
},
|
||||
|sim| {
|
||||
sim.run();
|
||||
},
|
||||
SmallInput,
|
||||
);
|
||||
});
|
||||
group.finish();
|
||||
for pacing in [false, true] {
|
||||
let mut group = c.benchmark_group(format!("transfer/pacing-{pacing}"));
|
||||
// Don't let criterion calculate throughput, as that's based on wall-clock time, not
|
||||
// simulator time.
|
||||
group.noise_threshold(0.03);
|
||||
group.bench_function(label, |b| {
|
||||
b.iter_batched(
|
||||
|| {
|
||||
let nodes = boxed![
|
||||
ConnectionNode::new_client(
|
||||
ConnectionParameters::default().pmtud(true).pacing(pacing),
|
||||
boxed![ReachState::new(State::Confirmed)],
|
||||
boxed![SendData::new(TRANSFER_AMOUNT)]
|
||||
),
|
||||
TailDrop::dsl_uplink(),
|
||||
Delay::new(ZERO..JITTER),
|
||||
ConnectionNode::new_server(
|
||||
ConnectionParameters::default().pmtud(true).pacing(pacing),
|
||||
boxed![ReachState::new(State::Confirmed)],
|
||||
boxed![ReceiveData::new(TRANSFER_AMOUNT)]
|
||||
),
|
||||
TailDrop::dsl_downlink(),
|
||||
Delay::new(ZERO..JITTER),
|
||||
];
|
||||
let mut sim = Simulator::new(label, nodes);
|
||||
if let Some(seed) = &seed {
|
||||
sim.seed_str(seed);
|
||||
}
|
||||
sim.setup()
|
||||
},
|
||||
|sim| {
|
||||
sim.run();
|
||||
},
|
||||
SmallInput,
|
||||
);
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
}
|
||||
|
||||
fn benchmark_transfer_variable(c: &mut Criterion) {
|
||||
benchmark_transfer(
|
||||
c,
|
||||
"Run multiple transfers with varying seeds",
|
||||
&std::env::var("SIMULATION_SEED").ok(),
|
||||
);
|
||||
benchmark_transfer(c, "varying-seeds", &std::env::var("SIMULATION_SEED").ok());
|
||||
}
|
||||
|
||||
fn benchmark_transfer_fixed(c: &mut Criterion) {
|
||||
benchmark_transfer(
|
||||
c,
|
||||
"Run multiple transfers with the same seed",
|
||||
"same-seed",
|
||||
&Some("62df6933ba1f543cece01db8f27fb2025529b27f93df39e19f006e1db3b8c843"),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -267,7 +267,7 @@ impl AddressValidation {
|
|||
|
||||
// Note: these lint override can be removed in later versions where the lints
|
||||
// either don't trip a false positive or don't apply. rustc 1.46 is fine.
|
||||
#[allow(dead_code, clippy::large_enum_variant)]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum NewTokenState {
|
||||
Client {
|
||||
/// Tokens that haven't been taken yet.
|
||||
|
|
|
@ -339,7 +339,7 @@ fn congestion_event_congestion_avoidance_2() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn congestion_event_congestion_avoidance_test_no_overflow() {
|
||||
fn congestion_event_congestion_avoidance_no_overflow() {
|
||||
const PTO: Duration = Duration::from_millis(120);
|
||||
let mut cubic = ClassicCongestionControl::new(Cubic::default(), Pmtud::new(IP_ADDR));
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ pub fn dump_packet(
|
|||
};
|
||||
let x = f.dump();
|
||||
if !x.is_empty() {
|
||||
write!(&mut s, "\n {} {}", dir, &x).unwrap();
|
||||
_ = write!(&mut s, "\n {} {}", dir, &x);
|
||||
}
|
||||
}
|
||||
qdebug!(
|
||||
|
|
|
@ -328,7 +328,7 @@ impl Connection {
|
|||
c.conn_params.get_versions().compatible(),
|
||||
Role::Client,
|
||||
&dcid,
|
||||
);
|
||||
)?;
|
||||
c.original_destination_cid = Some(dcid);
|
||||
let path = Path::temporary(
|
||||
local_addr,
|
||||
|
@ -1040,7 +1040,7 @@ impl Connection {
|
|||
qtrace!([self], "Idle/keepalive timer {:?}", idle_time);
|
||||
delays.push(idle_time);
|
||||
|
||||
if let Some(lr_time) = self.loss_recovery.next_timeout(rtt) {
|
||||
if let Some(lr_time) = self.loss_recovery.next_timeout(&path) {
|
||||
qtrace!([self], "Loss recovery timer {:?}", lr_time);
|
||||
delays.push(lr_time);
|
||||
}
|
||||
|
@ -1129,21 +1129,25 @@ impl Connection {
|
|||
output
|
||||
}
|
||||
|
||||
fn handle_retry(&mut self, packet: &PublicPacket, now: Instant) {
|
||||
fn handle_retry(&mut self, packet: &PublicPacket, now: Instant) -> Res<()> {
|
||||
qinfo!([self], "received Retry");
|
||||
if matches!(self.address_validation, AddressValidationInfo::Retry { .. }) {
|
||||
self.stats.borrow_mut().pkt_dropped("Extra Retry");
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
if packet.token().is_empty() {
|
||||
self.stats.borrow_mut().pkt_dropped("Retry without a token");
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
if !packet.is_valid_retry(self.original_destination_cid.as_ref().unwrap()) {
|
||||
if !packet.is_valid_retry(
|
||||
self.original_destination_cid
|
||||
.as_ref()
|
||||
.ok_or(Error::InvalidRetry)?,
|
||||
) {
|
||||
self.stats
|
||||
.borrow_mut()
|
||||
.pkt_dropped("Retry with bad integrity tag");
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
// At this point, we should only have the connection ID that we generated.
|
||||
// Update to the one that the server prefers.
|
||||
|
@ -1151,7 +1155,7 @@ impl Connection {
|
|||
self.stats
|
||||
.borrow_mut()
|
||||
.pkt_dropped("Retry without an existing path");
|
||||
return;
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
path.borrow_mut().set_remote_cid(packet.scid());
|
||||
|
@ -1171,11 +1175,12 @@ impl Connection {
|
|||
self.conn_params.get_versions().compatible(),
|
||||
self.role,
|
||||
&retry_scid,
|
||||
);
|
||||
)?;
|
||||
self.address_validation = AddressValidationInfo::Retry {
|
||||
token: packet.token().to_vec(),
|
||||
retry_source_cid: retry_scid,
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn discard_keys(&mut self, space: PacketNumberSpace, now: Instant) {
|
||||
|
@ -1194,8 +1199,8 @@ impl Connection {
|
|||
if d.len() < 16 || !self.state.connected() {
|
||||
return false;
|
||||
}
|
||||
let token = <&[u8; 16]>::try_from(&d[d.len() - 16..]).unwrap();
|
||||
path.borrow().is_stateless_reset(token)
|
||||
<&[u8; 16]>::try_from(&d[d.len() - 16..])
|
||||
.map_or(false, |token| path.borrow().is_stateless_reset(token))
|
||||
}
|
||||
|
||||
fn check_stateless_reset(
|
||||
|
@ -1265,7 +1270,7 @@ impl Connection {
|
|||
.clone()
|
||||
.versions(version, self.conn_params.get_versions().all().to_vec());
|
||||
let mut c = Self::new_client(
|
||||
self.crypto.server_name().unwrap(),
|
||||
self.crypto.server_name().ok_or(Error::VersionNegotiation)?,
|
||||
self.crypto.protocols(),
|
||||
self.cid_manager.generator(),
|
||||
local_addr,
|
||||
|
@ -1324,7 +1329,7 @@ impl Connection {
|
|||
|
||||
match (packet.packet_type(), &self.state, &self.role) {
|
||||
(PacketType::Initial, State::Init, Role::Server) => {
|
||||
let version = *packet.version().as_ref().unwrap();
|
||||
let version = packet.version().ok_or(Error::ProtocolViolation)?;
|
||||
if !packet.is_valid_initial()
|
||||
|| !self.conn_params.get_versions().all().contains(&version)
|
||||
{
|
||||
|
@ -1340,7 +1345,7 @@ impl Connection {
|
|||
// Record the client's selected CID so that it can be accepted until
|
||||
// the client starts using a real connection ID.
|
||||
let dcid = ConnectionId::from(packet.dcid());
|
||||
self.crypto.states.init_server(version, &dcid);
|
||||
self.crypto.states.init_server(version, &dcid)?;
|
||||
self.original_destination_cid = Some(dcid);
|
||||
self.set_state(State::WaitInitial);
|
||||
|
||||
|
@ -1359,7 +1364,7 @@ impl Connection {
|
|||
if versions.is_empty()
|
||||
|| versions.contains(&self.version().wire_version())
|
||||
|| versions.contains(&0)
|
||||
|| &packet.scid() != self.odcid().unwrap()
|
||||
|| &packet.scid() != self.odcid().ok_or(Error::InternalError)?
|
||||
|| matches!(self.address_validation, AddressValidationInfo::Retry { .. })
|
||||
{
|
||||
// Ignore VersionNegotiation packets that contain the current version.
|
||||
|
@ -1375,7 +1380,7 @@ impl Connection {
|
|||
return Ok(PreprocessResult::End);
|
||||
}
|
||||
(PacketType::Retry, State::WaitInitial, Role::Client) => {
|
||||
self.handle_retry(packet, now);
|
||||
self.handle_retry(packet, now)?;
|
||||
return Ok(PreprocessResult::Next);
|
||||
}
|
||||
(PacketType::Handshake | PacketType::Short, State::WaitInitial, Role::Client) => {
|
||||
|
@ -1664,7 +1669,9 @@ impl Connection {
|
|||
.clone(),
|
||||
),
|
||||
);
|
||||
path.borrow_mut().set_valid(now);
|
||||
if self.role == Role::Client {
|
||||
path.borrow_mut().set_valid(now);
|
||||
}
|
||||
}
|
||||
|
||||
/// If the path isn't permanent, assign it a connection ID to make it so.
|
||||
|
@ -2333,7 +2340,11 @@ impl Connection {
|
|||
);
|
||||
|
||||
self.stats.borrow_mut().packets_tx += 1;
|
||||
let tx = self.crypto.states.tx_mut(self.version, cspace).unwrap();
|
||||
let tx = self
|
||||
.crypto
|
||||
.states
|
||||
.tx_mut(self.version, cspace)
|
||||
.ok_or(Error::InternalError)?;
|
||||
encoder = builder.build(tx)?;
|
||||
self.crypto.states.auto_update()?;
|
||||
|
||||
|
@ -2375,7 +2386,7 @@ impl Connection {
|
|||
}
|
||||
|
||||
if encoder.is_empty() {
|
||||
qdebug!("TX blocked, profile={:?} ", profile);
|
||||
qdebug!("TX blocked, profile={:?}", profile);
|
||||
Ok(SendOption::No(profile.paced()))
|
||||
} else {
|
||||
// Perform additional padding for Initial packets as necessary.
|
||||
|
@ -2487,13 +2498,17 @@ impl Connection {
|
|||
self.validate_versions()?;
|
||||
{
|
||||
let tps = self.tps.borrow();
|
||||
let remote = tps.remote.as_ref().unwrap();
|
||||
let remote = tps.remote.as_ref().ok_or(Error::TransportParameterError)?;
|
||||
|
||||
// If the peer provided a preferred address, then we have to be a client
|
||||
// and they have to be using a non-empty connection ID.
|
||||
if remote.get_preferred_address().is_some()
|
||||
&& (self.role == Role::Server
|
||||
|| self.remote_initial_source_cid.as_ref().unwrap().is_empty())
|
||||
|| self
|
||||
.remote_initial_source_cid
|
||||
.as_ref()
|
||||
.ok_or(Error::UnknownConnectionId)?
|
||||
.is_empty())
|
||||
{
|
||||
return Err(Error::TransportParameterError);
|
||||
}
|
||||
|
@ -2529,7 +2544,7 @@ impl Connection {
|
|||
|
||||
fn validate_cids(&self) -> Res<()> {
|
||||
let tph = self.tps.borrow();
|
||||
let remote_tps = tph.remote.as_ref().unwrap();
|
||||
let remote_tps = tph.remote.as_ref().ok_or(Error::TransportParameterError)?;
|
||||
|
||||
let tp = remote_tps.get_bytes(tparams::INITIAL_SOURCE_CONNECTION_ID);
|
||||
if self
|
||||
|
@ -2590,7 +2605,7 @@ impl Connection {
|
|||
/// Validate the `version_negotiation` transport parameter from the peer.
|
||||
fn validate_versions(&self) -> Res<()> {
|
||||
let tph = self.tps.borrow();
|
||||
let remote_tps = tph.remote.as_ref().unwrap();
|
||||
let remote_tps = tph.remote.as_ref().ok_or(Error::TransportParameterError)?;
|
||||
// `current` and `other` are the value from the peer's transport parameters.
|
||||
// We're checking that these match our expectations.
|
||||
if let Some((current, other)) = remote_tps.get_versions() {
|
||||
|
@ -2653,19 +2668,23 @@ impl Connection {
|
|||
self.version = v;
|
||||
}
|
||||
|
||||
fn compatible_upgrade(&mut self, packet_version: Version) {
|
||||
fn compatible_upgrade(&mut self, packet_version: Version) -> Res<()> {
|
||||
if !matches!(self.state, State::WaitInitial | State::WaitVersion) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if self.role == Role::Client {
|
||||
self.confirm_version(packet_version);
|
||||
} else if self.tps.borrow().remote.is_some() {
|
||||
let version = self.tps.borrow().version();
|
||||
let dcid = self.original_destination_cid.as_ref().unwrap();
|
||||
self.crypto.states.init_server(version, dcid);
|
||||
let dcid = self
|
||||
.original_destination_cid
|
||||
.as_ref()
|
||||
.ok_or(Error::ProtocolViolation)?;
|
||||
self.crypto.states.init_server(version, dcid)?;
|
||||
self.confirm_version(version);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handshake(
|
||||
|
@ -2696,14 +2715,15 @@ impl Connection {
|
|||
}
|
||||
}
|
||||
_ => {
|
||||
unreachable!("Crypto state should not be new or failed after successful handshake")
|
||||
qerror!("Crypto state should not be new or failed after successful handshake");
|
||||
return Err(Error::CryptoError(neqo_crypto::Error::InternalError));
|
||||
}
|
||||
}
|
||||
|
||||
// There is a chance that this could be called less often, but getting the
|
||||
// conditions right is a little tricky, so call whenever CRYPTO data is used.
|
||||
if try_update {
|
||||
self.compatible_upgrade(packet_version);
|
||||
self.compatible_upgrade(packet_version)?;
|
||||
// We have transport parameters, it's go time.
|
||||
if self.tps.borrow().remote.is_some() {
|
||||
self.set_initial_limits();
|
||||
|
@ -2799,7 +2819,7 @@ impl Connection {
|
|||
if self.crypto.streams.data_ready(space) {
|
||||
let mut buf = Vec::new();
|
||||
let read = self.crypto.streams.read_to_end(space, &mut buf);
|
||||
qdebug!("Read {} bytes", read);
|
||||
qdebug!("Read {:?} bytes", read);
|
||||
self.handshake(now, packet_version, space, Some(&buf))?;
|
||||
self.create_resumption_token(now);
|
||||
} else {
|
||||
|
@ -3043,7 +3063,13 @@ impl Connection {
|
|||
// Generate a qlog event that the server connection started.
|
||||
qlog::server_connection_started(&self.qlog, &path);
|
||||
} else {
|
||||
self.zero_rtt_state = if self.crypto.tls.info().unwrap().early_data_accepted() {
|
||||
self.zero_rtt_state = if self
|
||||
.crypto
|
||||
.tls
|
||||
.info()
|
||||
.ok_or(Error::InternalError)?
|
||||
.early_data_accepted()
|
||||
{
|
||||
ZeroRttState::AcceptedClient
|
||||
} else {
|
||||
self.client_0rtt_rejected(now);
|
||||
|
@ -3060,7 +3086,12 @@ impl Connection {
|
|||
self.create_resumption_token(now);
|
||||
self.saved_datagrams
|
||||
.make_available(CryptoSpace::ApplicationData);
|
||||
self.stats.borrow_mut().resumed = self.crypto.tls.info().unwrap().resumed();
|
||||
self.stats.borrow_mut().resumed = self
|
||||
.crypto
|
||||
.tls
|
||||
.info()
|
||||
.ok_or(Error::InternalError)?
|
||||
.resumed();
|
||||
if self.role == Role::Server {
|
||||
self.state_signaling.handshake_done();
|
||||
self.set_confirmed()?;
|
||||
|
@ -3355,7 +3386,7 @@ impl Connection {
|
|||
);
|
||||
|
||||
let data_len_possible =
|
||||
u64::try_from(mtu.saturating_sub(tx.expansion() + builder.len() + 1)).unwrap();
|
||||
u64::try_from(mtu.saturating_sub(tx.expansion() + builder.len() + 1))?;
|
||||
Ok(min(data_len_possible, max_dgram_size))
|
||||
}
|
||||
|
||||
|
|
|
@ -371,17 +371,17 @@ impl ConnectionParameters {
|
|||
// default parameters
|
||||
tps.local.set_integer(
|
||||
tparams::ACTIVE_CONNECTION_ID_LIMIT,
|
||||
u64::try_from(LOCAL_ACTIVE_CID_LIMIT).unwrap(),
|
||||
u64::try_from(LOCAL_ACTIVE_CID_LIMIT)?,
|
||||
);
|
||||
tps.local.set_empty(tparams::DISABLE_MIGRATION);
|
||||
tps.local.set_empty(tparams::GREASE_QUIC_BIT);
|
||||
tps.local.set_integer(
|
||||
tparams::MAX_ACK_DELAY,
|
||||
u64::try_from(DEFAULT_ACK_DELAY.as_millis()).unwrap(),
|
||||
u64::try_from(DEFAULT_ACK_DELAY.as_millis())?,
|
||||
);
|
||||
tps.local.set_integer(
|
||||
tparams::MIN_ACK_DELAY,
|
||||
u64::try_from(GRANULARITY.as_micros()).unwrap(),
|
||||
u64::try_from(GRANULARITY.as_micros())?,
|
||||
);
|
||||
|
||||
// set configurable parameters
|
||||
|
|
|
@ -90,7 +90,6 @@ impl Ord for State {
|
|||
if mem::discriminant(self) == mem::discriminant(other) {
|
||||
return Ordering::Equal;
|
||||
}
|
||||
#[allow(clippy::match_same_arms)] // Lint bug: rust-lang/rust-clippy#860
|
||||
match (self, other) {
|
||||
(Self::Init, _) => Ordering::Less,
|
||||
(_, Self::Init) => Ordering::Greater,
|
||||
|
|
|
@ -382,7 +382,6 @@ fn dgram_no_allowed() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::assertions_on_constants)] // this is a static assert, thanks
|
||||
fn dgram_too_big() {
|
||||
let mut client =
|
||||
new_client(ConnectionParameters::default().datagram_size(DATAGRAM_LEN_SMALLER_THAN_MTU));
|
||||
|
|
|
@ -12,11 +12,11 @@ use test_fixture::{
|
|||
fixture_init, now, DEFAULT_ADDR_V4,
|
||||
};
|
||||
|
||||
use super::send_something_with_modifier;
|
||||
use super::{send_something_with_modifier, DEFAULT_RTT};
|
||||
use crate::{
|
||||
connection::tests::{
|
||||
connect_force_idle, connect_force_idle_with_modifier, default_client, default_server,
|
||||
migration::get_cid, new_client, new_server, send_something,
|
||||
handshake_with_modifier, migration::get_cid, new_client, new_server, send_something,
|
||||
},
|
||||
ecn::ECN_TEST_COUNT,
|
||||
ConnectionId, ConnectionParameters, StreamType,
|
||||
|
@ -67,6 +67,30 @@ fn drop() -> fn(Datagram) -> Option<Datagram> {
|
|||
|_| None
|
||||
}
|
||||
|
||||
fn drop_ecn_marked_datagrams() -> fn(Datagram) -> Option<Datagram> {
|
||||
|d| (!d.tos().is_ecn_marked()).then_some(d)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn handshake_delay_with_ecn_blackhole() {
|
||||
let start = now();
|
||||
let mut client = default_client();
|
||||
let mut server = default_server();
|
||||
let finish = handshake_with_modifier(
|
||||
&mut client,
|
||||
&mut server,
|
||||
start,
|
||||
DEFAULT_RTT,
|
||||
drop_ecn_marked_datagrams(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
(finish - start).as_millis() / DEFAULT_RTT.as_millis(),
|
||||
15,
|
||||
"expected 6 RTT for client to detect blackhole, 6 RTT for server to detect blackhole and 3 RTT for handshake to be confirmed.",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn disables_on_loss() {
|
||||
let now = now();
|
||||
|
|
|
@ -783,19 +783,15 @@ fn anti_amplification() {
|
|||
let c_init = client.process_output(now).dgram();
|
||||
now += DEFAULT_RTT / 2;
|
||||
let s_init1 = server.process(c_init.as_ref(), now).dgram().unwrap();
|
||||
assert_eq!(s_init1.len(), client.plpmtu());
|
||||
assert_eq!(s_init1.len(), server.plpmtu());
|
||||
let s_init2 = server.process_output(now).dgram().unwrap();
|
||||
assert_eq!(s_init2.len(), server.plpmtu());
|
||||
|
||||
// Skip the gap for pacing here.
|
||||
let s_pacing = server.process_output(now).callback();
|
||||
assert_ne!(s_pacing, Duration::new(0, 0));
|
||||
now += s_pacing;
|
||||
|
||||
let s_init3 = server.process_output(now).dgram().unwrap();
|
||||
assert_eq!(s_init3.len(), server.plpmtu());
|
||||
let cb = server.process_output(now).callback();
|
||||
assert_ne!(cb, Duration::new(0, 0));
|
||||
|
||||
// We are blocked by the amplification limit now.
|
||||
assert_eq!(cb, server.conn_params.get_idle_timeout());
|
||||
|
||||
now += DEFAULT_RTT / 2;
|
||||
client.process_input(&s_init1, now);
|
||||
|
|
|
@ -9,7 +9,7 @@ use std::{
|
|||
mem,
|
||||
net::{IpAddr, Ipv6Addr, SocketAddr},
|
||||
rc::Rc,
|
||||
time::{Duration, Instant},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use neqo_common::{Datagram, Decoder};
|
||||
|
@ -65,14 +65,6 @@ fn change_source_port(d: &Datagram) -> Datagram {
|
|||
Datagram::new(new_port(d.source()), d.destination(), d.tos(), &d[..])
|
||||
}
|
||||
|
||||
/// As these tests use a new path, that path often has a non-zero RTT.
|
||||
/// Pacing can be a problem when testing that path. This skips time forward.
|
||||
fn skip_pacing(c: &mut Connection, now: Instant) -> Instant {
|
||||
let pacing = c.process_output(now).callback();
|
||||
assert_ne!(pacing, Duration::new(0, 0));
|
||||
now + pacing
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rebinding_port() {
|
||||
let mut client = default_client();
|
||||
|
@ -100,7 +92,7 @@ fn path_forwarding_attack() {
|
|||
let mut client = default_client();
|
||||
let mut server = default_server();
|
||||
connect_force_idle(&mut client, &mut server);
|
||||
let mut now = now();
|
||||
let now = now();
|
||||
|
||||
let dgram = send_something(&mut client, now);
|
||||
let dgram = change_path(&dgram, DEFAULT_ADDR_V4);
|
||||
|
@ -160,16 +152,15 @@ fn path_forwarding_attack() {
|
|||
assert_v6_path(&client_data2, false);
|
||||
|
||||
// The server keeps sending on the new path.
|
||||
now = skip_pacing(&mut server, now);
|
||||
let server_data2 = send_something(&mut server, now);
|
||||
assert_v4_path(&server_data2, false);
|
||||
|
||||
// Until new data is received from the client on the old path.
|
||||
server.process_input(&client_data2, now);
|
||||
// The server sends a probe on the "old" path.
|
||||
// The server sends a probe on the new path.
|
||||
let server_data3 = send_something(&mut server, now);
|
||||
assert_v4_path(&server_data3, true);
|
||||
// But switches data transmission to the "new" path.
|
||||
// But switches data transmission to the old path.
|
||||
let server_data4 = server.process_output(now).dgram().unwrap();
|
||||
assert_v6_path(&server_data4, false);
|
||||
}
|
||||
|
|
|
@ -194,7 +194,6 @@ fn handshake_with_modifier(
|
|||
let mut did_ping = enum_map! {_ => false};
|
||||
while !is_done(a) {
|
||||
_ = maybe_authenticate(a);
|
||||
let had_input = input.is_some();
|
||||
// Insert a PING frame into the first application data packet an endpoint sends,
|
||||
// in order to force the peer to ACK it. For the server, this is depending on the
|
||||
// client's connection state, which is accessible during the tests.
|
||||
|
@ -213,12 +212,7 @@ fn handshake_with_modifier(
|
|||
a.test_frame_writer = None;
|
||||
did_ping[a.role()] = true;
|
||||
}
|
||||
assert!(had_input || output.is_some());
|
||||
if let Some(d) = output {
|
||||
input = modifier(d);
|
||||
} else {
|
||||
input = output;
|
||||
}
|
||||
input = output.and_then(modifier);
|
||||
qtrace!("handshake: t += {:?}", rtt / 2);
|
||||
now += rtt / 2;
|
||||
mem::swap(&mut a, &mut b);
|
||||
|
|
|
@ -584,6 +584,10 @@ fn loss_time_past_largest_acked() {
|
|||
let s_hs3 = server.process(None, now + s_pto).dgram();
|
||||
assert!(s_hs3.is_some());
|
||||
|
||||
// We are blocked by the amplification limit now.
|
||||
let cb = server.process_output(now).callback();
|
||||
assert_eq!(cb, server.conn_params.get_idle_timeout());
|
||||
|
||||
// Get some Handshake packets from the client.
|
||||
// We need one to be left unacknowledged before one that is acknowledged.
|
||||
// So that the client engages the loss recovery timer.
|
||||
|
|
|
@ -238,13 +238,13 @@ impl Crypto {
|
|||
};
|
||||
let secret = secret.ok_or(Error::InternalError)?;
|
||||
self.states
|
||||
.set_0rtt_keys(version, dir, &secret, cipher.unwrap());
|
||||
.set_0rtt_keys(version, dir, &secret, cipher.ok_or(Error::InternalError)?)?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
/// Lock in a compatible upgrade.
|
||||
pub fn confirm_version(&mut self, confirmed: Version) {
|
||||
self.states.confirm_version(self.version, confirmed);
|
||||
_ = self.states.confirm_version(self.version, confirmed);
|
||||
self.version = confirmed;
|
||||
}
|
||||
|
||||
|
@ -277,7 +277,7 @@ impl Crypto {
|
|||
}
|
||||
.ok_or(Error::InternalError)?;
|
||||
self.states
|
||||
.set_handshake_keys(self.version, &write_secret, &read_secret, cipher);
|
||||
.set_handshake_keys(self.version, &write_secret, &read_secret, cipher)?;
|
||||
qdebug!([self], "Handshake keys installed");
|
||||
Ok(true)
|
||||
}
|
||||
|
@ -313,7 +313,8 @@ impl Crypto {
|
|||
return Err(Error::ProtocolViolation);
|
||||
}
|
||||
qtrace!([self], "Adding CRYPTO data {:?}", r);
|
||||
self.streams.send(PacketNumberSpace::from(r.epoch), &r.data);
|
||||
self.streams
|
||||
.send(PacketNumberSpace::from(r.epoch), &r.data)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -437,14 +438,13 @@ pub struct CryptoDxState {
|
|||
const INITIAL_LARGEST_PACKET_LEN: usize = 1 << 11; // 2048
|
||||
|
||||
impl CryptoDxState {
|
||||
#[allow(clippy::reversed_empty_ranges)] // To initialize an empty range.
|
||||
pub fn new(
|
||||
version: Version,
|
||||
direction: CryptoDxDirection,
|
||||
epoch: Epoch,
|
||||
secret: &SymKey,
|
||||
cipher: Cipher,
|
||||
) -> Self {
|
||||
) -> Res<Self> {
|
||||
qdebug!(
|
||||
"Making {:?} {} CryptoDxState, v={:?} cipher={}",
|
||||
direction,
|
||||
|
@ -453,17 +453,17 @@ impl CryptoDxState {
|
|||
cipher,
|
||||
);
|
||||
let hplabel = String::from(version.label_prefix()) + "hp";
|
||||
Self {
|
||||
Ok(Self {
|
||||
version,
|
||||
direction,
|
||||
epoch: usize::from(epoch),
|
||||
aead: Aead::new(TLS_VERSION_1_3, cipher, secret, version.label_prefix()).unwrap(),
|
||||
hpkey: HpKey::extract(TLS_VERSION_1_3, cipher, secret, &hplabel).unwrap(),
|
||||
aead: Aead::new(TLS_VERSION_1_3, cipher, secret, version.label_prefix())?,
|
||||
hpkey: HpKey::extract(TLS_VERSION_1_3, cipher, secret, &hplabel)?,
|
||||
used_pn: 0..0,
|
||||
min_pn: 0,
|
||||
invocations: Self::limit(direction, cipher),
|
||||
largest_packet_len: INITIAL_LARGEST_PACKET_LEN,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_initial(
|
||||
|
@ -471,20 +471,18 @@ impl CryptoDxState {
|
|||
direction: CryptoDxDirection,
|
||||
label: &str,
|
||||
dcid: &[u8],
|
||||
) -> Self {
|
||||
) -> Res<Self> {
|
||||
qtrace!("new_initial {:?} {}", version, ConnectionIdRef::from(dcid));
|
||||
let salt = version.initial_salt();
|
||||
let cipher = TLS_AES_128_GCM_SHA256;
|
||||
let initial_secret = hkdf::extract(
|
||||
TLS_VERSION_1_3,
|
||||
cipher,
|
||||
Some(hkdf::import_key(TLS_VERSION_1_3, salt).as_ref().unwrap()),
|
||||
hkdf::import_key(TLS_VERSION_1_3, dcid).as_ref().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
Some(&hkdf::import_key(TLS_VERSION_1_3, salt)?),
|
||||
&hkdf::import_key(TLS_VERSION_1_3, dcid)?,
|
||||
)?;
|
||||
|
||||
let secret =
|
||||
hkdf::expand_label(TLS_VERSION_1_3, cipher, &initial_secret, &[], label).unwrap();
|
||||
let secret = hkdf::expand_label(TLS_VERSION_1_3, cipher, &initial_secret, &[], label)?;
|
||||
|
||||
Self::new(version, direction, TLS_EPOCH_INITIAL, &secret, cipher)
|
||||
}
|
||||
|
@ -531,7 +529,7 @@ impl CryptoDxState {
|
|||
self.invocations <= UPDATE_WRITE_KEYS_AT
|
||||
}
|
||||
|
||||
pub fn next(&self, next_secret: &SymKey, cipher: Cipher) -> Self {
|
||||
pub fn next(&self, next_secret: &SymKey, cipher: Cipher) -> Res<Self> {
|
||||
let pn = self.next_pn();
|
||||
// We count invocations of each write key just for that key, but all
|
||||
// attempts to invocations to read count toward a single limit.
|
||||
|
@ -541,7 +539,7 @@ impl CryptoDxState {
|
|||
} else {
|
||||
Self::limit(CryptoDxDirection::Write, cipher)
|
||||
};
|
||||
Self {
|
||||
Ok(Self {
|
||||
version: self.version,
|
||||
direction: self.direction,
|
||||
epoch: self.epoch + 1,
|
||||
|
@ -550,14 +548,13 @@ impl CryptoDxState {
|
|||
cipher,
|
||||
next_secret,
|
||||
self.version.label_prefix(),
|
||||
)
|
||||
.unwrap(),
|
||||
)?,
|
||||
hpkey: self.hpkey.clone(),
|
||||
used_pn: pn..pn,
|
||||
min_pn: pn,
|
||||
invocations,
|
||||
largest_packet_len: INITIAL_LARGEST_PACKET_LEN,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
|
@ -704,6 +701,7 @@ impl CryptoDxState {
|
|||
"server in",
|
||||
CLIENT_CID,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Get the amount of extra padding packets protected with this profile need.
|
||||
|
@ -764,7 +762,7 @@ impl CryptoDxAppData {
|
|||
cipher: Cipher,
|
||||
) -> Res<Self> {
|
||||
Ok(Self {
|
||||
dx: CryptoDxState::new(version, dir, TLS_EPOCH_APPLICATION_DATA, secret, cipher),
|
||||
dx: CryptoDxState::new(version, dir, TLS_EPOCH_APPLICATION_DATA, secret, cipher)?,
|
||||
cipher,
|
||||
next_secret: Self::update_secret(cipher, secret)?,
|
||||
})
|
||||
|
@ -782,7 +780,7 @@ impl CryptoDxAppData {
|
|||
}
|
||||
let next_secret = Self::update_secret(self.cipher, &self.next_secret)?;
|
||||
Ok(Self {
|
||||
dx: self.dx.next(&self.next_secret, self.cipher),
|
||||
dx: self.dx.next(&self.next_secret, self.cipher)?,
|
||||
cipher: self.cipher,
|
||||
next_secret,
|
||||
})
|
||||
|
@ -947,7 +945,7 @@ impl CryptoStates {
|
|||
|
||||
/// Create the initial crypto state.
|
||||
/// Note that the version here can change and that's OK.
|
||||
pub fn init<'v, V>(&mut self, versions: V, role: Role, dcid: &[u8])
|
||||
pub fn init<'v, V>(&mut self, versions: V, role: Role, dcid: &[u8]) -> Res<()>
|
||||
where
|
||||
V: IntoIterator<Item = &'v Version>,
|
||||
{
|
||||
|
@ -969,8 +967,8 @@ impl CryptoStates {
|
|||
);
|
||||
|
||||
let mut initial = CryptoState {
|
||||
tx: CryptoDxState::new_initial(*v, CryptoDxDirection::Write, write, dcid),
|
||||
rx: CryptoDxState::new_initial(*v, CryptoDxDirection::Read, read, dcid),
|
||||
tx: CryptoDxState::new_initial(*v, CryptoDxDirection::Write, write, dcid)?,
|
||||
rx: CryptoDxState::new_initial(*v, CryptoDxDirection::Read, read, dcid)?,
|
||||
};
|
||||
if let Some(prev) = self.initials.get(v) {
|
||||
qinfo!(
|
||||
|
@ -978,10 +976,11 @@ impl CryptoStates {
|
|||
"Continue packet numbers for initial after retry (write is {:?})",
|
||||
prev.rx.used_pn,
|
||||
);
|
||||
initial.tx.continuation(&prev.tx).unwrap();
|
||||
initial.tx.continuation(&prev.tx)?;
|
||||
}
|
||||
self.initials.insert(*v, initial);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// At a server, we can be more targeted in initializing.
|
||||
|
@ -990,24 +989,29 @@ impl CryptoStates {
|
|||
/// This is maybe slightly inefficient in the first case, because we might
|
||||
/// not need the send keys if the packet is subsequently discarded, but
|
||||
/// the overall effort is small enough to write off.
|
||||
pub fn init_server(&mut self, version: Version, dcid: &[u8]) {
|
||||
pub fn init_server(&mut self, version: Version, dcid: &[u8]) -> Res<()> {
|
||||
if !self.initials.contains_key(&version) {
|
||||
self.init(&[version], Role::Server, dcid);
|
||||
self.init(&[version], Role::Server, dcid)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn confirm_version(&mut self, orig: Version, confirmed: Version) {
|
||||
pub fn confirm_version(&mut self, orig: Version, confirmed: Version) -> Res<()> {
|
||||
if orig != confirmed {
|
||||
// This part where the old data is removed and then re-added is to
|
||||
// appease the borrow checker.
|
||||
// Note that on the server, we might not have initials for |orig| if it
|
||||
// was configured for |orig| and only |confirmed| Initial packets arrived.
|
||||
if let Some(prev) = self.initials.remove(&orig) {
|
||||
let next = self.initials.get_mut(&confirmed).unwrap();
|
||||
next.tx.continuation(&prev.tx).unwrap();
|
||||
let next = self
|
||||
.initials
|
||||
.get_mut(&confirmed)
|
||||
.ok_or(Error::VersionNegotiation)?;
|
||||
next.tx.continuation(&prev.tx)?;
|
||||
self.initials.insert(orig, prev);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_0rtt_keys(
|
||||
|
@ -1016,7 +1020,7 @@ impl CryptoStates {
|
|||
dir: CryptoDxDirection,
|
||||
secret: &SymKey,
|
||||
cipher: Cipher,
|
||||
) {
|
||||
) -> Res<()> {
|
||||
qtrace!([self], "install 0-RTT keys");
|
||||
self.zero_rtt = Some(CryptoDxState::new(
|
||||
version,
|
||||
|
@ -1024,7 +1028,8 @@ impl CryptoStates {
|
|||
TLS_EPOCH_ZERO_RTT,
|
||||
secret,
|
||||
cipher,
|
||||
));
|
||||
)?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Discard keys and return true if that happened.
|
||||
|
@ -1055,7 +1060,7 @@ impl CryptoStates {
|
|||
write_secret: &SymKey,
|
||||
read_secret: &SymKey,
|
||||
cipher: Cipher,
|
||||
) {
|
||||
) -> Res<()> {
|
||||
self.cipher = cipher;
|
||||
self.handshake = Some(CryptoState {
|
||||
tx: CryptoDxState::new(
|
||||
|
@ -1064,15 +1069,16 @@ impl CryptoStates {
|
|||
TLS_EPOCH_HANDSHAKE,
|
||||
write_secret,
|
||||
cipher,
|
||||
),
|
||||
)?,
|
||||
rx: CryptoDxState::new(
|
||||
version,
|
||||
CryptoDxDirection::Read,
|
||||
TLS_EPOCH_HANDSHAKE,
|
||||
read_secret,
|
||||
cipher,
|
||||
),
|
||||
)?,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_application_write_key(&mut self, version: Version, secret: &SymKey) -> Res<()> {
|
||||
|
@ -1115,7 +1121,7 @@ impl CryptoStates {
|
|||
// received an acknowledgement for a packet in the current phase.
|
||||
// Also, skip this if we are waiting for read keys on the existing
|
||||
// key update to be rolled over.
|
||||
let write = &self.app_write.as_ref().unwrap().dx;
|
||||
let write = &self.app_write.as_ref().ok_or(Error::InternalError)?.dx;
|
||||
if write.can_update(largest_acknowledged) && self.read_update_time.is_none() {
|
||||
// This call additionally checks that we don't advance to the next
|
||||
// epoch while a key update is in progress.
|
||||
|
@ -1137,8 +1143,8 @@ impl CryptoStates {
|
|||
// ahead of the read keys. If we initiated the key update, the write keys
|
||||
// will already be ahead.
|
||||
debug_assert!(self.read_update_time.is_none());
|
||||
let write = &self.app_write.as_ref().unwrap();
|
||||
let read = &self.app_read.as_ref().unwrap();
|
||||
let write = &self.app_write.as_ref().ok_or(Error::InternalError)?;
|
||||
let read = &self.app_read.as_ref().ok_or(Error::InternalError)?;
|
||||
if write.epoch() == read.epoch() {
|
||||
qdebug!([self], "Update write keys to epoch={}", write.epoch() + 1);
|
||||
self.app_write = Some(write.next()?);
|
||||
|
@ -1209,7 +1215,8 @@ impl CryptoStates {
|
|||
} else {
|
||||
qtrace!([self], "Rotating read keys");
|
||||
mem::swap(&mut self.app_read, &mut self.app_read_next);
|
||||
self.app_read_next = Some(self.app_read.as_ref().unwrap().next()?);
|
||||
self.app_read_next =
|
||||
Some(self.app_read.as_ref().ok_or(Error::InternalError)?.next()?);
|
||||
}
|
||||
self.read_update_time = None;
|
||||
}
|
||||
|
@ -1232,8 +1239,8 @@ impl CryptoStates {
|
|||
// We only need to do the check while we are waiting for read keys to be updated.
|
||||
if self.read_update_time.is_some() {
|
||||
qtrace!([self], "Checking for PN overlap");
|
||||
let next_dx = &mut self.app_read_next.as_mut().unwrap().dx;
|
||||
next_dx.continuation(&self.app_read.as_ref().unwrap().dx)?;
|
||||
let next_dx = &mut self.app_read_next.as_mut().ok_or(Error::InternalError)?.dx;
|
||||
next_dx.continuation(&self.app_read.as_ref().ok_or(Error::InternalError)?.dx)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1335,7 +1342,6 @@ pub struct CryptoStream {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)] // Suppress false positive: https://github.com/rust-lang/rust/issues/68408
|
||||
pub enum CryptoStreams {
|
||||
Initial {
|
||||
initial: CryptoStream,
|
||||
|
@ -1385,12 +1391,16 @@ impl CryptoStreams {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn send(&mut self, space: PacketNumberSpace, data: &[u8]) {
|
||||
self.get_mut(space).unwrap().tx.send(data);
|
||||
pub fn send(&mut self, space: PacketNumberSpace, data: &[u8]) -> Res<()> {
|
||||
self.get_mut(space)
|
||||
.ok_or(Error::ProtocolViolation)?
|
||||
.tx
|
||||
.send(data);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn inbound_frame(&mut self, space: PacketNumberSpace, offset: u64, data: &[u8]) -> Res<()> {
|
||||
let rx = &mut self.get_mut(space).unwrap().rx;
|
||||
let rx = &mut self.get_mut(space).ok_or(Error::InternalError)?.rx;
|
||||
rx.inbound_frame(offset, data);
|
||||
if rx.received() - rx.retired() <= Self::BUFFER_LIMIT {
|
||||
Ok(())
|
||||
|
@ -1403,8 +1413,12 @@ impl CryptoStreams {
|
|||
self.get(space).map_or(false, |cs| cs.rx.data_ready())
|
||||
}
|
||||
|
||||
pub fn read_to_end(&mut self, space: PacketNumberSpace, buf: &mut Vec<u8>) -> usize {
|
||||
self.get_mut(space).unwrap().rx.read_to_end(buf)
|
||||
pub fn read_to_end(&mut self, space: PacketNumberSpace, buf: &mut Vec<u8>) -> Res<usize> {
|
||||
Ok(self
|
||||
.get_mut(space)
|
||||
.ok_or(Error::ProtocolViolation)?
|
||||
.rx
|
||||
.read_to_end(buf))
|
||||
}
|
||||
|
||||
pub fn acked(&mut self, token: &CryptoRecoveryToken) {
|
||||
|
|
|
@ -9,18 +9,30 @@ use std::ops::{AddAssign, Deref, DerefMut, Sub};
|
|||
use enum_map::EnumMap;
|
||||
use neqo_common::{qdebug, qinfo, qwarn, IpTosEcn};
|
||||
|
||||
use crate::{packet::PacketNumber, recovery::SentPacket};
|
||||
use crate::{
|
||||
packet::{PacketNumber, PacketType},
|
||||
recovery::SentPacket,
|
||||
};
|
||||
|
||||
/// The number of packets to use for testing a path for ECN capability.
|
||||
pub const ECN_TEST_COUNT: usize = 10;
|
||||
|
||||
/// The number of packets to use for testing a path for ECN capability when exchanging
|
||||
/// Initials during the handshake. This is a lower number than [`ECN_TEST_COUNT`] to avoid
|
||||
/// unnecessarily delaying the handshake; we would otherwise double the PTO [`ECN_TEST_COUNT`]
|
||||
/// times.
|
||||
const ECN_TEST_COUNT_INITIAL_PHASE: usize = 3;
|
||||
|
||||
/// The state information related to testing a path for ECN capability.
|
||||
/// See RFC9000, Appendix A.4.
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
enum EcnValidationState {
|
||||
/// The path is currently being tested for ECN capability, with the number of probes sent so
|
||||
/// far on the path during the ECN validation.
|
||||
Testing(usize),
|
||||
Testing {
|
||||
probes_sent: usize,
|
||||
initial_probes_lost: usize,
|
||||
},
|
||||
/// The validation test has concluded but the path's ECN capability is not yet known.
|
||||
Unknown,
|
||||
/// The path is known to **not** be ECN capable.
|
||||
|
@ -31,7 +43,10 @@ enum EcnValidationState {
|
|||
|
||||
impl Default for EcnValidationState {
|
||||
fn default() -> Self {
|
||||
Self::Testing(0)
|
||||
Self::Testing {
|
||||
probes_sent: 0,
|
||||
initial_probes_lost: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,7 +127,7 @@ impl EcnInfo {
|
|||
/// We do not implement the part of the RFC that says to exit ECN validation if the time since
|
||||
/// the start of ECN validation exceeds 3 * PTO, since this seems to happen much too quickly.
|
||||
pub fn on_packet_sent(&mut self) {
|
||||
if let EcnValidationState::Testing(ref mut probes_sent) = &mut self.state {
|
||||
if let EcnValidationState::Testing { probes_sent, .. } = &mut self.state {
|
||||
*probes_sent += 1;
|
||||
qdebug!("ECN probing: sent {} probes", probes_sent);
|
||||
if *probes_sent == ECN_TEST_COUNT {
|
||||
|
@ -138,6 +153,28 @@ impl EcnInfo {
|
|||
&& (self.baseline - prev_baseline)[IpTosEcn::Ce] > 0
|
||||
}
|
||||
|
||||
pub fn on_packets_lost(&mut self, lost_packets: &[SentPacket]) {
|
||||
if let EcnValidationState::Testing {
|
||||
probes_sent,
|
||||
initial_probes_lost: probes_lost,
|
||||
} = &mut self.state
|
||||
{
|
||||
*probes_lost += lost_packets
|
||||
.iter()
|
||||
.filter(|p| p.packet_type() == PacketType::Initial && p.ecn_mark().is_ecn_marked())
|
||||
.count();
|
||||
// If we have lost all initial probes a bunch of times, we can conclude that the path
|
||||
// is not ECN capable and likely drops all ECN marked packets.
|
||||
if probes_sent == probes_lost && *probes_lost == ECN_TEST_COUNT_INITIAL_PHASE {
|
||||
qdebug!(
|
||||
"ECN validation failed, all {} initial marked packets were lost",
|
||||
probes_lost
|
||||
);
|
||||
self.state = EcnValidationState::Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// After the ECN validation test has ended, check if the path is ECN capable.
|
||||
pub fn validate_ack_ecn_and_update(
|
||||
&mut self,
|
||||
|
|
|
@ -943,7 +943,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_compare() {
|
||||
fn compare() {
|
||||
let f1 = Frame::Padding(1);
|
||||
let f2 = Frame::Padding(1);
|
||||
let f3 = Frame::Crypto {
|
||||
|
|
|
@ -14,6 +14,8 @@ use std::{
|
|||
|
||||
use neqo_common::qtrace;
|
||||
|
||||
use crate::rtt::GRANULARITY;
|
||||
|
||||
/// This value determines how much faster the pacer operates than the
|
||||
/// congestion window.
|
||||
///
|
||||
|
@ -74,19 +76,26 @@ impl Pacer {
|
|||
/// the current time is).
|
||||
pub fn next(&self, rtt: Duration, cwnd: usize) -> Instant {
|
||||
if self.c >= self.p {
|
||||
qtrace!([self], "next {}/{:?} no wait = {:?}", cwnd, rtt, self.t);
|
||||
self.t
|
||||
} else {
|
||||
// This is the inverse of the function in `spend`:
|
||||
// self.t + rtt * (self.p - self.c) / (PACER_SPEEDUP * cwnd)
|
||||
let r = rtt.as_nanos();
|
||||
let d = r.saturating_mul(u128::try_from(self.p - self.c).unwrap());
|
||||
let add = d / u128::try_from(cwnd * PACER_SPEEDUP).unwrap();
|
||||
let w = u64::try_from(add).map(Duration::from_nanos).unwrap_or(rtt);
|
||||
let nxt = self.t + w;
|
||||
qtrace!([self], "next {}/{:?} wait {:?} = {:?}", cwnd, rtt, w, nxt);
|
||||
nxt
|
||||
qtrace!([self], "next {cwnd}/{rtt:?} no wait = {:?}", self.t);
|
||||
return self.t;
|
||||
}
|
||||
|
||||
// This is the inverse of the function in `spend`:
|
||||
// self.t + rtt * (self.p - self.c) / (PACER_SPEEDUP * cwnd)
|
||||
let r = rtt.as_nanos();
|
||||
let d = r.saturating_mul(u128::try_from(self.p - self.c).unwrap());
|
||||
let add = d / u128::try_from(cwnd * PACER_SPEEDUP).unwrap();
|
||||
let w = u64::try_from(add).map(Duration::from_nanos).unwrap_or(rtt);
|
||||
|
||||
// If the increment is below the timer granularity, send immediately.
|
||||
if w < GRANULARITY {
|
||||
qtrace!([self], "next {cwnd}/{rtt:?} below granularity ({w:?})",);
|
||||
return self.t;
|
||||
}
|
||||
|
||||
let nxt = self.t + w;
|
||||
qtrace!([self], "next {cwnd}/{rtt:?} wait {w:?} = {nxt:?}");
|
||||
nxt
|
||||
}
|
||||
|
||||
/// Spend credit. This cannot fail; users of this API are expected to call
|
||||
|
@ -168,4 +177,18 @@ mod tests {
|
|||
p.spend(n, RTT, CWND, PACKET);
|
||||
assert_eq!(p.next(RTT, CWND), n);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_immediately_below_granularity() {
|
||||
const SHORT_RTT: Duration = Duration::from_millis(10);
|
||||
let n = now();
|
||||
let mut p = Pacer::new(true, n, PACKET, PACKET);
|
||||
assert_eq!(p.next(SHORT_RTT, CWND), n);
|
||||
p.spend(n, SHORT_RTT, CWND, PACKET);
|
||||
assert_eq!(
|
||||
p.next(SHORT_RTT, CWND),
|
||||
n,
|
||||
"Expect packet to be sent immediately, instead of being paced below timer granularity."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,7 +149,6 @@ impl PacketBuilder {
|
|||
///
|
||||
/// If, after calling this method, `remaining()` returns 0, then call `abort()` to get
|
||||
/// the encoder back.
|
||||
#[allow(clippy::reversed_empty_ranges)]
|
||||
pub fn short(mut encoder: Encoder, key_phase: bool, dcid: impl AsRef<[u8]>) -> Self {
|
||||
let mut limit = Self::infer_limit(&encoder);
|
||||
let header_start = encoder.len();
|
||||
|
@ -181,8 +180,7 @@ impl PacketBuilder {
|
|||
/// even if the token is empty.
|
||||
///
|
||||
/// See `short()` for more on how to handle this in cases where there is no space.
|
||||
#[allow(clippy::reversed_empty_ranges)] // For initializing an empty range.
|
||||
#[allow(clippy::similar_names)] // For dcid and scid, which are fine here.
|
||||
#[allow(clippy::similar_names)]
|
||||
pub fn long(
|
||||
mut encoder: Encoder,
|
||||
pt: PacketType,
|
||||
|
@ -454,7 +452,7 @@ impl PacketBuilder {
|
|||
/// # Errors
|
||||
///
|
||||
/// This will return an error if AEAD encrypt fails.
|
||||
#[allow(clippy::similar_names)] // scid and dcid are fine here.
|
||||
#[allow(clippy::similar_names)]
|
||||
pub fn retry(
|
||||
version: Version,
|
||||
dcid: &[u8],
|
||||
|
@ -486,8 +484,8 @@ impl PacketBuilder {
|
|||
}
|
||||
|
||||
/// Make a Version Negotiation packet.
|
||||
#[allow(clippy::similar_names)] // scid and dcid are fine here.
|
||||
#[must_use]
|
||||
#[allow(clippy::similar_names)]
|
||||
pub fn version_negotiation(
|
||||
dcid: &[u8],
|
||||
scid: &[u8],
|
||||
|
@ -602,7 +600,7 @@ impl<'a> PublicPacket<'a> {
|
|||
/// # Errors
|
||||
///
|
||||
/// This will return an error if the packet could not be decoded.
|
||||
#[allow(clippy::similar_names)] // For dcid and scid, which are fine.
|
||||
#[allow(clippy::similar_names)]
|
||||
pub fn decode(data: &'a [u8], dcid_decoder: &dyn ConnectionIdDecoder) -> Res<(Self, &'a [u8])> {
|
||||
let mut decoder = Decoder::new(data);
|
||||
let first = Self::opt(decoder.decode_byte())?;
|
||||
|
@ -760,7 +758,6 @@ impl<'a> PublicPacket<'a> {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
#[allow(clippy::len_without_is_empty)] // is_empty() would always return false in this case
|
||||
pub const fn len(&self) -> usize {
|
||||
self.data.len()
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ pub type PathRef = Rc<RefCell<Path>>;
|
|||
#[derive(Debug, Default)]
|
||||
pub struct Paths {
|
||||
/// All of the paths. All of these paths will be permanent.
|
||||
#[allow(unknown_lints)] // available with Rust v1.75
|
||||
#[allow(clippy::struct_field_names)]
|
||||
paths: Vec<PathRef>,
|
||||
/// This is the primary path. This will only be `None` initially, so
|
||||
|
@ -1003,6 +1002,7 @@ impl Path {
|
|||
now: Instant,
|
||||
) {
|
||||
debug_assert!(self.is_primary());
|
||||
self.ecn_info.on_packets_lost(lost_packets);
|
||||
let cwnd_reduced = self.sender.on_packets_lost(
|
||||
self.rtt.first_sample_time(),
|
||||
prev_largest_acked_sent,
|
||||
|
@ -1016,6 +1016,14 @@ impl Path {
|
|||
}
|
||||
}
|
||||
|
||||
/// Determine whether we should be setting a PTO for this path. This is true when either the
|
||||
/// path is valid or when there is enough remaining in the amplification limit to fit a
|
||||
/// full-sized path (i.e., the path MTU).
|
||||
pub fn pto_possible(&self) -> bool {
|
||||
// See the implementation of `amplification_limit` for details.
|
||||
self.amplification_limit() >= self.plpmtu()
|
||||
}
|
||||
|
||||
/// Get the number of bytes that can be written to this path.
|
||||
pub fn amplification_limit(&self) -> usize {
|
||||
if matches!(self.state, ProbeState::Failed) {
|
||||
|
|
|
@ -308,7 +308,7 @@ pub enum QlogMetric {
|
|||
MinRtt(Duration),
|
||||
SmoothedRtt(Duration),
|
||||
LatestRtt(Duration),
|
||||
RttVariance(u64),
|
||||
RttVariance(Duration),
|
||||
MaxAckDelay(u64),
|
||||
PtoCount(usize),
|
||||
CongestionWindow(usize),
|
||||
|
@ -340,7 +340,7 @@ pub fn metrics_updated(qlog: &NeqoQlog, updated_metrics: &[QlogMetric]) {
|
|||
QlogMetric::MinRtt(v) => min_rtt = Some(v.as_secs_f32() * 1000.0),
|
||||
QlogMetric::SmoothedRtt(v) => smoothed_rtt = Some(v.as_secs_f32() * 1000.0),
|
||||
QlogMetric::LatestRtt(v) => latest_rtt = Some(v.as_secs_f32() * 1000.0),
|
||||
QlogMetric::RttVariance(v) => rtt_variance = Some(*v as f32),
|
||||
QlogMetric::RttVariance(v) => rtt_variance = Some(v.as_secs_f32() * 1000.0),
|
||||
QlogMetric::PtoCount(v) => pto_count = Some(u16::try_from(*v).unwrap()),
|
||||
QlogMetric::CongestionWindow(v) => {
|
||||
congestion_window = Some(u64::try_from(*v).unwrap());
|
||||
|
|
|
@ -154,12 +154,15 @@ impl QuicDatagrams {
|
|||
tracking: DatagramTracking,
|
||||
stats: &mut Stats,
|
||||
) -> Res<()> {
|
||||
if u64::try_from(buf.len()).unwrap() > self.remote_datagram_size {
|
||||
if u64::try_from(buf.len())? > self.remote_datagram_size {
|
||||
return Err(Error::TooMuchData);
|
||||
}
|
||||
if self.datagrams.len() == self.max_queued_outgoing_datagrams {
|
||||
self.conn_events.datagram_outcome(
|
||||
self.datagrams.pop_front().unwrap().tracking(),
|
||||
self.datagrams
|
||||
.pop_front()
|
||||
.ok_or(Error::InternalError)?
|
||||
.tracking(),
|
||||
OutgoingDatagramOutcome::DroppedQueueFull,
|
||||
);
|
||||
stats.datagram_tx.dropped_queue_full += 1;
|
||||
|
@ -172,7 +175,7 @@ impl QuicDatagrams {
|
|||
}
|
||||
|
||||
pub fn handle_datagram(&self, data: &[u8], stats: &mut Stats) -> Res<()> {
|
||||
if self.local_datagram_size < u64::try_from(data.len()).unwrap() {
|
||||
if self.local_datagram_size < u64::try_from(data.len())? {
|
||||
return Err(Error::ProtocolViolation);
|
||||
}
|
||||
self.conn_events
|
||||
|
|
|
@ -735,9 +735,14 @@ impl LossRecovery {
|
|||
|
||||
/// Calculate when the next timeout is likely to be. This is the earlier of the loss timer
|
||||
/// and the PTO timer; either or both might be disabled, so this can return `None`.
|
||||
pub fn next_timeout(&self, rtt: &RttEstimate) -> Option<Instant> {
|
||||
pub fn next_timeout(&self, path: &Path) -> Option<Instant> {
|
||||
let rtt = path.rtt();
|
||||
let loss_time = self.earliest_loss_time(rtt);
|
||||
let pto_time = self.earliest_pto(rtt);
|
||||
let pto_time = if path.pto_possible() {
|
||||
self.earliest_pto(rtt)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
qtrace!(
|
||||
[self],
|
||||
"next_timeout loss={:?} pto={:?}",
|
||||
|
@ -1013,7 +1018,7 @@ mod tests {
|
|||
}
|
||||
|
||||
pub fn next_timeout(&self) -> Option<Instant> {
|
||||
self.lr.next_timeout(self.path.borrow().rtt())
|
||||
self.lr.next_timeout(&self.path.borrow())
|
||||
}
|
||||
|
||||
pub fn discard(&mut self, space: PacketNumberSpace, now: Instant) {
|
||||
|
|
|
@ -65,6 +65,7 @@ impl RecvStreams {
|
|||
pub fn get_mut(&mut self, id: StreamId) -> Res<&mut RecvStream> {
|
||||
self.streams.get_mut(&id).ok_or(Error::InvalidStreamId)
|
||||
}
|
||||
|
||||
#[allow(clippy::missing_errors_doc)]
|
||||
pub fn keep_alive(&mut self, id: StreamId, k: bool) -> Res<()> {
|
||||
let self_ka = &mut self.keep_alive;
|
||||
|
@ -386,7 +387,6 @@ impl RxStreamOrderer {
|
|||
|
||||
/// QUIC receiving states, based on -transport 3.2.
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
// Because a dead_code warning is easier than clippy::unused_self, see https://github.com/rust-lang/rust/issues/68408
|
||||
enum RecvStreamState {
|
||||
Recv {
|
||||
|
@ -643,7 +643,7 @@ impl RecvStream {
|
|||
// We should post a DataReadable event only once when we change from no-data-ready to
|
||||
// data-ready. Therefore remember the state before processing a new frame.
|
||||
let already_data_ready = self.data_ready();
|
||||
let new_end = offset + u64::try_from(data.len()).unwrap();
|
||||
let new_end = offset + u64::try_from(data.len())?;
|
||||
|
||||
self.state.flow_control_consume_data(new_end, fin)?;
|
||||
|
||||
|
@ -1051,7 +1051,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[allow(unknown_lints, clippy::single_range_in_vec_init)] // Because that lint makes no sense here.
|
||||
#[allow(clippy::single_range_in_vec_init)] // Because that lint makes no sense here.
|
||||
fn recv_noncontiguous() {
|
||||
// Non-contiguous with the start, no data available.
|
||||
recv_ranges(&[10..20], 0);
|
||||
|
|
|
@ -133,6 +133,7 @@ impl RttEstimate {
|
|||
QlogMetric::LatestRtt(self.latest_rtt),
|
||||
QlogMetric::MinRtt(self.min_rtt),
|
||||
QlogMetric::SmoothedRtt(self.smoothed_rtt),
|
||||
QlogMetric::RttVariance(self.rttvar),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2270,7 +2270,6 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
fn tx_buffer_next_bytes_1() {
|
||||
let mut txb = TxBuffer::new();
|
||||
|
||||
|
@ -2439,7 +2438,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_tx_buffer_acks() {
|
||||
fn tx_buffer_acks() {
|
||||
let mut tx = TxBuffer::new();
|
||||
assert_eq!(tx.send(&[4; 100]), 100);
|
||||
let res = tx.next_bytes().unwrap();
|
||||
|
@ -2673,7 +2672,6 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
// Verify lost frames handle fin properly with zero length fin
|
||||
fn send_stream_get_frame_zerolength_fin() {
|
||||
let conn_fc = connection_fc(100);
|
||||
|
|
|
@ -112,7 +112,6 @@ pub struct DatagramStats {
|
|||
|
||||
/// Connection statistics
|
||||
#[derive(Default, Clone)]
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
pub struct Stats {
|
||||
info: String,
|
||||
|
||||
|
|
|
@ -184,9 +184,8 @@ impl TransportParameter {
|
|||
|
||||
fn decode_preferred_address(d: &mut Decoder) -> Res<Self> {
|
||||
// IPv4 address (maybe)
|
||||
let v4ip =
|
||||
Ipv4Addr::from(<[u8; 4]>::try_from(d.decode(4).ok_or(Error::NoMoreData)?).unwrap());
|
||||
let v4port = u16::try_from(d.decode_uint(2).ok_or(Error::NoMoreData)?).unwrap();
|
||||
let v4ip = Ipv4Addr::from(<[u8; 4]>::try_from(d.decode(4).ok_or(Error::NoMoreData)?)?);
|
||||
let v4port = u16::try_from(d.decode_uint(2).ok_or(Error::NoMoreData)?)?;
|
||||
// Can't have non-zero IP and zero port, or vice versa.
|
||||
if v4ip.is_unspecified() ^ (v4port == 0) {
|
||||
return Err(Error::TransportParameterError);
|
||||
|
@ -198,9 +197,10 @@ impl TransportParameter {
|
|||
};
|
||||
|
||||
// IPv6 address (mostly the same as v4)
|
||||
let v6ip =
|
||||
Ipv6Addr::from(<[u8; 16]>::try_from(d.decode(16).ok_or(Error::NoMoreData)?).unwrap());
|
||||
let v6port = u16::try_from(d.decode_uint(2).ok_or(Error::NoMoreData)?).unwrap();
|
||||
let v6ip = Ipv6Addr::from(<[u8; 16]>::try_from(
|
||||
d.decode(16).ok_or(Error::NoMoreData)?,
|
||||
)?);
|
||||
let v6port = u16::try_from(d.decode_uint(2).ok_or(Error::NoMoreData)?)?;
|
||||
if v6ip.is_unspecified() ^ (v6port == 0) {
|
||||
return Err(Error::TransportParameterError);
|
||||
}
|
||||
|
@ -222,7 +222,7 @@ impl TransportParameter {
|
|||
|
||||
// Stateless reset token
|
||||
let srtbuf = d.decode(16).ok_or(Error::NoMoreData)?;
|
||||
let srt = <[u8; 16]>::try_from(srtbuf).unwrap();
|
||||
let srt = <[u8; 16]>::try_from(srtbuf)?;
|
||||
|
||||
Ok(Self::PreferredAddress { v4, v6, cid, srt })
|
||||
}
|
||||
|
|
|
@ -275,7 +275,7 @@ fn overflow_crypto() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_handshake_xyber() {
|
||||
fn handshake_xyber() {
|
||||
let mut client = default_client();
|
||||
let mut server = default_server();
|
||||
|
||||
|
|
|
@ -361,7 +361,6 @@ fn vn_after_retry() {
|
|||
// at least 8 bytes long. Otherwise, the second Initial won't have a
|
||||
// long enough connection ID.
|
||||
#[test]
|
||||
#[allow(clippy::shadow_unrelated)]
|
||||
fn mitm_retry() {
|
||||
let mut client = default_client();
|
||||
let mut retry_server = default_server();
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"0ea42b79cb133d629941bb4ebf2bb11de21a0e8b1987df1155140498934d2516","src/lib.rs":"974197080e48b72f587941bb5210a9ecc62c669819da240d0dd2b8d8c7ecae4d"},"package":null}
|
||||
{"files":{"Cargo.toml":"9f2c2dd38c3b49a54b3551b3d27b69118dee1478ea4cf95d323519dfe5068321","src/lib.rs":"bf3bc79b1d799a42b73e64d2b203ce688cc0859d7afa6c66eec429ec36199ba6"},"package":null}
|
|
@ -13,7 +13,7 @@
|
|||
edition = "2021"
|
||||
rust-version = "1.76.0"
|
||||
name = "neqo-udp"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
authors = ["The Neqo Authors <necko@mozilla.com>"]
|
||||
description = "Neqo, the Mozilla implementation of QUIC in Rust."
|
||||
homepage = "https://github.com/mozilla/neqo/"
|
||||
|
@ -47,7 +47,8 @@ default-features = false
|
|||
path = "./../neqo-common"
|
||||
|
||||
[dependencies.quinn-udp]
|
||||
version = "0.5.0"
|
||||
version = "0.5.4"
|
||||
features = ["direct-log"]
|
||||
default-features = false
|
||||
|
||||
[lints.clippy]
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
// except according to those terms.
|
||||
|
||||
#![allow(clippy::missing_errors_doc)] // Functions simply delegate to tokio and quinn-udp.
|
||||
#![allow(clippy::missing_panics_doc)] // Functions simply delegate to tokio and quinn-udp.
|
||||
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
|
@ -14,7 +13,7 @@ use std::{
|
|||
slice,
|
||||
};
|
||||
|
||||
use neqo_common::{qtrace, Datagram, IpTos};
|
||||
use neqo_common::{qdebug, qtrace, Datagram, IpTos};
|
||||
use quinn_udp::{EcnCodepoint, RecvMeta, Transmit, UdpSocketState};
|
||||
|
||||
/// Socket receive buffer size.
|
||||
|
@ -53,22 +52,44 @@ pub fn send_inner(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::os::fd::AsFd as SocketRef;
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::io::AsSocket as SocketRef;
|
||||
|
||||
pub fn recv_inner(
|
||||
local_address: &SocketAddr,
|
||||
state: &UdpSocketState,
|
||||
socket: quinn_udp::UdpSockRef<'_>,
|
||||
socket: impl SocketRef,
|
||||
) -> Result<Vec<Datagram>, io::Error> {
|
||||
let dgrams = RECV_BUF.with_borrow_mut(|recv_buf| -> Result<Vec<Datagram>, io::Error> {
|
||||
let mut meta = RecvMeta::default();
|
||||
let mut meta;
|
||||
|
||||
state.recv(
|
||||
socket,
|
||||
&mut [IoSliceMut::new(recv_buf)],
|
||||
slice::from_mut(&mut meta),
|
||||
)?;
|
||||
loop {
|
||||
meta = RecvMeta::default();
|
||||
|
||||
state.recv(
|
||||
(&socket).into(),
|
||||
&mut [IoSliceMut::new(recv_buf)],
|
||||
slice::from_mut(&mut meta),
|
||||
)?;
|
||||
|
||||
if meta.len == 0 || meta.stride == 0 {
|
||||
qdebug!(
|
||||
"ignoring datagram from {} to {} len {} stride {}",
|
||||
meta.addr,
|
||||
local_address,
|
||||
meta.len,
|
||||
meta.stride
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Ok(recv_buf[0..meta.len]
|
||||
.chunks(meta.stride.min(recv_buf.len()))
|
||||
.chunks(meta.stride)
|
||||
.map(|d| {
|
||||
qtrace!(
|
||||
"received {} bytes from {} to {}",
|
||||
|
@ -101,9 +122,7 @@ pub struct Socket<S> {
|
|||
inner: S,
|
||||
}
|
||||
|
||||
impl<#[cfg(unix)] S: std::os::fd::AsFd, #[cfg(windows)] S: std::os::windows::io::AsSocket>
|
||||
Socket<S>
|
||||
{
|
||||
impl<S: SocketRef> Socket<S> {
|
||||
/// Create a new [`Socket`] given a raw file descriptor managed externally.
|
||||
pub fn new(socket: S) -> Result<Self, io::Error> {
|
||||
Ok(Self {
|
||||
|
@ -120,7 +139,7 @@ impl<#[cfg(unix)] S: std::os::fd::AsFd, #[cfg(windows)] S: std::os::windows::io:
|
|||
/// Receive a batch of [`Datagram`]s on the given [`Socket`], each
|
||||
/// set with the provided local address.
|
||||
pub fn recv(&self, local_address: &SocketAddr) -> Result<Vec<Datagram>, io::Error> {
|
||||
recv_inner(local_address, &self.state, (&self.inner).into())
|
||||
recv_inner(local_address, &self.state, &self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,10 +149,37 @@ mod tests {
|
|||
|
||||
use super::*;
|
||||
|
||||
fn socket() -> Result<Socket<std::net::UdpSocket>, io::Error> {
|
||||
let socket = Socket::new(std::net::UdpSocket::bind("127.0.0.1:0")?)?;
|
||||
// Reverse non-blocking flag set by `UdpSocketState` to make the test non-racy.
|
||||
socket.inner.set_nonblocking(false)?;
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ignore_empty_datagram() -> Result<(), io::Error> {
|
||||
let sender = socket()?;
|
||||
let receiver = Socket::new(std::net::UdpSocket::bind("127.0.0.1:0")?)?;
|
||||
let receiver_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
|
||||
|
||||
let datagram = Datagram::new(
|
||||
sender.inner.local_addr()?,
|
||||
receiver.inner.local_addr()?,
|
||||
IpTos::default(),
|
||||
vec![],
|
||||
);
|
||||
|
||||
sender.send(&datagram)?;
|
||||
let res = receiver.recv(&receiver_addr);
|
||||
assert_eq!(res.unwrap_err().kind(), std::io::ErrorKind::WouldBlock);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn datagram_tos() -> Result<(), io::Error> {
|
||||
let sender = Socket::new(std::net::UdpSocket::bind("127.0.0.1:0")?)?;
|
||||
let receiver = Socket::new(std::net::UdpSocket::bind("127.0.0.1:0")?)?;
|
||||
let sender = socket()?;
|
||||
let receiver = socket()?;
|
||||
let receiver_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
|
||||
|
||||
let datagram = Datagram::new(
|
||||
|
@ -167,8 +213,8 @@ mod tests {
|
|||
fn many_datagrams_through_gro() -> Result<(), io::Error> {
|
||||
const SEGMENT_SIZE: usize = 128;
|
||||
|
||||
let sender = Socket::new(std::net::UdpSocket::bind("127.0.0.1:0")?)?;
|
||||
let receiver = Socket::new(std::net::UdpSocket::bind("127.0.0.1:0")?)?;
|
||||
let sender = socket()?;
|
||||
let receiver = socket()?;
|
||||
let receiver_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
|
||||
|
||||
// `neqo_udp::Socket::send` does not yet
|
||||
|
|
Загрузка…
Ссылка в новой задаче