Bug 1966980 - update neqo to v0.13.4 a=dmeehan DONTBUILD

Original Revision: https://phabricator.services.mozilla.com/D249829

Differential Revision: https://phabricator.services.mozilla.com/D251241
This commit is contained in:
Max Leonard Inden
2025-05-29 13:06:53 +00:00
committed by dmeehan@mozilla.com
parent 9d64600fbb
commit 3b461172fe
110 changed files with 1037 additions and 757 deletions

View File

@@ -100,9 +100,9 @@ git = "https://github.com/mozilla/mp4parse-rust"
rev = "e64650a686e5c5732395cd059e17cfd3b1e5b63b"
replace-with = "vendored-sources"
[source."git+https://github.com/mozilla/neqo?tag=v0.13.2"]
[source."git+https://github.com/mozilla/neqo?tag=v0.13.4"]
git = "https://github.com/mozilla/neqo"
tag = "v0.13.2"
tag = "v0.13.4"
replace-with = "vendored-sources"
[source."git+https://github.com/servo/rust-cssparser?rev=958a3f098acb92ddacdce18a7ef2c4a87ac3326f"]

45
Cargo.lock generated
View File

@@ -4673,15 +4673,15 @@ dependencies = [
"rustc-hash 1.999.999",
"serde",
"spirv",
"strum 0.27.1",
"strum",
"thiserror 2.0.9",
"unicode-ident",
]
[[package]]
name = "neqo-bin"
version = "0.13.2"
source = "git+https://github.com/mozilla/neqo?tag=v0.13.2#847a5989f20d30eb3675d1435180fd48a8c6a3ad"
version = "0.13.4"
source = "git+https://github.com/mozilla/neqo?tag=v0.13.4#c3179d9f363bf92a908d90e4240b315b9ff72516"
dependencies = [
"clap",
"clap-verbosity-flag",
@@ -4702,21 +4702,21 @@ dependencies = [
[[package]]
name = "neqo-common"
version = "0.13.2"
source = "git+https://github.com/mozilla/neqo?tag=v0.13.2#847a5989f20d30eb3675d1435180fd48a8c6a3ad"
version = "0.13.4"
source = "git+https://github.com/mozilla/neqo?tag=v0.13.4#c3179d9f363bf92a908d90e4240b315b9ff72516"
dependencies = [
"enum-map",
"env_logger",
"log",
"qlog",
"strum 0.26.999",
"strum",
"windows",
]
[[package]]
name = "neqo-crypto"
version = "0.13.2"
source = "git+https://github.com/mozilla/neqo?tag=v0.13.2#847a5989f20d30eb3675d1435180fd48a8c6a3ad"
version = "0.13.4"
source = "git+https://github.com/mozilla/neqo?tag=v0.13.4#c3179d9f363bf92a908d90e4240b315b9ff72516"
dependencies = [
"bindgen 0.69.4",
"enum-map",
@@ -4726,14 +4726,14 @@ dependencies = [
"semver",
"serde",
"serde_derive",
"strum 0.26.999",
"strum",
"toml",
]
[[package]]
name = "neqo-http3"
version = "0.13.2"
source = "git+https://github.com/mozilla/neqo?tag=v0.13.2#847a5989f20d30eb3675d1435180fd48a8c6a3ad"
version = "0.13.4"
source = "git+https://github.com/mozilla/neqo?tag=v0.13.4#c3179d9f363bf92a908d90e4240b315b9ff72516"
dependencies = [
"enumset",
"log",
@@ -4743,14 +4743,14 @@ dependencies = [
"neqo-transport",
"qlog",
"sfv",
"strum 0.26.999",
"strum",
"url",
]
[[package]]
name = "neqo-qpack"
version = "0.13.2"
source = "git+https://github.com/mozilla/neqo?tag=v0.13.2#847a5989f20d30eb3675d1435180fd48a8c6a3ad"
version = "0.13.4"
source = "git+https://github.com/mozilla/neqo?tag=v0.13.4#c3179d9f363bf92a908d90e4240b315b9ff72516"
dependencies = [
"log",
"neqo-common",
@@ -4761,8 +4761,8 @@ dependencies = [
[[package]]
name = "neqo-transport"
version = "0.13.2"
source = "git+https://github.com/mozilla/neqo?tag=v0.13.2#847a5989f20d30eb3675d1435180fd48a8c6a3ad"
version = "0.13.4"
source = "git+https://github.com/mozilla/neqo?tag=v0.13.4#c3179d9f363bf92a908d90e4240b315b9ff72516"
dependencies = [
"enum-map",
"enumset",
@@ -4774,13 +4774,13 @@ dependencies = [
"qlog",
"smallvec",
"static_assertions",
"strum 0.26.999",
"strum",
]
[[package]]
name = "neqo-udp"
version = "0.13.2"
source = "git+https://github.com/mozilla/neqo?tag=v0.13.2#847a5989f20d30eb3675d1435180fd48a8c6a3ad"
version = "0.13.4"
source = "git+https://github.com/mozilla/neqo?tag=v0.13.4#c3179d9f363bf92a908d90e4240b315b9ff72516"
dependencies = [
"cfg_aliases",
"log",
@@ -6297,13 +6297,6 @@ version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "strum"
version = "0.26.999"
dependencies = [
"strum 0.27.1",
]
[[package]]
name = "strum"
version = "0.27.1"

View File

@@ -217,9 +217,6 @@ half = { path = "build/rust/half" }
# Upgrade `rusqlite` 0.31 to 0.33.
rusqlite = { path = "build/rust/rusqlite" }
# Patch `strum` 0.26.* to 0.27.
strum = { path = "build/rust/strum" }
# Patch `itertools` 0.10.* to 0.14.
itertools = { path = "build/rust/itertools" }

View File

@@ -1,17 +0,0 @@
[package]
name = "strum"
version = "0.26.999"
edition = "2018"
license = "MIT OR Apache-2.0"
[lib]
path = "lib.rs"
[dependencies.strum]
version = "0.27.1"
default-features = false
[features]
default = ["strum/default"]
derive = ["strum/derive"]
std = ["strum/std"]

View File

@@ -1,5 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
pub use strum::*;

View File

@@ -10,11 +10,11 @@ name = "neqo_glue"
[dependencies]
firefox-on-glean = { path = "../../../toolkit/components/glean/api" }
neqo-udp = { tag = "v0.13.2", git = "https://github.com/mozilla/neqo" }
neqo-http3 = { tag = "v0.13.2", git = "https://github.com/mozilla/neqo" }
neqo-transport = { tag = "v0.13.2", git = "https://github.com/mozilla/neqo", features = ["gecko"] }
neqo-common = { tag = "v0.13.2", git = "https://github.com/mozilla/neqo" }
neqo-qpack = { tag = "v0.13.2", git = "https://github.com/mozilla/neqo" }
neqo-udp = { tag = "v0.13.4", git = "https://github.com/mozilla/neqo" }
neqo-http3 = { tag = "v0.13.4", git = "https://github.com/mozilla/neqo" }
neqo-transport = { tag = "v0.13.4", git = "https://github.com/mozilla/neqo", features = ["gecko"] }
neqo-common = { tag = "v0.13.4", git = "https://github.com/mozilla/neqo" }
neqo-qpack = { tag = "v0.13.4", git = "https://github.com/mozilla/neqo" }
nserror = { path = "../../../xpcom/rust/nserror" }
nsstring = { path = "../../../xpcom/rust/nsstring" }
xpcom = { path = "../../../xpcom/rust/xpcom" }
@@ -30,7 +30,7 @@ uuid = { version = "1.0", features = ["v4"] }
winapi = {version = "0.3", features = ["ws2def"] }
[dependencies.neqo-crypto]
tag = "v0.13.2"
tag = "v0.13.4"
git = "https://github.com/mozilla/neqo"
default-features = false
features = ["gecko"]

View File

@@ -6,11 +6,11 @@ edition = "2021"
license = "MPL-2.0"
[dependencies]
neqo-bin = { tag = "v0.13.2", git = "https://github.com/mozilla/neqo" }
neqo-transport = { tag = "v0.13.2", git = "https://github.com/mozilla/neqo", features = ["gecko"] }
neqo-common = { tag = "v0.13.2", git = "https://github.com/mozilla/neqo" }
neqo-http3 = { tag = "v0.13.2", git = "https://github.com/mozilla/neqo" }
neqo-qpack = { tag = "v0.13.2", git = "https://github.com/mozilla/neqo" }
neqo-bin = { tag = "v0.13.4", git = "https://github.com/mozilla/neqo" }
neqo-transport = { tag = "v0.13.4", git = "https://github.com/mozilla/neqo", features = ["gecko"] }
neqo-common = { tag = "v0.13.4", git = "https://github.com/mozilla/neqo" }
neqo-http3 = { tag = "v0.13.4", git = "https://github.com/mozilla/neqo" }
neqo-qpack = { tag = "v0.13.4", git = "https://github.com/mozilla/neqo" }
log = "0.4.0"
base64 = "0.22"
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.13.2"
tag = "v0.13.4"
git = "https://github.com/mozilla/neqo"
default-features = false
features = ["gecko"]

View File

@@ -1 +1 @@
{"files":{"Cargo.toml":"fe9c02bbcdb328cbe918ef5f0dcddcb86edbcb8ee571f4853eab1ee493101eeb","benches/main.rs":"7bd395227024b062e87eff0e7e2afa4a2dc70d7497c999aa665709577818f466","src/bin/client.rs":"71952208bcee80e8ff37a5dfe7cac19940274157e8ecf8acc6edc4d918c813b7","src/bin/server.rs":"88d3b2310f4a899053603cce4fd03703f26a8b91ff487bf5942b6e45c135a9fa","src/client/http09.rs":"b0b3ff496dbf35fe582a3f02780792bba34cb510d2acbcb43023180bec27cae1","src/client/http3.rs":"3f7bd425fa3bbdea005c91be6f25c861dc20819c2aeee42d4ffab7a7e3ef7282","src/client/mod.rs":"9185f1039d1e920a720330ec8b63f8b42d3924c26e95b6636436c9c5e1ae20a1","src/lib.rs":"ced2561bbebce6440b8ee902316afe7ca9df8dfeb632053587854838815e7c74","src/send_data.rs":"7537b7a0f67e9077cf121cc3d0fcd42edb085801dd4baf25b14c22a01f1bf04f","src/server/http09.rs":"b5236d9cc7b3c6c46cef9be521bc85e1b618960c0315465760a3d58e92c82c32","src/server/http3.rs":"2c826fb81a792221878a6d16bcaf6f1bed88fe0b424315c262eb08479ac5b4c4","src/server/mod.rs":"1c4c453452e5788ea3b3ab0c2d2193a291a39426466a28d8a0b384206392d485","src/udp.rs":"d68cd0fba6a0e679f79cce5c443bceba48c6ddbd2b5f492a075c9da8765b3047"},"package":null}
{"files":{"Cargo.toml":"e0ccf35b725320581203bcf6fb300faeffad669446c0fe87adb36e77d4175e1f","benches/main.rs":"4df49ffa42111e43c77e994c17d5b68037a5789561adbe4c762cb9617ada0cc4","src/bin/client.rs":"71952208bcee80e8ff37a5dfe7cac19940274157e8ecf8acc6edc4d918c813b7","src/bin/server.rs":"88d3b2310f4a899053603cce4fd03703f26a8b91ff487bf5942b6e45c135a9fa","src/client/http09.rs":"fe2932ee31dfdc6d9e884b9f3385a0794441e7e08fb45374913db1d1af7c263d","src/client/http3.rs":"6f4b0e099d7665bd164c23588e7fe49b883c15fe750a1438e74cb391cd3a4a56","src/client/mod.rs":"9185f1039d1e920a720330ec8b63f8b42d3924c26e95b6636436c9c5e1ae20a1","src/lib.rs":"b0de1791203ea0fc80ef09975a311c87ef5fbf8eb879e8858ec7d241d552d817","src/send_data.rs":"7537b7a0f67e9077cf121cc3d0fcd42edb085801dd4baf25b14c22a01f1bf04f","src/server/http09.rs":"9e366cc04fc7c891a72f0de17634a3e5073b0dc750b0d0cf0968629ca4f764cb","src/server/http3.rs":"491588eb1f72609171024bdab2b4365117be1a94a4def0a8c2615faf393bd004","src/server/mod.rs":"95ec163108964edd7eca814f0abdff6efa548624a840a778ada27299d58841dd","src/udp.rs":"be9cfd9378801fa212a4d3a767e475c124ec04b2ea8d7c208f975aac7368ea5d"},"package":null}

View File

@@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.82.0"
name = "neqo-bin"
version = "0.13.2"
version = "0.13.4"
authors = ["The Neqo Authors <necko@mozilla.com>"]
build = false
autolib = false
@@ -49,6 +49,7 @@ bench = [
"neqo-transport/bench",
]
draft-29 = []
fast-apple-datapath = ["quinn-udp/fast-apple-datapath"]
[lib]
name = "neqo_bin"
@@ -123,10 +124,7 @@ default-features = false
[dependencies.quinn-udp]
version = "0.5.11"
features = [
"direct-log",
"fast-apple-datapath",
]
features = ["direct-log"]
default-features = false
[dependencies.regex]
@@ -150,8 +148,11 @@ features = ["std"]
default-features = false
[dev-dependencies.criterion]
version = "0.5"
features = ["async_tokio"]
version = "0.6"
features = [
"async_tokio",
"cargo_bench_support",
]
default-features = false
[dev-dependencies.neqo-bin]
@@ -180,17 +181,20 @@ create_dir = "warn"
dbg_macro = "warn"
empty_drop = "warn"
empty_enum_variants_with_brackets = "warn"
field_scoped_visibility_modifiers = "warn"
filetype_is_file = "warn"
float_cmp_const = "warn"
fn_to_numeric_cast_any = "warn"
get_unwrap = "warn"
if_then_some_else_none = "warn"
infinite_loop = "warn"
iter_over_hash_type = "warn"
large_include_file = "warn"
let_underscore_must_use = "warn"
let_underscore_untyped = "warn"
literal_string_with_formatting_args = "allow"
lossy_float_literal = "warn"
map_with_unused_argument_over_ranges = "warn"
mem_forget = "warn"
mixed_read_write_in_expression = "warn"
module_name_repetitions = "warn"
@@ -199,14 +203,18 @@ multiple_inherent_impl = "warn"
mutex_atomic = "warn"
mutex_integer = "warn"
needless_raw_strings = "warn"
partial_pub_fields = "warn"
pathbuf_init_then_push = "warn"
precedence_bits = "warn"
pub_without_shorthand = "warn"
rc_buffer = "warn"
rc_mutex = "warn"
redundant_test_prefix = "warn"
redundant_type_annotations = "warn"
ref_patterns = "warn"
renamed_function_params = "warn"
rest_pat_in_fully_bound_structs = "warn"
return_and_then = "warn"
self_named_module_files = "warn"
semicolon_inside_block = "warn"
string_lit_chars_any = "warn"

View File

@@ -6,7 +6,7 @@
#![expect(clippy::unwrap_used, reason = "OK in a bench.")]
use std::{env, path::PathBuf, str::FromStr as _};
use std::{env, hint::black_box, path::PathBuf, str::FromStr as _, time::Duration};
use criterion::{criterion_group, criterion_main, BatchSize, Criterion, Throughput};
use neqo_bin::{client, server};
@@ -60,8 +60,10 @@ fn transfer(c: &mut Criterion) {
b.to_async(Builder::new_current_thread().enable_all().build().unwrap())
.iter_batched(
|| client::client(client::Args::new(&requests, upload)),
|client| async move {
client.await.unwrap();
|client| {
black_box(async move {
client.await.unwrap();
})
},
BatchSize::PerIteration,
);
@@ -72,11 +74,6 @@ fn transfer(c: &mut Criterion) {
done_sender.send(()).unwrap();
}
#[allow(
clippy::allow_attributes,
clippy::redundant_pub_crate,
reason = "TODO: Bug in clippy nursery?"
)]
fn spawn_server() -> tokio::sync::oneshot::Sender<()> {
let (done_sender, mut done_receiver) = tokio::sync::oneshot::channel();
std::thread::spawn(move || {
@@ -95,5 +92,9 @@ fn spawn_server() -> tokio::sync::oneshot::Sender<()> {
done_sender
}
criterion_group!(benches, transfer);
criterion_group! {
name = benches;
config = Criterion::default().warm_up_time(Duration::from_secs(5)).measurement_time(Duration::from_secs(60));
targets = transfer
}
criterion_main!(benches);

View File

@@ -11,6 +11,7 @@
use std::{
cell::RefCell,
collections::{HashMap, VecDeque},
fmt::Display,
fs::File,
io::{BufWriter, Write as _},
net::SocketAddr,
@@ -203,7 +204,7 @@ impl super::Client for Connection {
fn close<S>(&mut self, now: Instant, app_error: neqo_transport::AppError, msg: S)
where
S: AsRef<str> + std::fmt::Display,
S: AsRef<str> + Display,
{
if !self.state().closed() {
self.close(now, app_error, msg);

View File

@@ -186,8 +186,8 @@ impl super::Handler for Handler<'_> {
fin,
..
} => {
if let Some(handler) = self.url_handler.stream_handler(stream_id) {
handler.process_header_ready(stream_id, fin, headers);
if self.url_handler.stream_handler(stream_id).is_some() {
qdebug!("READ HEADERS[{stream_id}]: fin={fin} {headers:?}");
} else {
qwarn!("Data on unexpected stream: {stream_id}");
}
@@ -267,7 +267,6 @@ impl super::Handler for Handler<'_> {
}
trait StreamHandler {
fn process_header_ready(&mut self, stream_id: StreamId, fin: bool, headers: Vec<Header>);
fn process_data_readable(
&mut self,
stream_id: StreamId,
@@ -283,12 +282,6 @@ struct DownloadStreamHandler {
}
impl StreamHandler for DownloadStreamHandler {
fn process_header_ready(&mut self, stream_id: StreamId, fin: bool, headers: Vec<Header>) {
if self.out_file.is_none() {
qdebug!("READ HEADERS[{stream_id}]: fin={fin} {headers:?}");
}
}
fn process_data_readable(
&mut self,
stream_id: StreamId,
@@ -329,10 +322,6 @@ struct UploadStreamHandler {
}
impl StreamHandler for UploadStreamHandler {
fn process_header_ready(&mut self, stream_id: StreamId, fin: bool, headers: Vec<Header>) {
qdebug!("READ HEADERS[{stream_id}]: fin={fin} {headers:?}");
}
fn process_data_readable(
&mut self,
stream_id: StreamId,
@@ -344,8 +333,10 @@ impl StreamHandler for UploadStreamHandler {
let trimmed_txt = txt.trim_end_matches(char::from(0));
let parsed: usize = trimmed_txt.parse().map_err(|_| Error::InvalidInput)?;
if parsed == self.data.len() {
let upload_time = Instant::now().duration_since(self.start);
qinfo!("Stream ID: {stream_id:?}, Upload time: {upload_time:?}");
qinfo!(
"Stream ID: {stream_id:?}, Upload time: {:?}",
Instant::now().duration_since(self.start)
);
}
Ok(())
} else {

View File

@@ -36,32 +36,32 @@ pub struct SharedArgs {
/// ALPN labels to negotiate.
///
/// This client still only does HTTP/3 no matter what the ALPN says.
pub alpn: String,
alpn: String,
#[arg(name = "qlog-dir", long, value_parser=clap::value_parser!(PathBuf))]
/// Enable QLOG logging and QLOG traces to this directory
pub qlog_dir: Option<PathBuf>,
qlog_dir: Option<PathBuf>,
#[arg(name = "encoder-table-size", long, default_value = "16384")]
pub max_table_size_encoder: u64,
max_table_size_encoder: u64,
#[arg(name = "decoder-table-size", long, default_value = "16384")]
pub max_table_size_decoder: u64,
max_table_size_decoder: u64,
#[arg(name = "max-blocked-streams", short = 'b', long, default_value = "10")]
pub max_blocked_streams: u16,
max_blocked_streams: u16,
#[arg(short = 'c', long, number_of_values = 1)]
/// The set of TLS cipher suites to enable.
/// From: `TLS_AES_128_GCM_SHA256`, `TLS_AES_256_GCM_SHA384`, `TLS_CHACHA20_POLY1305_SHA256`.
pub ciphers: Vec<String>,
ciphers: Vec<String>,
#[arg(name = "qns-test", long)]
/// Enable special behavior for use with QUIC Network Simulator
pub qns_test: Option<String>,
qns_test: Option<String>,
#[command(flatten)]
pub quic_parameters: QuicParameters,
quic_parameters: QuicParameters,
}
#[cfg(any(test, feature = "bench"))]

View File

@@ -6,7 +6,15 @@
#![expect(clippy::unwrap_used, reason = "This is example code.")]
use std::{borrow::Cow, cell::RefCell, collections::HashMap, fmt::Display, rc::Rc, time::Instant};
use std::{
borrow::Cow,
cell::RefCell,
collections::HashMap,
fmt::{self, Display, Formatter},
rc::Rc,
slice, str,
time::Instant,
};
use neqo_common::{event::Provider as _, hex, qdebug, qerror, qinfo, qwarn, Datagram};
use neqo_crypto::{generate_ech_keys, random, AllowZeroRtt, AntiReplay};
@@ -43,8 +51,8 @@ impl HttpServer {
) -> Result<Self, Error> {
let mut server = Server::new(
args.now(),
&[args.key.clone()],
&[args.shared.alpn.clone()],
slice::from_ref(&args.key),
slice::from_ref(&args.shared.alpn),
anti_replay,
Box::new(AllowZeroRtt {}),
cid_manager,
@@ -61,8 +69,7 @@ impl HttpServer {
server
.enable_ech(random::<1>()[0], "public.example", &sk, &pk)
.map_err(|_| Error::Internal)?;
let cfg = server.ech_config();
qinfo!("ECHConfigList: {}", hex(cfg));
qinfo!("ECHConfigList: {}", hex(server.ech_config()));
}
let is_qns_test = args.shared.qns_test.is_some();
@@ -81,13 +88,19 @@ impl HttpServer {
}
fn save_partial(&mut self, stream_id: StreamId, partial: Vec<u8>, conn: &ConnectionRef) {
let url_dbg = String::from_utf8(partial.clone())
.unwrap_or_else(|_| format!("<invalid UTF-8: {}>", hex(&partial)));
if partial.len() < 4096 {
qdebug!("Saving partial URL: {url_dbg}");
qdebug!(
"Saving partial URL: {}",
String::from_utf8(partial.clone())
.unwrap_or_else(|_| format!("<invalid UTF-8: {}>", hex(&partial)))
);
self.read_state.insert(stream_id, partial);
} else {
qdebug!("Giving up on partial URL {url_dbg}");
qdebug!(
"Giving up on partial URL {}",
String::from_utf8(partial.clone())
.unwrap_or_else(|_| format!("<invalid UTF-8: {}>", hex(&partial)))
);
conn.borrow_mut().stream_stop_sending(stream_id, 0).unwrap();
}
}
@@ -118,7 +131,7 @@ impl HttpServer {
},
);
let Ok(msg) = std::str::from_utf8(&buf[..]) else {
let Ok(msg) = str::from_utf8(&buf[..]) else {
self.save_partial(stream_id, buf.to_vec(), conn);
return;
};
@@ -197,11 +210,14 @@ impl super::HttpServer for HttpServer {
reason = "ActiveConnectionRef::Hash doesn't access any of the interior mutable types"
)]
let active_conns = self.server.active_connections();
#[expect(
clippy::iter_over_hash_type,
reason = "OK to loop over active connections in an undefined order."
)]
for acr in active_conns {
loop {
let event = match acr.borrow_mut().next_event() {
None => break,
Some(e) => e,
let Some(event) = acr.borrow_mut().next_event() else {
break;
};
match event {
ConnectionEvent::NewStream { stream_id } => {
@@ -235,7 +251,7 @@ impl super::HttpServer for HttpServer {
}
impl Display for HttpServer {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Http 0.9 server ")
}
}

View File

@@ -11,6 +11,7 @@ use std::{
collections::HashMap,
fmt::{self, Display},
rc::Rc,
slice,
time::Instant,
};
@@ -40,8 +41,8 @@ impl HttpServer {
) -> Self {
let mut server = Http3Server::new(
args.now(),
&[args.key.clone()],
&[args.shared.alpn.clone()],
slice::from_ref(&args.key),
slice::from_ref(&args.shared.alpn),
anti_replay,
cid_mgr,
Http3Parameters::default()
@@ -63,8 +64,7 @@ impl HttpServer {
server
.enable_ech(random::<1>()[0], "public.example", &sk, &pk)
.unwrap();
let cfg = server.ech_config();
qinfo!("ECHConfigList: {}", hex(cfg));
qinfo!("ECHConfigList: {}", hex(server.ech_config()));
}
Self {
server,

View File

@@ -418,8 +418,10 @@ pub async fn server(mut args: Args) -> Res<()> {
.into_iter()
.map(|host| {
let socket = crate::udp::Socket::bind(host)?;
let local_addr = socket.local_addr()?;
qinfo!("Server waiting for connection on: {local_addr:?}");
qinfo!(
"Server waiting for connection on: {:?}",
socket.local_addr()
);
Ok((host, socket))
})

View File

@@ -30,7 +30,6 @@ impl Socket {
let socket = std::net::UdpSocket::bind(addr)?;
let state = quinn_udp::UdpSocketState::new((&socket).into())?;
let send_buf_before = state.send_buffer_size((&socket).into())?;
// FIXME: We need to experiment if increasing this actually improves performance.
// Also, on BSD and Apple targets, this seems to increase the `net.inet.udp.maxdgram`
// sysctl, which is not the same as the socket buffer.
@@ -41,15 +40,20 @@ impl Socket {
// {send_buf_after}"); } else {
// qdebug!("Default socket send buffer size is {send_buf_before}, not changing");
// }
qdebug!("Default socket send buffer size is {send_buf_before}");
qdebug!(
"Default socket send buffer size is {:?}",
state.send_buffer_size((&socket).into())
);
let recv_buf_before = state.recv_buffer_size((&socket).into())?;
if recv_buf_before < ONE_MB {
// Same as Firefox.
// <https://searchfox.org/mozilla-central/rev/fa5b44a4ea5c98b6a15f39638ea4cd04dc271f3d/modules/libpref/init/StaticPrefList.yaml#13474-13477>
state.set_recv_buffer_size((&socket).into(), ONE_MB)?;
let recv_buf_after = state.recv_buffer_size((&socket).into())?;
qdebug!("Increasing socket recv buffer size from {recv_buf_before} to {ONE_MB}, now: {recv_buf_after}");
qdebug!(
"Increasing socket recv buffer size from {recv_buf_before} to {ONE_MB}, now: {:?}",
state.recv_buffer_size((&socket).into())
);
} else {
qdebug!("Default socket receive buffer size is {recv_buf_before}, not changing");
}

View File

@@ -1 +1 @@
{"files":{"Cargo.toml":"ccf547219da914519d3e2a82b673bf911dc60632b342bab3fdaa64283c7c442b","benches/decoder.rs":"3b03abd08c064d11c07e6d4eaf041873c282adf93e9bc76e40f2f0137e342929","build.rs":"d9accad1f92a1d82aff73a588269342db882918173e8d9b2b914c514e42e2839","src/codec.rs":"b56abcf6fc76d7c24a6f25e0df556fa3c47a37249b43ae97451944082d344a30","src/datagram.rs":"88ef237b95b4ce10abe5e8e4740a4a8178f19146fc82c49053d3b62819ac428a","src/event.rs":"289cf8e265c33e7cded58820ac81e5b575e3f84dd52fa18b0761f4094fb361c0","src/fuzz.rs":"9e0f2dca1832ef49b93b214e8d5f1ca2f5f8cb84a856fead344f62a722c370db","src/header.rs":"b561dffd52ec8909297ec67ac5f75150dfca73399111e709cf6ea7a34998fca5","src/hrtime.rs":"7096fd12ccc33566aac58f19a4e7439690b2fa38c258584946f76a422ab98087","src/incrdecoder.rs":"029081f0ae19db49c3278c865f22584fc24315169e5ffc1bd5a0087e8c0d38b9","src/lib.rs":"5f15b8b96cd8935e4cc231bb37d45458794ffe23eea0db1b37e42ea7346ac10d","src/log.rs":"61a9b24bf6bf1493da67082bcf7fef8fe55f0a23d7f2a9ad13748982c54c85e2","src/qlog.rs":"3c6f403f0ad2b34fc7ba63b1338bc0855bc232a2b5dd5c1039846b10af2b1d35","src/tos.rs":"108ebfcadf172aae1ba1c722316080b70ec017bf9c866f1ab8d315231d04fd09","tests/log.rs":"671a963f938599b76c0678f3931592e1782765ed4ea13e6cbfec2ab97c36e2c9"},"package":null}
{"files":{"Cargo.toml":"6d253478c2ffa214d265a89e5aba2064a136a2911f3fba7258c9695d97c35f8b","benches/decoder.rs":"e314d87370b5f2ee1b743c5c77a245aeda423d2e78fc51c5e0316f733ab7648b","build.rs":"d9accad1f92a1d82aff73a588269342db882918173e8d9b2b914c514e42e2839","src/codec.rs":"fd6593c49deae63836882d7ac19fe3ec95f62d9ec3c2b476070cb04e33403ea5","src/datagram.rs":"685b810f44be30c5726200c3a9e06a42aa1d1552b3b5d409f7c8e3e2854abea0","src/event.rs":"289cf8e265c33e7cded58820ac81e5b575e3f84dd52fa18b0761f4094fb361c0","src/fuzz.rs":"9e0f2dca1832ef49b93b214e8d5f1ca2f5f8cb84a856fead344f62a722c370db","src/header.rs":"a316f48735375da268142ad9ac3430d240162c9df67114546f4a094c25a10024","src/hrtime.rs":"cc5efecc178ea0d650bc6834e03acd9975b0d000f6e384f0ce51e7b8141a6ba6","src/incrdecoder.rs":"029081f0ae19db49c3278c865f22584fc24315169e5ffc1bd5a0087e8c0d38b9","src/lib.rs":"201e2ee6b8fbfb8cabc719598b3033334b1be1a1d9e0526192cb599babe5aeed","src/log.rs":"61a9b24bf6bf1493da67082bcf7fef8fe55f0a23d7f2a9ad13748982c54c85e2","src/qlog.rs":"3c6f403f0ad2b34fc7ba63b1338bc0855bc232a2b5dd5c1039846b10af2b1d35","src/tos.rs":"a14e36fc1a6a2a8194fcad50ca861891fab8e3c5c8fe8a34bee22fe599f841b3","tests/log.rs":"671a963f938599b76c0678f3931592e1782765ed4ea13e6cbfec2ab97c36e2c9"},"package":null}

View File

@@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.82.0"
name = "neqo-common"
version = "0.13.2"
version = "0.13.4"
authors = ["The Neqo Authors <necko@mozilla.com>"]
build = "build.rs"
autolib = false
@@ -85,12 +85,13 @@ version = "0.15.1"
default-features = false
[dependencies.strum]
version = "0.26"
version = "0.27"
features = ["derive"]
default-features = false
[dev-dependencies.criterion]
version = "0.5"
version = "0.6"
features = ["cargo_bench_support"]
default-features = false
[dev-dependencies.neqo-crypto]
@@ -117,17 +118,20 @@ create_dir = "warn"
dbg_macro = "warn"
empty_drop = "warn"
empty_enum_variants_with_brackets = "warn"
field_scoped_visibility_modifiers = "warn"
filetype_is_file = "warn"
float_cmp_const = "warn"
fn_to_numeric_cast_any = "warn"
get_unwrap = "warn"
if_then_some_else_none = "warn"
infinite_loop = "warn"
iter_over_hash_type = "warn"
large_include_file = "warn"
let_underscore_must_use = "warn"
let_underscore_untyped = "warn"
literal_string_with_formatting_args = "allow"
lossy_float_literal = "warn"
map_with_unused_argument_over_ranges = "warn"
mem_forget = "warn"
mixed_read_write_in_expression = "warn"
module_name_repetitions = "warn"
@@ -136,14 +140,18 @@ multiple_inherent_impl = "warn"
mutex_atomic = "warn"
mutex_integer = "warn"
needless_raw_strings = "warn"
partial_pub_fields = "warn"
pathbuf_init_then_push = "warn"
precedence_bits = "warn"
pub_without_shorthand = "warn"
rc_buffer = "warn"
rc_mutex = "warn"
redundant_test_prefix = "warn"
redundant_type_annotations = "warn"
ref_patterns = "warn"
renamed_function_params = "warn"
rest_pat_in_fully_bound_structs = "warn"
return_and_then = "warn"
self_named_module_files = "warn"
semicolon_inside_block = "warn"
string_lit_chars_any = "warn"

View File

@@ -6,7 +6,9 @@
#![expect(clippy::unwrap_used, reason = "OK in a bench.")]
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use std::{hint::black_box, time::Duration};
use criterion::{criterion_group, criterion_main, Criterion};
use neqo_common::Decoder;
use neqo_crypto::{init, randomize};
@@ -50,5 +52,9 @@ fn benchmark_decoder(c: &mut Criterion) {
}
}
criterion_group!(benches, benchmark_decoder);
criterion_group! {
name = benches;
config = Criterion::default().warm_up_time(Duration::from_secs(5)).measurement_time(Duration::from_secs(60));
targets = benchmark_decoder
}
criterion_main!(benches);

View File

@@ -4,10 +4,12 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt::Debug;
use std::fmt::{self, Debug, Formatter, Write};
use crate::hex_with_len;
pub const MAX_VARINT: u64 = (1 << 62) - 1;
/// Decoder is a view into a byte array that has a read offset. Use it for parsing.
pub struct Decoder<'a> {
buf: &'a [u8],
@@ -113,7 +115,7 @@ impl<'a> Decoder<'a> {
/// Signed types will fail if the high bit is set.
pub fn decode_uint<T: TryFrom<u64>>(&mut self) -> Option<T> {
let v = self.decode_n(size_of::<T>());
v.and_then(|v| T::try_from(v).ok())
T::try_from(v?).ok()
}
/// Decodes a QUIC varint.
@@ -168,7 +170,7 @@ impl<'a> AsRef<[u8]> for Decoder<'a> {
}
impl Debug for Decoder<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.write_str(&hex_with_len(self.as_ref()))
}
}
@@ -433,7 +435,7 @@ impl Encoder {
}
impl Debug for Encoder {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.write_str(&hex_with_len(self))
}
}
@@ -470,6 +472,13 @@ impl From<Encoder> for Vec<u8> {
}
}
impl Write for Encoder {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.buf.extend_from_slice(s.as_bytes());
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::{Decoder, Encoder};

View File

@@ -5,6 +5,7 @@
// except according to those terms.
use std::{
fmt::{self, Debug, Formatter},
net::SocketAddr,
ops::{Deref, DerefMut},
};
@@ -80,8 +81,8 @@ impl<D: AsRef<[u8]>> Deref for Datagram<D> {
}
}
impl<D: AsRef<[u8]>> std::fmt::Debug for Datagram<D> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
impl<D: AsRef<[u8]>> Debug for Datagram<D> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(
f,
"Datagram {:?} {:?}->{:?}: {}",

View File

@@ -36,21 +36,11 @@ impl Header {
)
}
#[allow(
clippy::allow_attributes,
clippy::missing_const_for_fn,
reason = "TODO: False positive on nightly."
)]
#[must_use]
pub fn name(&self) -> &str {
&self.name
}
#[allow(
clippy::allow_attributes,
clippy::missing_const_for_fn,
reason = "TODO: False positive on nightly."
)]
#[must_use]
pub fn value(&self) -> &str {
&self.value

View File

@@ -392,8 +392,9 @@ mod test {
use super::Time;
const ONE: Duration = Duration::from_millis(1);
const ONE_AND_A_BIT: Duration = Duration::from_micros(1500);
const ONE_MS: Duration = Duration::from_millis(1);
const FIVE_MS: Duration = Duration::from_millis(5);
const ONE_MS_AND_A_BIT: Duration = Duration::from_micros(1500);
/// A limit for when high resolution timers are disabled.
const GENEROUS: Duration = Duration::from_millis(30);
@@ -405,9 +406,9 @@ mod test {
for d in durations {
sleep(d);
let e = Instant::now();
let actual = e - s;
let lag = actual - d;
println!("sleep({d:?}) \u{2192} {actual:?} \u{394}{lag:?}");
let actual = e.saturating_duration_since(s);
let lag = actual.saturating_sub(d);
println!("sleep({d:>4?}) \u{2192} {actual:>11.6?} \u{394}{lag:>10?}");
if lag > max_lag {
return Err(());
}
@@ -416,13 +417,33 @@ mod test {
Ok(())
}
/// Validate the delays twice. Sometimes the first run can stall.
/// Validate the delays multiple times. Sometimes a run can stall.
/// Reliability in CI is more important than reliable timers.
/// Any failure results in enqueing two additional checks,
/// up to a limit that is determined based on how small `max_lag` is.
/// If the count exceeds that limit, fail the test.
fn check_delays(max_lag: Duration) {
if validate_delays(max_lag).is_err() {
let max_loops = if max_lag < FIVE_MS {
5
} else if max_lag < GENEROUS {
3
} else {
1
};
let mut count = 1;
while count <= max_loops {
if validate_delays(max_lag).is_ok() {
count -= 1;
} else {
count += 1;
}
if count == 0 {
return;
}
sleep(Duration::from_millis(50));
validate_delays(max_lag).unwrap();
}
panic!("timers slipped too often");
}
/// Note that you have to run this test alone or other tests will
@@ -434,8 +455,8 @@ mod test {
#[test]
fn one_ms() {
let _hrt = Time::get(ONE);
check_delays(ONE_AND_A_BIT);
let _hrt = Time::get(ONE_MS);
check_delays(ONE_MS_AND_A_BIT);
}
#[test]
@@ -462,18 +483,19 @@ mod test {
one_ms();
});
let _hrt = Time::get(Duration::from_millis(4));
check_delays(Duration::from_millis(5));
check_delays(FIVE_MS);
thr.join().unwrap();
}
#[test]
fn update() {
let mut hrt = Time::get(Duration::from_millis(4));
check_delays(Duration::from_millis(5));
hrt.update(ONE);
check_delays(ONE_AND_A_BIT);
check_delays(FIVE_MS);
hrt.update(ONE_MS);
check_delays(ONE_MS_AND_A_BIT);
}
#[cfg(not(target_arch = "arm"))] // This test is flaky on linux/arm.
#[test]
fn update_multi() {
let thr = spawn(move || {
@@ -488,4 +510,11 @@ mod test {
let _hrt = Time::get(Duration::from_secs(1));
check_delays(GENEROUS);
}
#[test]
#[should_panic(expected = "timers slipped too often")]
fn slip() {
// This amount of timer resolution should be unachievable.
check_delays(Duration::from_nanos(1));
}
}

View File

@@ -24,7 +24,7 @@ use strum::Display;
#[cfg(feature = "build-fuzzing-corpus")]
pub use self::fuzz::write_item_to_fuzzing_corpus;
pub use self::{
codec::{Decoder, Encoder},
codec::{Decoder, Encoder, MAX_VARINT},
datagram::Datagram,
header::Header,
incrdecoder::{IncrementalDecoderBuffer, IncrementalDecoderIgnore, IncrementalDecoderUint},
@@ -35,7 +35,7 @@ pub use self::{
pub fn hex(buf: impl AsRef<[u8]>) -> String {
let mut ret = String::with_capacity(buf.as_ref().len() * 2);
for b in buf.as_ref() {
write!(&mut ret, "{b:02x}").unwrap();
write!(&mut ret, "{b:02x}").expect("write OK");
}
ret
}
@@ -48,13 +48,13 @@ pub fn hex_snip_middle(buf: impl AsRef<[u8]>) -> String {
hex_with_len(buf)
} else {
let mut ret = String::with_capacity(SHOW_LEN * 2 + 16);
write!(&mut ret, "[{}]: ", buf.len()).unwrap();
write!(&mut ret, "[{}]: ", buf.len()).expect("write OK");
for b in &buf[..SHOW_LEN] {
write!(&mut ret, "{b:02x}").unwrap();
write!(&mut ret, "{b:02x}").expect("write OK");
}
ret.push_str("..");
for b in &buf[buf.len() - SHOW_LEN..] {
write!(&mut ret, "{b:02x}").unwrap();
write!(&mut ret, "{b:02x}").expect("write OK");
}
ret
}
@@ -64,9 +64,9 @@ pub fn hex_snip_middle(buf: impl AsRef<[u8]>) -> String {
pub fn hex_with_len(buf: impl AsRef<[u8]>) -> String {
let buf = buf.as_ref();
let mut ret = String::with_capacity(10 + buf.len() * 2);
write!(&mut ret, "[{}]: ", buf.len()).unwrap();
write!(&mut ret, "[{}]: ", buf.len()).expect("write OK");
for b in buf {
write!(&mut ret, "{b:02x}").unwrap();
write!(&mut ret, "{b:02x}").expect("write OK");
}
ret
}

View File

@@ -9,7 +9,7 @@
reason = "<https://github.com/mozilla/neqo/issues/2284#issuecomment-2782711813>"
)]
use std::fmt::Debug;
use std::fmt::{self, Debug, Formatter};
use enum_map::Enum;
use strum::{EnumIter, FromRepr};
@@ -172,7 +172,7 @@ impl From<u8> for IpTos {
}
impl Debug for IpTos {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_tuple("IpTos")
.field(&IpTosDscp::from(*self))
.field(&IpTosEcn::from(*self))

View File

@@ -1 +1 @@
{"files":{"Cargo.toml":"a9d80fa781c5712b8e19e7b773c08a517462786be295ee0e9f39006c1790c551","bindings/bindings.toml":"e7e4b75736cfcf4d52febacb99a6f6c6c7b1d648ed8bdc424648be876c850e91","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":"97fb6b8f8bb76dc1ed47988025645da618f3301871827d2a98d57254f7c62d5b","min_version.txt":"0f9ddf9ddaeb5137a5ab3d238d06286822f9579b1f46ba76312a8c6d76176500","src/aead.rs":"08d7cad82e3bec32661cfd1689e6611b30ae328ec88481cb32201dd255777365","src/aead_null.rs":"a766e2f71fd8b77a8f81bc60aaaafcffb6aef1f0a1f39ea07fef45b3696718ce","src/agent.rs":"19d9ee826e30c29ca8680e9ec767d19eac2326323f61b2a19bb62874990bf349","src/agentio.rs":"82f0cdececcb475c7b8639c993d4479bce7ac5fdf64b0d560f4b2fd356d03b03","src/auth.rs":"7a1524bef0a0c71616f5ee8b3976d66201210b809271bcf5d06c0e560ae482af","src/cert.rs":"4fdaa3834d8a72f41198449010fd5c3f6be6a54e429427c37bde5aab9421585c","src/constants.rs":"83606aeb646b2833a8094f9d980c266ecc3e8cb40c93a4820da221988319dd1a","src/ech.rs":"19d16af5a30e2060a8942a72487bd820c0d9c62ff1d3c490871752c56781c44b","src/err.rs":"b1e76e595326598a9bac45859f337ad9fb9a92ba9461d8c87250556a2629e7b6","src/exp.rs":"30f91d321439edc75c7f9a595ef5a0064918826d51ab15642db211472694009c","src/ext.rs":"7486595a24d39bd6c573e2229be345d13dbcd6911755ab6ab96d89ce7e263dd3","src/hkdf.rs":"76c5abc8b2d6ee12d8a86cd730af2cf47a59b2fbfd3b8a635a1826636156794d","src/hp.rs":"6adf4ad78b5a065ab7310c69ad239eec156256043e2c185bf60b9d1f12ab1be4","src/lib.rs":"3ab979c264a909e663c5ef140cd57013180745b99937671c73a9003ca6347f41","src/min_version.rs":"c6e1f98b9f56db0622ac38c1be131c55acf4a0f09ed0d6283f4d6308e2d1301a","src/p11.rs":"5c0759bb8ea5faad1a3d06fa7afb3dba114c93ea21981c85824d707f654d7c3d","src/prio.rs":"1858088afd2668e8fbff56959765b7d4df09342371b9282ade27bb4d7bd6ce69","src/replay.rs":"594ce92f368cbc5fb71ebfb62214f07d1e86df8e5ce94255d5593ffabb91cd03","src/result.rs":"5a76688787741de7a935dbbab4bcb917d481d1c9c50a34df7e510036feb3da17","src/secrets.rs":"5d85b1e15f47cd267fe70fa8ea7e4ebc4b07eab7713f451afeefcf15f146f8a5","src/selfencrypt.rs":"4f106465f582c38d3bb04cb5cbcbf65a349e3186784726d9f2bf511a4a4a35ee","src/ssl.rs":"04950bb534b5304eb417909a3a39ebaa9be234c7c13eacdc41c00a8edab1b09f","src/time.rs":"22989caf3dab85cfe955cc279fcca98a6df02d14fcd0e93cac7b39374b8b5763","tests/aead.rs":"e36ae77802df1ea6d17cfd1bd2178a3706089577d6fd1554ca86e748b8b235b9","tests/agent.rs":"fb95a2d5c86ce3fafcb127cd0a2a163e5ee70baf09b2c8483e4d1fb25644cee2","tests/ext.rs":"57af4e2df211fa8afdb73125d4344ef5c70c1ea4579107c3e6f5746308ee3e7b","tests/handshake.rs":"c06ed3d27b0f84b03ff0d0356a16601768821d9860cab81a49fea3eebb3091f2","tests/hkdf.rs":"1d2098dc8398395864baf13e4886cfd1da6d36118727c3b264f457ee3da6b048","tests/hp.rs":"1ad88108b6d8c5d078fc7bb2a4337a54f637d4e149db750f4916032d90aa64a7","tests/init.rs":"3cfe8411ca31ad7dfb23822bb1570e1a5b2b334857173bdd7df086b65b81d95a","tests/selfencrypt.rs":"b65aed70e83dce660017159fc8a956d3b52e0807b590ad8d0a3a4265caa8c1fa"},"package":null}
{"files":{"Cargo.toml":"a57adef48614a58209447e8bd115a2de3d8a42917a0b9a2ae9a97cabc3400c6a","bindings/bindings.toml":"e7e4b75736cfcf4d52febacb99a6f6c6c7b1d648ed8bdc424648be876c850e91","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":"2f54f79958878ed7988441955344dd1a2a079b1bb409e8f12a70284fd7e351ef","min_version.txt":"0f9ddf9ddaeb5137a5ab3d238d06286822f9579b1f46ba76312a8c6d76176500","src/aead.rs":"08d7cad82e3bec32661cfd1689e6611b30ae328ec88481cb32201dd255777365","src/aead_null.rs":"a766e2f71fd8b77a8f81bc60aaaafcffb6aef1f0a1f39ea07fef45b3696718ce","src/agent.rs":"ec90d7556231c57da3a191f508eaf1f820f22d6b7912ee45d1a594eb0fea7a82","src/agentio.rs":"1baecfb725b54717a6a74bb4664692d187f62747cc5e0495f59b06729f96dea2","src/auth.rs":"7a1524bef0a0c71616f5ee8b3976d66201210b809271bcf5d06c0e560ae482af","src/cert.rs":"4fdaa3834d8a72f41198449010fd5c3f6be6a54e429427c37bde5aab9421585c","src/constants.rs":"83606aeb646b2833a8094f9d980c266ecc3e8cb40c93a4820da221988319dd1a","src/ech.rs":"19d16af5a30e2060a8942a72487bd820c0d9c62ff1d3c490871752c56781c44b","src/err.rs":"4c7d0b46955b58aa9375210c2c5d24012056c3ad8a856b72d2c7c9542cc97046","src/exp.rs":"cd864fb5a61cd1472baa5b1d0951fc712753c22d21af83ebed09a01585f33b48","src/ext.rs":"a5676f8b9815cc7f6ed1da6fea091cf8754d8b80e90d37b726e905abe18930f8","src/hkdf.rs":"76c5abc8b2d6ee12d8a86cd730af2cf47a59b2fbfd3b8a635a1826636156794d","src/hp.rs":"6adf4ad78b5a065ab7310c69ad239eec156256043e2c185bf60b9d1f12ab1be4","src/lib.rs":"3ab979c264a909e663c5ef140cd57013180745b99937671c73a9003ca6347f41","src/min_version.rs":"c6e1f98b9f56db0622ac38c1be131c55acf4a0f09ed0d6283f4d6308e2d1301a","src/p11.rs":"49bcde067e55228dab483bd11b70dc29d40dc3c59fa60136daccb205dc468df0","src/prio.rs":"1858088afd2668e8fbff56959765b7d4df09342371b9282ade27bb4d7bd6ce69","src/replay.rs":"594ce92f368cbc5fb71ebfb62214f07d1e86df8e5ce94255d5593ffabb91cd03","src/result.rs":"5a76688787741de7a935dbbab4bcb917d481d1c9c50a34df7e510036feb3da17","src/secrets.rs":"5d85b1e15f47cd267fe70fa8ea7e4ebc4b07eab7713f451afeefcf15f146f8a5","src/selfencrypt.rs":"4f106465f582c38d3bb04cb5cbcbf65a349e3186784726d9f2bf511a4a4a35ee","src/ssl.rs":"04950bb534b5304eb417909a3a39ebaa9be234c7c13eacdc41c00a8edab1b09f","src/time.rs":"22989caf3dab85cfe955cc279fcca98a6df02d14fcd0e93cac7b39374b8b5763","tests/aead.rs":"e36ae77802df1ea6d17cfd1bd2178a3706089577d6fd1554ca86e748b8b235b9","tests/agent.rs":"fb95a2d5c86ce3fafcb127cd0a2a163e5ee70baf09b2c8483e4d1fb25644cee2","tests/ext.rs":"57af4e2df211fa8afdb73125d4344ef5c70c1ea4579107c3e6f5746308ee3e7b","tests/handshake.rs":"df8a901048268a390785e05e28cbc97b82e41e47d7eab2d5c0a57e434ca1adcf","tests/hkdf.rs":"1d2098dc8398395864baf13e4886cfd1da6d36118727c3b264f457ee3da6b048","tests/hp.rs":"7ee5d7290a3f61af67ad2c94670cba376027136370d9784948db655b7e00fe54","tests/init.rs":"3cfe8411ca31ad7dfb23822bb1570e1a5b2b334857173bdd7df086b65b81d95a","tests/selfencrypt.rs":"b65aed70e83dce660017159fc8a956d3b52e0807b590ad8d0a3a4265caa8c1fa"},"package":null}

View File

@@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.82.0"
name = "neqo-crypto"
version = "0.13.2"
version = "0.13.4"
authors = ["The Neqo Authors <necko@mozilla.com>"]
build = "build.rs"
autolib = false
@@ -94,7 +94,7 @@ default-features = false
path = "../neqo-common"
[dependencies.strum]
version = "0.26"
version = "0.27"
features = ["derive"]
default-features = false
@@ -136,17 +136,20 @@ create_dir = "warn"
dbg_macro = "warn"
empty_drop = "warn"
empty_enum_variants_with_brackets = "warn"
field_scoped_visibility_modifiers = "warn"
filetype_is_file = "warn"
float_cmp_const = "warn"
fn_to_numeric_cast_any = "warn"
get_unwrap = "warn"
if_then_some_else_none = "warn"
infinite_loop = "warn"
iter_over_hash_type = "warn"
large_include_file = "warn"
let_underscore_must_use = "warn"
let_underscore_untyped = "warn"
literal_string_with_formatting_args = "allow"
lossy_float_literal = "warn"
map_with_unused_argument_over_ranges = "warn"
mem_forget = "warn"
mixed_read_write_in_expression = "warn"
module_name_repetitions = "warn"
@@ -155,14 +158,18 @@ multiple_inherent_impl = "warn"
mutex_atomic = "warn"
mutex_integer = "warn"
needless_raw_strings = "warn"
partial_pub_fields = "warn"
pathbuf_init_then_push = "warn"
precedence_bits = "warn"
pub_without_shorthand = "warn"
rc_buffer = "warn"
rc_mutex = "warn"
redundant_test_prefix = "warn"
redundant_type_annotations = "warn"
ref_patterns = "warn"
renamed_function_params = "warn"
rest_pat_in_fully_bound_structs = "warn"
return_and_then = "warn"
self_named_module_files = "warn"
semicolon_inside_block = "warn"
string_lit_chars_any = "warn"

View File

@@ -4,7 +4,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![expect(clippy::unwrap_used, reason = " OK in a build script.")]
#![expect(
clippy::unwrap_used,
clippy::iter_over_hash_type,
reason = "OK in a build script."
)]
use std::{
collections::HashMap,

View File

@@ -16,6 +16,7 @@
use std::{
cell::RefCell,
ffi::{CStr, CString},
fmt::{self, Debug, Display, Formatter},
mem::MaybeUninit,
ops::{Deref, DerefMut},
os::raw::{c_uint, c_void},
@@ -637,11 +638,6 @@ impl SecretAgent {
}
/// Return any fatal alert that the TLS stack might have sent.
#[allow(
clippy::allow_attributes,
clippy::missing_const_for_fn,
reason = "TODO: False positive on nightly."
)]
#[must_use]
pub fn alert(&self) -> Option<&Alert> {
(*self.alert).as_ref()
@@ -811,11 +807,6 @@ impl SecretAgent {
}
/// Get the active ECH configuration, which is empty if ECH is disabled.
#[allow(
clippy::allow_attributes,
clippy::missing_const_for_fn,
reason = "TODO: False positive on nightly."
)]
#[must_use]
pub fn ech_config(&self) -> &[u8] {
&self.ech_config
@@ -828,8 +819,8 @@ impl Drop for SecretAgent {
}
}
impl ::std::fmt::Display for SecretAgent {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for SecretAgent {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Agent {:p}", self.fd)
}
}
@@ -933,11 +924,6 @@ impl Client {
ssl::SECSuccess
}
#[allow(
clippy::allow_attributes,
clippy::missing_const_for_fn,
reason = "TODO: False positive on nightly."
)]
#[must_use]
pub fn server_name(&self) -> &str {
&self.server_name
@@ -1026,8 +1012,8 @@ impl DerefMut for Client {
}
}
impl ::std::fmt::Display for Client {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for Client {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Client {:p}", self.agent.fd)
}
}
@@ -1047,7 +1033,7 @@ pub enum ZeroRttCheckResult {
/// A `ZeroRttChecker` is used by the agent to validate the application token (as provided by
/// `send_ticket`)
pub trait ZeroRttChecker: std::fmt::Debug + Unpin {
pub trait ZeroRttChecker: Debug + Unpin {
fn check(&self, token: &[u8]) -> ZeroRttCheckResult;
}
@@ -1234,8 +1220,8 @@ impl DerefMut for Server {
}
}
impl ::std::fmt::Display for Server {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for Server {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Server {:p}", self.agent.fd)
}
}

View File

@@ -11,7 +11,8 @@
use std::{
cmp::min,
fmt, mem,
fmt::{self, Display, Formatter},
mem,
ops::Deref,
os::raw::{c_uint, c_void},
pin::Pin,
@@ -71,7 +72,7 @@ impl Record {
}
impl fmt::Debug for Record {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(
f,
"Record {:?}:{:?} {}",
@@ -205,8 +206,8 @@ impl AgentIoInput {
}
}
impl ::std::fmt::Display for AgentIoInput {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for AgentIoInput {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "AgentIoInput {:p}", self.input)
}
}
@@ -253,8 +254,8 @@ impl AgentIo {
}
}
impl ::std::fmt::Display for AgentIo {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for AgentIo {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "AgentIo")
}
}

View File

@@ -4,7 +4,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{os::raw::c_char, str::Utf8Error};
use std::{
fmt::{self, Display, Formatter},
os::raw::c_char,
str::Utf8Error,
};
use crate::ssl::{SECStatus, SECSuccess};
@@ -91,8 +95,8 @@ impl std::error::Error for Error {
}
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Error: {self:?}")
}
}

View File

@@ -12,13 +12,19 @@ macro_rules! experimental_api {
#[allow(clippy::allow_attributes, clippy::missing_safety_doc, reason = "Inherent in macro use.")]
#[allow(clippy::allow_attributes, clippy::missing_errors_doc, reason = "Inherent in macro use.")]
pub unsafe fn $n ( $( $a : $t ),* ) -> Result<(), $crate::err::Error> {
const EXP_FUNCTION: &str = stringify!($n);
let n = ::std::ffi::CString::new(EXP_FUNCTION)?;
let f = $crate::ssl::SSL_GetExperimentalAPI(n.as_ptr());
if f.is_null() {
struct ExperimentalAPI(*mut std::ffi::c_void);
unsafe impl Send for ExperimentalAPI {}
unsafe impl Sync for ExperimentalAPI {}
static EXP_API: ::std::sync::OnceLock<ExperimentalAPI> = ::std::sync::OnceLock::new();
let f = EXP_API.get_or_init(|| {
const EXP_FUNCTION: &str = stringify!($n);
let Ok(n) = ::std::ffi::CString::new(EXP_FUNCTION) else { return ExperimentalAPI(std::ptr::null_mut()); };
ExperimentalAPI($crate::ssl::SSL_GetExperimentalAPI(n.as_ptr()))
});
if f.0.is_null() {
return Err($crate::err::Error::InternalError);
}
let f: unsafe extern "C" fn( $( $t ),* ) -> $crate::ssl::SECStatus = ::std::mem::transmute(f);
let f: unsafe extern "C" fn( $( $t ),* ) -> $crate::ssl::SECStatus = ::std::mem::transmute(f.0);
let rv = f( $( $a ),* );
$crate::err::secstatus_to_res(rv)
}

View File

@@ -11,6 +11,7 @@
use std::{
cell::RefCell,
fmt::{self, Debug, Formatter},
os::raw::{c_uint, c_void},
pin::Pin,
rc::Rc,
@@ -176,8 +177,8 @@ impl ExtensionTracker {
}
}
impl std::fmt::Debug for ExtensionTracker {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
impl Debug for ExtensionTracker {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "ExtensionTracker: {:?}", self.extension)
}
}

View File

@@ -6,6 +6,7 @@
use std::{
cell::RefCell,
fmt::{self, Debug, Formatter},
ops::{Deref, DerefMut},
os::raw::c_uint,
ptr::null_mut,
@@ -46,7 +47,11 @@ macro_rules! scoped_ptr {
/// # Errors
///
/// When passed a null pointer generates an error.
#[allow(clippy::allow_attributes, dead_code, reason = "False positive.")]
#[allow(
clippy::allow_attributes,
dead_code,
reason = "False positive; is used in code calling the macro."
)]
pub fn from_ptr(ptr: *mut $target) -> Result<Self, $crate::err::Error> {
if ptr.is_null() {
Err($crate::err::Error::last_nss_error())
@@ -114,8 +119,8 @@ impl Clone for PublicKey {
}
}
impl std::fmt::Debug for PublicKey {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
impl Debug for PublicKey {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
if let Ok(b) = self.key_data() {
write!(f, "PublicKey {}", hex_with_len(b))
} else {
@@ -168,8 +173,8 @@ impl Clone for PrivateKey {
}
}
impl std::fmt::Debug for PrivateKey {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
impl Debug for PrivateKey {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
if let Ok(b) = self.key_data() {
write!(f, "PrivateKey {}", hex_with_len(b))
} else {
@@ -215,8 +220,8 @@ impl Clone for SymKey {
}
}
impl std::fmt::Debug for SymKey {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
impl Debug for SymKey {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
if let Ok(b) = self.as_bytes() {
write!(f, "SymKey {}", hex_with_len(b))
} else {

View File

@@ -102,7 +102,11 @@ pub fn connect_fail(client: &mut SecretAgent, server: &mut SecretAgent) {
assert!(!server.state().is_connected());
}
#[allow(clippy::allow_attributes, dead_code, reason = "False positive.")]
#[allow(
clippy::allow_attributes,
dead_code,
reason = "Yes, we currently don't construct WithoutZeroRtt and WithZeroRtt."
)]
#[derive(Clone, Copy, Debug)]
pub enum Resumption {
WithoutZeroRtt,

View File

@@ -26,7 +26,11 @@ fn hp_test(cipher: Cipher, expected: &[u8]) {
let mask = hp.mask(&[0; 16]).expect("should produce a mask");
assert_eq!(mask, expected, "first invocation should be correct");
#[expect(clippy::redundant_clone, reason = "This is deliberate.")]
#[allow(
clippy::allow_attributes,
clippy::redundant_clone,
reason = "False positive; remove once MSRV >= 1.88."
)]
let hp2 = hp.clone();
let mask = hp2.mask(&[0; 16]).expect("clone produces mask");
assert_eq!(mask, expected, "clone should produce the same mask");

View File

@@ -1 +1 @@
{"files":{"Cargo.toml":"2d85f5a7e70cb7d99fdfd12fe3b6a2b87c76b12db38c5e664555e5e74b97858d","benches/streams.rs":"c61292f3b246fededd84789d6fc9f443312e3b89ca0c1e7aaad9aeaccc5bfa39","src/buffered_send_stream.rs":"39c10972e27d2c5c79703a13cf74bd6e5b013c29176f2b352e16cf4d9481d4de","src/client_events.rs":"38e48177d4bc301dce85e4953670e54a39b6bf1ce657412f9fb3497589d099e9","src/conn_params.rs":"7f0df52bceda1923aef2b7c5c64a532f49ea083ea45e3dcd5bd4b03031b89643","src/connection.rs":"e1aecf717d032c5228f0d8bee86d2d2960f471596676ba3fd61445625aa23e77","src/connection_client.rs":"48cd86a73960affe2cf101c8db6d12f5e6c7e8dab3412051482a691537ad56b4","src/connection_server.rs":"d16f73685ae29492e2d32321158b6206349fe1b0016d89bc50c2727f47c64140","src/control_stream_local.rs":"6b7774bc392292d66da4b4e915a477942cdcc0b287b38d77c24f1638f4b85755","src/control_stream_remote.rs":"e7d0b5a195e3ef482b36972eac979b7d761215fcb76699112f2d4919708fcf26","src/features/extended_connect/mod.rs":"f24b419d28eaffe47444120443f2b5613db9b5b5154f4b5725b35d8640c222e1","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":"4e81ae458ecaa1d0f29b7565c19c9751658fe0c7496ce40d7c90a102d9f04a16","src/features/extended_connect/tests/webtransport/negotiation.rs":"b0083f8737bdea9bc0de1940c627d497fee8b79ebc218bbcea0a562ae530527f","src/features/extended_connect/tests/webtransport/sessions.rs":"64b29ec9ba34e636b1109d99ab588666d85c85442565faa9071b743f4f764d6e","src/features/extended_connect/tests/webtransport/streams.rs":"eb0e793dc43ca9296334d29ced70d5ab3d90fd0c4ca3a485abad06c14eec29a4","src/features/extended_connect/webtransport_session.rs":"5888cd09d204738b1ef4e53b83f6c5ccee33d5d3549502d39b5332db3c1c53bd","src/features/extended_connect/webtransport_streams.rs":"9855d77705acb7d21566333c4b297816e363be2ade14b8685fd1df4a4861cf74","src/features/mod.rs":"6f192996e6e2231a97f3fcae2aa02d648e571a6ec5e14b4a23b24b87888d117c","src/frames/hframe.rs":"8cf686390f2bfd28c92a0badcb647c6ea439eeee2a8392e088f6d9af6662854d","src/frames/mod.rs":"ec86e32919bd4cf0baa8686444cb6062d6eabea9b74ef58680f5da476fdcc77c","src/frames/reader.rs":"08df3ec01b29e7b1001160cf63b27f393eafdb1891888e9751d20dd36e903781","src/frames/tests/hframe.rs":"43a7735fc859692633e7f3c031710a9fb635611756cb4b9f387bac0a38c0fa09","src/frames/tests/mod.rs":"4bbdf566a7370605d49373027b38c4bcbd91113f7693efee29b9d91e3914ad98","src/frames/tests/reader.rs":"35f94d1ce1d088fca35592d8a2898c49bd6df0f3facfa12ef6b918124a1356bc","src/frames/tests/wtframe.rs":"c6598d24f5e12972f02de6e1394362671633982db637a07e1c0bb9b56d93ea2a","src/frames/wtframe.rs":"544bc8fa74e3b15cde6e45ba47bcc52f098658e78664abfda8249a89c88d51b9","src/headers_checks.rs":"93b69056321eefa8b0260bbfd8ba82064de2fcb915c7fd63e0f2855ea6187eba","src/lib.rs":"f085007ac4fe1f75ca6f66f55836c395d6c36ccd849b3dfa77958e8bfad2daa4","src/priority.rs":"a32de5a2e333d387e6c73ebe7f1cbd2b14e42724145aed5d6d6c1bd787ca7704","src/push_controller.rs":"ebd055be1be92f9709d57b4347a4f2ceb56b8d1e48e5df1dc7c8cb475529dae6","src/push_id.rs":"cd4cea3102b59918668b66725bbd19b66dc389e35d986132c5ceb72bbc9f3222","src/qlog.rs":"6c0b622cd3ec7d64cb920d38fca0b0e87a43759c6fd4c2d63c352aa9c7ad11bf","src/qpack_decoder_receiver.rs":"eb06c4be59da567fef70c20daa2c0f165c768131165479a210e69659f168b88f","src/qpack_encoder_receiver.rs":"831f3da9ec17966286786ba3f2c723395a132e65d6a33b4ec341fe7640c1a53d","src/recv_message.rs":"cfdc209630332c013b075ff13c28227ecde6d93358116eff82cba88ca37d1c61","src/request_target.rs":"8b8c2d1221e1956f13b66d18f8bc880062549ce5f204f15d39c7d69f727875c9","src/send_message.rs":"4eadd7d5bd8f33e0d2212472200eaacf9f848c795d940ec543247cf4e0f89dbf","src/server.rs":"58da712bfa9fd2901df72d17b1cc7afb2cb8e30af508e3b8239de8841284d36b","src/server_connection_events.rs":"9b429916357f967d697cd9806c720e3ca7cf152603b0ddb16a7f9992a8188ee2","src/server_events.rs":"5599f3c87dfe4ac168c1279967617f702722fac0cb6c9dacf2dfdd31388fb815","src/settings.rs":"ae0b57b462803b963a17616863054e5d6858a89ff1021b52b43de8f72365bdc8","src/stream_type_reader.rs":"5ba77600c5e8c4abdd9443aec20311cf8a812b97ab18a90408aa4e689f42bded","tests/httpconn.rs":"a4dbbfa8bed000ca983bf4f2a015ee49283603924ae5fca8293b0a38f8ee5c2b","tests/priority.rs":"31aede7d5b6c66c415cbf9f0298c8de6fd9591e3c2d455ce24c5a30d56922d09","tests/send_message.rs":"f07c152d97ad074caf6dd52ea26b5eeb57f60a850d109179bae376cd1dcd6dee","tests/webtransport.rs":"1634de76a3081877670d015cfd7b7f7225f8f1c7ddfba729bd5070a25ba10da0"},"package":null}
{"files":{"Cargo.toml":"d9b124039ba1d9553a3249e014c9ab50c71b1a21f426f2d1801b40ae31e4a976","benches/streams.rs":"13977cc2a0a024c3a29b43aef6fb1a7ab3ed6cea6cd80902e71b0e95049378fa","src/buffered_send_stream.rs":"456b535899e47cdb608fd472fea2f23a6bda4835e77be81f77b49f9edff8b19b","src/client_events.rs":"38e48177d4bc301dce85e4953670e54a39b6bf1ce657412f9fb3497589d099e9","src/conn_params.rs":"7f0df52bceda1923aef2b7c5c64a532f49ea083ea45e3dcd5bd4b03031b89643","src/connection.rs":"b55ebc262aa6a52b32571eac6304212956a64d386aa9e78a864a4de40186d3f4","src/connection_client.rs":"bcb9b4f3b4141f46a4758855627477b2655537fbbda76f9dfec24fe381eefa96","src/connection_server.rs":"3392693c1e0bde1f3ad70adb6fca698c9e8bdfeb8f7064f3be79a1e48d59ccab","src/control_stream_local.rs":"992a00e6776e6dae0693d359eec3cca9b6f88261272d629f60163d4bdc60bf7d","src/control_stream_remote.rs":"6477605bd2d7c66f1fea408cc1c265bb180d76b1cf40b463ba50c2f0f1a9e408","src/features/extended_connect/mod.rs":"f24b419d28eaffe47444120443f2b5613db9b5b5154f4b5725b35d8640c222e1","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":"4e81ae458ecaa1d0f29b7565c19c9751658fe0c7496ce40d7c90a102d9f04a16","src/features/extended_connect/tests/webtransport/negotiation.rs":"b0083f8737bdea9bc0de1940c627d497fee8b79ebc218bbcea0a562ae530527f","src/features/extended_connect/tests/webtransport/sessions.rs":"cc45a737ab2bf1ef0b273142b553ae7c71700ce8741e4d385178439762a98d92","src/features/extended_connect/tests/webtransport/streams.rs":"eb0e793dc43ca9296334d29ced70d5ab3d90fd0c4ca3a485abad06c14eec29a4","src/features/extended_connect/webtransport_session.rs":"bb7db350ce35e34129966ac768135da1f08b71ffea5856c15ea0b66dd21eafe0","src/features/extended_connect/webtransport_streams.rs":"9855d77705acb7d21566333c4b297816e363be2ade14b8685fd1df4a4861cf74","src/features/mod.rs":"6f192996e6e2231a97f3fcae2aa02d648e571a6ec5e14b4a23b24b87888d117c","src/frames/hframe.rs":"3532487ba49a9d947e588c7d8789f3bd522061127bef3e9cdf1a29cff13932d5","src/frames/mod.rs":"ec86e32919bd4cf0baa8686444cb6062d6eabea9b74ef58680f5da476fdcc77c","src/frames/reader.rs":"624d19721c872fe2c8649c3ef23a3b343d36718a292d211af9cf016529248249","src/frames/tests/hframe.rs":"43a7735fc859692633e7f3c031710a9fb635611756cb4b9f387bac0a38c0fa09","src/frames/tests/mod.rs":"4bbdf566a7370605d49373027b38c4bcbd91113f7693efee29b9d91e3914ad98","src/frames/tests/reader.rs":"f99b3f16cb186e449d81b0342c9f486401946bf9ed132c00095cbbd501b752d5","src/frames/tests/wtframe.rs":"c6598d24f5e12972f02de6e1394362671633982db637a07e1c0bb9b56d93ea2a","src/frames/wtframe.rs":"544bc8fa74e3b15cde6e45ba47bcc52f098658e78664abfda8249a89c88d51b9","src/headers_checks.rs":"93b69056321eefa8b0260bbfd8ba82064de2fcb915c7fd63e0f2855ea6187eba","src/lib.rs":"30aaf6e14754f47f240f23b5bc8aeb235901792cd135f4dba90476c223231ac1","src/priority.rs":"a32de5a2e333d387e6c73ebe7f1cbd2b14e42724145aed5d6d6c1bd787ca7704","src/push_controller.rs":"8a410fbb0833824c6bf5c7eecd00504b4ec4b2efe96805d7c644a7b208ecc326","src/push_id.rs":"bf931466d0490cbe8977cd7a732d1d4970e16220f331899f5e7dab8873ece5de","src/qlog.rs":"6c0b622cd3ec7d64cb920d38fca0b0e87a43759c6fd4c2d63c352aa9c7ad11bf","src/qpack_decoder_receiver.rs":"eb06c4be59da567fef70c20daa2c0f165c768131165479a210e69659f168b88f","src/qpack_encoder_receiver.rs":"831f3da9ec17966286786ba3f2c723395a132e65d6a33b4ec341fe7640c1a53d","src/recv_message.rs":"823a54d288039e51a9f0abcb6f7e9a8d799ff1955a2d27b1e091fbbf86deb414","src/request_target.rs":"9dce1088021527282b2693975f39038f8baf43f05f3c6f9a49ad945a4e86401b","src/send_message.rs":"ac161ad44d4902351c19c0326f82cb83d1bdda6a14236702596e811c135b3956","src/server.rs":"08da3d8f357b062d945070e2f8872baaa25b4aee62d5f0996058b521c3d0464d","src/server_connection_events.rs":"9b429916357f967d697cd9806c720e3ca7cf152603b0ddb16a7f9992a8188ee2","src/server_events.rs":"42aa312a5fbf1a0acb57b0b564c4fdfd08bbe0762ad077eac518711bd2aa0ccb","src/settings.rs":"ae0b57b462803b963a17616863054e5d6858a89ff1021b52b43de8f72365bdc8","src/stream_type_reader.rs":"145bd4986f573ad0228291392c72848f309dfd5108157440502ac34f0a3017b4","tests/httpconn.rs":"a4dbbfa8bed000ca983bf4f2a015ee49283603924ae5fca8293b0a38f8ee5c2b","tests/priority.rs":"31aede7d5b6c66c415cbf9f0298c8de6fd9591e3c2d455ce24c5a30d56922d09","tests/send_message.rs":"f07c152d97ad074caf6dd52ea26b5eeb57f60a850d109179bae376cd1dcd6dee","tests/webtransport.rs":"1634de76a3081877670d015cfd7b7f7225f8f1c7ddfba729bd5070a25ba10da0"},"package":null}

View File

@@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.82.0"
name = "neqo-http3"
version = "0.13.2"
version = "0.13.4"
authors = ["The Neqo Authors <necko@mozilla.com>"]
build = false
autolib = false
@@ -111,7 +111,7 @@ version = "0.9"
default-features = false
[dependencies.strum]
version = "0.26"
version = "0.27"
features = ["derive"]
default-features = false
@@ -121,7 +121,8 @@ features = ["std"]
default-features = false
[dev-dependencies.criterion]
version = "0.5"
version = "0.6"
features = ["cargo_bench_support"]
default-features = false
[dev-dependencies.neqo-http3]
@@ -144,17 +145,20 @@ create_dir = "warn"
dbg_macro = "warn"
empty_drop = "warn"
empty_enum_variants_with_brackets = "warn"
field_scoped_visibility_modifiers = "warn"
filetype_is_file = "warn"
float_cmp_const = "warn"
fn_to_numeric_cast_any = "warn"
get_unwrap = "warn"
if_then_some_else_none = "warn"
infinite_loop = "warn"
iter_over_hash_type = "warn"
large_include_file = "warn"
let_underscore_must_use = "warn"
let_underscore_untyped = "warn"
literal_string_with_formatting_args = "allow"
lossy_float_literal = "warn"
map_with_unused_argument_over_ranges = "warn"
mem_forget = "warn"
mixed_read_write_in_expression = "warn"
module_name_repetitions = "warn"
@@ -163,14 +167,18 @@ multiple_inherent_impl = "warn"
mutex_atomic = "warn"
mutex_integer = "warn"
needless_raw_strings = "warn"
partial_pub_fields = "warn"
pathbuf_init_then_push = "warn"
precedence_bits = "warn"
pub_without_shorthand = "warn"
rc_buffer = "warn"
rc_mutex = "warn"
redundant_test_prefix = "warn"
redundant_type_annotations = "warn"
ref_patterns = "warn"
renamed_function_params = "warn"
rest_pat_in_fully_bound_structs = "warn"
return_and_then = "warn"
self_named_module_files = "warn"
semicolon_inside_block = "warn"
string_lit_chars_any = "warn"

View File

@@ -6,6 +6,8 @@
#![expect(clippy::unwrap_used, reason = "OK in a bench.")]
use std::{hint::black_box, iter::repeat_with, time::Duration};
use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
use neqo_crypto::AuthenticationStatus;
use neqo_http3::{Http3Client, Http3Parameters, Http3Server, Priority};
@@ -35,19 +37,19 @@ fn exchange_packets(client: &mut Http3Client, server: &mut Http3Server, is_hands
}
fn use_streams(client: &mut Http3Client, server: &mut Http3Server, streams: usize, data: &[u8]) {
let stream_ids = (0..streams)
.map(|_| {
client
.fetch(
now(),
"GET",
&("https", DEFAULT_SERVER_NAME, "/"),
&[],
Priority::default(),
)
.unwrap()
})
.collect::<Vec<_>>();
let stream_ids = repeat_with(|| {
client
.fetch(
now(),
"GET",
&("https", DEFAULT_SERVER_NAME, "/"),
&[],
Priority::default(),
)
.unwrap()
})
.take(streams)
.collect::<Vec<_>>();
exchange_packets(client, server, false);
for stream_id in &stream_ids {
client.send_data(*stream_id, data).unwrap();
@@ -86,7 +88,7 @@ fn criterion_benchmark(c: &mut Criterion) {
let data = vec![0; data_size];
b.iter_batched_ref(
connect,
|(client, server)| use_streams(client, server, streams, &data),
|_| black_box(|(client, server)| use_streams(client, server, streams, &data)),
BatchSize::SmallInput,
);
});
@@ -94,5 +96,9 @@ fn criterion_benchmark(c: &mut Criterion) {
}
}
criterion_group!(benches, criterion_benchmark);
criterion_group! {
name = benches;
config = Criterion::default().warm_up_time(Duration::from_secs(5)).measurement_time(Duration::from_secs(60));
targets = criterion_benchmark
}
criterion_main!(benches);

View File

@@ -4,7 +4,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use neqo_common::qtrace;
use std::fmt::{self, Display, Formatter};
use neqo_transport::{Connection, StreamId};
use crate::{qlog, Res};
@@ -19,8 +20,8 @@ pub enum BufferedStream {
},
}
impl ::std::fmt::Display for BufferedStream {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for BufferedStream {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "BufferedStream {:?}", Option::<StreamId>::from(self))
}
}
@@ -60,14 +61,12 @@ impl BufferedStream {
///
/// Returns `neqo_transport` errors.
pub fn send_buffer(&mut self, conn: &mut Connection) -> Res<usize> {
let label = format!("{self}");
let Self::Initialized { stream_id, buf } = self else {
return Ok(0);
};
if buf.is_empty() {
return Ok(0);
}
qtrace!("[{label}] sending data");
let sent = conn.stream_send(*stream_id, &buf[..])?;
if sent == 0 {
return Ok(0);

View File

@@ -7,7 +7,7 @@
use std::{
cell::RefCell,
collections::{BTreeSet, HashMap},
fmt::Debug,
fmt::{self, Debug, Display, Formatter},
mem,
rc::Rc,
};
@@ -289,20 +289,20 @@ data is done in the `read_data` function.
#[derive(Debug)]
pub struct Http3Connection {
role: Role,
pub state: Http3State,
state: Http3State,
local_params: Http3Parameters,
control_stream_local: ControlStreamLocal,
pub qpack_encoder: Rc<RefCell<QPackEncoder>>,
pub qpack_decoder: Rc<RefCell<QPackDecoder>>,
qpack_encoder: Rc<RefCell<QPackEncoder>>,
qpack_decoder: Rc<RefCell<QPackDecoder>>,
settings_state: Http3RemoteSettingsState,
streams_with_pending_data: BTreeSet<StreamId>,
pub send_streams: HashMap<StreamId, Box<dyn SendStream>>,
pub recv_streams: HashMap<StreamId, Box<dyn RecvStream>>,
send_streams: HashMap<StreamId, Box<dyn SendStream>>,
recv_streams: HashMap<StreamId, Box<dyn RecvStream>>,
webtransport: ExtendedConnectFeature,
}
impl ::std::fmt::Display for Http3Connection {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for Http3Connection {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Http3 connection")
}
}
@@ -1440,11 +1440,6 @@ impl Http3Connection {
}
}
/// Return the current state on `Http3Connection`.
pub fn state(&self) -> Http3State {
self.state.clone()
}
/// Adds a new send and receive stream.
pub fn add_streams(
&mut self,
@@ -1582,4 +1577,48 @@ impl Http3Connection {
pub const fn webtransport_enabled(&self) -> bool {
self.webtransport.enabled()
}
#[must_use]
pub const fn state(&self) -> &Http3State {
&self.state
}
pub fn set_state(&mut self, state: Http3State) {
self.state = state;
}
#[must_use]
pub fn state_mut(&mut self) -> &mut Http3State {
&mut self.state
}
#[must_use]
pub const fn qpack_encoder(&self) -> &Rc<RefCell<QPackEncoder>> {
&self.qpack_encoder
}
#[must_use]
pub const fn qpack_decoder(&self) -> &Rc<RefCell<QPackDecoder>> {
&self.qpack_decoder
}
#[must_use]
pub fn send_streams(&self) -> &HashMap<StreamId, Box<dyn SendStream>> {
&self.send_streams
}
#[must_use]
pub fn send_streams_mut(&mut self) -> &mut HashMap<StreamId, Box<dyn SendStream>> {
&mut self.send_streams
}
#[must_use]
pub fn recv_streams(&self) -> &HashMap<StreamId, Box<dyn RecvStream>> {
&self.recv_streams
}
#[must_use]
pub fn recv_streams_mut(&mut self) -> &mut HashMap<StreamId, Box<dyn RecvStream>> {
&mut self.recv_streams
}
}

View File

@@ -6,7 +6,7 @@
use std::{
cell::RefCell,
fmt::{Debug, Display},
fmt::{self, Debug, Display, Formatter},
iter,
net::SocketAddr,
rc::Rc,
@@ -286,7 +286,7 @@ pub struct Http3Client {
}
impl Display for Http3Client {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Http3 client")
}
}
@@ -352,7 +352,7 @@ impl Http3Client {
/// The function returns the current state of the connection.
#[must_use]
pub fn state(&self) -> Http3State {
self.base_handler.state()
self.base_handler.state().clone()
}
#[must_use]
@@ -422,9 +422,8 @@ impl Http3Client {
/// connection the HTTP/3 setting will be decoded and used until the setting are received from
/// the server.
pub fn take_resumption_token(&mut self, now: Instant) -> Option<ResumptionToken> {
self.conn
.take_resumption_token(now)
.and_then(|t| self.encode_resumption_token(&t))
let t = self.conn.take_resumption_token(now)?;
self.encode_resumption_token(&t)
}
/// This may be call if an application has a resumption token. This must be called before
@@ -441,7 +440,7 @@ impl Http3Client {
///
/// On closing if the base handler can't handle it (debug only).
pub fn enable_resumption(&mut self, now: Instant, token: impl AsRef<[u8]>) -> Res<()> {
if self.base_handler.state != Http3State::Initializing {
if self.base_handler.state() != &Http3State::Initializing {
return Err(Error::InvalidState);
}
let mut dec = Decoder::from(token.as_ref());
@@ -470,7 +469,7 @@ impl Http3Client {
self.base_handler
.set_0rtt_settings(&mut self.conn, settings)?;
self.events
.connection_state_change(self.base_handler.state());
.connection_state_change(self.base_handler.state().clone());
self.push_handler
.borrow_mut()
.maybe_send_max_push_id_frame(&mut self.base_handler);
@@ -485,14 +484,14 @@ impl Http3Client {
{
qinfo!("[{self}] Close the connection error={error} msg={msg}");
if !matches!(
self.base_handler.state,
self.base_handler.state(),
Http3State::Closing(_) | Http3State::Closed(_)
) {
self.push_handler.borrow_mut().clear();
self.conn.close(now, error, msg);
self.base_handler.close(error);
self.events
.connection_state_change(self.base_handler.state());
.connection_state_change(self.base_handler.state().clone());
}
}
@@ -623,7 +622,7 @@ impl Http3Client {
buf.len()
);
self.base_handler
.send_streams
.send_streams_mut()
.get_mut(&stream_id)
.ok_or(Error::InvalidStreamId)?
.send_data(&mut self.conn, buf)
@@ -822,7 +821,7 @@ impl Http3Client {
/// `InvalidStreamId` if the stream does not exist.
pub fn webtransport_send_stream_stats(&mut self, stream_id: StreamId) -> Res<SendStreamStats> {
self.base_handler
.send_streams
.send_streams_mut()
.get_mut(&stream_id)
.ok_or(Error::InvalidStreamId)?
.stats(&mut self.conn)
@@ -835,7 +834,7 @@ impl Http3Client {
/// `InvalidStreamId` if the stream does not exist.
pub fn webtransport_recv_stream_stats(&mut self, stream_id: StreamId) -> Res<RecvStreamStats> {
self.base_handler
.recv_streams
.recv_streams_mut()
.get_mut(&stream_id)
.ok_or(Error::InvalidStreamId)?
.stats(&mut self.conn)
@@ -1000,7 +999,7 @@ impl Http3Client {
self.base_handler.add_new_stream(stream_id);
}
ConnectionEvent::SendStreamWritable { stream_id } => {
if let Some(s) = self.base_handler.send_streams.get_mut(&stream_id) {
if let Some(s) = self.base_handler.send_streams_mut().get_mut(&stream_id) {
s.stream_writable();
}
}
@@ -1035,7 +1034,7 @@ impl Http3Client {
.handle_state_change(&mut self.conn, &state)?
{
self.events
.connection_state_change(self.base_handler.state());
.connection_state_change(self.base_handler.state().clone());
}
}
ConnectionEvent::ZeroRttRejected => {
@@ -1156,7 +1155,7 @@ impl Http3Client {
stream_id,
first_frame_type: None,
},
Rc::clone(&self.base_handler.qpack_decoder),
Rc::clone(self.base_handler.qpack_decoder()),
Box::new(RecvPushEvents::new(push_id, Rc::clone(&self.push_handler))),
None,
// TODO: think about the right priority for the push streams.
@@ -1177,9 +1176,10 @@ impl Http3Client {
return Err(Error::HttpId);
}
match self.base_handler.state {
match self.base_handler.state_mut() {
Http3State::Connected => {
self.base_handler.state = Http3State::GoingAway(goaway_stream_id);
self.base_handler
.set_state(Http3State::GoingAway(goaway_stream_id));
}
Http3State::GoingAway(ref mut stream_id) => {
if goaway_stream_id > *stream_id {
@@ -1194,7 +1194,7 @@ impl Http3Client {
// Issue reset events for streams >= goaway stream id
let send_ids: Vec<StreamId> = self
.base_handler
.send_streams
.send_streams()
.iter()
.filter_map(id_gte(goaway_stream_id))
.collect();
@@ -1209,7 +1209,7 @@ impl Http3Client {
let recv_ids: Vec<StreamId> = self
.base_handler
.recv_streams
.recv_streams()
.iter()
.filter_map(id_gte(goaway_stream_id))
.collect();
@@ -1240,12 +1240,12 @@ impl Http3Client {
#[must_use]
pub fn qpack_decoder_stats(&self) -> QpackStats {
self.base_handler.qpack_decoder.borrow().stats()
self.base_handler.qpack_decoder().borrow().stats()
}
#[must_use]
pub fn qpack_encoder_stats(&self) -> QpackStats {
self.base_handler.qpack_encoder.borrow().stats()
self.base_handler.qpack_encoder().borrow().stats()
}
#[must_use]

View File

@@ -4,7 +4,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{rc::Rc, time::Instant};
use std::{
fmt::{self, Display, Formatter},
rc::Rc,
time::Instant,
};
use neqo_common::{event::Provider as _, qdebug, qinfo, qtrace, Header, MessageType, Role};
use neqo_transport::{
@@ -28,8 +32,8 @@ pub struct Http3ServerHandler {
needs_processing: bool,
}
impl ::std::fmt::Display for Http3ServerHandler {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for Http3ServerHandler {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Http3 server connection")
}
}
@@ -45,7 +49,7 @@ impl Http3ServerHandler {
#[must_use]
pub fn state(&self) -> Http3State {
self.base_handler.state()
self.base_handler.state().clone()
}
/// Supply a response for a request.
@@ -66,7 +70,7 @@ impl Http3ServerHandler {
) -> Res<usize> {
let n = self
.base_handler
.send_streams
.send_streams_mut()
.get_mut(&stream_id)
.ok_or(Error::InvalidStreamId)?
.send_data(conn, data)?;
@@ -85,7 +89,7 @@ impl Http3ServerHandler {
conn: &mut Connection,
) -> Res<()> {
self.base_handler
.send_streams
.send_streams_mut()
.get_mut(&stream_id)
.ok_or(Error::InvalidStreamId)?
.http_stream()
@@ -258,7 +262,7 @@ impl Http3ServerHandler {
conn.close(now, err.code(), format!("{err}"));
self.base_handler.close(err.code());
self.events
.connection_state_change(self.base_handler.state());
.connection_state_change(self.base_handler.state().clone());
}
// If this return an error the connection must be closed.
@@ -288,16 +292,16 @@ impl Http3ServerHandler {
.handle_stream_stop_sending(stream_id, app_error, conn)?,
ConnectionEvent::StateChange(state) => {
if self.base_handler.handle_state_change(conn, &state)? {
if self.base_handler.state() == Http3State::Connected {
if self.base_handler.state() == &Http3State::Connected {
let settings = self.base_handler.save_settings();
conn.send_ticket(now, &settings)?;
}
self.events
.connection_state_change(self.base_handler.state());
.connection_state_change(self.base_handler.state().clone());
}
}
ConnectionEvent::SendStreamWritable { stream_id } => {
if let Some(s) = self.base_handler.send_streams.get_mut(&stream_id) {
if let Some(s) = self.base_handler.send_streams_mut().get_mut(&stream_id) {
s.stream_writable();
}
}
@@ -325,7 +329,7 @@ impl Http3ServerHandler {
MessageType::Response,
Http3StreamType::Http,
stream_id,
Rc::clone(&self.base_handler.qpack_encoder),
Rc::clone(self.base_handler.qpack_encoder()),
Box::new(self.events.clone()),
)),
Box::new(RecvMessage::new(
@@ -335,7 +339,7 @@ impl Http3ServerHandler {
stream_id,
first_frame_type: Some(first_frame_type),
},
Rc::clone(&self.base_handler.qpack_decoder),
Rc::clone(self.base_handler.qpack_decoder()),
Box::new(self.events.clone()),
None,
PriorityHandler::new(false, Priority::default()),

View File

@@ -4,7 +4,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::collections::{HashMap, VecDeque};
use std::{
collections::{HashMap, VecDeque},
fmt::{self, Display, Formatter},
};
use neqo_common::{qtrace, Encoder};
use neqo_transport::{Connection, StreamId, StreamType};
@@ -21,8 +24,8 @@ pub struct ControlStreamLocal {
outstanding_priority_update: VecDeque<StreamId>,
}
impl ::std::fmt::Display for ControlStreamLocal {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for ControlStreamLocal {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Local control stream {:?}", self.stream)
}
}

View File

@@ -4,6 +4,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt::{self, Display, Formatter};
use neqo_common::qdebug;
use neqo_transport::{Connection, StreamId};
@@ -20,8 +22,8 @@ pub struct ControlStreamRemote {
frame_reader: FrameReader,
}
impl ::std::fmt::Display for ControlStreamRemote {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for ControlStreamRemote {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Http3 remote control stream {:?}", self.stream_id)
}
}

View File

@@ -366,9 +366,7 @@ fn receive_request(server: &Http3Server) -> Option<Http3OrWebTransportStream> {
}
#[test]
// Ignoring this test as it is panicking at wt.create_wt_stream_client
// Issue # 1386 is created to track this
#[ignore]
#[ignore = "Is panicking at wt.create_wt_stream_client; see issue #1386"]
fn wt_close_session_cannot_be_sent_at_once() {
const BUF: &[u8] = &[0; 443];
const ERROR_NUM: u32 = 23;

View File

@@ -4,7 +4,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{cell::RefCell, collections::BTreeSet, mem, rc::Rc};
use std::{
cell::RefCell,
collections::BTreeSet,
fmt::{self, Display, Formatter},
mem,
rc::Rc,
};
use neqo_common::{qtrace, Encoder, Header, MessageType, Role};
use neqo_qpack::{QPackDecoder, QPackEncoder};
@@ -48,8 +54,8 @@ pub struct WebTransportSession {
role: Role,
}
impl ::std::fmt::Display for WebTransportSession {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for WebTransportSession {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "WebTransportSession session={}", self.session_id)
}
}

View File

@@ -4,7 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{fmt::Debug, io::Write as _};
use std::fmt::{Debug, Write as _};
use neqo_common::{Decoder, Encoder};
use neqo_crypto::random;
@@ -146,15 +146,10 @@ impl HFrame {
element_id,
priority,
} => {
let mut update_frame = Encoder::new();
update_frame.encode_varint(*element_id);
let mut priority_enc: Vec<u8> = Vec::new();
write!(priority_enc, "{priority}").unwrap();
update_frame.encode(&priority_enc);
enc.encode_varint(update_frame.len() as u64);
enc.encode(update_frame.as_ref());
enc.encode_vvec_with(|enc_inner| {
enc_inner.encode_varint(*element_id);
write!(enc_inner, "{priority}").expect("write OK");
});
}
}
}

View File

@@ -8,7 +8,7 @@
clippy::module_name_repetitions,
reason = "<https://github.com/mozilla/neqo/issues/2284#issuecomment-2782711813>"
)]
use std::fmt::Debug;
use std::{cmp::min, fmt::Debug};
use neqo_common::{
hex_with_len, qtrace, Decoder, IncrementalDecoderBuffer, IncrementalDecoderIgnore,
@@ -19,7 +19,7 @@ use neqo_transport::{Connection, StreamId};
use super::hframe::HFrameType;
use crate::{Error, RecvStream, Res};
const MAX_READ_SIZE: usize = 4096;
const MAX_READ_SIZE: usize = 2048; // Given a practical MTU of 1500 bytes, this seems reasonable.
pub trait FrameDecoder<T> {
fn is_known_type(frame_type: HFrameType) -> bool;
@@ -100,6 +100,7 @@ pub struct FrameReader {
state: FrameReaderState,
frame_type: HFrameType,
frame_len: u64,
buffer: [u8; MAX_READ_SIZE],
}
impl Default for FrameReader {
@@ -117,6 +118,7 @@ impl FrameReader {
},
frame_type: HFrameType(u64::MAX),
frame_len: 0,
buffer: [0; MAX_READ_SIZE],
}
}
@@ -128,6 +130,7 @@ impl FrameReader {
},
frame_type,
frame_len: 0,
buffer: [0; MAX_READ_SIZE],
}
}
@@ -166,16 +169,15 @@ impl FrameReader {
stream_reader: &mut dyn StreamReader,
) -> Res<(Option<T>, bool)> {
loop {
let to_read = std::cmp::min(self.min_remaining(), MAX_READ_SIZE);
let mut buf = vec![0; to_read];
let to_read = min(self.min_remaining(), self.buffer.len());
let (output, read, fin) = match stream_reader
.read_data(&mut buf)
.read_data(&mut self.buffer[..to_read])
.map_err(|e| Error::map_stream_recv_errors(&e))?
{
(0, f) => (None, false, f),
(amount, f) => {
qtrace!("FrameReader::receive: reading {amount} byte, fin={f}");
(self.consume::<T>(Decoder::from(&buf[..amount]))?, true, f)
(self.consume::<T>(amount)?, true, f)
}
};
@@ -200,7 +202,8 @@ impl FrameReader {
/// # Errors
///
/// May return `HttpFrame` if a frame cannot be decoded.
fn consume<T: FrameDecoder<T>>(&mut self, mut input: Decoder) -> Res<Option<T>> {
fn consume<T: FrameDecoder<T>>(&mut self, amount: usize) -> Res<Option<T>> {
let mut input = Decoder::from(&self.buffer[..amount]);
match &mut self.state {
FrameReaderState::GetType { decoder } => {
if let Some(v) = decoder.consume(&mut input) {

View File

@@ -4,7 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt::Debug;
use std::{cmp::min, fmt::Debug};
use neqo_common::Encoder;
use neqo_transport::{Connection, StreamId, StreamType};
@@ -277,7 +277,7 @@ fn complete_and_incomplete_unknown_frame() {
let mut buf: Vec<_> = enc.into();
buf.resize(UNKNOWN_FRAME_LEN + buf.len(), 0);
let len = std::cmp::min(buf.len() - 1, 10);
let len = min(buf.len() - 1, 10);
for i in 1..len {
test_reading_frame::<HFrame>(
&buf[..i],
@@ -321,7 +321,7 @@ fn test_complete_and_incomplete_frame<T: FrameDecoder<T> + PartialEq + Debug>(
// Let's consume partial frames. It is enough to test partial frames
// up to 10 byte. 10 byte is greater than frame type and frame
// length and bit of data.
let len = std::cmp::min(buf.len() - 1, 10);
let len = min(buf.len() - 1, 10);
for i in 1..len {
test_reading_frame::<T>(
&buf[..i],

View File

@@ -158,7 +158,11 @@ mod server_events;
mod settings;
mod stream_type_reader;
use std::{cell::RefCell, fmt::Debug, rc::Rc};
use std::{
cell::RefCell,
fmt::{self, Debug, Display, Formatter},
rc::Rc,
};
use buffered_send_stream::BufferedStream;
pub use client_events::{Http3ClientEvent, WebTransportEvent};
@@ -411,8 +415,8 @@ impl ::std::error::Error for Error {
}
}
impl ::std::fmt::Display for Error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "HTTP/3 error: {self:?}")
}
}

View File

@@ -7,7 +7,7 @@
use std::{
cell::RefCell,
collections::VecDeque,
fmt::{Debug, Display},
fmt::{self, Debug, Display, Formatter},
mem,
rc::Rc,
slice::SliceIndex,
@@ -157,7 +157,7 @@ pub struct PushController {
}
impl Display for PushController {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Push controller")
}
}

View File

@@ -4,7 +4,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::ops::{Add, Sub};
use std::{
fmt::{self, Display, Formatter},
ops::{Add, Sub},
};
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd)]
pub struct PushId(u64);
@@ -32,8 +35,8 @@ impl From<PushId> for u64 {
}
}
impl ::std::fmt::Display for PushId {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for PushId {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}

View File

@@ -4,7 +4,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{cell::RefCell, cmp::min, collections::VecDeque, fmt::Debug, rc::Rc};
use std::{
cell::RefCell,
cmp::min,
collections::VecDeque,
fmt::{self, Debug, Display, Formatter},
rc::Rc,
};
use neqo_common::{header::HeadersExt as _, qdebug, qinfo, qtrace, Header};
use neqo_qpack::decoder::QPackDecoder;
@@ -77,8 +83,8 @@ pub struct RecvMessage {
blocked_push_promise: VecDeque<PushInfo>,
}
impl ::std::fmt::Display for RecvMessage {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for RecvMessage {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "RecvMessage stream_id:{}", self.stream_id)
}
}

View File

@@ -4,7 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt::{Debug, Formatter};
use std::fmt::{self, Debug, Formatter};
use url::{ParseError, Url};
@@ -46,7 +46,7 @@ impl<'s, 'a, 'p> RefRequestTarget<'s, 'a, 'p> {
}
impl Debug for RefRequestTarget<'_, '_, '_> {
fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}://{}{}", self.scheme, self.authority, self.path)
}
}
@@ -113,7 +113,7 @@ impl RequestTarget for UrlRequestTarget {
}
impl Debug for UrlRequestTarget {
fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.url.fmt(f)
}
}

View File

@@ -4,7 +4,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{cell::RefCell, cmp::min, fmt::Debug, num::NonZeroUsize, rc::Rc};
use std::{
cell::RefCell,
cmp::min,
fmt::{self, Debug, Display, Formatter},
num::NonZeroUsize,
rc::Rc,
};
use neqo_common::{qdebug, qtrace, Encoder, Header, MessageType};
use neqo_qpack::encoder::QPackEncoder;
@@ -324,8 +330,8 @@ impl HttpSendStream for SendMessage {
}
}
impl ::std::fmt::Display for SendMessage {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for SendMessage {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "SendMesage {}", self.stream_id())
}
}

View File

@@ -7,6 +7,7 @@
use std::{
cell::{RefCell, RefMut},
collections::HashMap,
fmt::{self, Display, Formatter},
path::PathBuf,
rc::Rc,
time::Instant,
@@ -41,8 +42,8 @@ pub struct Http3Server {
events: Http3ServerEvents,
}
impl ::std::fmt::Display for Http3Server {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for Http3Server {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Http3 server ")
}
}
@@ -150,6 +151,10 @@ impl Http3Server {
.cloned(),
);
#[expect(
clippy::iter_over_hash_type,
reason = "OK to loop over active connections in an undefined order."
)]
for conn in active_conns {
self.process_events(&conn, now);
}

View File

@@ -7,6 +7,7 @@
use std::{
cell::RefCell,
collections::VecDeque,
fmt::{self, Display, Formatter},
ops::{Deref, DerefMut},
rc::Rc,
};
@@ -30,8 +31,8 @@ pub struct StreamHandler {
pub stream_info: Http3StreamInfo,
}
impl ::std::fmt::Display for StreamHandler {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for StreamHandler {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let conn: &Connection = &self.conn.borrow();
write!(f, "conn={conn} stream_info={:?}", self.stream_info)
}
@@ -158,8 +159,8 @@ pub struct Http3OrWebTransportStream {
stream_handler: StreamHandler,
}
impl ::std::fmt::Display for Http3OrWebTransportStream {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for Http3OrWebTransportStream {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Stream server {:?}", self.stream_handler)
}
}
@@ -242,8 +243,8 @@ pub struct WebTransportRequest {
stream_handler: StreamHandler,
}
impl ::std::fmt::Display for WebTransportRequest {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for WebTransportRequest {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "WebTransport session {}", self.stream_handler)
}
}

View File

@@ -4,6 +4,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::cmp::min;
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};
@@ -108,9 +110,11 @@ impl NewStreamHeadReader {
reader, stream_id, ..
} = self
{
// This type only exists to read at most two varints (= 16 bytes) from the stream.
let mut buf = [0; 16];
loop {
let to_read = reader.min_remaining();
let mut buf = vec![0; to_read];
let to_read = min(reader.min_remaining(), buf.len());
let buf = &mut buf[0..to_read];
match conn.stream_recv(*stream_id, &mut buf[..])? {
(0, f) => return Ok((None, f)),
(amount, f) => {

View File

@@ -1 +1 @@
{"files":{"Cargo.toml":"7c7241b4fc7cd16200bf53b881509e7757c99d11a0508006eda1c8d52e13309a","src/decoder.rs":"06dc4b0362ddf0a502ab7f3a8622aa213aaa6ca599990471f46c918778df69e6","src/decoder_instructions.rs":"0e6c2036372061b16f71b172e3b6f7796683c0992f5f6a39e6c4b37d9fff349a","src/encoder.rs":"22ac6cf0e6cbd9be5c7d09d4b73ac396bf7a9ac0e8a8f5137dcdafb0e004f85f","src/encoder_instructions.rs":"210442f053b317c14b8630c57e9c2f75f66e9ce3de79f5ff6cd5c6fcf1fea17a","src/header_block.rs":"4285d03556b6eba3a00715c9450b00af676a3ee5f3aa07a9f4e5e33944695ee3","src/huffman.rs":"4ffaf7766b7a9e1c01f094d48c447a75516ee7be91f2302327f7041d328a8c3f","src/huffman_decode_helper.rs":"c799b85c7738cdf6a1f6ea039062d2ea5ce0b4f08789d64e90a8712d57040d2b","src/huffman_table.rs":"5a5819dd2708f88240a2f825d86aa8b5f45c28d1427c0b8463831653e8eb3527","src/lib.rs":"1cde51b6c8c3c5a187f2393ad636e7e3919e10902c53bc9cc568bfe6c74a50c4","src/prefix.rs":"31bfb11d334a6df619bcc2720621e44a656be2514fad9033531a712d47dbe672","src/qlog.rs":"d8e8482624f0cc4388546169772846d37a0422ce10287ee2f716dfc5f7a56c3d","src/qpack_send_buf.rs":"cf10375c0bc5fb27d6faaf82df8607743bd62c5772d2cfb3779d801f4650e4f2","src/reader.rs":"5f0c2ab16bc804a892a7bd2310dfd6e614fd8ab2b4f552914fca6ad32b4fb006","src/static_table.rs":"6e5ec26e2b6bd63375d2d77e72748151d430d1629a8e497ec0d0ea21c078524a","src/stats.rs":"cb01723249f60e15a5cd7efd9cbab409fddc588d1df655ed06ba8c80e3d5d28e","src/table.rs":"f7c773dd3e086ead69ffffe9850e5c9b9b007c9fdd188022cdde7d08def248eb"},"package":null}
{"files":{"Cargo.toml":"6d2244529e53fa1dc0e30b8525b3cbdbae2baef8b4695be3037772e0105cf68e","src/decoder.rs":"e83c4dd3b1eebefbff30714f1800689e8f7a496e0b35667eb3bdd55089ed7184","src/decoder_instructions.rs":"fc945c839db9e9565d2e2dc6e24fbc9f3bf8583dbfabb2ddf2454d5567fe700c","src/encoder.rs":"faedcd7ef2cafb165322206d4a97ffac48e456922e79f1e282944aa50b4b81fd","src/encoder_instructions.rs":"34895b571506742619a565a08a7b8147e4efbd98a2eae8614e1870a74313a661","src/header_block.rs":"73a3910abf10be34eab35d076b200fcbb5351f823790ec65332e48c60e4de486","src/huffman.rs":"4ffaf7766b7a9e1c01f094d48c447a75516ee7be91f2302327f7041d328a8c3f","src/huffman_decode_helper.rs":"c799b85c7738cdf6a1f6ea039062d2ea5ce0b4f08789d64e90a8712d57040d2b","src/huffman_table.rs":"5a5819dd2708f88240a2f825d86aa8b5f45c28d1427c0b8463831653e8eb3527","src/lib.rs":"d8296558932bf0a325fd2f22e2294f800138b1915b311a88198073af073891bc","src/prefix.rs":"31bfb11d334a6df619bcc2720621e44a656be2514fad9033531a712d47dbe672","src/qlog.rs":"d8e8482624f0cc4388546169772846d37a0422ce10287ee2f716dfc5f7a56c3d","src/qpack_send_buf.rs":"cf10375c0bc5fb27d6faaf82df8607743bd62c5772d2cfb3779d801f4650e4f2","src/reader.rs":"5f0c2ab16bc804a892a7bd2310dfd6e614fd8ab2b4f552914fca6ad32b4fb006","src/static_table.rs":"6e5ec26e2b6bd63375d2d77e72748151d430d1629a8e497ec0d0ea21c078524a","src/stats.rs":"cb01723249f60e15a5cd7efd9cbab409fddc588d1df655ed06ba8c80e3d5d28e","src/table.rs":"926a616160589b9e6cd80dcf18fba6cae3de6ae770836434a500e90dedb134c5"},"package":null}

View File

@@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.82.0"
name = "neqo-qpack"
version = "0.13.2"
version = "0.13.4"
authors = ["The Neqo Authors <necko@mozilla.com>"]
build = false
autolib = false
@@ -83,17 +83,20 @@ create_dir = "warn"
dbg_macro = "warn"
empty_drop = "warn"
empty_enum_variants_with_brackets = "warn"
field_scoped_visibility_modifiers = "warn"
filetype_is_file = "warn"
float_cmp_const = "warn"
fn_to_numeric_cast_any = "warn"
get_unwrap = "warn"
if_then_some_else_none = "warn"
infinite_loop = "warn"
iter_over_hash_type = "warn"
large_include_file = "warn"
let_underscore_must_use = "warn"
let_underscore_untyped = "warn"
literal_string_with_formatting_args = "allow"
lossy_float_literal = "warn"
map_with_unused_argument_over_ranges = "warn"
mem_forget = "warn"
mixed_read_write_in_expression = "warn"
module_name_repetitions = "warn"
@@ -102,14 +105,18 @@ multiple_inherent_impl = "warn"
mutex_atomic = "warn"
mutex_integer = "warn"
needless_raw_strings = "warn"
partial_pub_fields = "warn"
pathbuf_init_then_push = "warn"
precedence_bits = "warn"
pub_without_shorthand = "warn"
rc_buffer = "warn"
rc_mutex = "warn"
redundant_test_prefix = "warn"
redundant_type_annotations = "warn"
ref_patterns = "warn"
renamed_function_params = "warn"
rest_pat_in_fully_bound_structs = "warn"
return_and_then = "warn"
self_named_module_files = "warn"
semicolon_inside_block = "warn"
string_lit_chars_any = "warn"

View File

@@ -9,6 +9,8 @@
reason = "<https://github.com/mozilla/neqo/issues/2284#issuecomment-2782711813>"
)]
use std::fmt::{self, Display, Formatter};
use neqo_common::{qdebug, Header};
use neqo_transport::{Connection, StreamId};
@@ -273,8 +275,8 @@ impl QPackDecoder {
}
}
impl ::std::fmt::Display for QPackDecoder {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for QPackDecoder {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "QPackDecoder {}", self.capacity())
}
}

View File

@@ -4,7 +4,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::mem;
use std::{
fmt::{self, Display, Formatter},
mem,
};
use neqo_common::{qdebug, qtrace};
use neqo_transport::StreamId;
@@ -69,8 +72,8 @@ pub struct DecoderInstructionReader {
instruction: DecoderInstruction,
}
impl ::std::fmt::Display for DecoderInstructionReader {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for DecoderInstructionReader {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "InstructionReader")
}
}

View File

@@ -9,7 +9,11 @@
reason = "<https://github.com/mozilla/neqo/issues/2284#issuecomment-2782711813>"
)]
use std::collections::{HashMap, HashSet, VecDeque};
use std::{
cmp::min,
collections::{HashMap, HashSet, VecDeque},
fmt::{self, Display, Formatter},
};
use neqo_common::{qdebug, qerror, qlog::NeqoQlog, qtrace, Header};
use neqo_transport::{Connection, Error as TransportError, StreamId};
@@ -103,7 +107,7 @@ impl QPackEncoder {
self.max_table_size,
);
let new_cap = std::cmp::min(self.max_table_size, cap);
let new_cap = min(self.max_table_size, cap);
// we also set our table to the max allowed.
self.change_capacity(new_cap);
Ok(())
@@ -146,6 +150,10 @@ impl QPackEncoder {
fn recalculate_blocked_streams(&mut self) {
let acked_inserts_cnt = self.table.get_acked_inserts_cnt();
self.blocked_stream_cnt = 0;
#[expect(
clippy::iter_over_hash_type,
reason = "OK to loop over unACKed blocks in an undefined order."
)]
for hb_list in self.unacked_header_blocks.values_mut() {
debug_assert!(!hb_list.is_empty());
if hb_list.iter().flatten().any(|e| *e >= acked_inserts_cnt) {
@@ -167,6 +175,10 @@ impl QPackEncoder {
let mut new_acked = self.table.get_acked_inserts_cnt();
if let Some(hb_list) = self.unacked_header_blocks.get_mut(&stream_id) {
if let Some(ref_list) = hb_list.pop_back() {
#[expect(
clippy::iter_over_hash_type,
reason = "OK to loop over unACKed blocks in an undefined order."
)]
for iter in ref_list {
self.table.remove_ref(iter);
if iter >= new_acked {
@@ -192,6 +204,10 @@ impl QPackEncoder {
if let Some(mut hb_list) = self.unacked_header_blocks.remove(&stream_id) {
debug_assert!(!hb_list.is_empty());
while let Some(ref_list) = hb_list.pop_front() {
#[expect(
clippy::iter_over_hash_type,
reason = "OK to loop over unACKed blocks in an undefined order."
)]
for iter in ref_list {
self.table.remove_ref(iter);
was_blocker = was_blocker || (iter >= self.table.get_acked_inserts_cnt());
@@ -500,8 +516,8 @@ impl QPackEncoder {
}
}
impl ::std::fmt::Display for QPackEncoder {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for QPackEncoder {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "QPackEncoder")
}
}

View File

@@ -4,7 +4,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::mem;
use std::{
fmt::{self, Display, Formatter},
mem,
};
use neqo_common::{qdebug, qtrace};
@@ -135,8 +138,8 @@ pub struct EncoderInstructionReader {
instruction: DecodedEncoderInstruction,
}
impl ::std::fmt::Display for EncoderInstructionReader {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for EncoderInstructionReader {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(
f,
"EncoderInstructionReader state={:?} instruction:{:?}",

View File

@@ -5,6 +5,7 @@
// except according to those terms.
use std::{
fmt::{self, Display, Formatter},
mem,
ops::{Deref, Div as _},
};
@@ -34,8 +35,8 @@ pub struct HeaderEncoder {
max_dynamic_index_ref: Option<u64>,
}
impl ::std::fmt::Display for HeaderEncoder {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for HeaderEncoder {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "HeaderEncoder")
}
}
@@ -163,8 +164,8 @@ pub struct HeaderDecoder<'a> {
req_insert_cnt: u64,
}
impl ::std::fmt::Display for HeaderDecoder<'_> {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for HeaderDecoder<'_> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "HeaderDecoder")
}
}

View File

@@ -20,6 +20,8 @@ mod static_table;
mod stats;
mod table;
use std::fmt::{self, Display, Formatter};
pub use decoder::QPackDecoder;
pub use encoder::QPackEncoder;
pub use stats::Stats;
@@ -96,8 +98,8 @@ impl ::std::error::Error for Error {
}
}
impl ::std::fmt::Display for Error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "QPACK error: {self:?}")
}
}

View File

@@ -4,7 +4,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::collections::VecDeque;
use std::{
collections::VecDeque,
fmt::{self, Display, Formatter},
};
use neqo_common::qtrace;
@@ -49,20 +52,10 @@ impl DynamicTableEntry {
self.refs -= 1;
}
#[allow(
clippy::allow_attributes,
clippy::missing_const_for_fn,
reason = "TODO: False positive on nightly."
)]
pub fn name(&self) -> &[u8] {
&self.name
}
#[allow(
clippy::allow_attributes,
clippy::missing_const_for_fn,
reason = "TODO: False positive on nightly."
)]
pub fn value(&self) -> &[u8] {
&self.value
}
@@ -87,8 +80,8 @@ pub struct HeaderTable {
acked_inserts_cnt: u64,
}
impl ::std::fmt::Display for HeaderTable {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for HeaderTable {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(
f,
"HeaderTable for (base={} acked_inserts_cnt={} capacity={})",

File diff suppressed because one or more lines are too long

View File

@@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.82.0"
name = "neqo-transport"
version = "0.13.2"
version = "0.13.4"
authors = ["The Neqo Authors <necko@mozilla.com>"]
build = "build.rs"
autolib = false
@@ -160,12 +160,13 @@ version = "1.1"
default-features = false
[dependencies.strum]
version = "0.26"
version = "0.27"
features = ["derive"]
default-features = false
[dev-dependencies.criterion]
version = "0.5"
version = "0.6"
features = ["cargo_bench_support"]
default-features = false
[dev-dependencies.neqo-transport]
@@ -184,17 +185,20 @@ create_dir = "warn"
dbg_macro = "warn"
empty_drop = "warn"
empty_enum_variants_with_brackets = "warn"
field_scoped_visibility_modifiers = "warn"
filetype_is_file = "warn"
float_cmp_const = "warn"
fn_to_numeric_cast_any = "warn"
get_unwrap = "warn"
if_then_some_else_none = "warn"
infinite_loop = "warn"
iter_over_hash_type = "warn"
large_include_file = "warn"
let_underscore_must_use = "warn"
let_underscore_untyped = "warn"
literal_string_with_formatting_args = "allow"
lossy_float_literal = "warn"
map_with_unused_argument_over_ranges = "warn"
mem_forget = "warn"
mixed_read_write_in_expression = "warn"
module_name_repetitions = "warn"
@@ -203,14 +207,18 @@ multiple_inherent_impl = "warn"
mutex_atomic = "warn"
mutex_integer = "warn"
needless_raw_strings = "warn"
partial_pub_fields = "warn"
pathbuf_init_then_push = "warn"
precedence_bits = "warn"
pub_without_shorthand = "warn"
rc_buffer = "warn"
rc_mutex = "warn"
redundant_test_prefix = "warn"
redundant_type_annotations = "warn"
ref_patterns = "warn"
renamed_function_params = "warn"
rest_pat_in_fully_bound_structs = "warn"
return_and_then = "warn"
self_named_module_files = "warn"
semicolon_inside_block = "warn"
string_lit_chars_any = "warn"

View File

@@ -4,6 +4,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{hint::black_box, time::Duration};
use criterion::{criterion_group, criterion_main, Criterion};
use neqo_transport::send_stream::RangeTracker;
@@ -29,12 +31,12 @@ fn coalesce(c: &mut Criterion, count: u64) {
|b| {
b.iter_batched_ref(
|| build_coalesce(count),
|used| {
black_box(|used: &mut RangeTracker| {
used.mark_acked(CHUNK, chunk);
let tail = (count + 1) * CHUNK;
used.mark_sent(tail, chunk);
used.mark_acked(tail, chunk);
},
}),
criterion::BatchSize::SmallInput,
);
},
@@ -48,5 +50,9 @@ fn benchmark_coalesce(c: &mut Criterion) {
coalesce(c, 1000);
}
criterion_group!(benches, benchmark_coalesce);
criterion_group! {
name = benches;
config = Criterion::default().warm_up_time(Duration::from_secs(5)).measurement_time(Duration::from_secs(60));
targets = benchmark_coalesce
}
criterion_main!(benches);

View File

@@ -4,6 +4,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{hint::black_box, time::Duration};
use criterion::{criterion_group, criterion_main, Criterion};
use neqo_transport::recv_stream::RxStreamOrderer;
@@ -18,9 +20,13 @@ fn rx_stream_orderer() {
fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("RxStreamOrderer::inbound_frame()", |b| {
b.iter(rx_stream_orderer);
b.iter(black_box(rx_stream_orderer));
});
}
criterion_group!(benches, criterion_benchmark);
criterion_group! {
name = benches;
config = Criterion::default().warm_up_time(Duration::from_secs(5)).measurement_time(Duration::from_secs(60));
targets = criterion_benchmark
}
criterion_main!(benches);

View File

@@ -4,7 +4,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::time::Instant;
use std::{
hint::black_box,
time::{Duration, Instant},
};
use criterion::{criterion_group, criterion_main, Criterion};
use neqo_transport::{
@@ -40,11 +43,15 @@ fn take_ranges(c: &mut Criterion) {
b.iter_batched_ref(
sent_packets,
// Take the first 90 packets, minus some gaps.
|pkts| pkts.take_ranges([70..=89, 40..=59, 10..=29]),
|pkts| black_box(pkts.take_ranges([70..=89, 40..=59, 10..=29])),
criterion::BatchSize::SmallInput,
);
});
}
criterion_group!(benches, take_ranges);
criterion_group! {
name = benches;
config = Criterion::default().warm_up_time(Duration::from_secs(5)).measurement_time(Duration::from_secs(60));
targets = take_ranges
}
criterion_main!(benches);

View File

@@ -4,7 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::time::Duration;
use std::{hint::black_box, time::Duration};
use criterion::{criterion_group, criterion_main, BatchSize::SmallInput, Criterion};
use neqo_transport::{ConnectionParameters, State};
@@ -62,7 +62,7 @@ fn benchmark_transfer(c: &mut Criterion, label: &str, seed: Option<impl AsRef<st
}
sim.setup()
},
ReadySimulator::run,
black_box(ReadySimulator::run),
SmallInput,
);
});
@@ -84,7 +84,7 @@ fn benchmark_transfer_fixed(c: &mut Criterion) {
criterion_group! {
name = transfer;
config = Criterion::default().warm_up_time(Duration::from_secs(5)).measurement_time(Duration::from_secs(15));
config = Criterion::default().warm_up_time(Duration::from_secs(5)).measurement_time(Duration::from_secs(60));
targets = benchmark_transfer_variable, benchmark_transfer_fixed
}
criterion_main!(transfer);

View File

@@ -10,6 +10,7 @@ use std::{
borrow::Borrow,
cell::{Ref, RefCell},
cmp::{max, min},
fmt::{self, Debug, Display, Formatter},
ops::Deref,
rc::Rc,
};
@@ -33,7 +34,7 @@ const CONNECTION_ID_SEQNO_EMPTY: u64 = u64::MAX - 1;
#[derive(Clone, Default, Eq, Hash, PartialEq)]
pub struct ConnectionId {
pub(crate) cid: SmallVec<[u8; MAX_CONNECTION_ID_LEN]>,
cid: SmallVec<[u8; MAX_CONNECTION_ID_LEN]>,
}
impl ConnectionId {
@@ -100,14 +101,14 @@ impl Deref for ConnectionId {
}
}
impl ::std::fmt::Debug for ConnectionId {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Debug for ConnectionId {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "CID {}", hex_with_len(&self.cid))
}
}
impl ::std::fmt::Display for ConnectionId {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for ConnectionId {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", hex(&self.cid))
}
}
@@ -123,14 +124,14 @@ pub struct ConnectionIdRef<'a> {
cid: &'a [u8],
}
impl ::std::fmt::Debug for ConnectionIdRef<'_> {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Debug for ConnectionIdRef<'_> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "CID {}", hex_with_len(self.cid))
}
}
impl ::std::fmt::Display for ConnectionIdRef<'_> {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for ConnectionIdRef<'_> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", hex(self.cid))
}
}
@@ -314,11 +315,6 @@ impl ConnectionIdEntry<[u8; 16]> {
true
}
#[allow(
clippy::allow_attributes,
clippy::missing_const_for_fn,
reason = "TODO: False positive on nightly."
)]
pub fn is_empty(&self) -> bool {
self.seqno == CONNECTION_ID_SEQNO_EMPTY || self.cid.is_empty()
}

View File

@@ -9,7 +9,7 @@
use std::{
cell::RefCell,
cmp::{max, min},
fmt::{self, Debug, Write as _},
fmt::{self, Debug, Display, Formatter, Write as _},
iter, mem,
net::{IpAddr, SocketAddr},
num::NonZeroUsize,
@@ -199,11 +199,6 @@ enum AddressValidationInfo {
}
impl AddressValidationInfo {
#[allow(
clippy::allow_attributes,
clippy::missing_const_for_fn,
reason = "TODO: False positive on nightly."
)]
pub fn token(&self) -> &[u8] {
match self {
Self::NewToken(token) | Self::Retry { token, .. } => token,
@@ -213,12 +208,11 @@ impl AddressValidationInfo {
pub fn generate_new_token(&self, peer_address: SocketAddr, now: Instant) -> Option<Vec<u8>> {
match self {
Self::Server(w) => w.upgrade().and_then(|validation| {
validation
.borrow()
.generate_new_token(peer_address, now)
.ok()
}),
Self::Server(w) => w
.upgrade()?
.borrow()
.generate_new_token(peer_address, now)
.ok(),
Self::None => None,
_ => unreachable!("called a server function on a client"),
}
@@ -276,8 +270,8 @@ pub struct Connection {
/// <https://datatracker.ietf.org/doc/html/draft-ietf-quic-datagram>
quic_datagrams: QuicDatagrams,
pub(crate) crypto: Crypto,
pub(crate) acks: AckTracker,
crypto: Crypto,
acks: AckTracker,
idle_timeout: IdleTimeout,
streams: Streams,
state_signaling: StateSignaling,
@@ -296,11 +290,11 @@ pub struct Connection {
/// otherwise be sent, just to see how a connection handles them. Inserting them
/// into packets proper mean that the frames follow the entire processing path.
#[cfg(test)]
pub test_frame_writer: Option<Box<dyn test_internal::FrameWriter>>,
test_frame_writer: Option<Box<dyn test_internal::FrameWriter>>,
}
impl Debug for Connection {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(
f,
"{:?} Connection: {:?} {:?}",
@@ -336,7 +330,7 @@ impl Connection {
protocols,
conn_params,
)?;
c.crypto.states.init(
c.crypto.states_mut().init(
c.conn_params.get_versions().compatible(),
Role::Client,
&dcid,
@@ -387,7 +381,7 @@ impl Connection {
let mut cid_manager =
ConnectionIdManager::new(cid_generator, local_initial_source_cid.clone());
let mut tps = conn_params.create_transport_parameter(role, &mut cid_manager)?;
tps.local
tps.local_mut()
.set_bytes(InitialSourceConnectionId, local_initial_source_cid.to_vec());
let tphandler = Rc::new(RefCell::new(tps));
@@ -514,7 +508,7 @@ impl Connection {
value: tparams::TransportParameter,
) -> Res<()> {
if *self.state() == State::Init {
self.tps.borrow_mut().local.set(tp, value);
self.tps.borrow_mut().local_mut().set(tp, value);
Ok(())
} else {
qerror!("Current state: {:?}", self.state());
@@ -536,9 +530,14 @@ impl Connection {
debug_assert_eq!(self.role, Role::Server);
qtrace!("[{self}] Retry CIDs: odcid={odcid} remote={remote_cid} retry={retry_cid}");
// We advertise "our" choices in transport parameters.
let local_tps = &mut self.tps.borrow_mut().local;
local_tps.set_bytes(OriginalDestinationConnectionId, odcid.to_vec());
local_tps.set_bytes(RetrySourceConnectionId, retry_cid.to_vec());
self.tps
.borrow_mut()
.local_mut()
.set_bytes(OriginalDestinationConnectionId, odcid.to_vec());
self.tps
.borrow_mut()
.local_mut()
.set_bytes(RetrySourceConnectionId, retry_cid.to_vec());
// ...and save their choices for later validation.
self.remote_initial_source_cid = Some(remote_cid);
@@ -547,7 +546,7 @@ impl Connection {
fn retry_sent(&self) -> bool {
self.tps
.borrow()
.local
.local()
.get_bytes(RetrySourceConnectionId)
.is_some()
}
@@ -557,7 +556,7 @@ impl Connection {
/// # Errors
/// When the operation fails, which is usually due to bad inputs or bad connection state.
pub fn set_alpn(&mut self, protocols: &[impl AsRef<str>]) -> Res<()> {
self.crypto.tls.set_alpn(protocols)?;
self.crypto.tls_mut().set_alpn(protocols)?;
Ok(())
}
@@ -569,7 +568,7 @@ impl Connection {
qerror!("[{self}] Cannot enable ciphers in state {:?}", self.state);
return Err(Error::ConnectionState);
}
self.crypto.tls.set_ciphers(ciphers)?;
self.crypto.tls_mut().set_ciphers(ciphers)?;
Ok(())
}
@@ -581,7 +580,7 @@ impl Connection {
qerror!("[{self}] Cannot enable groups in state {:?}", self.state);
return Err(Error::ConnectionState);
}
self.crypto.tls.set_groups(groups)?;
self.crypto.tls_mut().set_groups(groups)?;
Ok(())
}
@@ -593,7 +592,7 @@ impl Connection {
qerror!("[{self}] Cannot enable groups in state {:?}", self.state);
return Err(Error::ConnectionState);
}
self.crypto.tls.send_additional_key_shares(count)?;
self.crypto.tls_mut().send_additional_key_shares(count)?;
Ok(())
}
@@ -626,7 +625,7 @@ impl Connection {
self.new_token.take_token(),
self.tps
.borrow()
.remote
.remote_handshake()
.as_ref()
.expect("should have transport parameters"),
self.version,
@@ -761,7 +760,7 @@ impl Connection {
let tok = dec.decode_remainder();
qtrace!("[{self}] TLS token {}", hex(tok));
match self.crypto.tls {
match self.crypto.tls_mut() {
Agent::Client(ref mut c) => {
let res = c.enable_resumption(tok);
if let Err(e) = res {
@@ -775,7 +774,7 @@ impl Connection {
self.version = version;
self.conn_params.get_versions_mut().set_initial(version);
self.tps.borrow_mut().set_version(version);
self.tps.borrow_mut().remote_0rtt = Some(tp);
self.tps.borrow_mut().set_remote_0rtt(Some(tp));
if !init_token.is_empty() {
self.address_validation = AddressValidationInfo::NewToken(init_token.to_vec());
}
@@ -808,10 +807,10 @@ impl Connection {
}
let tps = &self.tps;
if let Agent::Server(ref mut s) = self.crypto.tls {
if let Agent::Server(ref mut s) = self.crypto.tls_mut() {
let mut enc = Encoder::default();
enc.encode_vvec_with(|enc_inner| {
tps.borrow().local.encode(enc_inner);
tps.borrow().local().encode(enc_inner);
});
enc.encode(extra);
let records = s.send_ticket(now, enc.as_ref())?;
@@ -837,26 +836,21 @@ impl Connection {
}
}
#[allow(
clippy::allow_attributes,
clippy::missing_const_for_fn,
reason = "TODO: False positive on nightly."
)]
#[must_use]
pub fn tls_info(&self) -> Option<&SecretAgentInfo> {
self.crypto.tls.info()
self.crypto.tls().info()
}
/// # Errors
/// When there is no information to obtain.
pub fn tls_preinfo(&self) -> Res<SecretAgentPreInfo> {
Ok(self.crypto.tls.preinfo()?)
Ok(self.crypto.tls().preinfo()?)
}
/// Get the peer's certificate chain and other info.
#[must_use]
pub fn peer_certificate(&self) -> Option<CertificateInfo> {
self.crypto.tls.peer_certificate()
self.crypto.tls().peer_certificate()
}
/// Call by application when the peer cert has been verified.
@@ -867,7 +861,7 @@ impl Connection {
/// exchanged, it's not OK.
pub fn authenticated(&mut self, status: AuthenticationStatus, now: Instant) {
qdebug!("[{self}] Authenticated {status:?}");
self.crypto.tls.authenticated(status);
self.crypto.tls_mut().authenticated(status);
let res = self.handshake(now, self.version, PacketNumberSpace::Handshake, None);
self.absorb_error(now, res);
self.process_saved(now);
@@ -1011,7 +1005,7 @@ impl Connection {
self.streams.cleanup_closed_streams();
let res = self.crypto.states.check_key_update(now);
let res = self.crypto.states_mut().check_key_update(now);
self.absorb_error(now, res);
if let Some(path) = self.paths.primary() {
@@ -1112,7 +1106,7 @@ impl Connection {
}
}
if let Some(key_update_time) = self.crypto.states.update_time() {
if let Some(key_update_time) = self.crypto.states().update_time() {
qtrace!("[{self}] Key update timer {key_update_time:?}");
delays.push(key_update_time);
}
@@ -1239,7 +1233,7 @@ impl Connection {
let lost_packets = self.loss_recovery.retry(&path, now);
self.handle_lost_packets(&lost_packets);
self.crypto.states.init(
self.crypto.states_mut().init(
self.conn_params.get_versions().compatible(),
self.role,
&retry_scid,
@@ -1300,7 +1294,11 @@ impl Connection {
fn process_saved(&mut self, now: Instant) {
while let Some(epoch) = self.saved_datagrams.available() {
qdebug!("[{self}] process saved for epoch {epoch:?}");
debug_assert!(self.crypto.states.rx_hp(self.version, epoch).is_some());
debug_assert!(self
.crypto
.states_mut()
.rx_hp(self.version, epoch)
.is_some());
for saved in self.saved_datagrams.take_saved() {
qtrace!("[{self}] input saved @{:?}: {:?}", saved.t, saved.d);
self.input(saved.d, saved.t, now);
@@ -1426,7 +1424,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_mut().init_server(version, &dcid)?;
self.original_destination_cid = Some(dcid);
self.set_state(State::WaitInitial, now);
@@ -1436,7 +1434,7 @@ impl Connection {
if !self.retry_sent() {
self.tps
.borrow_mut()
.local
.local_mut()
.set_bytes(OriginalDestinationConnectionId, packet.dcid().to_vec());
}
}
@@ -1649,7 +1647,7 @@ impl Connection {
qtrace!("[{self}] Received unverified packet {packet:?}");
let packet_len = packet.len();
match packet.decrypt(&mut self.crypto.states, now + pto) {
match packet.decrypt(self.crypto.states_mut(), now + pto) {
Ok(payload) => {
// OK, we have a valid packet.
let pn = payload.pn();
@@ -1754,7 +1752,7 @@ impl Connection {
// packet number to verify the ACK against.
let next_pn = self
.crypto
.states
.states()
.select_tx(self.version, PacketNumberSpace::from(packet.packet_type()))
.map_or(0, |(_, tx)| tx.next_pn());
@@ -1894,7 +1892,7 @@ impl Connection {
fn has_version(&self) -> bool {
if self.role == Role::Server {
// The server knows the final version if it has remote transport parameters.
self.tps.borrow().remote.is_some()
self.tps.borrow().remote_handshake().is_some()
} else {
// The client knows the final version if it processed a CRYPTO frame.
self.stats.borrow().frame_rx.crypto > 0
@@ -2141,13 +2139,13 @@ impl Connection {
fn can_grease_quic_bit(&self) -> bool {
let tph = self.tps.borrow();
if let Some(r) = &tph.remote {
r.get_empty(GreaseQuicBit)
} else if let Some(r) = &tph.remote_0rtt {
r.get_empty(GreaseQuicBit)
} else {
false
}
tph.remote_handshake().as_ref().map_or_else(
|| {
tph.remote_0rtt()
.is_some_and(|r| r.get_empty(GreaseQuicBit))
},
|r| r.get_empty(GreaseQuicBit),
)
}
/// Write the frames that are exchanged in the application data space.
@@ -2450,7 +2448,8 @@ impl Connection {
let mut encoder = Encoder::with_capacity(profile.limit());
for space in PacketNumberSpace::iter() {
// Ensure we have tx crypto state for this epoch, or skip it.
let Some((epoch, tx)) = self.crypto.states.select_tx_mut(self.version, space) else {
let Some((epoch, tx)) = self.crypto.states_mut().select_tx_mut(self.version, space)
else {
continue;
};
@@ -2525,11 +2524,11 @@ impl Connection {
self.stats.borrow_mut().packets_tx += 1;
let tx = self
.crypto
.states
.states_mut()
.tx_mut(self.version, epoch)
.ok_or(Error::InternalError)?;
encoder = builder.build(tx)?;
self.crypto.states.auto_update()?;
self.crypto.states_mut().auto_update()?;
if ack_eliciting {
self.idle_timeout.on_packet_sent(now);
@@ -2580,7 +2579,7 @@ impl Connection {
// decrypt yet.
if self.role == Role::Client
&& space == PacketNumberSpace::Initial
&& !self.crypto.streams.is_empty(space)
&& !self.crypto.streams_mut().is_empty(space)
{
break;
}
@@ -2623,7 +2622,7 @@ impl Connection {
.loss_recovery
.largest_acknowledged_pn(PacketNumberSpace::ApplicationData);
qinfo!("[{self}] Initiating key update");
self.crypto.states.initiate_key_update(la)
self.crypto.states_mut().initiate_key_update(la)
} else {
Err(Error::KeyUpdateBlocked)
}
@@ -2632,7 +2631,7 @@ impl Connection {
#[cfg(test)]
#[must_use]
pub fn get_epochs(&self) -> (Option<usize>, Option<usize>) {
self.crypto.states.get_epochs()
self.crypto.states().get_epochs()
}
fn client_start(&mut self, now: Instant) -> Res<()> {
@@ -2703,7 +2702,9 @@ impl Connection {
self.validate_versions()?;
{
let tps = self.tps.borrow();
let remote = tps.remote.as_ref().ok_or(Error::TransportParameterError)?;
let remote = tps
.remote_handshake()
.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.
@@ -2748,7 +2749,9 @@ impl Connection {
fn validate_cids(&self) -> Res<()> {
let tph = self.tps.borrow();
let remote_tps = tph.remote.as_ref().ok_or(Error::TransportParameterError)?;
let remote_tps = tph
.remote_handshake()
.ok_or(Error::TransportParameterError)?;
let tp = remote_tps.get_bytes(InitialSourceConnectionId);
if self
@@ -2805,7 +2808,9 @@ 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().ok_or(Error::TransportParameterError)?;
let remote_tps = tph
.remote_handshake()
.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() {
@@ -2873,13 +2878,13 @@ impl Connection {
if self.role == Role::Client {
self.confirm_version(packet_version)?;
} else if self.tps.borrow().remote.is_some() {
} else if self.tps.borrow().remote_handshake().is_some() {
let version = self.tps.borrow().version();
let dcid = self
.original_destination_cid
.as_ref()
.ok_or(Error::ProtocolViolation)?;
self.crypto.states.init_server(version, dcid)?;
self.crypto.states_mut().init_server(version, dcid)?;
self.confirm_version(version)?;
}
Ok(())
@@ -2895,7 +2900,7 @@ impl Connection {
qtrace!("[{self}] Handshake space={space} data={data:0x?}");
let was_authentication_pending =
*self.crypto.tls.state() == HandshakeState::AuthenticationPending;
*self.crypto.tls().state() == HandshakeState::AuthenticationPending;
let try_update = data.is_some();
match self.crypto.handshake(now, space, data)? {
HandshakeState::Authenticated(_) | HandshakeState::InProgress => (),
@@ -2923,7 +2928,7 @@ impl Connection {
if try_update {
self.compatible_upgrade(packet_version)?;
// We have transport parameters, it's go time.
if self.tps.borrow().remote.is_some() {
if self.tps.borrow().remote_handshake().is_some() {
self.set_initial_limits();
}
if self.crypto.install_keys(self.role)? {
@@ -3004,10 +3009,12 @@ impl Connection {
&data
);
self.stats.borrow_mut().frame_rx.crypto += 1;
self.crypto.streams.inbound_frame(space, offset, data)?;
if self.crypto.streams.data_ready(space) {
self.crypto
.streams_mut()
.inbound_frame(space, offset, data)?;
if self.crypto.streams().data_ready(space) {
let mut buf = Vec::new();
let read = self.crypto.streams.read_to_end(space, &mut buf);
let read = self.crypto.streams_mut().read_to_end(space, &mut buf);
qdebug!("Read {read:?} bytes");
self.handshake(now, packet_version, space, Some(&buf))?;
self.create_resumption_token(now);
@@ -3170,7 +3177,7 @@ impl Connection {
fn decode_ack_delay(&self, v: u64) -> Res<Duration> {
// If we have remote transport parameters, use them.
// Otherwise, ack delay should be zero (because it's the handshake).
self.tps.borrow().remote.as_ref().map_or_else(
self.tps.borrow().remote_handshake().map_or_else(
|| Ok(Duration::default()),
|r| {
let exponent = u32::try_from(r.get_integer(AckDelayExponent))?;
@@ -3258,13 +3265,19 @@ impl Connection {
qdebug!("[{self}] 0-RTT rejected");
self.resend_0rtt(now);
self.streams.zero_rtt_rejected();
self.crypto.states.discard_0rtt_keys();
self.crypto.states_mut().discard_0rtt_keys();
self.events.client_0rtt_rejected();
}
fn set_connected(&mut self, now: Instant) -> Res<()> {
qdebug!("[{self}] TLS connection complete");
if self.crypto.tls.info().map(SecretAgentInfo::alpn).is_none() {
if self
.crypto
.tls()
.info()
.map(SecretAgentInfo::alpn)
.is_none()
{
qwarn!("[{self}] No ALPN, closing connection");
// 120 = no_application_protocol
return Err(Error::CryptoAlert(120));
@@ -3280,7 +3293,7 @@ impl Connection {
} else {
self.zero_rtt_state = if self
.crypto
.tls
.tls()
.info()
.ok_or(Error::InternalError)?
.early_data_accepted()
@@ -3302,7 +3315,7 @@ impl Connection {
self.saved_datagrams.make_available(Epoch::ApplicationData);
self.stats.borrow_mut().resumed = self
.crypto
.tls
.tls()
.info()
.ok_or(Error::InternalError)?
.resumed();
@@ -3573,7 +3586,7 @@ impl Connection {
let version = self.version();
let Some((epoch, tx)) = self
.crypto
.states
.states()
.select_tx(self.version, PacketNumberSpace::ApplicationData)
else {
return Err(Error::NotAvailable);
@@ -3632,23 +3645,22 @@ impl Connection {
}
fn log_packet(&self, meta: packet::MetaData, now: Instant) {
if !log::log_enabled!(log::Level::Debug) {
return;
if log::log_enabled!(log::Level::Debug) {
let mut s = String::new();
let mut d = Decoder::from(meta.payload());
while d.remaining() > 0 {
let Ok(f) = Frame::decode(&mut d) else {
s.push_str(" [broken]...");
break;
};
let x = f.dump();
if !x.is_empty() {
_ = write!(&mut s, "\n {} {}", meta.direction(), &x);
}
}
qdebug!("[{self}] {meta}{s}");
}
let mut s = String::new();
let mut d = Decoder::from(meta.payload());
while d.remaining() > 0 {
let Ok(f) = Frame::decode(&mut d) else {
s.push_str(" [broken]...");
break;
};
let x = f.dump();
if !x.is_empty() {
_ = write!(&mut s, "\n {} {}", meta.direction(), &x);
}
}
qdebug!("[{self}] {meta}{s}");
qlog::packet_io(&self.qlog, meta, now);
}
}
@@ -3669,11 +3681,11 @@ impl EventProvider for Connection {
}
}
impl ::std::fmt::Display for Connection {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for Connection {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{:?} ", self.role)?;
if let Some(cid) = self.odcid() {
fmt::Display::fmt(&cid, f)
Display::fmt(&cid, f)
} else {
write!(f, "...")
}

View File

@@ -6,6 +6,8 @@
use std::{cmp::max, time::Duration};
use neqo_common::MAX_VARINT;
pub use crate::recovery::FAST_PTO_SCALE;
use crate::{
connection::{ConnectionIdManager, Role, LOCAL_ACTIVE_CID_LIMIT},
@@ -27,7 +29,7 @@ use crate::{
CongestionControlAlgorithm, Res,
};
const LOCAL_MAX_DATA: u64 = 0x3FFF_FFFF_FFFF_FFFF; // 2^62-1
const LOCAL_MAX_DATA: u64 = MAX_VARINT;
const LOCAL_STREAM_LIMIT_BIDI: u64 = 16;
const LOCAL_STREAM_LIMIT_UNI: u64 = 16;
/// See `ConnectionParameters.ack_ratio` for a discussion of this value.
@@ -432,47 +434,47 @@ impl ConnectionParameters {
) -> Res<TransportParametersHandler> {
let mut tps = TransportParametersHandler::new(role, self.versions.clone());
// default parameters
tps.local.set_integer(
tps.local_mut().set_integer(
ActiveConnectionIdLimit,
u64::try_from(LOCAL_ACTIVE_CID_LIMIT)?,
);
if self.disable_migration {
tps.local.set_empty(DisableMigration);
tps.local_mut().set_empty(DisableMigration);
}
if self.grease {
tps.local.set_empty(GreaseQuicBit);
tps.local_mut().set_empty(GreaseQuicBit);
}
tps.local.set_integer(
tps.local_mut().set_integer(
MaxAckDelay,
u64::try_from(DEFAULT_LOCAL_ACK_DELAY.as_millis())?,
);
tps.local
tps.local_mut()
.set_integer(MinAckDelay, u64::try_from(GRANULARITY.as_micros())?);
// set configurable parameters
tps.local.set_integer(InitialMaxData, self.max_data);
tps.local.set_integer(
tps.local_mut().set_integer(InitialMaxData, self.max_data);
tps.local_mut().set_integer(
InitialMaxStreamDataBidiLocal,
self.max_stream_data_bidi_local,
);
tps.local.set_integer(
tps.local_mut().set_integer(
InitialMaxStreamDataBidiRemote,
self.max_stream_data_bidi_remote,
);
tps.local
tps.local_mut()
.set_integer(InitialMaxStreamDataUni, self.max_stream_data_uni);
tps.local
tps.local_mut()
.set_integer(InitialMaxStreamsBidi, self.max_streams_bidi);
tps.local
tps.local_mut()
.set_integer(InitialMaxStreamsUni, self.max_streams_uni);
tps.local.set_integer(
tps.local_mut().set_integer(
TransportParameterId::IdleTimeout,
u64::try_from(self.idle_timeout.as_millis()).unwrap_or(0),
);
if let PreferredAddressConfig::Address(preferred) = &self.preferred_address {
if role == Role::Server {
let (cid, srt) = cid_manager.preferred_address_cid()?;
tps.local.set(
tps.local_mut().set(
TransportParameterId::PreferredAddress,
TransportParameter::PreferredAddress {
v4: preferred.ipv4(),
@@ -483,7 +485,7 @@ impl ConnectionParameters {
);
}
}
tps.local
tps.local_mut()
.set_integer(MaxDatagramFrameSize, self.datagram_size);
Ok(tps)
}

View File

@@ -104,7 +104,7 @@ fn bad_tls_version() {
// Do a bad, bad thing.
client
.crypto
.tls
.tls_mut()
.set_option(neqo_crypto::Opt::Tls13CompatMode, true)
.unwrap();
let mut server = default_server();

View File

@@ -1375,7 +1375,7 @@ fn grease_quic_bit_transport_parameter() {
fn get_remote_tp(conn: &Connection) -> bool {
conn.tps
.borrow()
.remote
.remote_handshake()
.as_ref()
.unwrap()
.get_empty(GreaseQuicBit)

View File

@@ -96,7 +96,7 @@ fn asymmetric_idle_timeout() {
server
.tps
.borrow_mut()
.local
.local_mut()
.set_integer(TransportParameterId::IdleTimeout, LOWER_TIMEOUT_MS);
server.idle_timeout = IdleTimeout::new(LOWER_TIMEOUT);
@@ -309,7 +309,7 @@ fn idle_caching() {
// to send CRYPTO frames again, so manually extract and discard those.
server.process_input(dgram.unwrap(), middle);
let mut tokens = Vec::new();
server.crypto.streams.write_frame(
server.crypto.streams_mut().write_frame(
PacketNumberSpace::Initial,
server.conn_params.sni_slicing_enabled(),
&mut builder,
@@ -318,7 +318,7 @@ fn idle_caching() {
);
assert_eq!(tokens.len(), 1);
tokens.clear();
server.crypto.streams.write_frame(
server.crypto.streams_mut().write_frame(
PacketNumberSpace::Initial,
server.conn_params.sni_slicing_enabled(),
&mut builder,

View File

@@ -728,7 +728,7 @@ fn create_server() {
fn tp_grease() {
for enable in [true, false] {
let client = new_client(ConnectionParameters::default().grease(enable));
let grease = client.tps.borrow_mut().local.get_empty(GreaseQuicBit);
let grease = client.tps.borrow_mut().local().get_empty(GreaseQuicBit);
assert_eq!(enable, grease);
}
}
@@ -737,7 +737,7 @@ fn tp_grease() {
fn tp_disable_migration() {
for disable in [true, false] {
let client = new_client(ConnectionParameters::default().disable_migration(disable));
let disable_migration = client.tps.borrow_mut().local.get_empty(DisableMigration);
let disable_migration = client.tps.borrow_mut().local().get_empty(DisableMigration);
assert_eq!(disable, disable_migration);
}
}

View File

@@ -222,8 +222,8 @@ fn address_validation_token_resume() {
// Now try to complete the handshake after giving time for a client PTO.
now += AT_LEAST_PTO;
connect_with_rtt(&mut client, &mut server, now, RTT);
assert!(client.crypto.tls.info().unwrap().resumed());
assert!(server.crypto.tls.info().unwrap().resumed());
assert!(client.crypto.tls().info().unwrap().resumed());
assert!(server.crypto.tls().info().unwrap().resumed());
}
fn can_resume(token: impl AsRef<[u8]>, initial_has_token: bool) {

View File

@@ -4,7 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{cmp::max, collections::HashMap};
use std::{cmp::max, collections::HashMap, fmt::Debug};
use neqo_common::{event::Provider as _, qdebug};
use test_fixture::now;
@@ -224,7 +224,7 @@ fn fairness_test<S, R>(source: S, number_iterates: usize, truncate_to: usize, re
where
S: IntoIterator,
S::Item: Into<StreamId>,
R: IntoIterator + std::fmt::Debug,
R: IntoIterator + Debug,
R::Item: Into<StreamId>,
Vec<u64>: PartialEq<R>,
{

View File

@@ -287,6 +287,10 @@ fn compatible_upgrade_large_initial() {
assert!(
server.stats().dscp_rx[IpTosDscp::Cs0] == server.stats().packets_rx
|| server.stats().dscp_rx[IpTosDscp::Cs0] == server.stats().packets_rx + 1
|| server.stats().dscp_rx[IpTosDscp::Cs0] == server.stats().packets_rx - 1,
"dscp_rx[IpTosDscp::Cs0] {} != packets_rx {} (possibly +/- 1)",
server.stats().dscp_rx[IpTosDscp::Cs0],
server.stats().packets_rx
);
}

View File

@@ -7,6 +7,7 @@
use std::{
cell::RefCell,
cmp::{max, min},
fmt::{self, Display, Formatter},
mem,
ops::{Index, IndexMut, Range},
rc::Rc,
@@ -57,9 +58,9 @@ thread_local!(pub static OVERWRITE_INVOCATIONS: RefCell<Option<PacketNumber>> =
pub struct Crypto {
version: Version,
protocols: Vec<String>,
pub(crate) tls: Agent,
pub(crate) streams: CryptoStreams,
pub(crate) states: CryptoStates,
tls: Agent,
streams: CryptoStreams,
states: CryptoStates,
}
type TpHandler = Rc<RefCell<TransportParametersHandler>>;
@@ -130,11 +131,6 @@ impl Crypto {
}
/// Get the set of enabled protocols.
#[allow(
clippy::allow_attributes,
clippy::missing_const_for_fn,
reason = "TODO: False positive on nightly."
)]
pub fn protocols(&self) -> &[String] {
&self.protocols
}
@@ -396,10 +392,40 @@ impl Crypto {
unreachable!("It is a server");
}
}
#[must_use]
pub fn tls_mut(&mut self) -> &mut Agent {
&mut self.tls
}
#[must_use]
pub const fn tls(&self) -> &Agent {
&self.tls
}
#[must_use]
pub const fn streams(&self) -> &CryptoStreams {
&self.streams
}
#[must_use]
pub fn streams_mut(&mut self) -> &mut CryptoStreams {
&mut self.streams
}
#[must_use]
pub const fn states(&self) -> &CryptoStates {
&self.states
}
#[must_use]
pub fn states_mut(&mut self) -> &mut CryptoStates {
&mut self.states
}
}
impl ::std::fmt::Display for Crypto {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for Crypto {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Crypto")
}
}
@@ -712,8 +738,8 @@ impl CryptoDxState {
}
}
impl std::fmt::Display for CryptoDxState {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for CryptoDxState {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "epoch {} {:?}", self.epoch, self.direction)
}
}
@@ -1321,8 +1347,8 @@ impl CryptoStates {
}
}
impl std::fmt::Display for CryptoStates {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for CryptoStates {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "CryptoStates")
}
}

View File

@@ -15,7 +15,7 @@ use std::{
time::{Duration, Instant},
};
use neqo_common::{qdebug, qtrace, Role};
use neqo_common::{qdebug, qtrace, Role, MAX_VARINT};
use crate::{
frame::FrameType,
@@ -283,8 +283,13 @@ where
self.frame_pending
}
pub const fn next_limit(&self) -> u64 {
self.retired + self.max_active
pub fn next_limit(&self) -> u64 {
min(
self.retired + self.max_active,
// Flow control limits are encoded as QUIC varints and are thus
// limited to the maximum QUIC varint value.
MAX_VARINT,
)
}
pub const fn max_active(&self) -> u64 {
@@ -655,7 +660,7 @@ mod test {
time::{Duration, Instant},
};
use neqo_common::{qdebug, Encoder, Role};
use neqo_common::{qdebug, Encoder, Role, MAX_VARINT};
use neqo_crypto::random;
use super::{LocalStreamLimits, ReceiverFlowControl, RemoteStreamLimits, SenderFlowControl};
@@ -665,7 +670,7 @@ mod test {
recv_stream::MAX_RECV_WINDOW_SIZE,
stats::FrameStats,
stream_id::{StreamId, StreamType},
Error, Res, INITIAL_RECV_WINDOW_SIZE,
ConnectionParameters, Error, Res, INITIAL_RECV_WINDOW_SIZE,
};
#[test]
@@ -1221,4 +1226,25 @@ mod test {
Ok(())
}
#[test]
fn max_active_larger_max_varint() {
// Instead of doing proper connection flow control, Neqo simply sets
// the largest connection flow control limit possible.
let max_data = ConnectionParameters::default().get_max_data();
assert_eq!(max_data, MAX_VARINT);
let mut fc = ReceiverFlowControl::new((), max_data);
// Say that the remote consumes 1 byte of that connection flow control
// limit and then requests a connection flow control update.
fc.consume(1).unwrap();
fc.add_retired(1);
fc.send_flowc_update();
// Neqo should never attempt writing a connection flow control update
// larger than the largest possible QUIC varint value.
let mut builder = PacketBuilder::short(Encoder::new(), false, None::<&[u8]>);
let mut tokens = Vec::new();
fc.write_frames(&mut builder, &mut tokens, &mut FrameStats::default());
}
}

View File

@@ -8,7 +8,7 @@
use std::ops::RangeInclusive;
use neqo_common::{qtrace, Decoder, Encoder};
use neqo_common::{qtrace, Decoder, Encoder, MAX_VARINT};
use strum::FromRepr;
use crate::{
@@ -155,8 +155,8 @@ impl From<std::array::TryFromSliceError> for Error {
#[derive(PartialEq, Eq, Debug, Default, Clone)]
pub struct AckRange {
pub(crate) gap: u64,
pub(crate) range: u64,
gap: u64,
range: u64,
}
#[derive(PartialEq, Eq, Debug, Clone)]
@@ -543,7 +543,7 @@ impl<'a> Frame<'a> {
FrameType::Crypto => {
let offset = dv(dec)?;
let data = d(dec.decode_vvec())?;
if offset + u64::try_from(data.len())? > ((1 << 62) - 1) {
if offset + u64::try_from(data.len())? > MAX_VARINT {
return Err(Error::FrameEncodingError);
}
Ok(Self::Crypto { offset, data })
@@ -577,7 +577,7 @@ impl<'a> Frame<'a> {
qtrace!("STREAM frame, with length");
d(dec.decode_vvec())?
};
if o + u64::try_from(data.len())? > ((1 << 62) - 1) {
if o + u64::try_from(data.len())? > MAX_VARINT {
return Err(Error::FrameEncodingError);
}
Ok(Self::Stream {

View File

@@ -4,6 +4,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt::{self, Display, Formatter};
use neqo_common::qwarn;
use neqo_crypto::Error as CryptoError;
@@ -206,8 +208,8 @@ impl ::std::error::Error for Error {
}
}
impl ::std::fmt::Display for Error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Transport error: {self:?}")
}
}

View File

@@ -8,7 +8,7 @@
use std::{
cmp::min,
fmt::{Debug, Display},
fmt::{self, Debug, Display, Formatter},
time::{Duration, Instant},
};
@@ -127,13 +127,13 @@ impl Pacer {
}
impl Display for Pacer {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Pacer {}/{}", self.c, self.p)
}
}
impl Debug for Pacer {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Pacer@{:?} {}/{}..{}", self.t, self.c, self.p, self.m)
}
}

View File

@@ -7,7 +7,7 @@
// Enable just this file for logging to just see packets.
// e.g. "RUST_LOG=neqo_transport::dump neqo-client ..."
use std::fmt::Display;
use std::fmt::{self, Display, Formatter};
use neqo_common::IpTos;
use qlog::events::quic::PacketHeader;
@@ -38,11 +38,6 @@ pub struct MetaData<'a> {
}
impl MetaData<'_> {
#[allow(
clippy::allow_attributes,
clippy::missing_const_for_fn,
reason = "TODO: False positive on nightly."
)]
pub fn new_in<'a>(
path: &'a PathRef,
tos: IpTos,
@@ -108,7 +103,7 @@ impl From<MetaData<'_>> for PacketHeader {
}
impl Display for MetaData<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
f,
"pn={} type={:?} {} {:?} len {}",

View File

@@ -91,15 +91,16 @@ impl PacketType {
}
}
#[expect(clippy::fallible_impl_from, reason = "TODO: Use strum.")]
impl From<PacketType> for Epoch {
fn from(v: PacketType) -> Self {
impl TryFrom<PacketType> for Epoch {
type Error = Error;
fn try_from(v: PacketType) -> Res<Self> {
match v {
PacketType::Initial => Self::Initial,
PacketType::ZeroRtt => Self::ZeroRtt,
PacketType::Handshake => Self::Handshake,
PacketType::Short => Self::ApplicationData,
_ => panic!("shouldn't be here"),
PacketType::Initial => Ok(Self::Initial),
PacketType::ZeroRtt => Ok(Self::ZeroRtt),
PacketType::Handshake => Ok(Self::Handshake),
PacketType::Short => Ok(Self::ApplicationData),
_ => Err(Error::InvalidPacket),
}
}
}
@@ -425,13 +426,11 @@ impl PacketBuilder {
self.write_len(crypto.expansion());
}
let hdr = &self.encoder.as_ref()[self.header.clone()];
let body = &self.encoder.as_ref()[self.header.end..];
qtrace!(
"Packet build pn={} hdr={} body={}",
self.pn,
hex(hdr),
hex(body)
hex(&self.encoder.as_ref()[self.header.clone()]),
hex(&self.encoder.as_ref()[self.header.end..])
);
// Add space for crypto expansion.
@@ -771,11 +770,6 @@ impl<'a> PublicPacket<'a> {
.as_cid_ref()
}
#[allow(
clippy::allow_attributes,
clippy::missing_const_for_fn,
reason = "TODO: False positive on nightly."
)]
#[must_use]
pub fn token(&self) -> &[u8] {
&self.token
@@ -783,7 +777,7 @@ impl<'a> PublicPacket<'a> {
#[must_use]
pub fn version(&self) -> Option<Version> {
self.version.and_then(|v| Version::try_from(v).ok())
Version::try_from(self.version?).ok()
}
#[must_use]
@@ -881,7 +875,7 @@ impl<'a> PublicPacket<'a> {
crypto: &mut CryptoStates,
release_at: Instant,
) -> Res<DecryptedPacket> {
let epoch: Epoch = self.packet_type.into();
let epoch: Epoch = self.packet_type.try_into()?;
// When we don't have a version, the crypto code doesn't need a version
// for lookup, so use the default, but fix it up if decryption succeeds.
let version = self.version().unwrap_or_default();

View File

@@ -875,11 +875,6 @@ impl Path {
/// This only considers retransmissions of probes, not cleanup of the path.
/// If there is no other activity, then there is no real need to schedule a
/// timer to cleanup old paths.
#[allow(
clippy::allow_attributes,
clippy::missing_const_for_fn,
reason = "TODO: False positive on nightly."
)]
pub fn next_timeout(&self, pto: Duration) -> Option<Instant> {
if let ProbeState::Probing { sent, .. } = &self.state {
Some(*sent + pto)

View File

@@ -261,9 +261,7 @@ pub fn packet_dropped(qlog: &NeqoQlog, public_packet: &PublicPacket, now: Instan
PacketHeader::with_type(public_packet.packet_type().into(), None, None, None, None);
let raw = RawInfo {
length: Some(public_packet.len() as u64),
payload_length: None,
data: None,
// TODO: ..Default::default() once qlog is past 0.15.1
..Default::default()
};
let ev_data = EventData::PacketDropped(PacketDropped {

View File

@@ -19,6 +19,7 @@ mod token;
use std::{
cmp::{max, min},
fmt::{self, Display, Formatter},
ops::RangeInclusive,
time::{Duration, Instant},
};
@@ -507,7 +508,7 @@ impl LossRecovery {
#[must_use]
pub fn largest_acknowledged_pn(&self, pn_space: PacketNumberSpace) -> Option<PacketNumber> {
self.spaces.get(pn_space).and_then(|sp| sp.largest_acked)
self.spaces.get(pn_space)?.largest_acked
}
pub fn set_qlog(&mut self, qlog: NeqoQlog) {
@@ -780,8 +781,9 @@ impl LossRecovery {
// Calculate PTO time for the given space.
fn pto_time(&self, rtt: &RttEstimate, pn_space: PacketNumberSpace) -> Option<Instant> {
self.spaces
.get(pn_space)
.and_then(|space| space.pto_base_time().map(|t| t + self.pto_period(rtt)))
.get(pn_space)?
.pto_base_time()
.map(|t| t + self.pto_period(rtt))
}
/// Find the earliest PTO time for all active packet number spaces.
@@ -903,6 +905,11 @@ impl LossRecovery {
qtrace!("[{self}] get send profile {now:?}");
let sender = path.sender();
let mtu = path.plpmtu();
#[allow(
clippy::allow_attributes,
clippy::return_and_then,
reason = "TODO: False positive on nightly; function isn't returning Option or Result"
)]
if let Some(profile) = self
.pto_state
.as_mut()
@@ -933,8 +940,8 @@ impl LossRecovery {
}
}
impl ::std::fmt::Display for LossRecovery {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for LossRecovery {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "LossRecovery")
}
}

View File

@@ -106,11 +106,6 @@ impl SentPacket {
}
/// Access the recovery tokens that this holds.
#[allow(
clippy::allow_attributes,
clippy::missing_const_for_fn,
reason = "TODO: False positive on nightly."
)]
#[must_use]
pub fn tokens(&self) -> &[RecoveryToken] {
&self.tokens

View File

@@ -16,6 +16,7 @@ use std::{
cell::RefCell,
cmp::max,
collections::BTreeMap,
fmt::Debug,
mem,
rc::{Rc, Weak},
time::{Duration, Instant},
@@ -997,6 +998,7 @@ impl RecvStream {
mod tests {
use std::{
cell::RefCell,
fmt::Debug,
ops::Range,
rc::Rc,
time::{Duration, Instant},
@@ -1656,7 +1658,7 @@ mod tests {
assert!(session_fc.borrow().frame_needed());
}
fn check_fc<T: std::fmt::Debug>(fc: &ReceiverFlowControl<T>, consumed: u64, retired: u64) {
fn check_fc<T: Debug>(fc: &ReceiverFlowControl<T>, consumed: u64, retired: u64) {
assert_eq!(fc.consumed(), consumed);
assert_eq!(fc.retired(), retired);
}

View File

@@ -129,11 +129,7 @@ impl RttEstimate {
self.first_sample_time = Some(now);
} else {
// Calculate EWMA RTT (based on {{?RFC6298}}).
let rttvar_sample = if self.smoothed_rtt > rtt_sample {
self.smoothed_rtt - rtt_sample
} else {
rtt_sample - self.smoothed_rtt
};
let rttvar_sample = self.smoothed_rtt.abs_diff(rtt_sample);
self.latest_rtt = rtt_sample;
self.rttvar = (self.rttvar * 3 + rttvar_sample) / 4;

View File

@@ -15,6 +15,7 @@ use std::{
cell::RefCell,
cmp::{max, min, Ordering},
collections::{btree_map::Entry, BTreeMap, VecDeque},
fmt::{self, Display, Formatter},
mem,
num::NonZeroUsize,
ops::Add,
@@ -851,7 +852,8 @@ impl SendStream {
match self.state {
SendStreamState::Send {
ref mut send_buf, ..
} => send_buf.next_bytes().and_then(|(offset, slice)| {
} => {
let (offset, slice) = send_buf.next_bytes()?;
if retransmission_only {
qtrace!(
"next_bytes apply retransmission limit at {}",
@@ -867,7 +869,7 @@ impl SendStream {
} else {
Some((offset, slice))
}
}),
}
SendStreamState::DataSent {
ref mut send_buf,
fin_sent,
@@ -1386,8 +1388,8 @@ impl SendStream {
}
}
impl ::std::fmt::Display for SendStream {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for SendStream {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "SendStream {}", self.stream_id)
}
}
@@ -1796,7 +1798,7 @@ impl<'a> IntoIterator for &'a mut SendStreams {
#[derive(Debug, Clone)]
pub struct SendStreamRecoveryToken {
pub(crate) id: StreamId,
id: StreamId,
offset: u64,
length: usize,
fin: bool,
@@ -1806,7 +1808,7 @@ pub struct SendStreamRecoveryToken {
mod tests {
use std::{cell::RefCell, collections::VecDeque, num::NonZeroUsize, rc::Rc};
use neqo_common::{event::Provider as _, hex_with_len, qtrace, Encoder};
use neqo_common::{event::Provider as _, hex_with_len, qtrace, Encoder, MAX_VARINT};
use super::SendStreamRecoveryToken;
use crate::{
@@ -2931,8 +2933,6 @@ mod tests {
/// Create a `SendStream` and force it into a state where it believes that
/// `offset` bytes have already been sent and acknowledged.
fn stream_with_sent(stream: u64, offset: usize) -> SendStream {
const MAX_VARINT: u64 = (1 << 62) - 1;
let conn_fc = connection_fc(MAX_VARINT);
let mut s = SendStream::new(
StreamId::from(stream),

View File

@@ -10,6 +10,7 @@ use std::{
cell::RefCell,
cmp::min,
collections::HashSet,
fmt::{self, Display, Formatter},
ops::{Deref, DerefMut},
path::PathBuf,
rc::Rc,
@@ -419,12 +420,7 @@ impl Server {
now,
);
return Output::Datagram(Datagram::new(
dgram.destination(),
dgram.source(),
IpTos::default(),
vn,
));
return Output::Datagram(Datagram::new(destination, source, IpTos::default(), vn));
}
match packet.packet_type() {
@@ -439,8 +435,10 @@ impl Server {
self.handle_initial(initial, dgram, now)
}
PacketType::ZeroRtt => {
let dcid = ConnectionId::from(packet.dcid());
qdebug!("[{self}] Dropping 0-RTT for unknown connection {dcid}");
qdebug!(
"[{self}] Dropping 0-RTT for unknown connection {}",
ConnectionId::from(packet.dcid())
);
Output::None
}
PacketType::OtherVersion => unreachable!(),
@@ -553,8 +551,8 @@ impl PartialEq for ConnectionRef {
impl Eq for ConnectionRef {}
impl ::std::fmt::Display for Server {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
impl Display for Server {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Server")
}
}

Some files were not shown because too many files have changed in this diff Show More