From 67afcab3e4208e7615fcc1f7684934f3923d1885 Mon Sep 17 00:00:00 2001 From: Sandor Molnar Date: Mon, 8 Apr 2024 16:47:13 +0300 Subject: [PATCH] Backed out changeset 317994df7ee4 (bug 1889691) for causing dt failures @ browser_webconsole_csp_violation.js / browser_inspector_reload_iframe.js --- .cargo/config.toml.in | 4 +- Cargo.lock | 21 +- netwerk/socket/neqo_glue/Cargo.toml | 12 +- netwerk/socket/neqo_glue/src/lib.rs | 2 +- netwerk/test/http3server/Cargo.toml | 10 +- netwerk/test/http3server/src/main.rs | 2 +- third_party/rust/neqo-common/.cargo-checksum.json | 2 +- third_party/rust/neqo-common/Cargo.toml | 24 +- third_party/rust/neqo-common/src/datagram.rs | 15 +- third_party/rust/neqo-common/src/lib.rs | 3 + third_party/rust/neqo-common/src/log.rs | 21 +- third_party/rust/neqo-common/src/timer.rs | 396 +++++++++++++++++++++ third_party/rust/neqo-common/src/tos.rs | 48 +-- third_party/rust/neqo-common/src/udp.rs | 222 ++++++++++++ third_party/rust/neqo-crypto/.cargo-checksum.json | 2 +- third_party/rust/neqo-crypto/Cargo.toml | 8 +- .../rust/neqo-crypto/bindings/bindings.toml | 5 + third_party/rust/neqo-crypto/bindings/mozpkix.hpp | 1 + third_party/rust/neqo-crypto/build.rs | 105 +++--- third_party/rust/neqo-crypto/min_version.txt | 1 - third_party/rust/neqo-crypto/src/aead.rs | 8 +- .../src/{aead_null.rs => aead_fuzzing.rs} | 67 ++-- third_party/rust/neqo-crypto/src/agent.rs | 11 +- third_party/rust/neqo-crypto/src/err.rs | 30 +- third_party/rust/neqo-crypto/src/lib.rs | 68 ++-- third_party/rust/neqo-crypto/src/min_version.rs | 9 - third_party/rust/neqo-crypto/src/selfencrypt.rs | 2 +- third_party/rust/neqo-crypto/tests/aead.rs | 3 +- third_party/rust/neqo-crypto/tests/init.rs | 51 +-- third_party/rust/neqo-crypto/tests/selfencrypt.rs | 6 +- third_party/rust/neqo-http3/.cargo-checksum.json | 2 +- third_party/rust/neqo-http3/Cargo.toml | 8 +- third_party/rust/neqo-http3/src/connection.rs | 16 +- .../rust/neqo-http3/src/connection_client.rs | 4 +- .../rust/neqo-http3/src/connection_server.rs | 4 +- third_party/rust/neqo-http3/src/recv_message.rs | 2 +- third_party/rust/neqo-http3/src/send_message.rs | 6 +- third_party/rust/neqo-http3/src/server_events.rs | 8 +- third_party/rust/neqo-qpack/.cargo-checksum.json | 2 +- third_party/rust/neqo-qpack/Cargo.toml | 2 +- .../rust/neqo-transport/.cargo-checksum.json | 2 +- third_party/rust/neqo-transport/Cargo.toml | 4 +- .../rust/neqo-transport/benches/range_tracker.rs | 16 +- .../neqo-transport/benches/rx_stream_orderer.rs | 4 +- .../rust/neqo-transport/benches/transfer.rs | 16 +- .../rust/neqo-transport/src/cc/classic_cc.rs | 16 +- .../rust/neqo-transport/src/connection/dump.rs | 16 +- .../rust/neqo-transport/src/connection/mod.rs | 52 +-- .../rust/neqo-transport/src/connection/params.rs | 13 + .../rust/neqo-transport/src/connection/state.rs | 5 +- .../src/connection/tests/{null.rs => fuzzing.rs} | 8 +- .../src/connection/tests/handshake.rs | 11 +- .../neqo-transport/src/connection/tests/mod.rs | 85 +---- .../neqo-transport/src/connection/tests/stream.rs | 6 + third_party/rust/neqo-transport/src/crypto.rs | 96 ++++- third_party/rust/neqo-transport/src/frame.rs | 86 ++--- third_party/rust/neqo-transport/src/lib.rs | 4 +- third_party/rust/neqo-transport/src/packet/mod.rs | 73 +--- .../rust/neqo-transport/src/packet/retry.rs | 1 + third_party/rust/neqo-transport/src/path.rs | 2 +- third_party/rust/neqo-transport/src/qlog.rs | 347 +++++++++--------- third_party/rust/neqo-transport/src/server.rs | 87 ++--- third_party/rust/neqo-transport/src/stats.rs | 6 +- .../rust/neqo-transport/tests/common/mod.rs | 9 +- .../rust/neqo-transport/tests/conn_vectors.rs | 2 +- .../rust/neqo-transport/tests/connection.rs | 70 ---- third_party/rust/neqo-transport/tests/retry.rs | 2 +- 67 files changed, 1344 insertions(+), 908 deletions(-) create mode 100644 third_party/rust/neqo-common/src/timer.rs create mode 100644 third_party/rust/neqo-common/src/udp.rs rewrite third_party/rust/neqo-crypto/.cargo-checksum.json (100%) create mode 100644 third_party/rust/neqo-crypto/bindings/mozpkix.hpp delete mode 100644 third_party/rust/neqo-crypto/min_version.txt rename third_party/rust/neqo-crypto/src/{aead_null.rs => aead_fuzzing.rs} (53%) delete mode 100644 third_party/rust/neqo-crypto/src/min_version.rs rewrite third_party/rust/neqo-transport/.cargo-checksum.json (78%) rename third_party/rust/neqo-transport/src/connection/tests/{null.rs => fuzzing.rs} (84%) diff --git a/.cargo/config.toml.in b/.cargo/config.toml.in index 2603a47564da..ac39dbea00b9 100644 --- a/.cargo/config.toml.in +++ b/.cargo/config.toml.in @@ -85,9 +85,9 @@ git = "https://github.com/mozilla/mp4parse-rust" rev = "a138e40ec1c603615873e524b5b22e11c0ec4820" replace-with = "vendored-sources" -[source."git+https://github.com/mozilla/neqo?tag=v0.7.3"] +[source."git+https://github.com/mozilla/neqo?tag=v0.7.2"] git = "https://github.com/mozilla/neqo" -tag = "v0.7.3" +tag = "v0.7.2" replace-with = "vendored-sources" [source."git+https://github.com/mozilla/uniffi-rs.git?rev=afb29ebdc1d9edf15021b1c5332fc9f285bbe13b"] diff --git a/Cargo.lock b/Cargo.lock index f133fe3ec0d5..77d089d7e456 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3947,8 +3947,8 @@ dependencies = [ [[package]] name = "neqo-common" -version = "0.7.3" -source = "git+https://github.com/mozilla/neqo?tag=v0.7.3#1dc8ea33e27b65a0294ff3502204285358fc4a77" +version = "0.7.2" +source = "git+https://github.com/mozilla/neqo?tag=v0.7.2#ce5cbe4dfc2e38b238abb022c39eee4215058221" dependencies = [ "enum-map", "env_logger", @@ -3960,14 +3960,13 @@ dependencies = [ [[package]] name = "neqo-crypto" -version = "0.7.3" -source = "git+https://github.com/mozilla/neqo?tag=v0.7.3#1dc8ea33e27b65a0294ff3502204285358fc4a77" +version = "0.7.2" +source = "git+https://github.com/mozilla/neqo?tag=v0.7.2#ce5cbe4dfc2e38b238abb022c39eee4215058221" dependencies = [ "bindgen 0.69.4", "log", "mozbuild", "neqo-common", - "semver", "serde", "serde_derive", "toml", @@ -3975,8 +3974,8 @@ dependencies = [ [[package]] name = "neqo-http3" -version = "0.7.3" -source = "git+https://github.com/mozilla/neqo?tag=v0.7.3#1dc8ea33e27b65a0294ff3502204285358fc4a77" +version = "0.7.2" +source = "git+https://github.com/mozilla/neqo?tag=v0.7.2#ce5cbe4dfc2e38b238abb022c39eee4215058221" dependencies = [ "enumset", "log", @@ -3992,8 +3991,8 @@ dependencies = [ [[package]] name = "neqo-qpack" -version = "0.7.3" -source = "git+https://github.com/mozilla/neqo?tag=v0.7.3#1dc8ea33e27b65a0294ff3502204285358fc4a77" +version = "0.7.2" +source = "git+https://github.com/mozilla/neqo?tag=v0.7.2#ce5cbe4dfc2e38b238abb022c39eee4215058221" dependencies = [ "log", "neqo-common", @@ -4005,8 +4004,8 @@ dependencies = [ [[package]] name = "neqo-transport" -version = "0.7.3" -source = "git+https://github.com/mozilla/neqo?tag=v0.7.3#1dc8ea33e27b65a0294ff3502204285358fc4a77" +version = "0.7.2" +source = "git+https://github.com/mozilla/neqo?tag=v0.7.2#ce5cbe4dfc2e38b238abb022c39eee4215058221" dependencies = [ "indexmap 1.9.3", "log", diff --git a/netwerk/socket/neqo_glue/Cargo.toml b/netwerk/socket/neqo_glue/Cargo.toml index 51e9287acd87..2d7f0d9a5f25 100644 --- a/netwerk/socket/neqo_glue/Cargo.toml +++ b/netwerk/socket/neqo_glue/Cargo.toml @@ -9,10 +9,10 @@ license = "MPL-2.0" name = "neqo_glue" [dependencies] -neqo-http3 = { tag = "v0.7.3", git = "https://github.com/mozilla/neqo" } -neqo-transport = { tag = "v0.7.3", git = "https://github.com/mozilla/neqo" } -neqo-common = { tag = "v0.7.3", git = "https://github.com/mozilla/neqo" } -neqo-qpack = { tag = "v0.7.3", git = "https://github.com/mozilla/neqo" } +neqo-http3 = { tag = "v0.7.2", git = "https://github.com/mozilla/neqo" } +neqo-transport = { tag = "v0.7.2", git = "https://github.com/mozilla/neqo" } +neqo-common = { tag = "v0.7.2", git = "https://github.com/mozilla/neqo" } +neqo-qpack = { tag = "v0.7.2", git = "https://github.com/mozilla/neqo" } nserror = { path = "../../../xpcom/rust/nserror" } nsstring = { path = "../../../xpcom/rust/nsstring" } xpcom = { path = "../../../xpcom/rust/xpcom" } @@ -27,10 +27,10 @@ uuid = { version = "1.0", features = ["v4"] } winapi = {version = "0.3", features = ["ws2def"] } [dependencies.neqo-crypto] -tag = "v0.7.3" +tag = "v0.7.2" git = "https://github.com/mozilla/neqo" default-features = false features = ["gecko"] [features] -fuzzing = ["neqo-http3/disable-encryption"] +fuzzing = ["neqo-http3/fuzzing"] diff --git a/netwerk/socket/neqo_glue/src/lib.rs b/netwerk/socket/neqo_glue/src/lib.rs index fd527a7fb98b..6c86211ed505 100644 --- a/netwerk/socket/neqo_glue/src/lib.rs +++ b/netwerk/socket/neqo_glue/src/lib.rs @@ -121,7 +121,7 @@ impl NeqoHttp3Conn { max_accumlated_time_ms: u32, ) -> Result, nsresult> { // Nss init. - init().map_err(|_| NS_ERROR_UNEXPECTED)?; + init(); let origin_conv = str::from_utf8(origin).map_err(|_| NS_ERROR_INVALID_ARG)?; diff --git a/netwerk/test/http3server/Cargo.toml b/netwerk/test/http3server/Cargo.toml index 527b0d7f4cd8..60ff22c530b9 100644 --- a/netwerk/test/http3server/Cargo.toml +++ b/netwerk/test/http3server/Cargo.toml @@ -6,10 +6,10 @@ edition = "2018" license = "MPL-2.0" [dependencies] -neqo-transport = { tag = "v0.7.3", git = "https://github.com/mozilla/neqo" } -neqo-common = { tag = "v0.7.3", git = "https://github.com/mozilla/neqo" } -neqo-http3 = { tag = "v0.7.3", git = "https://github.com/mozilla/neqo" } -neqo-qpack = { tag = "v0.7.3", git = "https://github.com/mozilla/neqo" } +neqo-transport = { tag = "v0.7.2", git = "https://github.com/mozilla/neqo" } +neqo-common = { tag = "v0.7.2", git = "https://github.com/mozilla/neqo" } +neqo-http3 = { tag = "v0.7.2", git = "https://github.com/mozilla/neqo" } +neqo-qpack = { tag = "v0.7.2", git = "https://github.com/mozilla/neqo" } mio = "0.6.17" mio-extras = "2.0.5" log = "0.4.0" @@ -21,7 +21,7 @@ tokio = { version = "1", features = ["rt-multi-thread"] } mozilla-central-workspace-hack = { version = "0.1", features = ["http3server"], optional = true } [dependencies.neqo-crypto] -tag = "v0.7.3" +tag = "v0.7.2" git = "https://github.com/mozilla/neqo" default-features = false features = ["gecko"] diff --git a/netwerk/test/http3server/src/main.rs b/netwerk/test/http3server/src/main.rs index 1543e3aeb3f8..a308f5644242 100644 --- a/netwerk/test/http3server/src/main.rs +++ b/netwerk/test/http3server/src/main.rs @@ -1378,7 +1378,7 @@ fn main() -> Result<(), io::Error> { } }); - init_db(PathBuf::from(args[1].clone())).unwrap(); + init_db(PathBuf::from(args[1].clone())); let mut servers_runner = ServersRunner::new()?; servers_runner.init(); diff --git a/third_party/rust/neqo-common/.cargo-checksum.json b/third_party/rust/neqo-common/.cargo-checksum.json index 7f9259d130ea..e7daca119151 100644 --- a/third_party/rust/neqo-common/.cargo-checksum.json +++ b/third_party/rust/neqo-common/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"a5ff5210d8d2f1210eff53a0c3f9b9f930d9259b83d58b3c2104665f722d5e2c","build.rs":"306b2f909a25ae38daf5404a4e128d2a94e8975b70870864c2a71cafec9717c7","src/codec.rs":"fd239f75d374db6ff744211344c82bcd19ecf753e07410e1fe37732bbb81dfe9","src/datagram.rs":"691ad94a3618d6bf5202a7911419b5e75e318d09c8cc57a9a542a864dcc764ec","src/event.rs":"106ca6c4afb107fa49a1bc72f5eb4ae95f4baa1ba19736aa38c8ba973774c160","src/header.rs":"467b947f78bfe354d8bb51e8df0c2be69e75a45e2be688d81f0d268aa77c89ef","src/hrtime.rs":"112dc758e65301b8a7a508b125d3d61063180d432bffaec566a050d4f907ab18","src/incrdecoder.rs":"577c32b9ace51f2daaf940be6d0c391c4f55cd42ef6848c68c1ffc970d8c57b5","src/lib.rs":"32b1902796d06129eb66b16195e45eed8a95ae79017eda72c2c347e232645126","src/log.rs":"6ed99e15707c4256ae793011ed2f4b33aa81fed70205aaf5f8d3cd11ad451cf0","src/qlog.rs":"9b081f32bf158fd340300693acc97fe0554b617ae664eba86e4d3572e2b1e16e","src/tos.rs":"baec87b4f8a6253b88cd257730bd1e3147c046ef993288b08235d54a24f88fbe","tests/log.rs":"a11e21fb570258ca93bb40e3923817d381e1e605accbc3aed1df5a0a9918b41d"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"b49758e5e8f0a6955d761e689be39530f193f7089de07f2295a7a3aef4df5898","build.rs":"306b2f909a25ae38daf5404a4e128d2a94e8975b70870864c2a71cafec9717c7","src/codec.rs":"fd239f75d374db6ff744211344c82bcd19ecf753e07410e1fe37732bbb81dfe9","src/datagram.rs":"f2ff56faa0e513edbf4331b6ee2c9e6d6111483bda7aff08d16b9f05bce5c320","src/event.rs":"106ca6c4afb107fa49a1bc72f5eb4ae95f4baa1ba19736aa38c8ba973774c160","src/header.rs":"467b947f78bfe354d8bb51e8df0c2be69e75a45e2be688d81f0d268aa77c89ef","src/hrtime.rs":"112dc758e65301b8a7a508b125d3d61063180d432bffaec566a050d4f907ab18","src/incrdecoder.rs":"577c32b9ace51f2daaf940be6d0c391c4f55cd42ef6848c68c1ffc970d8c57b5","src/lib.rs":"a86aae69900933bf83044fa96166ee51216277415eafcdb15c04a907bb2dd10e","src/log.rs":"7246053bffd704b264d42fc82f986b9d62079472a76a9fc3749c25cfc7698532","src/qlog.rs":"9b081f32bf158fd340300693acc97fe0554b617ae664eba86e4d3572e2b1e16e","src/timer.rs":"350a730cc5a159dfdac5d78ec8e8a34c5172a476d827a566703edec24c791842","src/tos.rs":"440616cb0aee9082abe00623b33e68dbe80eda47aec889ac5f4145b1566bf692","src/udp.rs":"2b92132e078791e35b66f68d99d79ff5df55efd03e788474f7781a00403a5533","tests/log.rs":"a11e21fb570258ca93bb40e3923817d381e1e605accbc3aed1df5a0a9918b41d"},"package":null} \ No newline at end of file diff --git a/third_party/rust/neqo-common/Cargo.toml b/third_party/rust/neqo-common/Cargo.toml index 9bbdfb27d367..dc5bed385f74 100644 --- a/third_party/rust/neqo-common/Cargo.toml +++ b/third_party/rust/neqo-common/Cargo.toml @@ -13,7 +13,7 @@ edition = "2021" rust-version = "1.74.0" name = "neqo-common" -version = "0.7.3" +version = "0.7.2" authors = ["The Neqo Authors "] build = "build.rs" homepage = "https://github.com/mozilla/neqo/" @@ -39,14 +39,26 @@ default-features = false version = "0.12" default-features = false +[dependencies.quinn-udp] +git = "https://github.com/quinn-rs/quinn/" +rev = "a947962131aba8a6521253d03cc948b20098a2d6" +optional = true + [dependencies.time] version = "0.3" features = ["formatting"] default-features = false -[dev-dependencies.criterion] -version = "0.5" -features = ["html_reports"] +[dependencies.tokio] +version = "1" +features = [ + "net", + "time", + "macros", + "rt", + "rt-multi-thread", +] +optional = true default-features = false [dev-dependencies.test-fixture] @@ -54,6 +66,10 @@ path = "../test-fixture" [features] ci = [] +udp = [ + "dep:quinn-udp", + "dep:tokio", +] [target."cfg(windows)".dependencies.winapi] version = "0.3" diff --git a/third_party/rust/neqo-common/src/datagram.rs b/third_party/rust/neqo-common/src/datagram.rs index cc2cb7d11337..04ba1a45a14a 100644 --- a/third_party/rust/neqo-common/src/datagram.rs +++ b/third_party/rust/neqo-common/src/datagram.rs @@ -54,8 +54,10 @@ impl Datagram { self.ttl } - pub fn set_tos(&mut self, tos: IpTos) { - self.tos = tos; + #[cfg(feature = "udp")] + #[must_use] + pub(crate) fn into_data(self) -> Vec { + self.d } } @@ -81,12 +83,6 @@ impl std::fmt::Debug for Datagram { } } -impl From for Vec { - fn from(datagram: Datagram) -> Self { - datagram.d - } -} - #[cfg(test)] use test_fixture::datagram; @@ -94,7 +90,8 @@ use test_fixture::datagram; fn fmt_datagram() { let d = datagram([0; 1].to_vec()); assert_eq!( - &format!("{d:?}"), + format!("{d:?}"), "Datagram IpTos(Cs0, NotEct) TTL Some(128) [fe80::1]:443->[fe80::1]:443: [1]: 00" + .to_string() ); } diff --git a/third_party/rust/neqo-common/src/lib.rs b/third_party/rust/neqo-common/src/lib.rs index f3e8e63023c5..fe8809798356 100644 --- a/third_party/rust/neqo-common/src/lib.rs +++ b/third_party/rust/neqo-common/src/lib.rs @@ -14,7 +14,10 @@ pub mod hrtime; mod incrdecoder; pub mod log; pub mod qlog; +pub mod timer; pub mod tos; +#[cfg(feature = "udp")] +pub mod udp; use std::fmt::Write; diff --git a/third_party/rust/neqo-common/src/log.rs b/third_party/rust/neqo-common/src/log.rs index 04028a26bdaf..c5b89be8a662 100644 --- a/third_party/rust/neqo-common/src/log.rs +++ b/third_party/rust/neqo-common/src/log.rs @@ -50,7 +50,7 @@ fn since_start() -> Duration { START_TIME.get_or_init(Instant::now).elapsed() } -pub fn init(level_filter: Option) { +pub fn init() { static INIT_ONCE: Once = Once::new(); if ::log::STATIC_MAX_LEVEL == ::log::LevelFilter::Off { @@ -59,9 +59,6 @@ pub fn init(level_filter: Option) { INIT_ONCE.call_once(|| { let mut builder = Builder::from_env("RUST_LOG"); - if let Some(filter) = level_filter { - builder.filter_level(filter); - } builder.format(|buf, record| { let elapsed = since_start(); writeln!( @@ -74,9 +71,9 @@ pub fn init(level_filter: Option) { ) }); if let Err(e) = builder.try_init() { - do_log!(::log::Level::Warn, "Logging initialization error {:?}", e); + do_log!(::log::Level::Info, "Logging initialization error {:?}", e); } else { - do_log!(::log::Level::Debug, "Logging initialized"); + do_log!(::log::Level::Info, "Logging initialized"); } }); } @@ -84,32 +81,32 @@ pub fn init(level_filter: Option) { #[macro_export] macro_rules! log_invoke { ($lvl:expr, $ctx:expr, $($arg:tt)*) => ( { - ::neqo_common::log::init(None); + ::neqo_common::log::init(); ::neqo_common::do_log!($lvl, "[{}] {}", $ctx, format!($($arg)*)); } ) } #[macro_export] macro_rules! qerror { ([$ctx:expr], $($arg:tt)*) => (::neqo_common::log_invoke!(::log::Level::Error, $ctx, $($arg)*);); - ($($arg:tt)*) => ( { ::neqo_common::log::init(None); ::neqo_common::do_log!(::log::Level::Error, $($arg)*); } ); + ($($arg:tt)*) => ( { ::neqo_common::log::init(); ::neqo_common::do_log!(::log::Level::Error, $($arg)*); } ); } #[macro_export] macro_rules! qwarn { ([$ctx:expr], $($arg:tt)*) => (::neqo_common::log_invoke!(::log::Level::Warn, $ctx, $($arg)*);); - ($($arg:tt)*) => ( { ::neqo_common::log::init(None); ::neqo_common::do_log!(::log::Level::Warn, $($arg)*); } ); + ($($arg:tt)*) => ( { ::neqo_common::log::init(); ::neqo_common::do_log!(::log::Level::Warn, $($arg)*); } ); } #[macro_export] macro_rules! qinfo { ([$ctx:expr], $($arg:tt)*) => (::neqo_common::log_invoke!(::log::Level::Info, $ctx, $($arg)*);); - ($($arg:tt)*) => ( { ::neqo_common::log::init(None); ::neqo_common::do_log!(::log::Level::Info, $($arg)*); } ); + ($($arg:tt)*) => ( { ::neqo_common::log::init(); ::neqo_common::do_log!(::log::Level::Info, $($arg)*); } ); } #[macro_export] macro_rules! qdebug { ([$ctx:expr], $($arg:tt)*) => (::neqo_common::log_invoke!(::log::Level::Debug, $ctx, $($arg)*);); - ($($arg:tt)*) => ( { ::neqo_common::log::init(None); ::neqo_common::do_log!(::log::Level::Debug, $($arg)*); } ); + ($($arg:tt)*) => ( { ::neqo_common::log::init(); ::neqo_common::do_log!(::log::Level::Debug, $($arg)*); } ); } #[macro_export] macro_rules! qtrace { ([$ctx:expr], $($arg:tt)*) => (::neqo_common::log_invoke!(::log::Level::Trace, $ctx, $($arg)*);); - ($($arg:tt)*) => ( { ::neqo_common::log::init(None); ::neqo_common::do_log!(::log::Level::Trace, $($arg)*); } ); + ($($arg:tt)*) => ( { ::neqo_common::log::init(); ::neqo_common::do_log!(::log::Level::Trace, $($arg)*); } ); } diff --git a/third_party/rust/neqo-common/src/timer.rs b/third_party/rust/neqo-common/src/timer.rs new file mode 100644 index 000000000000..a413252e08e8 --- /dev/null +++ b/third_party/rust/neqo-common/src/timer.rs @@ -0,0 +1,396 @@ +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::{ + mem, + time::{Duration, Instant}, +}; + +/// Internal structure for a timer item. +struct TimerItem { + time: Instant, + item: T, +} + +impl TimerItem { + fn time(ti: &Self) -> Instant { + ti.time + } +} + +/// A timer queue. +/// This uses a classic timer wheel arrangement, with some characteristics that might be considered +/// peculiar. Each slot in the wheel is sorted (complexity O(N) insertions, but O(logN) to find cut +/// points). Time is relative, the wheel has an origin time and it is unable to represent times that +/// are more than `granularity * capacity` past that time. +pub struct Timer { + items: Vec>>, + now: Instant, + granularity: Duration, + cursor: usize, +} + +impl Timer { + /// Construct a new wheel at the given granularity, starting at the given time. + /// + /// # Panics + /// + /// When `capacity` is too large to fit in `u32` or `granularity` is zero. + pub fn new(now: Instant, granularity: Duration, capacity: usize) -> Self { + assert!(u32::try_from(capacity).is_ok()); + assert!(granularity.as_nanos() > 0); + let mut items = Vec::with_capacity(capacity); + items.resize_with(capacity, Default::default); + Self { + items, + now, + granularity, + cursor: 0, + } + } + + /// Return a reference to the time of the next entry. + #[must_use] + pub fn next_time(&self) -> Option { + for i in 0..self.items.len() { + let idx = self.bucket(i); + if let Some(t) = self.items[idx].first() { + return Some(t.time); + } + } + None + } + + /// Get the full span of time that this can cover. + /// Two timers cannot be more than this far apart. + /// In practice, this value is less by one amount of the timer granularity. + #[inline] + #[allow(clippy::cast_possible_truncation)] // guarded by assertion + #[must_use] + pub fn span(&self) -> Duration { + self.granularity * (self.items.len() as u32) + } + + /// For the given `time`, get the number of whole buckets in the future that is. + #[inline] + #[allow(clippy::cast_possible_truncation)] // guarded by assertion + fn delta(&self, time: Instant) -> usize { + // This really should use Duration::div_duration_f??(), but it can't yet. + ((time - self.now).as_nanos() / self.granularity.as_nanos()) as usize + } + + #[inline] + fn time_bucket(&self, time: Instant) -> usize { + self.bucket(self.delta(time)) + } + + #[inline] + fn bucket(&self, delta: usize) -> usize { + debug_assert!(delta < self.items.len()); + (self.cursor + delta) % self.items.len() + } + + /// Slide forward in time by `n * self.granularity`. + #[allow(clippy::cast_possible_truncation, clippy::reversed_empty_ranges)] + // cast_possible_truncation is ok because we have an assertion guard. + // reversed_empty_ranges is to avoid different types on the if/else. + fn tick(&mut self, n: usize) { + let new = self.bucket(n); + let iter = if new < self.cursor { + (self.cursor..self.items.len()).chain(0..new) + } else { + (self.cursor..new).chain(0..0) + }; + for i in iter { + assert!(self.items[i].is_empty()); + } + self.now += self.granularity * (n as u32); + self.cursor = new; + } + + /// Asserts if the time given is in the past or too far in the future. + /// + /// # Panics + /// + /// When `time` is in the past relative to previous calls. + pub fn add(&mut self, time: Instant, item: T) { + assert!(time >= self.now); + // Skip forward quickly if there is too large a gap. + let short_span = self.span() - self.granularity; + if time >= (self.now + self.span() + short_span) { + // Assert that there aren't any items. + for i in &self.items { + debug_assert!(i.is_empty()); + } + self.now = time.checked_sub(short_span).unwrap(); + self.cursor = 0; + } + + // Adjust time forward the minimum amount necessary. + let mut d = self.delta(time); + if d >= self.items.len() { + self.tick(1 + d - self.items.len()); + d = self.items.len() - 1; + } + + let bucket = self.bucket(d); + let ins = match self.items[bucket].binary_search_by_key(&time, TimerItem::time) { + Ok(j) | Err(j) => j, + }; + self.items[bucket].insert(ins, TimerItem { time, item }); + } + + /// Given knowledge of the time an item was added, remove it. + /// This requires use of a predicate that identifies matching items. + pub fn remove(&mut self, time: Instant, mut selector: F) -> Option + where + F: FnMut(&T) -> bool, + { + if time < self.now { + return None; + } + if time > self.now + self.span() { + return None; + } + let bucket = self.time_bucket(time); + let Ok(start_index) = self.items[bucket].binary_search_by_key(&time, TimerItem::time) + else { + return None; + }; + // start_index is just one of potentially many items with the same time. + // Search backwards for a match, ... + for i in (0..=start_index).rev() { + if self.items[bucket][i].time != time { + break; + } + if selector(&self.items[bucket][i].item) { + return Some(self.items[bucket].remove(i).item); + } + } + // ... then forwards. + for i in (start_index + 1)..self.items[bucket].len() { + if self.items[bucket][i].time != time { + break; + } + if selector(&self.items[bucket][i].item) { + return Some(self.items[bucket].remove(i).item); + } + } + None + } + + /// Take the next item, unless there are no items with + /// a timeout in the past relative to `until`. + pub fn take_next(&mut self, until: Instant) -> Option { + for i in 0..self.items.len() { + let idx = self.bucket(i); + if !self.items[idx].is_empty() && self.items[idx][0].time <= until { + return Some(self.items[idx].remove(0).item); + } + } + None + } + + /// Create an iterator that takes all items until the given time. + /// Note: Items might be removed even if the iterator is not fully exhausted. + pub fn take_until(&mut self, until: Instant) -> impl Iterator { + let get_item = move |x: TimerItem| x.item; + if until >= self.now + self.span() { + // Drain everything, so a clean sweep. + let mut empty_items = Vec::with_capacity(self.items.len()); + empty_items.resize_with(self.items.len(), Vec::default); + let mut items = mem::replace(&mut self.items, empty_items); + self.now = until; + self.cursor = 0; + + let tail = items.split_off(self.cursor); + return tail.into_iter().chain(items).flatten().map(get_item); + } + + // Only returning a partial span, so do it bucket at a time. + let delta = self.delta(until); + let mut buckets = Vec::with_capacity(delta + 1); + + // First, the whole buckets. + for i in 0..delta { + let idx = self.bucket(i); + buckets.push(mem::take(&mut self.items[idx])); + } + self.tick(delta); + + // Now we need to split the last bucket, because there might be + // some items with `item.time > until`. + let bucket = &mut self.items[self.cursor]; + let last_idx = match bucket.binary_search_by_key(&until, TimerItem::time) { + Ok(mut m) => { + // If there are multiple values, the search will hit any of them. + // Make sure to get them all. + while m < bucket.len() && bucket[m].time == until { + m += 1; + } + m + } + Err(ins) => ins, + }; + let tail = bucket.split_off(last_idx); + buckets.push(mem::replace(bucket, tail)); + // This tomfoolery with the empty vector ensures that + // the returned type here matches the one above precisely + // without having to invoke the `either` crate. + buckets.into_iter().chain(vec![]).flatten().map(get_item) + } +} + +#[cfg(test)] +mod test { + use std::sync::OnceLock; + + use super::{Duration, Instant, Timer}; + + fn now() -> Instant { + static NOW: OnceLock = OnceLock::new(); + *NOW.get_or_init(Instant::now) + } + + const GRANULARITY: Duration = Duration::from_millis(10); + const CAPACITY: usize = 10; + #[test] + fn create() { + let t: Timer<()> = Timer::new(now(), GRANULARITY, CAPACITY); + assert_eq!(t.span(), Duration::from_millis(100)); + assert_eq!(None, t.next_time()); + } + + #[test] + fn immediate_entry() { + let mut t = Timer::new(now(), GRANULARITY, CAPACITY); + t.add(now(), 12); + assert_eq!(now(), t.next_time().expect("should have an entry")); + let values: Vec<_> = t.take_until(now()).collect(); + assert_eq!(vec![12], values); + } + + #[test] + fn same_time() { + let mut t = Timer::new(now(), GRANULARITY, CAPACITY); + let v1 = 12; + let v2 = 13; + t.add(now(), v1); + t.add(now(), v2); + assert_eq!(now(), t.next_time().expect("should have an entry")); + let values: Vec<_> = t.take_until(now()).collect(); + assert!(values.contains(&v1)); + assert!(values.contains(&v2)); + } + + #[test] + fn add() { + let mut t = Timer::new(now(), GRANULARITY, CAPACITY); + let near_future = now() + Duration::from_millis(17); + let v = 9; + t.add(near_future, v); + assert_eq!(near_future, t.next_time().expect("should return a value")); + assert_eq!( + t.take_until(near_future.checked_sub(Duration::from_millis(1)).unwrap()) + .count(), + 0 + ); + assert!(t + .take_until(near_future + Duration::from_millis(1)) + .any(|x| x == v)); + } + + #[test] + fn add_future() { + let mut t = Timer::new(now(), GRANULARITY, CAPACITY); + let future = now() + Duration::from_millis(117); + let v = 9; + t.add(future, v); + assert_eq!(future, t.next_time().expect("should return a value")); + assert!(t.take_until(future).any(|x| x == v)); + } + + #[test] + fn add_far_future() { + let mut t = Timer::new(now(), GRANULARITY, CAPACITY); + let far_future = now() + Duration::from_millis(892); + let v = 9; + t.add(far_future, v); + assert_eq!(far_future, t.next_time().expect("should return a value")); + assert!(t.take_until(far_future).any(|x| x == v)); + } + + const TIMES: &[Duration] = &[ + Duration::from_millis(40), + Duration::from_millis(91), + Duration::from_millis(6), + Duration::from_millis(3), + Duration::from_millis(22), + Duration::from_millis(40), + ]; + + fn with_times() -> Timer { + let mut t = Timer::new(now(), GRANULARITY, CAPACITY); + for (i, time) in TIMES.iter().enumerate() { + t.add(now() + *time, i); + } + assert_eq!( + now() + *TIMES.iter().min().unwrap(), + t.next_time().expect("should have a time") + ); + t + } + + #[test] + #[allow(clippy::needless_collect)] // false positive + fn multiple_values() { + let mut t = with_times(); + let values: Vec<_> = t.take_until(now() + *TIMES.iter().max().unwrap()).collect(); + for i in 0..TIMES.len() { + assert!(values.contains(&i)); + } + } + + #[test] + #[allow(clippy::needless_collect)] // false positive + fn take_far_future() { + let mut t = with_times(); + let values: Vec<_> = t.take_until(now() + Duration::from_secs(100)).collect(); + for i in 0..TIMES.len() { + assert!(values.contains(&i)); + } + } + + #[test] + fn remove_each() { + let mut t = with_times(); + for (i, time) in TIMES.iter().enumerate() { + assert_eq!(Some(i), t.remove(now() + *time, |&x| x == i)); + } + assert_eq!(None, t.next_time()); + } + + #[test] + fn remove_future() { + let mut t = Timer::new(now(), GRANULARITY, CAPACITY); + let future = now() + Duration::from_millis(117); + let v = 9; + t.add(future, v); + + assert_eq!(Some(v), t.remove(future, |candidate| *candidate == v)); + } + + #[test] + fn remove_too_far_future() { + let mut t = Timer::new(now(), GRANULARITY, CAPACITY); + let future = now() + Duration::from_millis(117); + let too_far_future = now() + t.span() + Duration::from_millis(117); + let v = 9; + t.add(future, v); + + assert_eq!(None, t.remove(too_far_future, |candidate| *candidate == v)); + } +} diff --git a/third_party/rust/neqo-common/src/tos.rs b/third_party/rust/neqo-common/src/tos.rs index 533c5447e255..3610f7275092 100644 --- a/third_party/rust/neqo-common/src/tos.rs +++ b/third_party/rust/neqo-common/src/tos.rs @@ -36,7 +36,7 @@ impl From for u8 { impl From for IpTosEcn { fn from(v: u8) -> Self { - match v & 0b0000_0011 { + match v & 0b11 { 0b00 => IpTosEcn::NotEct, 0b01 => IpTosEcn::Ect1, 0b10 => IpTosEcn::Ect0, @@ -47,8 +47,8 @@ impl From for IpTosEcn { } impl From for IpTosEcn { - fn from(v: IpTos) -> Self { - IpTosEcn::from(u8::from(v)) + fn from(value: IpTos) -> Self { + IpTosEcn::from(value.0 & 0x3) } } @@ -166,13 +166,14 @@ impl From for IpTosDscp { } impl From for IpTosDscp { - fn from(v: IpTos) -> Self { - IpTosDscp::from(u8::from(v)) + fn from(value: IpTos) -> Self { + IpTosDscp::from(value.0 & 0xfc) } } /// The type-of-service field in an IP packet. -#[derive(Copy, Clone, PartialEq, Eq, Default)] +#[allow(clippy::module_name_repetitions)] +#[derive(Copy, Clone, PartialEq, Eq)] pub struct IpTos(u8); impl From for IpTos { @@ -214,19 +215,15 @@ impl From for IpTos { impl Debug for IpTos { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("IpTos") - .field(&IpTosDscp::from(*self)) - .field(&IpTosEcn::from(*self)) + .field(&IpTosDscp::from(self.0 & 0xfc)) + .field(&IpTosEcn::from(self.0 & 0x3)) .finish() } } -impl IpTos { - pub fn set_ecn(&mut self, ecn: IpTosEcn) { - self.0 = u8::from(IpTosDscp::from(*self)) | u8::from(ecn); - } - - pub fn set_dscp(&mut self, dscp: IpTosDscp) { - self.0 = u8::from(IpTosEcn::from(*self)) | u8::from(dscp); +impl Default for IpTos { + fn default() -> Self { + (IpTosDscp::default(), IpTosEcn::default()).into() } } @@ -325,25 +322,4 @@ mod tests { assert_eq!(tos, u8::from(iptos)); assert_eq!(IpTos::from(tos), iptos); } - - #[test] - fn iptos_to_iptosdscp() { - let tos = IpTos::from((IpTosDscp::Af41, IpTosEcn::NotEct)); - let dscp = IpTosDscp::from(tos); - assert_eq!(dscp, IpTosDscp::Af41); - } - - #[test] - fn tos_modify_ecn() { - let mut iptos: IpTos = (IpTosDscp::Af41, IpTosEcn::NotEct).into(); - iptos.set_ecn(IpTosEcn::Ce); - assert_eq!(u8::from(iptos), 0b1000_1011); - } - - #[test] - fn tos_modify_dscp() { - let mut iptos: IpTos = (IpTosDscp::Af41, IpTosEcn::Ect1).into(); - iptos.set_dscp(IpTosDscp::Le); - assert_eq!(u8::from(iptos), 0b0000_0101); - } } diff --git a/third_party/rust/neqo-common/src/udp.rs b/third_party/rust/neqo-common/src/udp.rs new file mode 100644 index 000000000000..c27b0632ff2a --- /dev/null +++ b/third_party/rust/neqo-common/src/udp.rs @@ -0,0 +1,222 @@ +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(clippy::missing_errors_doc)] // Functions simply delegate to tokio and quinn-udp. +#![allow(clippy::missing_panics_doc)] // Functions simply delegate to tokio and quinn-udp. + +use std::{ + io::{self, IoSliceMut}, + net::{SocketAddr, ToSocketAddrs}, + slice, +}; + +use quinn_udp::{EcnCodepoint, RecvMeta, Transmit, UdpSocketState}; +use tokio::io::Interest; + +use crate::{Datagram, IpTos}; + +/// Socket receive buffer size. +/// +/// Allows reading multiple datagrams in a single [`Socket::recv`] call. +const RECV_BUF_SIZE: usize = u16::MAX as usize; + +pub struct Socket { + socket: tokio::net::UdpSocket, + state: UdpSocketState, + recv_buf: Vec, +} + +impl Socket { + /// Calls [`std::net::UdpSocket::bind`] and instantiates [`quinn_udp::UdpSocketState`]. + pub fn bind(addr: A) -> Result { + let socket = std::net::UdpSocket::bind(addr)?; + + Ok(Self { + state: quinn_udp::UdpSocketState::new((&socket).into())?, + socket: tokio::net::UdpSocket::from_std(socket)?, + recv_buf: vec![0; RECV_BUF_SIZE], + }) + } + + /// See [`tokio::net::UdpSocket::local_addr`]. + pub fn local_addr(&self) -> io::Result { + self.socket.local_addr() + } + + /// See [`tokio::net::UdpSocket::writable`]. + pub async fn writable(&self) -> Result<(), io::Error> { + self.socket.writable().await + } + + /// See [`tokio::net::UdpSocket::readable`]. + pub async fn readable(&self) -> Result<(), io::Error> { + self.socket.readable().await + } + + /// Send the UDP datagram on the specified socket. + pub fn send(&self, d: Datagram) -> io::Result { + let transmit = Transmit { + destination: d.destination(), + ecn: EcnCodepoint::from_bits(Into::::into(d.tos())), + contents: d.into_data().into(), + segment_size: None, + src_ip: None, + }; + + let n = self.socket.try_io(Interest::WRITABLE, || { + self.state + .send((&self.socket).into(), slice::from_ref(&transmit)) + })?; + + assert_eq!(n, 1, "only passed one slice"); + + Ok(n) + } + + /// Receive a UDP datagram on the specified socket. + pub fn recv(&mut self, local_address: &SocketAddr) -> Result, io::Error> { + let mut meta = RecvMeta::default(); + + match self.socket.try_io(Interest::READABLE, || { + self.state.recv( + (&self.socket).into(), + &mut [IoSliceMut::new(&mut self.recv_buf)], + slice::from_mut(&mut meta), + ) + }) { + Ok(n) => { + assert_eq!(n, 1, "only passed one slice"); + } + Err(ref err) + if err.kind() == io::ErrorKind::WouldBlock + || err.kind() == io::ErrorKind::Interrupted => + { + return Ok(vec![]) + } + Err(err) => { + return Err(err); + } + }; + + if meta.len == 0 { + eprintln!("zero length datagram received?"); + return Ok(vec![]); + } + if meta.len == self.recv_buf.len() { + eprintln!( + "Might have received more than {} bytes", + self.recv_buf.len() + ); + } + + Ok(self.recv_buf[0..meta.len] + .chunks(meta.stride.min(self.recv_buf.len())) + .map(|d| { + Datagram::new( + meta.addr, + *local_address, + meta.ecn.map(|n| IpTos::from(n as u8)).unwrap_or_default(), + None, // TODO: get the real TTL https://github.com/quinn-rs/quinn/issues/1749 + d, + ) + }) + .collect()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{IpTosDscp, IpTosEcn}; + + #[tokio::test] + async fn datagram_tos() -> Result<(), io::Error> { + let sender = Socket::bind("127.0.0.1:0")?; + let receiver_addr: SocketAddr = "127.0.0.1:0".parse().unwrap(); + let mut receiver = Socket::bind(receiver_addr)?; + + let datagram = Datagram::new( + sender.local_addr()?, + receiver.local_addr()?, + IpTos::from((IpTosDscp::Le, IpTosEcn::Ect1)), + None, + "Hello, world!".as_bytes().to_vec(), + ); + + sender.writable().await?; + sender.send(datagram.clone())?; + + receiver.readable().await?; + let received_datagram = receiver + .recv(&receiver_addr) + .expect("receive to succeed") + .into_iter() + .next() + .expect("receive to yield datagram"); + + // Assert that the ECN is correct. + assert_eq!( + IpTosEcn::from(datagram.tos()), + IpTosEcn::from(received_datagram.tos()) + ); + + Ok(()) + } + + /// Expect [`Socket::recv`] to handle multiple [`Datagram`]s on GRO read. + #[tokio::test] + #[cfg_attr(not(any(target_os = "linux", target_os = "windows")), ignore)] + async fn many_datagrams_through_gro() -> Result<(), io::Error> { + const SEGMENT_SIZE: usize = 128; + + let sender = Socket::bind("127.0.0.1:0")?; + let receiver_addr: SocketAddr = "127.0.0.1:0".parse().unwrap(); + let mut receiver = Socket::bind(receiver_addr)?; + + // `neqo_common::udp::Socket::send` does not yet + // (https://github.com/mozilla/neqo/issues/1693) support GSO. Use + // `quinn_udp` directly. + let max_gso_segments = sender.state.max_gso_segments(); + let msg = vec![0xAB; SEGMENT_SIZE * max_gso_segments]; + let transmit = Transmit { + destination: receiver.local_addr()?, + ecn: EcnCodepoint::from_bits(Into::::into(IpTos::from(( + IpTosDscp::Le, + IpTosEcn::Ect1, + )))), + contents: msg.clone().into(), + segment_size: Some(SEGMENT_SIZE), + src_ip: None, + }; + sender.writable().await?; + let n = sender.socket.try_io(Interest::WRITABLE, || { + sender + .state + .send((&sender.socket).into(), slice::from_ref(&transmit)) + })?; + assert_eq!(n, 1, "only passed one slice"); + + // Allow for one GSO sendmmsg to result in multiple GRO recvmmsg. + let mut num_received = 0; + while num_received < max_gso_segments { + receiver.readable().await?; + receiver + .recv(&receiver_addr) + .expect("receive to succeed") + .into_iter() + .for_each(|d| { + assert_eq!( + SEGMENT_SIZE, + d.len(), + "Expect received datagrams to have same length as sent datagrams." + ); + num_received += 1; + }); + } + + Ok(()) + } +} diff --git a/third_party/rust/neqo-crypto/.cargo-checksum.json b/third_party/rust/neqo-crypto/.cargo-checksum.json dissimilarity index 100% index bacdf2d95b8e..5622e7f4ad3f 100644 --- a/third_party/rust/neqo-crypto/.cargo-checksum.json +++ b/third_party/rust/neqo-crypto/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"9414077b6a604ab5cf1bf64fa2f81860df8c5e1f31cb0a7fe5883dc1a1c9a706","bindings/bindings.toml":"29ec7a8ef3d5f1e4a632003e2d36c270e1caf12fd3fcf108a22d1893b90a41a6","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":"cbf6a7d912314784c8c124cf7319c910a786d0e263f466843edd3f43826f036c","min_version.txt":"7e98f86c69cddb4f65cf96a6de1f4297e3ce224a4c4628609e29042b6c4dcfb9","src/aead.rs":"fc42bc20b84d2e5ccfd56271ae2d2db082e55586ea2926470c102da177f22296","src/aead_null.rs":"664f80bbb56d0abd3794b99cc927fd5f678ddb4ce95456001413ec18a6c6a6a9","src/agent.rs":"b12004faee4a136c10e8168848d397443b5927e9497edb62c72e6db3eb1c10a0","src/agentio.rs":"c4cb1b3cd92ef53eb0b4fb0b34a597068d82d78ba470dae5821670a0f06c9cda","src/auth.rs":"ced1a18f691894984244088020ea25dc1ee678603317f0c7dfc8b8842fa750b4","src/cert.rs":"8942cb3ce25a61f92b6ffc30fb286052ed6f56eeda3be12fd46ea76ceba6c1cf","src/constants.rs":"f22bf16bd8cb539862cb1e47138dbba79e93fe738f4b907e465891326f98883c","src/ech.rs":"9d322fcc01c0886f1dfe9bb6273cb9f88a746452ac9a802761b1816a05930c1f","src/err.rs":"ae979f334604aba89640c4491262641910033f0bd790d58671f649f5039b291c","src/exp.rs":"cec59d61fc95914f9703d2fb6490a8507af993c9db710dde894f2f8fd38123c7","src/ext.rs":"cbf7d9f5ecabf4b8c9efd6c334637ab1596ec5266d38ab8d2d6ceae305283deb","src/hkdf.rs":"ef32f20e30a9bd7f094199536d19c87c4231b7fbbe4a9c54c70e84ca9c6575be","src/hp.rs":"644f1bed67f1c6189a67c8d02ab3358aaa7f63af4b913dd7395becbc01a84291","src/lib.rs":"6b2d0eb2c55f6351d673d3a3e5fc5adac8d1030c67dae9af4c79552de0f57455","src/min_version.rs":"89b7ef6f9d2301db4f689f4d963b58375d577f705b92003a804048441e00cfd1","src/p11.rs":"e8c366def0df470101f3d120dcc4391f74f921fe59e2f3db2a56832e2852b855","src/prio.rs":"e5e169296c0ac69919c59fb6c1f8bd6bf079452eaa13d75da0edd41d435d3f6f","src/replay.rs":"96b7af8eff9e14313e79303092018b12e8834f780c96b8e247c497fdc680c696","src/result.rs":"0587cbb6aace71a7f9765ef7c01dcd9f73a49dcc6331e1d8fe4de2aef6ca65b6","src/secrets.rs":"4ffaa66f25df47dadf042063bff5953effa7bf2f4920cafe827757d6a659cb58","src/selfencrypt.rs":"b7cc1c896c7661c37461fc3a8bcbfdf2589433b907fa5f968ae4f6907704b441","src/ssl.rs":"c83baa5518b81dd06f2e4072ea3c2d666ccdeb8b1ff6e3746eea9f1af47023a6","src/time.rs":"3b2829a98a1648eb052db19bb470808b6b015a1eca27ab7be64b5d196c0271c0","tests/aead.rs":"e36ae77802df1ea6d17cfd1bd2178a3706089577d6fd1554ca86e748b8b235b9","tests/agent.rs":"824735f88e487a3748200844e9481e81a72163ad74d82faa9aa16594d9b9bb25","tests/ext.rs":"1b047d23d9b224ad06eb65d8f3a7b351e263774e404c79bbcbe8f43790e29c18","tests/handshake.rs":"e892a2839b31414be16e96cdf3b1a65978716094700c1a4989229f7edbf578a0","tests/hkdf.rs":"1d2098dc8398395864baf13e4886cfd1da6d36118727c3b264f457ee3da6b048","tests/hp.rs":"b24fec53771c169be788772532d2617a5349196cf87d6444dc74214f7c73e92c","tests/init.rs":"616313cb38eac44b8c71a1d23a52a7d7b4c7c07d4c20dc9ea6600c3317f92613","tests/selfencrypt.rs":"8d10840b41629bf449a6b3a551377315e8a05ca26c6b041548748196652c5909"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"6f1917fbd4cbf53cb4883c30e8fcb9c20f8ebe15e19576c7d37cb6ba0ab9e42b","bindings/bindings.toml":"0660c1661318b8a5094834c2f1bb12266287ef467307f66947eff7762528f70a","bindings/mozpkix.hpp":"77072c8bb0f6eb6bfe8cbadc111dcd92e0c79936d13f2e501aae1e5d289a6675","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":"21d9a0140b2afd708583f58f2af0a4ba93ab07ec088680b4cbf0e184aeb8785b","src/aead.rs":"8f50e4557b7829edb67f57c80c777c6ae23c868e2b2eeaaae0736af04dc0d298","src/aead_fuzzing.rs":"c3e590572314e0bb3fafa13dac3c831358b8a7b5570fe9cfe592752fce8cbdee","src/agent.rs":"e995e9cc5108470594bae1b0d4e4bc6b7a8ac2b66488f71ea99e2836c0edbd7e","src/agentio.rs":"c4cb1b3cd92ef53eb0b4fb0b34a597068d82d78ba470dae5821670a0f06c9cda","src/auth.rs":"ced1a18f691894984244088020ea25dc1ee678603317f0c7dfc8b8842fa750b4","src/cert.rs":"8942cb3ce25a61f92b6ffc30fb286052ed6f56eeda3be12fd46ea76ceba6c1cf","src/constants.rs":"f22bf16bd8cb539862cb1e47138dbba79e93fe738f4b907e465891326f98883c","src/ech.rs":"9d322fcc01c0886f1dfe9bb6273cb9f88a746452ac9a802761b1816a05930c1f","src/err.rs":"fca0222167883231a5e0a569a593f44214501819adf5aadf814be27891c87c24","src/exp.rs":"cec59d61fc95914f9703d2fb6490a8507af993c9db710dde894f2f8fd38123c7","src/ext.rs":"cbf7d9f5ecabf4b8c9efd6c334637ab1596ec5266d38ab8d2d6ceae305283deb","src/hkdf.rs":"ef32f20e30a9bd7f094199536d19c87c4231b7fbbe4a9c54c70e84ca9c6575be","src/hp.rs":"644f1bed67f1c6189a67c8d02ab3358aaa7f63af4b913dd7395becbc01a84291","src/lib.rs":"23732c7799be038c0e0835b54e7c40cf6c6536113e0adb6ae3b41b216a6e5220","src/p11.rs":"e8c366def0df470101f3d120dcc4391f74f921fe59e2f3db2a56832e2852b855","src/prio.rs":"e5e169296c0ac69919c59fb6c1f8bd6bf079452eaa13d75da0edd41d435d3f6f","src/replay.rs":"96b7af8eff9e14313e79303092018b12e8834f780c96b8e247c497fdc680c696","src/result.rs":"0587cbb6aace71a7f9765ef7c01dcd9f73a49dcc6331e1d8fe4de2aef6ca65b6","src/secrets.rs":"4ffaa66f25df47dadf042063bff5953effa7bf2f4920cafe827757d6a659cb58","src/selfencrypt.rs":"ac65b13f5bade9d03ab4709364f9ec937fa4ca009965c77ca73b481534a0a470","src/ssl.rs":"c83baa5518b81dd06f2e4072ea3c2d666ccdeb8b1ff6e3746eea9f1af47023a6","src/time.rs":"3b2829a98a1648eb052db19bb470808b6b015a1eca27ab7be64b5d196c0271c0","tests/aead.rs":"3ac4fe4ab79922b5d0191a9717058fc8d0710380ce9b25448095f870f511844f","tests/agent.rs":"824735f88e487a3748200844e9481e81a72163ad74d82faa9aa16594d9b9bb25","tests/ext.rs":"1b047d23d9b224ad06eb65d8f3a7b351e263774e404c79bbcbe8f43790e29c18","tests/handshake.rs":"e892a2839b31414be16e96cdf3b1a65978716094700c1a4989229f7edbf578a0","tests/hkdf.rs":"1d2098dc8398395864baf13e4886cfd1da6d36118727c3b264f457ee3da6b048","tests/hp.rs":"b24fec53771c169be788772532d2617a5349196cf87d6444dc74214f7c73e92c","tests/init.rs":"44fe7626b75ab8c57adfee361bb70a83d5958797e1eb6c4531bb74988ba3a990","tests/selfencrypt.rs":"25813b0c6f32fc8383bb7685745feb750eb3fdc0a6a172a50d961c68d39f2a46"},"package":null} \ No newline at end of file diff --git a/third_party/rust/neqo-crypto/Cargo.toml b/third_party/rust/neqo-crypto/Cargo.toml index e53d8c3dac72..499921e5315c 100644 --- a/third_party/rust/neqo-crypto/Cargo.toml +++ b/third_party/rust/neqo-crypto/Cargo.toml @@ -13,7 +13,7 @@ edition = "2021" rust-version = "1.74.0" name = "neqo-crypto" -version = "0.7.3" +version = "0.7.2" authors = ["The Neqo Authors "] build = "build.rs" homepage = "https://github.com/mozilla/neqo/" @@ -43,10 +43,6 @@ version = "0.1" optional = true default-features = false -[build-dependencies.semver] -version = "1.0" -default-features = false - [build-dependencies.serde] version = "1.0" default-features = false @@ -60,7 +56,7 @@ version = "0.5" default-features = false [features] -disable-encryption = [] +fuzzing = [] gecko = ["mozbuild"] [lints.clippy.pedantic] diff --git a/third_party/rust/neqo-crypto/bindings/bindings.toml b/third_party/rust/neqo-crypto/bindings/bindings.toml index 72c6d524d5f1..3e5c1fdf7d2d 100644 --- a/third_party/rust/neqo-crypto/bindings/bindings.toml +++ b/third_party/rust/neqo-crypto/bindings/bindings.toml @@ -265,3 +265,8 @@ enums = [ [nspr_time] types = ["PRTime"] functions = ["PR_Now"] + +[mozpkix] +cplusplus = true +types = ["mozilla::pkix::ErrorCode"] +enums = ["mozilla::pkix::ErrorCode"] diff --git a/third_party/rust/neqo-crypto/bindings/mozpkix.hpp b/third_party/rust/neqo-crypto/bindings/mozpkix.hpp new file mode 100644 index 000000000000..d0a6cb58619d --- /dev/null +++ b/third_party/rust/neqo-crypto/bindings/mozpkix.hpp @@ -0,0 +1 @@ +#include "mozpkix/pkixnss.h" \ No newline at end of file diff --git a/third_party/rust/neqo-crypto/build.rs b/third_party/rust/neqo-crypto/build.rs index 2dd45437972d..c4c2a73e75e3 100644 --- a/third_party/rust/neqo-crypto/build.rs +++ b/third_party/rust/neqo-crypto/build.rs @@ -12,13 +12,8 @@ use std::{ }; use bindgen::Builder; -use semver::{Version, VersionReq}; use serde_derive::Deserialize; -#[path = "src/min_version.rs"] -mod min_version; -use min_version::MINIMUM_NSS_VERSION; - const BINDINGS_DIR: &str = "bindings"; const BINDINGS_CONFIG: &str = "bindings.toml"; @@ -95,6 +90,46 @@ fn setup_clang() { } } +fn nss_dir() -> PathBuf { + let dir = if let Ok(dir) = env::var("NSS_DIR") { + let path = PathBuf::from(dir.trim()); + assert!( + !path.is_relative(), + "The NSS_DIR environment variable is expected to be an absolute path." + ); + path + } else { + let out_dir = env::var("OUT_DIR").unwrap(); + let dir = Path::new(&out_dir).join("nss"); + if !dir.exists() { + Command::new("hg") + .args([ + "clone", + "https://hg.mozilla.org/projects/nss", + dir.to_str().unwrap(), + ]) + .status() + .expect("can't clone nss"); + } + let nspr_dir = Path::new(&out_dir).join("nspr"); + if !nspr_dir.exists() { + Command::new("hg") + .args([ + "clone", + "https://hg.mozilla.org/projects/nspr", + nspr_dir.to_str().unwrap(), + ]) + .status() + .expect("can't clone nspr"); + } + dir + }; + assert!(dir.is_dir(), "NSS_DIR {dir:?} doesn't exist"); + // Note that this returns a relative path because UNC + // paths on windows cause certain tools to explode. + dir +} + fn get_bash() -> PathBuf { // If BASH is set, use that. if let Ok(bash) = env::var("BASH") { @@ -260,63 +295,11 @@ fn build_bindings(base: &str, bindings: &Bindings, flags: &[String], gecko: bool .expect("couldn't write bindings"); } -fn pkg_config() -> Vec { - let modversion = Command::new("pkg-config") - .args(["--modversion", "nss"]) - .output() - .expect("pkg-config reports NSS as absent") - .stdout; - let modversion = String::from_utf8(modversion).expect("non-UTF8 from pkg-config"); - let modversion = modversion.trim(); - // The NSS version number does not follow semver numbering, because it omits the patch version - // when that's 0. Deal with that. - let modversion_for_cmp = if modversion.chars().filter(|c| *c == '.').count() == 1 { - modversion.to_owned() + ".0" - } else { - modversion.to_owned() - }; - let modversion_for_cmp = - Version::parse(&modversion_for_cmp).expect("NSS version not in semver format"); - let version_req = VersionReq::parse(&format!(">={}", MINIMUM_NSS_VERSION.trim())).unwrap(); - assert!( - version_req.matches(&modversion_for_cmp), - "neqo has NSS version requirement {version_req}, found {modversion}" - ); - - let cfg = Command::new("pkg-config") - .args(["--cflags", "--libs", "nss"]) - .output() - .expect("NSS flags not returned by pkg-config") - .stdout; - let cfg_str = String::from_utf8(cfg).expect("non-UTF8 from pkg-config"); - - let mut flags: Vec = Vec::new(); - for f in cfg_str.split(' ') { - if let Some(include) = f.strip_prefix("-I") { - flags.push(String::from(f)); - println!("cargo:include={include}"); - } else if let Some(path) = f.strip_prefix("-L") { - println!("cargo:rustc-link-search=native={path}"); - } else if let Some(lib) = f.strip_prefix("-l") { - println!("cargo:rustc-link-lib=dylib={lib}"); - } else { - println!("Warning: Unknown flag from pkg-config: {f}"); - } - } - - flags -} - -fn setup_standalone(nss: &str) -> Vec { +fn setup_standalone() -> Vec { setup_clang(); println!("cargo:rerun-if-env-changed=NSS_DIR"); - let nss = PathBuf::from(nss); - assert!( - !nss.is_relative(), - "The NSS_DIR environment variable is expected to be an absolute path." - ); - + let nss = nss_dir(); build_nss(nss.clone()); // $NSS_DIR/../dist/ @@ -423,10 +406,8 @@ fn setup_for_gecko() -> Vec { fn main() { let flags = if cfg!(feature = "gecko") { setup_for_gecko() - } else if let Ok(nss_dir) = env::var("NSS_DIR") { - setup_standalone(nss_dir.trim()) } else { - pkg_config() + setup_standalone() }; let config_file = PathBuf::from(BINDINGS_DIR).join(BINDINGS_CONFIG); diff --git a/third_party/rust/neqo-crypto/min_version.txt b/third_party/rust/neqo-crypto/min_version.txt deleted file mode 100644 index 422c9c70937c..000000000000 --- a/third_party/rust/neqo-crypto/min_version.txt +++ /dev/null @@ -1 +0,0 @@ -3.98 diff --git a/third_party/rust/neqo-crypto/src/aead.rs b/third_party/rust/neqo-crypto/src/aead.rs index 21027d55b265..bf7d7fe9d7f7 100644 --- a/third_party/rust/neqo-crypto/src/aead.rs +++ b/third_party/rust/neqo-crypto/src/aead.rs @@ -63,7 +63,13 @@ impl RealAead { /// # Errors /// /// Returns `Error` when the supporting NSS functions fail. - pub fn new(version: Version, cipher: Cipher, secret: &SymKey, prefix: &str) -> Res { + pub fn new( + _fuzzing: bool, + version: Version, + cipher: Cipher, + secret: &SymKey, + prefix: &str, + ) -> Res { let s: *mut PK11SymKey = **secret; unsafe { Self::from_raw(version, cipher, s, prefix) } } diff --git a/third_party/rust/neqo-crypto/src/aead_null.rs b/third_party/rust/neqo-crypto/src/aead_fuzzing.rs similarity index 53% rename from third_party/rust/neqo-crypto/src/aead_null.rs rename to third_party/rust/neqo-crypto/src/aead_fuzzing.rs index 2d5656de7399..4e5a6de07f23 100644 --- a/third_party/rust/neqo-crypto/src/aead_null.rs +++ b/third_party/rust/neqo-crypto/src/aead_fuzzing.rs @@ -4,63 +4,84 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![cfg(feature = "disable-encryption")] - use std::fmt; use crate::{ constants::{Cipher, Version}, err::{sec::SEC_ERROR_BAD_DATA, Error, Res}, p11::SymKey, + RealAead, }; -pub const AEAD_NULL_TAG: &[u8] = &[0x0a; 16]; +pub const FIXED_TAG_FUZZING: &[u8] = &[0x0a; 16]; -pub struct AeadNull {} +pub struct FuzzingAead { + real: Option, +} -impl AeadNull { - #[allow(clippy::missing_errors_doc)] - pub fn new(_version: Version, _cipher: Cipher, _secret: &SymKey, _prefix: &str) -> Res { - Ok(Self {}) +impl FuzzingAead { + pub fn new( + fuzzing: bool, + version: Version, + cipher: Cipher, + secret: &SymKey, + prefix: &str, + ) -> Res { + let real = if fuzzing { + None + } else { + Some(RealAead::new(false, version, cipher, secret, prefix)?) + }; + Ok(Self { real }) } #[must_use] pub fn expansion(&self) -> usize { - AEAD_NULL_TAG.len() + if let Some(aead) = &self.real { + aead.expansion() + } else { + FIXED_TAG_FUZZING.len() + } } - #[allow(clippy::missing_errors_doc)] pub fn encrypt<'a>( &self, - _count: u64, - _aad: &[u8], + count: u64, + aad: &[u8], input: &[u8], output: &'a mut [u8], ) -> Res<&'a [u8]> { + if let Some(aead) = &self.real { + return aead.encrypt(count, aad, input, output); + } + let l = input.len(); output[..l].copy_from_slice(input); - output[l..l + 16].copy_from_slice(AEAD_NULL_TAG); + output[l..l + 16].copy_from_slice(FIXED_TAG_FUZZING); Ok(&output[..l + 16]) } - #[allow(clippy::missing_errors_doc)] pub fn decrypt<'a>( &self, - _count: u64, - _aad: &[u8], + count: u64, + aad: &[u8], input: &[u8], output: &'a mut [u8], ) -> Res<&'a [u8]> { - if input.len() < AEAD_NULL_TAG.len() { + if let Some(aead) = &self.real { + return aead.decrypt(count, aad, input, output); + } + + if input.len() < FIXED_TAG_FUZZING.len() { return Err(Error::from(SEC_ERROR_BAD_DATA)); } - let len_encrypted = input.len() - AEAD_NULL_TAG.len(); + let len_encrypted = input.len() - FIXED_TAG_FUZZING.len(); // Check that: // 1) expansion is all zeros and // 2) if the encrypted data is also supplied that at least some values are no zero // (otherwise padding will be interpreted as a valid packet) - if &input[len_encrypted..] == AEAD_NULL_TAG + if &input[len_encrypted..] == FIXED_TAG_FUZZING && (len_encrypted == 0 || input[..len_encrypted].iter().any(|x| *x != 0x0)) { output[..len_encrypted].copy_from_slice(&input[..len_encrypted]); @@ -71,8 +92,12 @@ impl AeadNull { } } -impl fmt::Debug for AeadNull { +impl fmt::Debug for FuzzingAead { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "[NULL AEAD]") + if let Some(a) = &self.real { + a.fmt(f) + } else { + write!(f, "[FUZZING AEAD]") + } } } diff --git a/third_party/rust/neqo-crypto/src/agent.rs b/third_party/rust/neqo-crypto/src/agent.rs index 3d5a8b9f353e..82a6dacd4884 100644 --- a/third_party/rust/neqo-crypto/src/agent.rs +++ b/third_party/rust/neqo-crypto/src/agent.rs @@ -16,7 +16,7 @@ use std::{ time::Instant, }; -use neqo_common::{hex_snip_middle, hex_with_len, qdebug, qtrace, qwarn}; +use neqo_common::{hex_snip_middle, hex_with_len, qdebug, qinfo, qtrace, qwarn}; pub use crate::{ agentio::{as_c_void, Record, RecordList}, @@ -406,7 +406,10 @@ impl SecretAgent { self.set_option(ssl::Opt::Locking, false)?; self.set_option(ssl::Opt::Tickets, false)?; self.set_option(ssl::Opt::OcspStapling, true)?; - self.set_option(ssl::Opt::Grease, grease)?; + if let Err(e) = self.set_option(ssl::Opt::Grease, grease) { + // Until NSS supports greasing, it's OK to fail here. + qinfo!([self], "Failed to enable greasing {:?}", e); + } Ok(()) } @@ -667,7 +670,7 @@ impl SecretAgent { let info = self.capture_error(SecretAgentInfo::new(self.fd))?; HandshakeState::Complete(info) }; - qdebug!([self], "state -> {:?}", self.state); + qinfo!([self], "state -> {:?}", self.state); Ok(()) } @@ -895,7 +898,7 @@ impl Client { let len = usize::try_from(len).unwrap(); let mut v = Vec::with_capacity(len); v.extend_from_slice(null_safe_slice(token, len)); - qdebug!( + qinfo!( [format!("{fd:p}")], "Got resumption token {}", hex_snip_middle(&v) diff --git a/third_party/rust/neqo-crypto/src/err.rs b/third_party/rust/neqo-crypto/src/err.rs index 8d4f239a0bb3..187303d2a960 100644 --- a/third_party/rust/neqo-crypto/src/err.rs +++ b/third_party/rust/neqo-crypto/src/err.rs @@ -16,39 +16,13 @@ mod codes { #![allow(non_snake_case)] include!(concat!(env!("OUT_DIR"), "/nss_secerr.rs")); include!(concat!(env!("OUT_DIR"), "/nss_sslerr.rs")); + include!(concat!(env!("OUT_DIR"), "/mozpkix.rs")); } -pub use codes::{SECErrorCodes as sec, SSLErrorCodes as ssl}; +pub use codes::{mozilla_pkix_ErrorCode as mozpkix, SECErrorCodes as sec, SSLErrorCodes as ssl}; pub mod nspr { include!(concat!(env!("OUT_DIR"), "/nspr_err.rs")); } -pub mod mozpkix { - // These are manually extracted from the many bindings generated - // by bindgen when provided with the simple header: - // #include "mozpkix/pkixnss.h" - - #[allow(non_camel_case_types)] - pub type mozilla_pkix_ErrorCode = ::std::os::raw::c_int; - pub const MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE: mozilla_pkix_ErrorCode = -16384; - pub const MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY: mozilla_pkix_ErrorCode = -16383; - pub const MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE: mozilla_pkix_ErrorCode = -16382; - pub const MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA: mozilla_pkix_ErrorCode = -16381; - pub const MOZILLA_PKIX_ERROR_NO_RFC822NAME_MATCH: mozilla_pkix_ErrorCode = -16380; - pub const MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE: mozilla_pkix_ErrorCode = -16379; - pub const MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE: mozilla_pkix_ErrorCode = -16378; - pub const MOZILLA_PKIX_ERROR_SIGNATURE_ALGORITHM_MISMATCH: mozilla_pkix_ErrorCode = -16377; - pub const MOZILLA_PKIX_ERROR_OCSP_RESPONSE_FOR_CERT_MISSING: mozilla_pkix_ErrorCode = -16376; - pub const MOZILLA_PKIX_ERROR_VALIDITY_TOO_LONG: mozilla_pkix_ErrorCode = -16375; - pub const MOZILLA_PKIX_ERROR_REQUIRED_TLS_FEATURE_MISSING: mozilla_pkix_ErrorCode = -16374; - pub const MOZILLA_PKIX_ERROR_INVALID_INTEGER_ENCODING: mozilla_pkix_ErrorCode = -16373; - pub const MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME: mozilla_pkix_ErrorCode = -16372; - pub const MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED: mozilla_pkix_ErrorCode = - -16371; - pub const MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT: mozilla_pkix_ErrorCode = -16370; - pub const MOZILLA_PKIX_ERROR_MITM_DETECTED: mozilla_pkix_ErrorCode = -16369; - pub const END_OF_LIST: mozilla_pkix_ErrorCode = -16368; -} - pub type Res = Result; #[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)] diff --git a/third_party/rust/neqo-crypto/src/lib.rs b/third_party/rust/neqo-crypto/src/lib.rs index 2db985e8ee1e..2ec1b4a3ea89 100644 --- a/third_party/rust/neqo-crypto/src/lib.rs +++ b/third_party/rust/neqo-crypto/src/lib.rs @@ -8,8 +8,8 @@ #![allow(clippy::unseparated_literal_suffix, clippy::used_underscore_binding)] // For bindgen code. mod aead; -#[cfg(feature = "disable-encryption")] -pub mod aead_null; +#[cfg(feature = "fuzzing")] +mod aead_fuzzing; pub mod agent; mod agentio; mod auth; @@ -33,12 +33,12 @@ mod time; use std::{ffi::CString, path::PathBuf, ptr::null, sync::OnceLock}; -#[cfg(not(feature = "disable-encryption"))] +#[cfg(not(feature = "fuzzing"))] pub use self::aead::RealAead as Aead; -#[cfg(feature = "disable-encryption")] +#[cfg(feature = "fuzzing")] pub use self::aead::RealAead; -#[cfg(feature = "disable-encryption")] -pub use self::aead_null::AeadNull as Aead; +#[cfg(feature = "fuzzing")] +pub use self::aead_fuzzing::FuzzingAead as Aead; pub use self::{ agent::{ Agent, AllowZeroRtt, Client, HandshakeState, Record, RecordList, ResumptionToken, @@ -59,8 +59,7 @@ pub use self::{ ssl::Opt, }; -mod min_version; -use min_version::MINIMUM_NSS_VERSION; +const MINIMUM_NSS_VERSION: &str = "3.97"; #[allow(non_upper_case_globals, clippy::redundant_static_lifetimes)] #[allow(clippy::upper_case_acronyms)] @@ -90,7 +89,7 @@ impl Drop for NssLoaded { } } -static INITIALIZED: OnceLock> = OnceLock::new(); +static INITIALIZED: OnceLock = OnceLock::new(); fn already_initialized() -> bool { unsafe { nss::NSS_IsInitialized() != 0 } @@ -108,24 +107,24 @@ fn version_check() { /// Initialize NSS. This only executes the initialization routines once, so if there is any chance /// that /// -/// # Errors +/// # Panics /// /// When NSS initialization fails. -pub fn init() -> Res<()> { +pub fn init() { // Set time zero. time::init(); - let res = INITIALIZED.get_or_init(|| { + _ = INITIALIZED.get_or_init(|| { version_check(); if already_initialized() { - return Ok(NssLoaded::External); + return NssLoaded::External; } - secstatus_to_res(unsafe { nss::NSS_NoDB_Init(null()) })?; - secstatus_to_res(unsafe { nss::NSS_SetDomesticPolicy() })?; + secstatus_to_res(unsafe { nss::NSS_NoDB_Init(null()) }).expect("NSS_NoDB_Init failed"); + secstatus_to_res(unsafe { nss::NSS_SetDomesticPolicy() }) + .expect("NSS_SetDomesticPolicy failed"); - Ok(NssLoaded::NoDb) + NssLoaded::NoDb }); - res.as_ref().map(|_| ()).map_err(Clone::clone) } /// This enables SSLTRACE by calling a simple, harmless function to trigger its @@ -133,32 +132,31 @@ pub fn init() -> Res<()> { /// global options are accessed. Reading an option is the least impact approach. /// This allows us to use SSLTRACE in all of our unit tests and programs. #[cfg(debug_assertions)] -fn enable_ssl_trace() -> Res<()> { +fn enable_ssl_trace() { let opt = ssl::Opt::Locking.as_int(); let mut v: ::std::os::raw::c_int = 0; secstatus_to_res(unsafe { ssl::SSL_OptionGetDefault(opt, &mut v) }) + .expect("SSL_OptionGetDefault failed"); } /// Initialize with a database. /// -/// # Errors +/// # Panics /// /// If NSS cannot be initialized. -pub fn init_db>(dir: P) -> Res<()> { +pub fn init_db>(dir: P) { time::init(); - let res = INITIALIZED.get_or_init(|| { + _ = INITIALIZED.get_or_init(|| { version_check(); if already_initialized() { - return Ok(NssLoaded::External); + return NssLoaded::External; } let path = dir.into(); - if !path.is_dir() { - return Err(Error::InternalError); - } - let pathstr = path.to_str().ok_or(Error::InternalError)?; - let dircstr = CString::new(pathstr)?; - let empty = CString::new("")?; + assert!(path.is_dir()); + let pathstr = path.to_str().expect("path converts to string").to_string(); + let dircstr = CString::new(pathstr).unwrap(); + let empty = CString::new("").unwrap(); secstatus_to_res(unsafe { nss::NSS_Initialize( dircstr.as_ptr(), @@ -167,19 +165,21 @@ pub fn init_db>(dir: P) -> Res<()> { nss::SECMOD_DB.as_ptr().cast(), nss::NSS_INIT_READONLY, ) - })?; + }) + .expect("NSS_Initialize failed"); - secstatus_to_res(unsafe { nss::NSS_SetDomesticPolicy() })?; + secstatus_to_res(unsafe { nss::NSS_SetDomesticPolicy() }) + .expect("NSS_SetDomesticPolicy failed"); secstatus_to_res(unsafe { ssl::SSL_ConfigServerSessionIDCache(1024, 0, 0, dircstr.as_ptr()) - })?; + }) + .expect("SSL_ConfigServerSessionIDCache failed"); #[cfg(debug_assertions)] - enable_ssl_trace()?; + enable_ssl_trace(); - Ok(NssLoaded::Db) + NssLoaded::Db }); - res.as_ref().map(|_| ()).map_err(Clone::clone) } /// # Panics diff --git a/third_party/rust/neqo-crypto/src/min_version.rs b/third_party/rust/neqo-crypto/src/min_version.rs deleted file mode 100644 index 4386371b1b4e..000000000000 --- a/third_party/rust/neqo-crypto/src/min_version.rs +++ /dev/null @@ -1,9 +0,0 @@ -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/// The minimum version of NSS that is required by this version of neqo. -/// Note that the string may contain whitespace at the beginning and/or end. -pub(crate) const MINIMUM_NSS_VERSION: &str = include_str!("../min_version.txt"); diff --git a/third_party/rust/neqo-crypto/src/selfencrypt.rs b/third_party/rust/neqo-crypto/src/selfencrypt.rs index d0a85830b0c9..1130c3525019 100644 --- a/third_party/rust/neqo-crypto/src/selfencrypt.rs +++ b/third_party/rust/neqo-crypto/src/selfencrypt.rs @@ -47,7 +47,7 @@ impl SelfEncrypt { debug_assert_eq!(salt.len(), Self::SALT_LENGTH); let salt = hkdf::import_key(self.version, salt)?; let secret = hkdf::extract(self.version, self.cipher, Some(&salt), k)?; - Aead::new(self.version, self.cipher, &secret, "neqo self") + Aead::new(false, self.version, self.cipher, &secret, "neqo self") } /// Rotate keys. This causes any previous key that is being held to be replaced by the current diff --git a/third_party/rust/neqo-crypto/tests/aead.rs b/third_party/rust/neqo-crypto/tests/aead.rs index f8416ed9a7bd..5cf0034aec09 100644 --- a/third_party/rust/neqo-crypto/tests/aead.rs +++ b/third_party/rust/neqo-crypto/tests/aead.rs @@ -5,7 +5,7 @@ // except according to those terms. #![warn(clippy::pedantic)] -#![cfg(not(feature = "disable-encryption"))] +#![cfg(not(feature = "fuzzing"))] use neqo_crypto::{ constants::{Cipher, TLS_AES_128_GCM_SHA256, TLS_VERSION_1_3}, @@ -40,6 +40,7 @@ fn make_aead(cipher: Cipher) -> Aead { ) .expect("make a secret"); Aead::new( + false, TLS_VERSION_1_3, cipher, &secret, diff --git a/third_party/rust/neqo-crypto/tests/init.rs b/third_party/rust/neqo-crypto/tests/init.rs index ee7d808e29b5..13218cc34095 100644 --- a/third_party/rust/neqo-crypto/tests/init.rs +++ b/third_party/rust/neqo-crypto/tests/init.rs @@ -15,7 +15,13 @@ use neqo_crypto::{assert_initialized, init_db}; // Pull in the NSS internals so that we can ask NSS if it thinks that // it is properly initialized. -#[allow(dead_code, non_upper_case_globals)] +#[allow( + dead_code, + non_upper_case_globals, + clippy::redundant_static_lifetimes, + clippy::unseparated_literal_suffix, + clippy::upper_case_acronyms +)] mod nss { include!(concat!(env!("OUT_DIR"), "/nss_init.rs")); } @@ -23,54 +29,19 @@ mod nss { #[cfg(nss_nodb)] #[test] fn init_nodb() { - neqo_crypto::init().unwrap(); + init(); assert_initialized(); unsafe { - assert_ne!(nss::NSS_IsInitialized(), 0); + assert!(nss::NSS_IsInitialized() != 0); } } -#[cfg(nss_nodb)] -#[test] -fn init_twice_nodb() { - unsafe { - nss::NSS_NoDB_Init(std::ptr::null()); - assert_ne!(nss::NSS_IsInitialized(), 0); - } - // Now do it again - init_nodb(); -} - #[cfg(not(nss_nodb))] #[test] fn init_withdb() { - init_db(::test_fixture::NSS_DB_PATH).unwrap(); + init_db(::test_fixture::NSS_DB_PATH); assert_initialized(); unsafe { - assert_ne!(nss::NSS_IsInitialized(), 0); - } -} - -#[cfg(not(nss_nodb))] -#[test] -fn init_twice_withdb() { - use std::{ffi::CString, path::PathBuf}; - - let empty = CString::new("").unwrap(); - let path: PathBuf = ::test_fixture::NSS_DB_PATH.into(); - assert!(path.is_dir()); - let pathstr = path.to_str().unwrap(); - let dircstr = CString::new(pathstr).unwrap(); - unsafe { - nss::NSS_Initialize( - dircstr.as_ptr(), - empty.as_ptr(), - empty.as_ptr(), - nss::SECMOD_DB.as_ptr().cast(), - nss::NSS_INIT_READONLY, - ); - assert_ne!(nss::NSS_IsInitialized(), 0); + assert!(nss::NSS_IsInitialized() != 0); } - // Now do it again - init_withdb(); } diff --git a/third_party/rust/neqo-crypto/tests/selfencrypt.rs b/third_party/rust/neqo-crypto/tests/selfencrypt.rs index 9fc2162fe20b..4c574a3ae9c3 100644 --- a/third_party/rust/neqo-crypto/tests/selfencrypt.rs +++ b/third_party/rust/neqo-crypto/tests/selfencrypt.rs @@ -4,7 +4,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![cfg(not(feature = "disable-encryption"))] +#![cfg(not(feature = "fuzzing"))] use neqo_crypto::{ constants::{TLS_AES_128_GCM_SHA256, TLS_VERSION_1_3}, @@ -15,7 +15,7 @@ use neqo_crypto::{ #[test] fn se_create() { - init().unwrap(); + init(); SelfEncrypt::new(TLS_VERSION_1_3, TLS_AES_128_GCM_SHA256).expect("constructor works"); } @@ -23,7 +23,7 @@ const PLAINTEXT: &[u8] = b"PLAINTEXT"; const AAD: &[u8] = b"AAD"; fn sealed() -> (SelfEncrypt, Vec) { - init().unwrap(); + init(); let se = SelfEncrypt::new(TLS_VERSION_1_3, TLS_AES_128_GCM_SHA256).unwrap(); let sealed = se.seal(AAD, PLAINTEXT).expect("sealing works"); (se, sealed) diff --git a/third_party/rust/neqo-http3/.cargo-checksum.json b/third_party/rust/neqo-http3/.cargo-checksum.json index 127edf43cb4f..0459fea7cc30 100644 --- a/third_party/rust/neqo-http3/.cargo-checksum.json +++ b/third_party/rust/neqo-http3/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"14fc8adbe57d4828725c060fdcb432e4bd7e7041f95267bc62fb6f5eaee34a82","src/buffered_send_stream.rs":"f45bdf9ad2a04b3828c74ff5440681d3c9d1af39b55470e4f729842dc2412295","src/client_events.rs":"77fedca72ce54956eaba3fb7103085d196a631b764662584ea2629224c5c234e","src/conn_params.rs":"224a8ea6ef632930a7788a1cabf47ce69ad41bd4bc8dcf3053fbd998fdb38e82","src/connection.rs":"57e4660838c0d16d8f97e92c010b80ffd6c92de86c2f162f04ab2d31e724c02d","src/connection_client.rs":"796eba806f44d4a689cdeb009d7abfa3b76ba56bc66c551ce02a50465f0d59c5","src/connection_server.rs":"d8de13ca23ccaf4a485d552cdae09454a3ee6577b8e5fac0931e909f79461625","src/control_stream_local.rs":"ae52e3286f1686ca1265e7de841392addd42616db02799bb967a59feb6039cb5","src/control_stream_remote.rs":"59eb4041e366d92f9f294e8446755caa5e91fd943bba7b79b726698ba13be248","src/features/extended_connect/mod.rs":"3b02f6b18627f3855465a81b1d9b285e6f13839e75a8a6db648ed9082908d7f0","src/features/extended_connect/tests/mod.rs":"fd6aee37243713e80fc526552f21f0222338cec9890409b6575a2a637b17ec1f","src/features/extended_connect/tests/webtransport/datagrams.rs":"4c85a90afb753ce588e3fdeb773669bc49c013aebc28912340359eb01b74fd70","src/features/extended_connect/tests/webtransport/mod.rs":"a30ea715f5271a826a739278b18e145964dedbce7026eed45f1b7d0355c407d5","src/features/extended_connect/tests/webtransport/negotiation.rs":"98254ef8446581ec520026b04ef9549645602181b61602c9936f6660141edf0b","src/features/extended_connect/tests/webtransport/sessions.rs":"de3d836f666c2bec31e70b33bdc2669572cabbe17df2225db7282613a224a364","src/features/extended_connect/tests/webtransport/streams.rs":"8b3c34cac1b2171252a4bb53d420ac2098549a20309c327bf56e2e9ba9e33538","src/features/extended_connect/webtransport_session.rs":"239d92c06fbc5f6226078bb411a803f57b555dea0077349d49d7f57671cf2eab","src/features/extended_connect/webtransport_streams.rs":"5d7507aaf6a819d266fbea9b7a415c8324329df0f6936d9045b73e17a5b844ee","src/features/mod.rs":"925aae4427ad82e4d019354802b223d53db5e5585d4a940f5417a24a9503d7ee","src/frames/hframe.rs":"56c36ac597504f28c73cf2370acd82104f8c7a7b9ffc0f6d222378abc524482d","src/frames/mod.rs":"7d0a46ca147336d14781edb8dbee8b03c2e4bcd6646f5473a9d93d31fe73fecb","src/frames/reader.rs":"e07ee9de74bc499c10afcda592fefd9a7eef3381c045aa14f6596d67313546ca","src/frames/tests/hframe.rs":"01ec74eb3eb25d95042aa0263f9267f89535e6b7b8c1161fab4ba9ee5352d4a7","src/frames/tests/mod.rs":"0610609b316767a6a022837d32ee0452e37ea296fde37e51bec87e7c77e923a3","src/frames/tests/reader.rs":"2bfadc7afbc41bff9f5f930b31550259a8a92484d35f6c5d8dd8fd9acfb88f5b","src/frames/tests/wtframe.rs":"589ebe1e62ce4da63b37b7d22cde7ba572ddbf29336fdcdbbcd0a745f79dacd8","src/frames/wtframe.rs":"1d9d0256ace2ba7262343ed035df795f21a4d45065792d3fd45b3391b6916b2f","src/headers_checks.rs":"be0f0109298dcc3a40350b7c0950076ddfe20617d195b305e3ffc8582557ab18","src/lib.rs":"4f908a021222bcc79b9d569bc3759a493379a20b47dfa228fddf51600bf6e446","src/priority.rs":"f3b77c208962e44a4e2d13138c6998b703d40e7bcf8f73ea84d8ef5b556e0aee","src/push_controller.rs":"13bccf2834ae19109504cf695a5948c3b2d03fd101bc032a92bb77a033423854","src/qlog.rs":"2debd75c7ea103c95ff79e44412f1408c3e496e324976100c55d5a833912b6c3","src/qpack_decoder_receiver.rs":"c927dfc3e58c71d282210ba79280f6f03e789733bc3bedc247e68bab516b9e9e","src/qpack_encoder_receiver.rs":"d0ac03cc111b6e1c555a8654d3234116f2b135b5b040edac23cefe2d640beba9","src/recv_message.rs":"7ac8d4057ba53874e4edfc62cd25ad5d3f0b10aaac5bf6e156103c3bc44e18cc","src/request_target.rs":"6041a69a0a74969ec08bc164509c055e9bad99f53bbeb16c0aa17d108dd68b8c","src/send_message.rs":"374e168f60063b8102a2aff52c719ae2e1e5078527cf50d095b3e7217f6ec7d2","src/server.rs":"b9e6060da36cfb467478f5b78b17e22a123214ad2d64c919ce688ea2bc0e24bb","src/server_connection_events.rs":"12d353ca6301467f6d475dde3b789951a5716c89ddd7dbf1383efef8082361f3","src/server_events.rs":"1cda8d6c413fad0fa67fcfd7cb78e795bf7ef7f0e09b5720992646a82d51ce16","src/settings.rs":"476b154b5eea4c8d69a4a790fee3e527cef4d375df1cfb5eed04ec56406fe15a","src/stream_type_reader.rs":"7a7226b7911d69f7e00ec4987c2a32a5e8a33463203398cbee1e6645d2691478","tests/httpconn.rs":"bb6927801a8c75e4f05eb6cdb1e7f2d57be69b74e68ddad2a1614f2aeed04369","tests/priority.rs":"364754507873298612ad12e8d1d106d26d993712142d0be4cbf056da5338854c","tests/send_message.rs":"b5435045b16429d9e626ea94a8f10e2937e1a5a878af0035763a4f5ec09bf53c","tests/webtransport.rs":"25794305017ff58e57dc3c3b9b078e5bfc1814ea82a521b7b7156228e613c092"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"458f04261cda071d61402c52cf64062ad7cfc24f3f312bfaa5d52cae47409010","src/buffered_send_stream.rs":"f45bdf9ad2a04b3828c74ff5440681d3c9d1af39b55470e4f729842dc2412295","src/client_events.rs":"77fedca72ce54956eaba3fb7103085d196a631b764662584ea2629224c5c234e","src/conn_params.rs":"224a8ea6ef632930a7788a1cabf47ce69ad41bd4bc8dcf3053fbd998fdb38e82","src/connection.rs":"9384cdfd8481a30a0cd13f56f590188ccfa47b4472f35f7a4978537bab19adc1","src/connection_client.rs":"8db29409f3a265f7dff7c7a7eaf2ac607d6923e4b3238e82eab6dc22854e4303","src/connection_server.rs":"ca33b50650bd1ca2a952851b72712d55ec2e48b48f1f06e4184c808b8e1e009a","src/control_stream_local.rs":"ae52e3286f1686ca1265e7de841392addd42616db02799bb967a59feb6039cb5","src/control_stream_remote.rs":"59eb4041e366d92f9f294e8446755caa5e91fd943bba7b79b726698ba13be248","src/features/extended_connect/mod.rs":"3b02f6b18627f3855465a81b1d9b285e6f13839e75a8a6db648ed9082908d7f0","src/features/extended_connect/tests/mod.rs":"fd6aee37243713e80fc526552f21f0222338cec9890409b6575a2a637b17ec1f","src/features/extended_connect/tests/webtransport/datagrams.rs":"4c85a90afb753ce588e3fdeb773669bc49c013aebc28912340359eb01b74fd70","src/features/extended_connect/tests/webtransport/mod.rs":"a30ea715f5271a826a739278b18e145964dedbce7026eed45f1b7d0355c407d5","src/features/extended_connect/tests/webtransport/negotiation.rs":"98254ef8446581ec520026b04ef9549645602181b61602c9936f6660141edf0b","src/features/extended_connect/tests/webtransport/sessions.rs":"de3d836f666c2bec31e70b33bdc2669572cabbe17df2225db7282613a224a364","src/features/extended_connect/tests/webtransport/streams.rs":"8b3c34cac1b2171252a4bb53d420ac2098549a20309c327bf56e2e9ba9e33538","src/features/extended_connect/webtransport_session.rs":"239d92c06fbc5f6226078bb411a803f57b555dea0077349d49d7f57671cf2eab","src/features/extended_connect/webtransport_streams.rs":"5d7507aaf6a819d266fbea9b7a415c8324329df0f6936d9045b73e17a5b844ee","src/features/mod.rs":"925aae4427ad82e4d019354802b223d53db5e5585d4a940f5417a24a9503d7ee","src/frames/hframe.rs":"56c36ac597504f28c73cf2370acd82104f8c7a7b9ffc0f6d222378abc524482d","src/frames/mod.rs":"7d0a46ca147336d14781edb8dbee8b03c2e4bcd6646f5473a9d93d31fe73fecb","src/frames/reader.rs":"e07ee9de74bc499c10afcda592fefd9a7eef3381c045aa14f6596d67313546ca","src/frames/tests/hframe.rs":"01ec74eb3eb25d95042aa0263f9267f89535e6b7b8c1161fab4ba9ee5352d4a7","src/frames/tests/mod.rs":"0610609b316767a6a022837d32ee0452e37ea296fde37e51bec87e7c77e923a3","src/frames/tests/reader.rs":"2bfadc7afbc41bff9f5f930b31550259a8a92484d35f6c5d8dd8fd9acfb88f5b","src/frames/tests/wtframe.rs":"589ebe1e62ce4da63b37b7d22cde7ba572ddbf29336fdcdbbcd0a745f79dacd8","src/frames/wtframe.rs":"1d9d0256ace2ba7262343ed035df795f21a4d45065792d3fd45b3391b6916b2f","src/headers_checks.rs":"be0f0109298dcc3a40350b7c0950076ddfe20617d195b305e3ffc8582557ab18","src/lib.rs":"4f908a021222bcc79b9d569bc3759a493379a20b47dfa228fddf51600bf6e446","src/priority.rs":"f3b77c208962e44a4e2d13138c6998b703d40e7bcf8f73ea84d8ef5b556e0aee","src/push_controller.rs":"13bccf2834ae19109504cf695a5948c3b2d03fd101bc032a92bb77a033423854","src/qlog.rs":"2debd75c7ea103c95ff79e44412f1408c3e496e324976100c55d5a833912b6c3","src/qpack_decoder_receiver.rs":"c927dfc3e58c71d282210ba79280f6f03e789733bc3bedc247e68bab516b9e9e","src/qpack_encoder_receiver.rs":"d0ac03cc111b6e1c555a8654d3234116f2b135b5b040edac23cefe2d640beba9","src/recv_message.rs":"eb711dbc6b3371373c26b75333ac5858edf0d30184b0e05d67ab02c656eb6619","src/request_target.rs":"6041a69a0a74969ec08bc164509c055e9bad99f53bbeb16c0aa17d108dd68b8c","src/send_message.rs":"7785af11b77cee398faf3f7a2875b41e251ed7a1b272c23f81a48334596ab836","src/server.rs":"b9e6060da36cfb467478f5b78b17e22a123214ad2d64c919ce688ea2bc0e24bb","src/server_connection_events.rs":"12d353ca6301467f6d475dde3b789951a5716c89ddd7dbf1383efef8082361f3","src/server_events.rs":"463dd2cb6f97a800bac32c93c4aa2a6289f71e33a89f3b33152460cb941fc378","src/settings.rs":"476b154b5eea4c8d69a4a790fee3e527cef4d375df1cfb5eed04ec56406fe15a","src/stream_type_reader.rs":"7a7226b7911d69f7e00ec4987c2a32a5e8a33463203398cbee1e6645d2691478","tests/httpconn.rs":"bb6927801a8c75e4f05eb6cdb1e7f2d57be69b74e68ddad2a1614f2aeed04369","tests/priority.rs":"364754507873298612ad12e8d1d106d26d993712142d0be4cbf056da5338854c","tests/send_message.rs":"b5435045b16429d9e626ea94a8f10e2937e1a5a878af0035763a4f5ec09bf53c","tests/webtransport.rs":"25794305017ff58e57dc3c3b9b078e5bfc1814ea82a521b7b7156228e613c092"},"package":null} \ No newline at end of file diff --git a/third_party/rust/neqo-http3/Cargo.toml b/third_party/rust/neqo-http3/Cargo.toml index fe6f758402e0..12b9a125d048 100644 --- a/third_party/rust/neqo-http3/Cargo.toml +++ b/third_party/rust/neqo-http3/Cargo.toml @@ -13,7 +13,7 @@ edition = "2021" rust-version = "1.74.0" name = "neqo-http3" -version = "0.7.3" +version = "0.7.2" authors = ["The Neqo Authors "] homepage = "https://github.com/mozilla/neqo/" license = "MIT OR Apache-2.0" @@ -62,9 +62,9 @@ default-features = false path = "../test-fixture" [features] -disable-encryption = [ - "neqo-transport/disable-encryption", - "neqo-crypto/disable-encryption", +fuzzing = [ + "neqo-transport/fuzzing", + "neqo-crypto/fuzzing", ] [lints.clippy.pedantic] diff --git a/third_party/rust/neqo-http3/src/connection.rs b/third_party/rust/neqo-http3/src/connection.rs index cfa78df787de..287ea2c2afd3 100644 --- a/third_party/rust/neqo-http3/src/connection.rs +++ b/third_party/rust/neqo-http3/src/connection.rs @@ -354,7 +354,7 @@ impl Http3Connection { /// This function creates and initializes, i.e. send stream type, the control and qpack /// streams. fn initialize_http3_connection(&mut self, conn: &mut Connection) -> Res<()> { - qdebug!([self], "Initialize the http3 connection."); + qinfo!([self], "Initialize the http3 connection."); self.control_stream_local.create(conn)?; self.send_settings(); @@ -704,7 +704,7 @@ impl Http3Connection { ); } NewStreamType::Decoder => { - qdebug!([self], "A new remote qpack encoder stream {}", stream_id); + qinfo!([self], "A new remote qpack encoder stream {}", stream_id); self.check_stream_exists(Http3StreamType::Decoder)?; self.recv_streams.insert( stream_id, @@ -715,7 +715,7 @@ impl Http3Connection { ); } NewStreamType::Encoder => { - qdebug!([self], "A new remote qpack decoder stream {}", stream_id); + qinfo!([self], "A new remote qpack decoder stream {}", stream_id); self.check_stream_exists(Http3StreamType::Encoder)?; self.recv_streams.insert( stream_id, @@ -766,7 +766,7 @@ impl Http3Connection { /// This is called when an application closes the connection. pub fn close(&mut self, error: AppError) { - qdebug!([self], "Close connection error {:?}.", error); + qinfo!([self], "Close connection error {:?}.", error); self.state = Http3State::Closing(ConnectionError::Application(error)); if (!self.send_streams.is_empty() || !self.recv_streams.is_empty()) && (error == 0) { qwarn!("close(0) called when streams still active"); @@ -952,7 +952,7 @@ impl Http3Connection { stream_id: StreamId, buf: &mut [u8], ) -> Res<(usize, bool)> { - qdebug!([self], "read_data from stream {}.", stream_id); + qinfo!([self], "read_data from stream {}.", stream_id); let res = self .recv_streams .get_mut(&stream_id) @@ -1091,7 +1091,7 @@ impl Http3Connection { /// This is called when an application wants to close the sending side of a stream. pub fn stream_close_send(&mut self, conn: &mut Connection, stream_id: StreamId) -> Res<()> { - qdebug!([self], "Close the sending side for stream {}.", stream_id); + qinfo!([self], "Close the sending side for stream {}.", stream_id); debug_assert!(self.state.active()); let send_stream = self .send_streams @@ -1402,7 +1402,7 @@ impl Http3Connection { /// `PriorityUpdateRequestPush` which handling is specific to the client and server, we must /// give them to the specific client/server handler. fn handle_control_frame(&mut self, f: HFrame) -> Res> { - qdebug!([self], "Handle a control frame {:?}", f); + qinfo!([self], "Handle a control frame {:?}", f); if !matches!(f, HFrame::Settings { .. }) && !matches!( self.settings_state, @@ -1433,7 +1433,7 @@ impl Http3Connection { } fn handle_settings(&mut self, new_settings: HSettings) -> Res<()> { - qdebug!([self], "Handle SETTINGS frame."); + qinfo!([self], "Handle SETTINGS frame."); match &self.settings_state { Http3RemoteSettingsState::NotReceived => { self.set_qpack_settings(&new_settings)?; diff --git a/third_party/rust/neqo-http3/src/connection_client.rs b/third_party/rust/neqo-http3/src/connection_client.rs index 836816b33732..52572a760de7 100644 --- a/third_party/rust/neqo-http3/src/connection_client.rs +++ b/third_party/rust/neqo-http3/src/connection_client.rs @@ -590,7 +590,7 @@ impl Http3Client { /// /// An error will be return if stream does not exist. pub fn stream_close_send(&mut self, stream_id: StreamId) -> Res<()> { - qdebug!([self], "Close sending side stream={}.", stream_id); + qinfo!([self], "Close sending side stream={}.", stream_id); self.base_handler .stream_close_send(&mut self.conn, stream_id) } @@ -652,7 +652,7 @@ impl Http3Client { stream_id: StreamId, buf: &mut [u8], ) -> Res<(usize, bool)> { - qdebug!([self], "read_data from stream {}.", stream_id); + qinfo!([self], "read_data from stream {}.", stream_id); let res = self.base_handler.read_data(&mut self.conn, stream_id, buf); if let Err(e) = &res { if e.connection_error() { diff --git a/third_party/rust/neqo-http3/src/connection_server.rs b/third_party/rust/neqo-http3/src/connection_server.rs index dcf759f177a9..097209a2269a 100644 --- a/third_party/rust/neqo-http3/src/connection_server.rs +++ b/third_party/rust/neqo-http3/src/connection_server.rs @@ -98,7 +98,7 @@ impl Http3ServerHandler { /// /// An error will be returned if stream does not exist. pub fn stream_close_send(&mut self, stream_id: StreamId, conn: &mut Connection) -> Res<()> { - qdebug!([self], "Close sending side stream={}.", stream_id); + qinfo!([self], "Close sending side stream={}.", stream_id); self.base_handler.stream_close_send(conn, stream_id)?; self.base_handler.stream_has_pending_data(stream_id); self.needs_processing = true; @@ -408,7 +408,7 @@ impl Http3ServerHandler { stream_id: StreamId, buf: &mut [u8], ) -> Res<(usize, bool)> { - qdebug!([self], "read_data from stream {}.", stream_id); + qinfo!([self], "read_data from stream {}.", stream_id); let res = self.base_handler.read_data(conn, stream_id, buf); if let Err(e) = &res { if e.connection_error() { diff --git a/third_party/rust/neqo-http3/src/recv_message.rs b/third_party/rust/neqo-http3/src/recv_message.rs index 55970849ef64..be58b7e47c34 100644 --- a/third_party/rust/neqo-http3/src/recv_message.rs +++ b/third_party/rust/neqo-http3/src/recv_message.rs @@ -271,7 +271,7 @@ impl RecvMessage { } (None, false) => break Ok(()), (Some(frame), fin) => { - qdebug!( + qinfo!( [self], "A new frame has been received: {:?}; state={:?} fin={}", frame, diff --git a/third_party/rust/neqo-http3/src/send_message.rs b/third_party/rust/neqo-http3/src/send_message.rs index 15965c44f698..c50e3e056ad8 100644 --- a/third_party/rust/neqo-http3/src/send_message.rs +++ b/third_party/rust/neqo-http3/src/send_message.rs @@ -6,7 +6,7 @@ use std::{cell::RefCell, cmp::min, fmt::Debug, rc::Rc}; -use neqo_common::{qdebug, qtrace, Encoder, Header, MessageType}; +use neqo_common::{qdebug, qinfo, qtrace, Encoder, Header, MessageType}; use neqo_qpack::encoder::QPackEncoder; use neqo_transport::{Connection, StreamId}; @@ -119,7 +119,7 @@ impl SendMessage { encoder: Rc>, conn_events: Box, ) -> Self { - qdebug!("Create a request stream_id={}", stream_id); + qinfo!("Create a request stream_id={}", stream_id); Self { state: MessageState::WaitingForHeaders, message_type, @@ -193,7 +193,7 @@ impl SendStream for SendMessage { min(buf.len(), available - 9) }; - qdebug!( + qinfo!( [self], "send_request_body: available={} to_send={}.", available, diff --git a/third_party/rust/neqo-http3/src/server_events.rs b/third_party/rust/neqo-http3/src/server_events.rs index 214a48c757a4..a85ece0bfb51 100644 --- a/third_party/rust/neqo-http3/src/server_events.rs +++ b/third_party/rust/neqo-http3/src/server_events.rs @@ -13,7 +13,7 @@ use std::{ rc::Rc, }; -use neqo_common::{qdebug, Encoder, Header}; +use neqo_common::{qdebug, qinfo, Encoder, Header}; use neqo_transport::{ server::ActiveConnectionRef, AppError, Connection, DatagramTracking, StreamId, StreamType, }; @@ -189,7 +189,7 @@ impl Http3OrWebTransportStream { /// /// It may return `InvalidStreamId` if a stream does not exist anymore. pub fn send_data(&mut self, data: &[u8]) -> Res { - qdebug!([self], "Set new response."); + qinfo!([self], "Set new response."); self.stream_handler.send_data(data) } @@ -199,7 +199,7 @@ impl Http3OrWebTransportStream { /// /// It may return `InvalidStreamId` if a stream does not exist anymore. pub fn stream_close_send(&mut self) -> Res<()> { - qdebug!([self], "Set new response."); + qinfo!([self], "Set new response."); self.stream_handler.stream_close_send() } } @@ -270,7 +270,7 @@ impl WebTransportRequest { /// /// It may return `InvalidStreamId` if a stream does not exist anymore. pub fn response(&mut self, accept: &WebTransportSessionAcceptAction) -> Res<()> { - qdebug!([self], "Set a response for a WebTransport session."); + qinfo!([self], "Set a response for a WebTransport session."); self.stream_handler .handler .borrow_mut() diff --git a/third_party/rust/neqo-qpack/.cargo-checksum.json b/third_party/rust/neqo-qpack/.cargo-checksum.json index 3c577eaf4dd3..aae0a1e59462 100644 --- a/third_party/rust/neqo-qpack/.cargo-checksum.json +++ b/third_party/rust/neqo-qpack/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"3e347de7641de127199b93fcb75f225073ff80fac83feef6067d2c1d6b5d54fe","src/decoder.rs":"0675444129e074e9d5d56f0d45d2eaed614c85e22cfe9f2d28cdee912c15b420","src/decoder_instructions.rs":"d991d70e51f079bc5b30d3982fd0176edfa9bb7ba14c17a20ec3eea878c56206","src/encoder.rs":"84649cbee81e050f55d7ea691ac871e072741abd8bbf96303eb2e98aa8ee0aea","src/encoder_instructions.rs":"86e3abbd9cf94332041326ac6cf806ed64623e3fd38dbc0385b1f63c37e73fd9","src/header_block.rs":"3925476df69b90d950594faadc5cb24c374d46de8c75a374a235f0d27323a7d8","src/huffman.rs":"71ec740426eee0abb6205104e504f5b97f525a76c4a5f5827b78034d28ce1876","src/huffman_decode_helper.rs":"9ce470e318b3664f58aa109bed483ab15bfd9e0b17d261ea2b609668a42a9d80","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"fd673630b5ed64197851c9a9758685096d3c0aa04f4994290733a38057004ee6","src/prefix.rs":"fb4a9acbcf6fd3178f4474404cd3d3b131abca934f69fe14a9d744bc7e636dc5","src/qlog.rs":"e320007ea8309546b26f9c0019ab8722da80dbd38fa976233fd8ae19a0af637c","src/qpack_send_buf.rs":"755af90fe077b1bcca34a1a2a1bdce5ce601ea490b2ca3f1313e0107d13e67e2","src/reader.rs":"1581261741a0922b147a6975cc8b1a3503846f6dbfdb771d254760c298996982","src/static_table.rs":"fda9d5c6f38f94b0bf92d3afdf8432dce6e27e189736596e16727090c77b78ec","src/stats.rs":"624dfa3b40858c304097bb0ce5b1be1bb4d7916b1abfc222f1aa705907009730","src/table.rs":"6e16debdceadc453546f247f8316883af9eeeedd12f2070219d8484a0a131d46"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"c2152600379c3961ba79e661e164630a63531744f79e082fce39cdf1cbe75ddd","src/decoder.rs":"0675444129e074e9d5d56f0d45d2eaed614c85e22cfe9f2d28cdee912c15b420","src/decoder_instructions.rs":"d991d70e51f079bc5b30d3982fd0176edfa9bb7ba14c17a20ec3eea878c56206","src/encoder.rs":"84649cbee81e050f55d7ea691ac871e072741abd8bbf96303eb2e98aa8ee0aea","src/encoder_instructions.rs":"86e3abbd9cf94332041326ac6cf806ed64623e3fd38dbc0385b1f63c37e73fd9","src/header_block.rs":"3925476df69b90d950594faadc5cb24c374d46de8c75a374a235f0d27323a7d8","src/huffman.rs":"71ec740426eee0abb6205104e504f5b97f525a76c4a5f5827b78034d28ce1876","src/huffman_decode_helper.rs":"9ce470e318b3664f58aa109bed483ab15bfd9e0b17d261ea2b609668a42a9d80","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"fd673630b5ed64197851c9a9758685096d3c0aa04f4994290733a38057004ee6","src/prefix.rs":"fb4a9acbcf6fd3178f4474404cd3d3b131abca934f69fe14a9d744bc7e636dc5","src/qlog.rs":"e320007ea8309546b26f9c0019ab8722da80dbd38fa976233fd8ae19a0af637c","src/qpack_send_buf.rs":"755af90fe077b1bcca34a1a2a1bdce5ce601ea490b2ca3f1313e0107d13e67e2","src/reader.rs":"1581261741a0922b147a6975cc8b1a3503846f6dbfdb771d254760c298996982","src/static_table.rs":"fda9d5c6f38f94b0bf92d3afdf8432dce6e27e189736596e16727090c77b78ec","src/stats.rs":"624dfa3b40858c304097bb0ce5b1be1bb4d7916b1abfc222f1aa705907009730","src/table.rs":"6e16debdceadc453546f247f8316883af9eeeedd12f2070219d8484a0a131d46"},"package":null} \ No newline at end of file diff --git a/third_party/rust/neqo-qpack/Cargo.toml b/third_party/rust/neqo-qpack/Cargo.toml index 2ccdccfdcb1f..1becac819001 100644 --- a/third_party/rust/neqo-qpack/Cargo.toml +++ b/third_party/rust/neqo-qpack/Cargo.toml @@ -13,7 +13,7 @@ edition = "2021" rust-version = "1.74.0" name = "neqo-qpack" -version = "0.7.3" +version = "0.7.2" authors = ["The Neqo Authors "] homepage = "https://github.com/mozilla/neqo/" license = "MIT OR Apache-2.0" diff --git a/third_party/rust/neqo-transport/.cargo-checksum.json b/third_party/rust/neqo-transport/.cargo-checksum.json dissimilarity index 78% index 4951f630e0e6..669c0120f03d 100644 --- a/third_party/rust/neqo-transport/.cargo-checksum.json +++ b/third_party/rust/neqo-transport/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"eae5f69e42fb8379704c2346d53905ca8f9907452d81d637bada91d82a4fb74a","benches/range_tracker.rs":"590dd1f81c92e89ce28af1efdda583d85240438bd9c4c68767286d22a299ad4b","benches/rx_stream_orderer.rs":"53a008357703251a18100521a12d8fa9443c5601ddc3cbd1b3c2899074da4c4f","benches/transfer.rs":"94eb0ec1a0a7d0a4863ddc1c6d006521e52c1f2e7f03c69428b18f7eb827d33f","src/ackrate.rs":"4bb882e1069a0707dc85338b75327e2910c93ee5f36575767a0d58c4c41c9d4f","src/addr_valid.rs":"03c0b2ff85254179c5d425b12acfdcc6b1ea5735aeb0f604b9b3603451b3ef0a","src/cc/classic_cc.rs":"d27b503ea8c4c705b43315d2d31d12488546163cf88ca085f7ccf883ad4d77f9","src/cc/cubic.rs":"24c6913cc6346e5361007221c26e8096ece51583431fc3ab9c99e4ce4b0a9f5d","src/cc/mod.rs":"e0837937c9991b37edad15cd870ea9e0623489babfccc340074dd8322e1ef401","src/cc/new_reno.rs":"25d0921005688e0f0666efd0a4931b4f8cd44363587d98e5b6404818c5d05dd4","src/cc/tests/cubic.rs":"109fc8be5efba8959e777288c32ae8f2db581fc08719f318ad676e187f655478","src/cc/tests/mod.rs":"44f8df551e742ae1037cd1cdb85b2c1334c2e5ab3c23ed63d856dbc6b8743afc","src/cc/tests/new_reno.rs":"5414e26b6c928c5f82c5eeb42f04772b05be1ec2c8ee21c2b698ce8cb32829a1","src/cid.rs":"9686a3070c593cfca846d7549863728e31211b304b9fa876220f79bff5e24173","src/connection/dump.rs":"bd4fb55785fe42f5c94f7bcc14ccf4ae377d28b691fb55dbf1139ae9412b0ea9","src/connection/idle.rs":"b3bc2ad1290e54278d8703092d135eda973eb12316d1f6dffedaffdf25e2a47e","src/connection/mod.rs":"a14a969d993914dcfd64c3847ba4b80f60735de8d1ed83de12c7e9f4bcae13c2","src/connection/params.rs":"38e0b47c8cc5fbe602e3174d7a70df410829bc240b42f21cebd10818e606ef7c","src/connection/saved.rs":"97eb19792be3c4d721057021a43ea50a52f89a3cfa583d3d3dcf5d9144b332f5","src/connection/state.rs":"c0c4b1c15624a8762eabc8d5fa76f169f3f93945a9ee86f30fbd7714f1ac1d37","src/connection/test_internal.rs":"f3ebfe97b25c9c716d41406066295e5aff4e96a3051ef4e2b5fb258282bbc14c","src/connection/tests/ackrate.rs":"4a2b835575850ae4a14209d3e51883ecb1e69afb44ef91b5e13a5e6cb7174fab","src/connection/tests/cc.rs":"d0d6ac038572ad3dcd9e6734596eaeedc6d3222d24e31b023aaab3540d195e46","src/connection/tests/close.rs":"20bf9b044ba52517693c2bd10820ff04a8c07de01d59c8c47b4e9478aa730211","src/connection/tests/datagram.rs":"f4c85099b6a8739fb99eadd8711b02066ad80fc8341a2e5e0dae2520378af9fe","src/connection/tests/handshake.rs":"c759737ee98c7b33b2327eb7d521f45c63aed15dc8f272b7bbcc510ee8e48877","src/connection/tests/idle.rs":"f3bcb12cd79cb8eabc969ce3fb0fab4eea26d6383b81a323c0e18ca9c42cfb59","src/connection/tests/keys.rs":"55558c057beb4221245beb262076de3991dca3f2661411db61c09d21194873df","src/connection/tests/migration.rs":"624985d925236be197eee52208dbdebe35c0df5bd9d30982d6f183dfda4cbab5","src/connection/tests/mod.rs":"280077d4e69faabd2fc1fe03f754096b8b83a8e2b2438fd05b3d7cd924154489","src/connection/tests/null.rs":"38f76a4ea15e6b11634d4374cb0f2a68bd250e5d35831edfce0fa48deeaa420d","src/connection/tests/priority.rs":"dd3504f52d3fce7a96441624bc1c82c733e6bb556b9b79d24d0f4fb4efaf5a9e","src/connection/tests/recovery.rs":"7f28767f3cca2ff60e3dcfa803e12ef043486a222f54681a8faf2ea2fee564a1","src/connection/tests/resumption.rs":"1a0de0993cd325224fc79a3c094d22636d5b122ab1123d16265d4fafb23574bd","src/connection/tests/stream.rs":"8e4af07d8033a951fc57f2afda570a08843b36931eca53ba3781a5992978afb2","src/connection/tests/vn.rs":"550eb6b4d39d5960aafc70037c25a1a0f5db1232ce0ec6080b2c29a731a9574e","src/connection/tests/zerortt.rs":"67f77721e33d9fa2691c5ea3ef4a90935987541d81f0f42fbcfca31e690b352a","src/crypto.rs":"4df1342655899aa953be101fb08de9c012a6080418b564abe8828faab8c78aa3","src/events.rs":"6e115f309c5c46f30f6223e1347bea477ada457f8bb2189ecccc6d65483318d6","src/fc.rs":"ec9de1028286870c0adf88a92e1355acf13dede8b1e91179230df3263e3827a9","src/frame.rs":"5c8e5bc21e1052367f7db31523ee422efa4278ccdfc8cd581bb44a50ee205f16","src/lib.rs":"5e1c6cfff5b299d2b10c99075a06e91649a528c432dff7b70c87aac096b6315b","src/pace.rs":"86a674ac4d086148ea297214910458c3705918bd627b996ba8bbb12f2c4bf99e","src/packet/mod.rs":"4ce239362b5eec79083d2a744416c246dad5fe9505ef481dbd8001db4271ea24","src/packet/retry.rs":"d5f999485f21b388a7383cd011fc6e96109c1a9fb5aef79b19017df6844271ff","src/path.rs":"610e6ce83da91b785d0690995591fa4da7b5a1add3d0022eea0be5050612cee9","src/qlog.rs":"f3d3661835a29e6023014f7a0996494fc8dc1f2d062154b94346a0c21bbf6fd1","src/quic_datagrams.rs":"3d33ecb9e6e80c77b812e8260fc807352300fb2305a29b797259ae34c52b67c5","src/recovery.rs":"1dadc6717dd133007943e762231a50680087392466904c2f2e6fface084e2ba9","src/recv_stream.rs":"f21ae0bb786901bb7d726a94cb3352607b0057128beaa331808137f2f57a330b","src/rtt.rs":"4635dc0c401b78a1fd9d34da6f9bf7f6e7f5be3a57ed9716e0efc8f0f94f1e47","src/send_stream.rs":"f717f64b75e368cf5fa4ca43078aa7c1b5aff48b4f6266713e6fa7dc458328aa","src/sender.rs":"5f760988bdd6fbbd5956877a97abe7c17370dd531f68b751a9e4e4459583f87b","src/server.rs":"faa57bdb5c443d7a46f3cf0272d0038ae945d99ee2d05b5adb41fd4eda7f9913","src/stats.rs":"257ab1242ea2e6bfac0900e6c4bdad794bc67b666930323d24e022e46b9be82b","src/stream_id.rs":"fd07cbb81709a54bdb0659f676ef851cd145c004b817044ede5b21e54fdb60e4","src/streams.rs":"062b1b61edd1a76a86914f2cc1ca007c03edd9136c0c3409d960ddb805805fc6","src/tparams.rs":"10d62ac64865e0606c3c14141f9674631c610b3f042e274e110bdcef5d388491","src/tracking.rs":"f9a9aa01abc79fdd7a2cfb2c3ae342b9ab709e6a2a11076ec5c475fc89c1f598","src/version.rs":"182484ed9ecc2e17cab73cc61914a86a2d206936cab313825ae76fd37eeade77","tests/common/mod.rs":"a6584d268da0157190f8f61842a655ffe81ee68702b3e6569ae300a169080eab","tests/conn_vectors.rs":"997702f4d8b8fa3b987b33077a0eb325e968b25b61fb4703532f8d97e1d4c98c","tests/connection.rs":"d1bc28294d70a5a484eb869162115e399862742caa791749fbd6b923b702b7cc","tests/network.rs":"9e30b8610124250262fceef27d09fdecf2d6e9c3a96b1e676ff4189b9e06d5ba","tests/retry.rs":"3225b64c0c0ca918df12d94df21f6023091e72606701c1dc8c060ce3c1e09c52","tests/server.rs":"cb83de909d858950bfd75a789fc23c3c44fcdf1d965b63800b2c7b498507987f"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"8eac0a271cef9232d100eb45093a3f7978a93e0576c64c99c161092ff445825d","benches/range_tracker.rs":"4821443d3cccc697b8976b7c50d787a7aa8cb86ab8633a7582be3f85135168db","benches/rx_stream_orderer.rs":"a8db922390d8506c483a3a1f40ac9bf12806ebdb4f501716904776dd58e995be","benches/transfer.rs":"11343c1ac9131585c42236749d32d9e272a33b6acd58831fa3415be4d4f1cf86","src/ackrate.rs":"4bb882e1069a0707dc85338b75327e2910c93ee5f36575767a0d58c4c41c9d4f","src/addr_valid.rs":"03c0b2ff85254179c5d425b12acfdcc6b1ea5735aeb0f604b9b3603451b3ef0a","src/cc/classic_cc.rs":"4528bb4e9059524942ee7ef931de5de90c78ee13f76489185a964ad45c12c0b3","src/cc/cubic.rs":"24c6913cc6346e5361007221c26e8096ece51583431fc3ab9c99e4ce4b0a9f5d","src/cc/mod.rs":"e0837937c9991b37edad15cd870ea9e0623489babfccc340074dd8322e1ef401","src/cc/new_reno.rs":"25d0921005688e0f0666efd0a4931b4f8cd44363587d98e5b6404818c5d05dd4","src/cc/tests/cubic.rs":"109fc8be5efba8959e777288c32ae8f2db581fc08719f318ad676e187f655478","src/cc/tests/mod.rs":"44f8df551e742ae1037cd1cdb85b2c1334c2e5ab3c23ed63d856dbc6b8743afc","src/cc/tests/new_reno.rs":"5414e26b6c928c5f82c5eeb42f04772b05be1ec2c8ee21c2b698ce8cb32829a1","src/cid.rs":"9686a3070c593cfca846d7549863728e31211b304b9fa876220f79bff5e24173","src/connection/dump.rs":"c539caffdf5b4dfaf0173bb20d1974f5242b5432a0a32fc0b8ab56ee682cb1eb","src/connection/idle.rs":"b3bc2ad1290e54278d8703092d135eda973eb12316d1f6dffedaffdf25e2a47e","src/connection/mod.rs":"dcfba9574b707318292f460dc40f54f3cdf8fd883f5f0d604f1d0d466f99f481","src/connection/params.rs":"9731bc5faa584874c48538ed19839c7a310277df39144c580cdf3001153f5a56","src/connection/saved.rs":"97eb19792be3c4d721057021a43ea50a52f89a3cfa583d3d3dcf5d9144b332f5","src/connection/state.rs":"c1820864cc63073e1f44b875be1fcde9835df644e0fa8c2e05652421ad78b7b2","src/connection/test_internal.rs":"f3ebfe97b25c9c716d41406066295e5aff4e96a3051ef4e2b5fb258282bbc14c","src/connection/tests/ackrate.rs":"4a2b835575850ae4a14209d3e51883ecb1e69afb44ef91b5e13a5e6cb7174fab","src/connection/tests/cc.rs":"d0d6ac038572ad3dcd9e6734596eaeedc6d3222d24e31b023aaab3540d195e46","src/connection/tests/close.rs":"20bf9b044ba52517693c2bd10820ff04a8c07de01d59c8c47b4e9478aa730211","src/connection/tests/datagram.rs":"f4c85099b6a8739fb99eadd8711b02066ad80fc8341a2e5e0dae2520378af9fe","src/connection/tests/fuzzing.rs":"79d9ac83fe2d952a3a13140d603569c332d29dbba2e0d2b8ee5f6e42e8f4708a","src/connection/tests/handshake.rs":"eda7308fdd46570ee3b5569ad34e63761ccde89eb5ca854c877e3a53e7de5ec8","src/connection/tests/idle.rs":"f3bcb12cd79cb8eabc969ce3fb0fab4eea26d6383b81a323c0e18ca9c42cfb59","src/connection/tests/keys.rs":"55558c057beb4221245beb262076de3991dca3f2661411db61c09d21194873df","src/connection/tests/migration.rs":"624985d925236be197eee52208dbdebe35c0df5bd9d30982d6f183dfda4cbab5","src/connection/tests/mod.rs":"8b6709a5c89becf2daed407515f894ba3337e87b2d45b21acffa02e67f37eeec","src/connection/tests/priority.rs":"dd3504f52d3fce7a96441624bc1c82c733e6bb556b9b79d24d0f4fb4efaf5a9e","src/connection/tests/recovery.rs":"7f28767f3cca2ff60e3dcfa803e12ef043486a222f54681a8faf2ea2fee564a1","src/connection/tests/resumption.rs":"1a0de0993cd325224fc79a3c094d22636d5b122ab1123d16265d4fafb23574bd","src/connection/tests/stream.rs":"e5590c2b52d33fbe1b4e995edf1c016dda460ecfa2a9f021005e4abe8ea13580","src/connection/tests/vn.rs":"550eb6b4d39d5960aafc70037c25a1a0f5db1232ce0ec6080b2c29a731a9574e","src/connection/tests/zerortt.rs":"67f77721e33d9fa2691c5ea3ef4a90935987541d81f0f42fbcfca31e690b352a","src/crypto.rs":"c5780ab85ca84e830024c31346a416f1f470694372d732ee5e5b7c5df3adc202","src/events.rs":"6e115f309c5c46f30f6223e1347bea477ada457f8bb2189ecccc6d65483318d6","src/fc.rs":"ec9de1028286870c0adf88a92e1355acf13dede8b1e91179230df3263e3827a9","src/frame.rs":"eb35c4add314f0013ad7837157fa9daeb76a2286fc7f8c922993624f54a09569","src/lib.rs":"f8d83b370cab19b3d172d0689f8d76115f5fd26c742e394fca62e253809cedc4","src/pace.rs":"86a674ac4d086148ea297214910458c3705918bd627b996ba8bbb12f2c4bf99e","src/packet/mod.rs":"9fac8f4046ada084dbbcc6601391a2bf8bbc23a09d6fe7df3c135a36840dbee3","src/packet/retry.rs":"1f10bb2c39ae4335e65b8d5d97f2b6df62e04877740af27c7b965a65e7f7ca66","src/path.rs":"3eb7e5e3bc496bfefc729c1e15fba0f9f83572151a850bf13b9c931297789279","src/qlog.rs":"b94aa36d5bac2799d8635cf6b25b9bb9383944d5607ea85aff55715f70af5f7b","src/quic_datagrams.rs":"3d33ecb9e6e80c77b812e8260fc807352300fb2305a29b797259ae34c52b67c5","src/recovery.rs":"1dadc6717dd133007943e762231a50680087392466904c2f2e6fface084e2ba9","src/recv_stream.rs":"f21ae0bb786901bb7d726a94cb3352607b0057128beaa331808137f2f57a330b","src/rtt.rs":"4635dc0c401b78a1fd9d34da6f9bf7f6e7f5be3a57ed9716e0efc8f0f94f1e47","src/send_stream.rs":"f717f64b75e368cf5fa4ca43078aa7c1b5aff48b4f6266713e6fa7dc458328aa","src/sender.rs":"5f760988bdd6fbbd5956877a97abe7c17370dd531f68b751a9e4e4459583f87b","src/server.rs":"048aaac84e15d49fd25850294759107fe1855bbbc0481c16f8bd888d8f2a8f6d","src/stats.rs":"b2a4c03d5b24edeecd00d809019c56f1a22a4e35967309ae6e6053331aafcf30","src/stream_id.rs":"fd07cbb81709a54bdb0659f676ef851cd145c004b817044ede5b21e54fdb60e4","src/streams.rs":"062b1b61edd1a76a86914f2cc1ca007c03edd9136c0c3409d960ddb805805fc6","src/tparams.rs":"10d62ac64865e0606c3c14141f9674631c610b3f042e274e110bdcef5d388491","src/tracking.rs":"f9a9aa01abc79fdd7a2cfb2c3ae342b9ab709e6a2a11076ec5c475fc89c1f598","src/version.rs":"182484ed9ecc2e17cab73cc61914a86a2d206936cab313825ae76fd37eeade77","tests/common/mod.rs":"0aa6674ae4efd2f151a65737ed5eab9e700bd1b3da5b4c165cb24de2b01598ce","tests/conn_vectors.rs":"290550072bd0c37652b79ac119729064dd486452c3a740353a6669bcdb2b82cf","tests/connection.rs":"b3c2ce0c62c4b79f80e42289eadd51933931b0ae44c0adc20ce5141edd454e00","tests/network.rs":"9e30b8610124250262fceef27d09fdecf2d6e9c3a96b1e676ff4189b9e06d5ba","tests/retry.rs":"da5c6a6f9ec1a8f556073b2d2e11fbcd2f58463818b0f08f8d23158016fea0d5","tests/server.rs":"cb83de909d858950bfd75a789fc23c3c44fcdf1d965b63800b2c7b498507987f"},"package":null} \ No newline at end of file diff --git a/third_party/rust/neqo-transport/Cargo.toml b/third_party/rust/neqo-transport/Cargo.toml index 009aa51233b4..a309987434b1 100644 --- a/third_party/rust/neqo-transport/Cargo.toml +++ b/third_party/rust/neqo-transport/Cargo.toml @@ -13,7 +13,7 @@ edition = "2021" rust-version = "1.74.0" name = "neqo-transport" -version = "0.7.3" +version = "0.7.2" authors = ["The Neqo Authors "] homepage = "https://github.com/mozilla/neqo/" license = "MIT OR Apache-2.0" @@ -73,7 +73,7 @@ path = "../test-fixture" [features] bench = [] -disable-encryption = ["neqo-crypto/disable-encryption"] +fuzzing = ["neqo-crypto/fuzzing"] [lints.clippy.pedantic] level = "warn" diff --git a/third_party/rust/neqo-transport/benches/range_tracker.rs b/third_party/rust/neqo-transport/benches/range_tracker.rs index ee611cf4ea6f..c2f78f48748e 100644 --- a/third_party/rust/neqo-transport/benches/range_tracker.rs +++ b/third_party/rust/neqo-transport/benches/range_tracker.rs @@ -11,32 +11,30 @@ const CHUNK: u64 = 1000; const END: u64 = 100_000; fn build_coalesce(len: u64) -> RangeTracker { let mut used = RangeTracker::default(); - let chunk = usize::try_from(CHUNK).expect("should fit"); - used.mark_acked(0, chunk); - used.mark_sent(CHUNK, usize::try_from(END).expect("should fit")); + used.mark_acked(0, CHUNK as usize); + used.mark_sent(CHUNK, END as usize); // leave a gap or it will coalesce here for i in 2..=len { // These do not get immediately coalesced when marking since they're not at the end or start - used.mark_acked(i * CHUNK, chunk); + used.mark_acked(i * CHUNK, CHUNK as usize); } used } fn coalesce(c: &mut Criterion, count: u64) { - let chunk = usize::try_from(CHUNK).expect("should fit"); c.bench_function( &format!("coalesce_acked_from_zero {count}+1 entries"), |b| { b.iter_batched_ref( || build_coalesce(count), |used| { - used.mark_acked(CHUNK, chunk); + used.mark_acked(CHUNK, CHUNK as usize); let tail = (count + 1) * CHUNK; - used.mark_sent(tail, chunk); - used.mark_acked(tail, chunk); + used.mark_sent(tail, CHUNK as usize); + used.mark_acked(tail, CHUNK as usize); }, criterion::BatchSize::SmallInput, - ); + ) }, ); } diff --git a/third_party/rust/neqo-transport/benches/rx_stream_orderer.rs b/third_party/rust/neqo-transport/benches/rx_stream_orderer.rs index d58e11ee8632..0a1e763e9785 100644 --- a/third_party/rust/neqo-transport/benches/rx_stream_orderer.rs +++ b/third_party/rust/neqo-transport/benches/rx_stream_orderer.rs @@ -11,14 +11,14 @@ fn rx_stream_orderer() { let mut rx = RxStreamOrderer::new(); let data: &[u8] = &[0; 1337]; - for i in 0..100_000 { + for i in 0..100000 { rx.inbound_frame(i * 1337, data); } } fn criterion_benchmark(c: &mut Criterion) { c.bench_function("RxStreamOrderer::inbound_frame()", |b| { - b.iter(rx_stream_orderer); + b.iter(rx_stream_orderer) }); } diff --git a/third_party/rust/neqo-transport/benches/transfer.rs b/third_party/rust/neqo-transport/benches/transfer.rs index 32959f6cb5be..444f738f9c5b 100644 --- a/third_party/rust/neqo-transport/benches/transfer.rs +++ b/third_party/rust/neqo-transport/benches/transfer.rs @@ -6,7 +6,7 @@ use std::time::Duration; -use criterion::{criterion_group, criterion_main, BatchSize::SmallInput, Criterion, Throughput}; +use criterion::{criterion_group, criterion_main, BatchSize::SmallInput, Criterion}; use test_fixture::{ boxed, sim::{ @@ -20,11 +20,8 @@ const ZERO: Duration = Duration::from_millis(0); const JITTER: Duration = Duration::from_millis(10); const TRANSFER_AMOUNT: usize = 1 << 22; // 4Mbyte -fn benchmark_transfer(c: &mut Criterion, label: &str, seed: &Option>) { - let mut group = c.benchmark_group("transfer"); - group.throughput(Throughput::Bytes(u64::try_from(TRANSFER_AMOUNT).unwrap())); - group.noise_threshold(0.03); - group.bench_function(label, |b| { +fn benchmark_transfer(c: &mut Criterion, label: &str, seed: Option>) { + c.bench_function(label, |b| { b.iter_batched( || { let nodes = boxed![ @@ -45,16 +42,15 @@ fn benchmark_transfer(c: &mut Criterion, label: &str, seed: &Option CongestionControl for ClassicCongestionControl { let mut is_app_limited = true; let mut new_acked = 0; for pkt in acked_pkts { - qdebug!( + qinfo!( "packet_acked this={:p}, pn={}, ps={}, ignored={}, lost={}, rtt_est={:?}", self, pkt.pn, @@ -198,7 +198,7 @@ impl CongestionControl for ClassicCongestionControl { if is_app_limited { self.cc_algorithm.on_app_limited(); - qdebug!("on_packets_acked this={:p}, limited=1, bytes_in_flight={}, cwnd={}, state={:?}, new_acked={}", self, self.bytes_in_flight, self.congestion_window, self.state, new_acked); + qinfo!("on_packets_acked this={:p}, limited=1, bytes_in_flight={}, cwnd={}, state={:?}, new_acked={}", self, self.bytes_in_flight, self.congestion_window, self.state, new_acked); return; } @@ -208,7 +208,7 @@ impl CongestionControl for ClassicCongestionControl { let increase = min(self.ssthresh - self.congestion_window, self.acked_bytes); self.congestion_window += increase; self.acked_bytes -= increase; - qdebug!([self], "slow start += {}", increase); + qinfo!([self], "slow start += {}", increase); if self.congestion_window == self.ssthresh { // This doesn't look like it is necessary, but it can happen // after persistent congestion. @@ -249,7 +249,7 @@ impl CongestionControl for ClassicCongestionControl { QlogMetric::BytesInFlight(self.bytes_in_flight), ], ); - qdebug!([self], "on_packets_acked this={:p}, limited=0, bytes_in_flight={}, cwnd={}, state={:?}, new_acked={}", self, self.bytes_in_flight, self.congestion_window, self.state, new_acked); + qinfo!([self], "on_packets_acked this={:p}, limited=0, bytes_in_flight={}, cwnd={}, state={:?}, new_acked={}", self, self.bytes_in_flight, self.congestion_window, self.state, new_acked); } /// Update congestion controller state based on lost packets. @@ -265,7 +265,7 @@ impl CongestionControl for ClassicCongestionControl { } for pkt in lost_packets.iter().filter(|pkt| pkt.cc_in_flight()) { - qdebug!( + qinfo!( "packet_lost this={:p}, pn={}, ps={}", self, pkt.pn, @@ -286,7 +286,7 @@ impl CongestionControl for ClassicCongestionControl { pto, lost_packets, ); - qdebug!( + qinfo!( "on_packets_lost this={:p}, bytes_in_flight={}, cwnd={}, state={:?}", self, self.bytes_in_flight, @@ -335,7 +335,7 @@ impl CongestionControl for ClassicCongestionControl { } self.bytes_in_flight += pkt.size; - qdebug!( + qinfo!( "packet_sent this={:p}, pn={}, ps={}", self, pkt.pn, @@ -498,7 +498,7 @@ impl ClassicCongestionControl { self.congestion_window = max(cwnd, CWND_MIN); self.acked_bytes = acked_bytes; self.ssthresh = self.congestion_window; - qdebug!( + qinfo!( [self], "Cong event -> recovery; cwnd {}, ssthresh {}", self.congestion_window, diff --git a/third_party/rust/neqo-transport/src/connection/dump.rs b/third_party/rust/neqo-transport/src/connection/dump.rs index 12d337c57023..8a4f34dbb8ff 100644 --- a/third_party/rust/neqo-transport/src/connection/dump.rs +++ b/third_party/rust/neqo-transport/src/connection/dump.rs @@ -9,7 +9,7 @@ use std::fmt::Write; -use neqo_common::{qdebug, Decoder, IpTos}; +use neqo_common::{qdebug, Decoder}; use crate::{ connection::Connection, @@ -26,7 +26,6 @@ pub fn dump_packet( pt: PacketType, pn: PacketNumber, payload: &[u8], - tos: IpTos, ) { if log::STATIC_MAX_LEVEL == log::LevelFilter::Off || !log::log_enabled!(log::Level::Debug) { return; @@ -39,18 +38,9 @@ pub fn dump_packet( s.push_str(" [broken]..."); break; }; - let x = f.dump(); - if !x.is_empty() { + if let Some(x) = f.dump() { write!(&mut s, "\n {} {}", dir, &x).unwrap(); } } - qdebug!( - [conn], - "pn={} type={:?} {} {:?}{}", - pn, - pt, - path.borrow(), - tos, - s - ); + qdebug!([conn], "pn={} type={:?} {}{}", pn, pt, path.borrow(), s); } diff --git a/third_party/rust/neqo-transport/src/connection/mod.rs b/third_party/rust/neqo-transport/src/connection/mod.rs index 06d6cab9e13d..c81a3727c670 100644 --- a/third_party/rust/neqo-transport/src/connection/mod.rs +++ b/third_party/rust/neqo-transport/src/connection/mod.rs @@ -19,7 +19,7 @@ use std::{ use neqo_common::{ event::Provider as EventProvider, hex, hex_snip_middle, hrtime, qdebug, qerror, qinfo, - qlog::NeqoQlog, qtrace, qwarn, Datagram, Decoder, Encoder, IpTos, Role, + qlog::NeqoQlog, qtrace, qwarn, Datagram, Decoder, Encoder, Role, }; use neqo_crypto::{ agent::CertificateInfo, Agent, AntiReplay, AuthenticationStatus, Cipher, Client, Group, @@ -383,6 +383,7 @@ impl Connection { agent, protocols.iter().map(P::as_ref).map(String::from).collect(), Rc::clone(&tphandler), + conn_params.is_fuzzing(), )?; let stats = StatsCell::default(); @@ -460,7 +461,7 @@ impl Connection { } /// # Errors - /// When the operation fails. + /// When the operation fails. pub fn client_enable_ech(&mut self, ech_config_list: impl AsRef<[u8]>) -> Res<()> { self.crypto.client_enable_ech(ech_config_list) } @@ -777,7 +778,7 @@ impl Connection { }); enc.encode(extra); let records = s.send_ticket(now, enc.as_ref())?; - qdebug!([self], "send session ticket {}", hex(&enc)); + qinfo!([self], "send session ticket {}", hex(&enc)); self.crypto.buffer_records(records)?; } else { unreachable!(); @@ -823,7 +824,7 @@ impl Connection { /// the connection to fail. However, if no packets have been /// exchanged, it's not OK. pub fn authenticated(&mut self, status: AuthenticationStatus, now: Instant) { - qdebug!([self], "Authenticated {:?}", status); + qinfo!([self], "Authenticated {:?}", status); self.crypto.tls.authenticated(status); let res = self.handshake(now, self.version, PacketNumberSpace::Handshake, None); self.absorb_error(now, res); @@ -1153,7 +1154,7 @@ impl Connection { fn discard_keys(&mut self, space: PacketNumberSpace, now: Instant) { if self.crypto.discard(space) { - qdebug!([self], "Drop packet number space {}", space); + qinfo!([self], "Drop packet number space {}", space); let primary = self.paths.primary(); self.loss_recovery.discard(&primary, space, now); self.acks.drop_space(space); @@ -1491,7 +1492,6 @@ impl Connection { payload.packet_type(), payload.pn(), &payload[..], - d.tos(), ); qlog::packet_received(&mut self.qlog, &packet, &payload); @@ -1552,10 +1552,6 @@ impl Connection { packet: &DecryptedPacket, now: Instant, ) -> Res { - (!packet.is_empty()) - .then_some(()) - .ok_or(Error::ProtocolViolation)?; - // TODO(ekr@rtfm.com): Have the server blow away the initial // crypto state if this fails? Otherwise, we will get a panic // on the assert for doesn't exist. @@ -1564,8 +1560,24 @@ impl Connection { let mut ack_eliciting = false; let mut probing = true; let mut d = Decoder::from(&packet[..]); + let mut consecutive_padding = 0; while d.remaining() > 0 { - let f = Frame::decode(&mut d)?; + let mut f = Frame::decode(&mut d)?; + + // Skip padding + while f == Frame::Padding && d.remaining() > 0 { + consecutive_padding += 1; + f = Frame::decode(&mut d)?; + } + if consecutive_padding > 0 { + qdebug!( + [self], + "PADDING frame repeated {} times", + consecutive_padding + ); + consecutive_padding = 0; + } + ack_eliciting |= f.ack_eliciting(); probing &= f.path_probing(); let t = f.get_type(); @@ -2259,7 +2271,6 @@ impl Connection { pt, pn, &builder.as_ref()[payload_start..], - IpTos::default(), // TODO: set from path ); qlog::packet_sent( &mut self.qlog, @@ -2312,7 +2323,7 @@ impl Connection { } if encoder.is_empty() { - qdebug!("TX blocked, profile={:?} ", profile); + qinfo!("TX blocked, profile={:?} ", profile); Ok(SendOption::No(profile.paced())) } else { // Perform additional padding for Initial packets as necessary. @@ -2356,7 +2367,7 @@ impl Connection { } fn client_start(&mut self, now: Instant) -> Res<()> { - qdebug!([self], "client_start"); + qinfo!([self], "client_start"); debug_assert_eq!(self.role, Role::Client); qlog::client_connection_started(&mut self.qlog, &self.paths.primary()); qlog::client_version_information_initiated(&mut self.qlog, self.conn_params.get_versions()); @@ -2588,7 +2599,7 @@ impl Connection { fn confirm_version(&mut self, v: Version) { if self.version != v { - qdebug!([self], "Compatible upgrade {:?} ==> {:?}", self.version, v); + qinfo!([self], "Compatible upgrade {:?} ==> {:?}", self.version, v); } self.crypto.confirm_version(v); self.version = v; @@ -2683,8 +2694,9 @@ impl Connection { .input_frame(&frame, &mut self.stats.borrow_mut().frame_rx); } match frame { - Frame::Padding(length) => { - self.stats.borrow_mut().frame_rx.padding += usize::from(length); + Frame::Padding => { + // Note: This counts contiguous padding as a single frame. + self.stats.borrow_mut().frame_rx.padding += 1; } Frame::Ping => { // If we get a PING and there are outstanding CRYPTO frames, @@ -2887,7 +2899,7 @@ impl Connection { R: IntoIterator> + Debug, R::IntoIter: ExactSizeIterator, { - qdebug!([self], "Rx ACK space={}, ranges={:?}", space, ack_ranges); + qinfo!([self], "Rx ACK space={}, ranges={:?}", space, ack_ranges); let (acked_packets, lost_packets) = self.loss_recovery.on_ack_received( &self.paths.primary(), @@ -2941,7 +2953,7 @@ impl Connection { } fn set_connected(&mut self, now: Instant) -> Res<()> { - qdebug!([self], "TLS connection complete"); + qinfo!([self], "TLS connection complete"); if self.crypto.tls.info().map(SecretAgentInfo::alpn).is_none() { qwarn!([self], "No ALPN. Closing connection."); // 120 = no_application_protocol @@ -2984,7 +2996,7 @@ impl Connection { fn set_state(&mut self, state: State) { if state > self.state { - qdebug!([self], "State change from {:?} -> {:?}", self.state, state); + qinfo!([self], "State change from {:?} -> {:?}", self.state, state); self.state = state.clone(); if self.state.closed() { self.streams.clear_streams(); diff --git a/third_party/rust/neqo-transport/src/connection/params.rs b/third_party/rust/neqo-transport/src/connection/params.rs index d8aa617024a1..72d1efa3eeb2 100644 --- a/third_party/rust/neqo-transport/src/connection/params.rs +++ b/third_party/rust/neqo-transport/src/connection/params.rs @@ -77,6 +77,7 @@ pub struct ConnectionParameters { outgoing_datagram_queue: usize, incoming_datagram_queue: usize, fast_pto: u8, + fuzzing: bool, grease: bool, pacing: bool, } @@ -99,6 +100,7 @@ impl Default for ConnectionParameters { outgoing_datagram_queue: MAX_QUEUED_DATAGRAMS_DEFAULT, incoming_datagram_queue: MAX_QUEUED_DATAGRAMS_DEFAULT, fast_pto: FAST_PTO_SCALE, + fuzzing: false, grease: true, pacing: true, } @@ -323,6 +325,17 @@ impl ConnectionParameters { } #[must_use] + pub fn is_fuzzing(&self) -> bool { + self.fuzzing + } + + #[must_use] + pub fn fuzzing(mut self, enable: bool) -> Self { + self.fuzzing = enable; + self + } + + #[must_use] pub fn is_greasing(&self) -> bool { self.grease } diff --git a/third_party/rust/neqo-transport/src/connection/state.rs b/third_party/rust/neqo-transport/src/connection/state.rs index cc2f6e30d20d..9789151d3f1c 100644 --- a/third_party/rust/neqo-transport/src/connection/state.rs +++ b/third_party/rust/neqo-transport/src/connection/state.rs @@ -209,10 +209,7 @@ pub enum StateSignaling { impl StateSignaling { pub fn handshake_done(&mut self) { if !matches!(self, Self::Idle) { - debug_assert!( - false, - "StateSignaling must be in Idle state but is in {self:?} state.", - ); + debug_assert!(false, "StateSignaling must be in Idle state."); return; } *self = Self::HandshakeDone; diff --git a/third_party/rust/neqo-transport/src/connection/tests/null.rs b/third_party/rust/neqo-transport/src/connection/tests/fuzzing.rs similarity index 84% rename from third_party/rust/neqo-transport/src/connection/tests/null.rs rename to third_party/rust/neqo-transport/src/connection/tests/fuzzing.rs index e4d60445c6f0..9924c06fa4ca 100644 --- a/third_party/rust/neqo-transport/src/connection/tests/null.rs +++ b/third_party/rust/neqo-transport/src/connection/tests/fuzzing.rs @@ -4,9 +4,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![cfg(feature = "disable-encryption")] +#![cfg(feature = "fuzzing")] -use neqo_crypto::aead_null::AEAD_NULL_TAG; +use neqo_crypto::FIXED_TAG_FUZZING; use test_fixture::now; use super::{connect_force_idle, default_client, default_server}; @@ -24,7 +24,7 @@ fn no_encryption() { client.stream_send(stream_id, DATA_CLIENT).unwrap(); let client_pkt = client.process_output(now()).dgram().unwrap(); - assert!(client_pkt[..client_pkt.len() - AEAD_NULL_TAG.len()].ends_with(DATA_CLIENT)); + assert!(client_pkt[..client_pkt.len() - FIXED_TAG_FUZZING.len()].ends_with(DATA_CLIENT)); server.process_input(&client_pkt, now()); let mut buf = vec![0; 100]; @@ -33,7 +33,7 @@ fn no_encryption() { assert_eq!(&buf[..len], DATA_CLIENT); server.stream_send(stream_id, DATA_SERVER).unwrap(); let server_pkt = server.process_output(now()).dgram().unwrap(); - assert!(server_pkt[..server_pkt.len() - AEAD_NULL_TAG.len()].ends_with(DATA_SERVER)); + assert!(server_pkt[..server_pkt.len() - FIXED_TAG_FUZZING.len()].ends_with(DATA_SERVER)); client.process_input(&server_pkt, now()); let (len, _) = client.stream_recv(stream_id, &mut buf).unwrap(); diff --git a/third_party/rust/neqo-transport/src/connection/tests/handshake.rs b/third_party/rust/neqo-transport/src/connection/tests/handshake.rs index f2103523ec70..af0352ce9071 100644 --- a/third_party/rust/neqo-transport/src/connection/tests/handshake.rs +++ b/third_party/rust/neqo-transport/src/connection/tests/handshake.rs @@ -16,10 +16,9 @@ use neqo_common::{event::Provider, qdebug, Datagram}; use neqo_crypto::{ constants::TLS_CHACHA20_POLY1305_SHA256, generate_ech_keys, AuthenticationStatus, }; -#[cfg(not(feature = "disable-encryption"))] -use test_fixture::datagram; use test_fixture::{ - assertions, assertions::assert_coalesced_0rtt, fixture_init, now, split_datagram, DEFAULT_ADDR, + assertions, assertions::assert_coalesced_0rtt, datagram, fixture_init, now, split_datagram, + DEFAULT_ADDR, }; use super::{ @@ -459,7 +458,7 @@ fn coalesce_05rtt() { assert_eq!(client.stats().dropped_rx, 0); // No Initial padding. assert_eq!(client.stats().packets_rx, 4); assert_eq!(client.stats().saved_datagrams, 1); - assert!(client.stats().frame_rx.padding > 0); // Padding uses frames. + assert_eq!(client.stats().frame_rx.padding, 1); // Padding uses frames. // Allow the handshake to complete. now += RTT / 2; @@ -606,7 +605,7 @@ fn reorder_1rtt() { } } -#[cfg(not(feature = "disable-encryption"))] +#[cfg(not(feature = "fuzzing"))] #[test] fn corrupted_initial() { let mut client = default_client(); @@ -809,7 +808,7 @@ fn anti_amplification() { assert_eq!(*server.state(), State::Confirmed); } -#[cfg(not(feature = "disable-encryption"))] +#[cfg(not(feature = "fuzzing"))] #[test] fn garbage_initial() { let mut client = default_client(); diff --git a/third_party/rust/neqo-transport/src/connection/tests/mod.rs b/third_party/rust/neqo-transport/src/connection/tests/mod.rs index c8c87a0df090..b6ce08f8d17d 100644 --- a/third_party/rust/neqo-transport/src/connection/tests/mod.rs +++ b/third_party/rust/neqo-transport/src/connection/tests/mod.rs @@ -37,11 +37,11 @@ mod ackrate; mod cc; mod close; mod datagram; +mod fuzzing; mod handshake; mod idle; mod keys; mod migration; -mod null; mod priority; mod recovery; mod resumption; @@ -170,17 +170,12 @@ impl crate::connection::test_internal::FrameWriter for PingWriter { } } -trait DatagramModifier: FnMut(Datagram) -> Option {} - -impl DatagramModifier for T where T: FnMut(Datagram) -> Option {} - /// Drive the handshake between the client and server. -fn handshake_with_modifier( +fn handshake( client: &mut Connection, server: &mut Connection, now: Instant, rtt: Duration, - mut modifier: impl DatagramModifier, ) -> Instant { let mut a = client; let mut b = server; @@ -217,11 +212,7 @@ fn handshake_with_modifier( did_ping[a.role()] = true; } assert!(had_input || output.is_some()); - if let Some(d) = output { - input = modifier(d); - } else { - input = output; - } + input = output; qtrace!("handshake: t += {:?}", rtt / 2); now += rtt / 2; mem::swap(&mut a, &mut b); @@ -232,15 +223,6 @@ fn handshake_with_modifier( now } -fn handshake( - client: &mut Connection, - server: &mut Connection, - now: Instant, - rtt: Duration, -) -> Instant { - handshake_with_modifier(client, server, now, rtt, Some) -} - fn connect_fail( client: &mut Connection, server: &mut Connection, @@ -252,12 +234,11 @@ fn connect_fail( assert_error(server, &ConnectionError::Transport(server_error)); } -fn connect_with_rtt_and_modifier( +fn connect_with_rtt( client: &mut Connection, server: &mut Connection, now: Instant, rtt: Duration, - modifier: impl DatagramModifier, ) -> Instant { fn check_rtt(stats: &Stats, rtt: Duration) { assert_eq!(stats.rtt, rtt); @@ -265,7 +246,7 @@ fn connect_with_rtt_and_modifier( let n = stats.frame_rx.ack + usize::from(stats.rtt_init_guess); assert_eq!(stats.rttvar, rttvar_after_n_updates(n, rtt)); } - let now = handshake_with_modifier(client, server, now, rtt, modifier); + let now = handshake(client, server, now, rtt); assert_eq!(*client.state(), State::Confirmed); assert_eq!(*server.state(), State::Confirmed); @@ -274,15 +255,6 @@ fn connect_with_rtt_and_modifier( now } -fn connect_with_rtt( - client: &mut Connection, - server: &mut Connection, - now: Instant, - rtt: Duration, -) -> Instant { - connect_with_rtt_and_modifier(client, server, now, rtt, Some) -} - fn connect(client: &mut Connection, server: &mut Connection) { connect_with_rtt(client, server, now(), Duration::new(0, 0)); } @@ -329,13 +301,8 @@ fn assert_idle(client: &mut Connection, server: &mut Connection, rtt: Duration, } /// Connect with an RTT and then force both peers to be idle. -fn connect_rtt_idle_with_modifier( - client: &mut Connection, - server: &mut Connection, - rtt: Duration, - modifier: impl DatagramModifier, -) -> Instant { - let now = connect_with_rtt_and_modifier(client, server, now(), rtt, modifier); +fn connect_rtt_idle(client: &mut Connection, server: &mut Connection, rtt: Duration) -> Instant { + let now = connect_with_rtt(client, server, now(), rtt); assert_idle(client, server, rtt, now); // Drain events from both as well. _ = client.events().count(); @@ -344,20 +311,8 @@ fn connect_rtt_idle_with_modifier( now } -fn connect_rtt_idle(client: &mut Connection, server: &mut Connection, rtt: Duration) -> Instant { - connect_rtt_idle_with_modifier(client, server, rtt, Some) -} - -fn connect_force_idle_with_modifier( - client: &mut Connection, - server: &mut Connection, - modifier: impl DatagramModifier, -) { - connect_rtt_idle_with_modifier(client, server, Duration::new(0, 0), modifier); -} - fn connect_force_idle(client: &mut Connection, server: &mut Connection) { - connect_force_idle_with_modifier(client, server, Some); + connect_rtt_idle(client, server, Duration::new(0, 0)); } fn fill_stream(c: &mut Connection, stream: StreamId) { @@ -569,14 +524,12 @@ fn assert_full_cwnd(packets: &[Datagram], cwnd: usize) { } /// Send something on a stream from `sender` to `receiver`, maybe allowing for pacing. -/// Takes a modifier function that can be used to modify the datagram before it is sent. /// Return the resulting datagram and the new time. #[must_use] -fn send_something_paced_with_modifier( +fn send_something_paced( sender: &mut Connection, mut now: Instant, allow_pacing: bool, - mut modifier: impl DatagramModifier, ) -> (Datagram, Instant) { let stream_id = sender.stream_create(StreamType::UniDi).unwrap(); assert!(sender.stream_send(stream_id, DEFAULT_STREAM_DATA).is_ok()); @@ -591,32 +544,16 @@ fn send_something_paced_with_modifier( .dgram() .expect("send_something: should have something to send") } - Output::Datagram(d) => modifier(d).unwrap(), + Output::Datagram(d) => d, Output::None => panic!("send_something: got Output::None"), }; (dgram, now) } -fn send_something_paced( - sender: &mut Connection, - now: Instant, - allow_pacing: bool, -) -> (Datagram, Instant) { - send_something_paced_with_modifier(sender, now, allow_pacing, Some) -} - -fn send_something_with_modifier( - sender: &mut Connection, - now: Instant, - modifier: impl DatagramModifier, -) -> Datagram { - send_something_paced_with_modifier(sender, now, false, modifier).0 -} - /// Send something on a stream from `sender` to `receiver`. /// Return the resulting datagram. fn send_something(sender: &mut Connection, now: Instant) -> Datagram { - send_something_with_modifier(sender, now, Some) + send_something_paced(sender, now, false).0 } /// Send something on a stream from `sender` to `receiver`. diff --git a/third_party/rust/neqo-transport/src/connection/tests/stream.rs b/third_party/rust/neqo-transport/src/connection/tests/stream.rs index 66d3bf32f35f..f469866d5065 100644 --- a/third_party/rust/neqo-transport/src/connection/tests/stream.rs +++ b/third_party/rust/neqo-transport/src/connection/tests/stream.rs @@ -116,6 +116,12 @@ fn transfer() { assert!(fin3); } +#[derive(PartialEq, Eq, PartialOrd, Ord)] +struct IdEntry { + sendorder: StreamOrder, + stream_id: StreamId, +} + // tests stream sendorder priorization fn sendorder_test(order_of_sendorder: &[Option]) { let mut client = default_client(); diff --git a/third_party/rust/neqo-transport/src/crypto.rs b/third_party/rust/neqo-transport/src/crypto.rs index 54bfe622cf49..9840eaa1e166 100644 --- a/third_party/rust/neqo-transport/src/crypto.rs +++ b/third_party/rust/neqo-transport/src/crypto.rs @@ -69,6 +69,7 @@ impl Crypto { mut agent: Agent, protocols: Vec, tphandler: TpHandler, + fuzzing: bool, ) -> Res { agent.set_version_range(TLS_VERSION_1_3, TLS_VERSION_1_3)?; agent.set_ciphers(&[ @@ -101,6 +102,7 @@ impl Crypto { tls: agent, streams: CryptoStreams::default(), states: CryptoStates { + fuzzing, ..CryptoStates::default() }, }) @@ -315,7 +317,7 @@ impl Crypto { } pub fn acked(&mut self, token: &CryptoRecoveryToken) { - qdebug!( + qinfo!( "Acked crypto frame space={} offset={} length={}", token.space, token.offset, @@ -365,7 +367,7 @@ impl Crypto { }); enc.encode_vvec(new_token.unwrap_or(&[])); enc.encode(t.as_ref()); - qdebug!("resumption token {}", hex_snip_middle(enc.as_ref())); + qinfo!("resumption token {}", hex_snip_middle(enc.as_ref())); Some(ResumptionToken::new(enc.into(), t.expiration_time())) } else { None @@ -418,6 +420,7 @@ pub struct CryptoDxState { /// The total number of operations that are remaining before the keys /// become exhausted and can't be used any more. invocations: PacketNumber, + fuzzing: bool, } impl CryptoDxState { @@ -428,8 +431,9 @@ impl CryptoDxState { epoch: Epoch, secret: &SymKey, cipher: Cipher, + fuzzing: bool, ) -> Self { - qdebug!( + qinfo!( "Making {:?} {} CryptoDxState, v={:?} cipher={}", direction, epoch, @@ -441,11 +445,19 @@ impl CryptoDxState { version, direction, epoch: usize::from(epoch), - aead: Aead::new(TLS_VERSION_1_3, cipher, secret, version.label_prefix()).unwrap(), + aead: Aead::new( + fuzzing, + TLS_VERSION_1_3, + cipher, + secret, + version.label_prefix(), + ) + .unwrap(), hpkey: HpKey::extract(TLS_VERSION_1_3, cipher, secret, &hplabel).unwrap(), used_pn: 0..0, min_pn: 0, invocations: Self::limit(direction, cipher), + fuzzing, } } @@ -454,6 +466,7 @@ impl CryptoDxState { direction: CryptoDxDirection, label: &str, dcid: &[u8], + fuzzing: bool, ) -> Self { qtrace!("new_initial {:?} {}", version, ConnectionIdRef::from(dcid)); let salt = version.initial_salt(); @@ -469,7 +482,14 @@ impl CryptoDxState { let secret = hkdf::expand_label(TLS_VERSION_1_3, cipher, &initial_secret, &[], label).unwrap(); - Self::new(version, direction, TLS_EPOCH_INITIAL, &secret, cipher) + Self::new( + version, + direction, + TLS_EPOCH_INITIAL, + &secret, + cipher, + fuzzing, + ) } /// Determine the confidentiality and integrity limits for the cipher. @@ -529,6 +549,7 @@ impl CryptoDxState { direction: self.direction, epoch: self.epoch + 1, aead: Aead::new( + self.fuzzing, TLS_VERSION_1_3, cipher, next_secret, @@ -539,6 +560,7 @@ impl CryptoDxState { used_pn: pn..pn, min_pn: pn, invocations, + fuzzing: self.fuzzing, } } @@ -674,7 +696,7 @@ impl CryptoDxState { Ok(res.to_vec()) } - #[cfg(all(test, not(feature = "disable-encryption")))] + #[cfg(all(test, not(feature = "fuzzing")))] pub(crate) fn test_default() -> Self { // This matches the value in packet.rs const CLIENT_CID: &[u8] = &[0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08]; @@ -683,6 +705,7 @@ impl CryptoDxState { CryptoDxDirection::Write, "server in", CLIENT_CID, + false, ) } @@ -736,6 +759,7 @@ pub(crate) struct CryptoDxAppData { cipher: Cipher, // Not the secret used to create `self.dx`, but the one needed for the next iteration. next_secret: SymKey, + fuzzing: bool, } impl CryptoDxAppData { @@ -744,11 +768,20 @@ impl CryptoDxAppData { dir: CryptoDxDirection, secret: &SymKey, cipher: Cipher, + fuzzing: bool, ) -> Res { Ok(Self { - dx: CryptoDxState::new(version, dir, TLS_EPOCH_APPLICATION_DATA, secret, cipher), + dx: CryptoDxState::new( + version, + dir, + TLS_EPOCH_APPLICATION_DATA, + secret, + cipher, + fuzzing, + ), cipher, next_secret: Self::update_secret(cipher, secret)?, + fuzzing, }) } @@ -767,6 +800,7 @@ impl CryptoDxAppData { dx: self.dx.next(&self.next_secret, self.cipher), cipher: self.cipher, next_secret, + fuzzing: self.fuzzing, }) } @@ -800,6 +834,7 @@ pub struct CryptoStates { // If this is set, then we have noticed a genuine update. // Once this time passes, we should switch in new keys. read_update_time: Option, + fuzzing: bool, } impl CryptoStates { @@ -945,7 +980,7 @@ impl CryptoStates { }; for v in versions { - qdebug!( + qinfo!( [self], "Creating initial cipher state v={:?}, role={:?} dcid={}", v, @@ -954,8 +989,20 @@ impl CryptoStates { ); let mut initial = CryptoState { - tx: CryptoDxState::new_initial(*v, CryptoDxDirection::Write, write, dcid), - rx: CryptoDxState::new_initial(*v, CryptoDxDirection::Read, read, dcid), + tx: CryptoDxState::new_initial( + *v, + CryptoDxDirection::Write, + write, + dcid, + self.fuzzing, + ), + rx: CryptoDxState::new_initial( + *v, + CryptoDxDirection::Read, + read, + dcid, + self.fuzzing, + ), }; if let Some(prev) = self.initials.get(v) { qinfo!( @@ -1009,6 +1056,7 @@ impl CryptoStates { TLS_EPOCH_ZERO_RTT, secret, cipher, + self.fuzzing, )); } @@ -1049,6 +1097,7 @@ impl CryptoStates { TLS_EPOCH_HANDSHAKE, write_secret, cipher, + self.fuzzing, ), rx: CryptoDxState::new( version, @@ -1056,6 +1105,7 @@ impl CryptoStates { TLS_EPOCH_HANDSHAKE, read_secret, cipher, + self.fuzzing, ), }); } @@ -1063,7 +1113,13 @@ impl CryptoStates { pub fn set_application_write_key(&mut self, version: Version, secret: &SymKey) -> Res<()> { debug_assert!(self.app_write.is_none()); debug_assert_ne!(self.cipher, 0); - let mut app = CryptoDxAppData::new(version, CryptoDxDirection::Write, secret, self.cipher)?; + let mut app = CryptoDxAppData::new( + version, + CryptoDxDirection::Write, + secret, + self.cipher, + self.fuzzing, + )?; if let Some(z) = &self.zero_rtt { if z.direction == CryptoDxDirection::Write { app.dx.continuation(z)?; @@ -1082,7 +1138,13 @@ impl CryptoStates { ) -> Res<()> { debug_assert!(self.app_write.is_some(), "should have write keys installed"); debug_assert!(self.app_read.is_none()); - let mut app = CryptoDxAppData::new(version, CryptoDxDirection::Read, secret, self.cipher)?; + let mut app = CryptoDxAppData::new( + version, + CryptoDxDirection::Read, + secret, + self.cipher, + self.fuzzing, + )?; if let Some(z) = &self.zero_rtt { if z.direction == CryptoDxDirection::Read { app.dx.continuation(z)?; @@ -1224,7 +1286,7 @@ impl CryptoStates { } /// Make some state for removing protection in tests. - #[cfg(not(feature = "disable-encryption"))] + #[cfg(not(feature = "fuzzing"))] #[cfg(test)] pub(crate) fn test_default() -> Self { let read = |epoch| { @@ -1237,6 +1299,7 @@ impl CryptoStates { dx: read(epoch), cipher: TLS_AES_128_GCM_SHA256, next_secret: hkdf::import_key(TLS_VERSION_1_3, &[0xaa; 32]).unwrap(), + fuzzing: false, }; let mut initials = HashMap::new(); initials.insert( @@ -1256,10 +1319,11 @@ impl CryptoStates { app_read: Some(app_read(3)), app_read_next: Some(app_read(4)), read_update_time: None, + fuzzing: false, } } - #[cfg(all(not(feature = "disable-encryption"), test))] + #[cfg(all(not(feature = "fuzzing"), test))] pub(crate) fn test_chacha() -> Self { const SECRET: &[u8] = &[ 0x9a, 0xc3, 0x12, 0xa7, 0xf8, 0x77, 0x46, 0x8e, 0xbe, 0x69, 0x42, 0x27, 0x48, 0xad, @@ -1273,6 +1337,7 @@ impl CryptoStates { direction: CryptoDxDirection::Read, epoch, aead: Aead::new( + false, TLS_VERSION_1_3, TLS_CHACHA20_POLY1305_SHA256, &secret, @@ -1289,9 +1354,11 @@ impl CryptoStates { used_pn: 0..645_971_972, min_pn: 0, invocations: 10, + fuzzing: false, }, cipher: TLS_CHACHA20_POLY1305_SHA256, next_secret: secret.clone(), + fuzzing: false, }; Self { initials: HashMap::new(), @@ -1302,6 +1369,7 @@ impl CryptoStates { app_read: Some(app_read(3)), app_read_next: Some(app_read(4)), read_update_time: None, + fuzzing: false, } } } diff --git a/third_party/rust/neqo-transport/src/frame.rs b/third_party/rust/neqo-transport/src/frame.rs index d84eb61ce8cf..b3bb024a2ca3 100644 --- a/third_party/rust/neqo-transport/src/frame.rs +++ b/third_party/rust/neqo-transport/src/frame.rs @@ -20,7 +20,7 @@ use crate::{ #[allow(clippy::module_name_repetitions)] pub type FrameType = u64; -pub const FRAME_TYPE_PADDING: FrameType = 0x0; +const FRAME_TYPE_PADDING: FrameType = 0x0; pub const FRAME_TYPE_PING: FrameType = 0x1; pub const FRAME_TYPE_ACK: FrameType = 0x2; const FRAME_TYPE_ACK_ECN: FrameType = 0x3; @@ -95,12 +95,6 @@ impl From for CloseError { } } -impl From for Error { - fn from(_err: std::array::TryFromSliceError) -> Self { - Self::FrameEncodingError - } -} - #[derive(PartialEq, Eq, Debug, Default, Clone)] pub struct AckRange { pub(crate) gap: u64, @@ -109,7 +103,7 @@ pub struct AckRange { #[derive(PartialEq, Eq, Debug, Clone)] pub enum Frame<'a> { - Padding(u16), + Padding, Ping, Ack { largest_acknowledged: u64, @@ -219,10 +213,9 @@ impl<'a> Frame<'a> { } } - #[must_use] pub fn get_type(&self) -> FrameType { match self { - Self::Padding { .. } => FRAME_TYPE_PADDING, + Self::Padding => FRAME_TYPE_PADDING, Self::Ping => FRAME_TYPE_PING, Self::Ack { .. } => FRAME_TYPE_ACK, // We don't do ACK ECN. Self::ResetStream { .. } => FRAME_TYPE_RESET_STREAM, @@ -261,7 +254,6 @@ impl<'a> Frame<'a> { } } - #[must_use] pub fn is_stream(&self) -> bool { matches!( self, @@ -277,7 +269,6 @@ impl<'a> Frame<'a> { ) } - #[must_use] pub fn stream_type(fin: bool, nonzero_offset: bool, fill: bool) -> u64 { let mut t = FRAME_TYPE_STREAM; if fin { @@ -294,21 +285,19 @@ impl<'a> Frame<'a> { /// If the frame causes a recipient to generate an ACK within its /// advertised maximum acknowledgement delay. - #[must_use] pub fn ack_eliciting(&self) -> bool { !matches!( self, - Self::Ack { .. } | Self::Padding { .. } | Self::ConnectionClose { .. } + Self::Ack { .. } | Self::Padding | Self::ConnectionClose { .. } ) } /// If the frame can be sent in a path probe /// without initiating migration to that path. - #[must_use] pub fn path_probing(&self) -> bool { matches!( self, - Self::Padding { .. } + Self::Padding | Self::NewConnectionId { .. } | Self::PathChallenge { .. } | Self::PathResponse { .. } @@ -318,10 +307,6 @@ impl<'a> Frame<'a> { /// Converts `AckRanges` as encoded in a ACK frame (see -transport /// 19.3.1) into ranges of acked packets (end, start), inclusive of /// start and end values. - /// - /// # Errors - /// - /// Returns an error if the ranges are invalid. pub fn decode_ack_frame( largest_acked: u64, first_ack_range: u64, @@ -362,36 +347,36 @@ impl<'a> Frame<'a> { Ok(acked_ranges) } - #[must_use] - pub fn dump(&self) -> String { + pub fn dump(&self) -> Option { match self { - Self::Crypto { offset, data } => { - format!("Crypto {{ offset: {}, len: {} }}", offset, data.len()) - } + Self::Crypto { offset, data } => Some(format!( + "Crypto {{ offset: {}, len: {} }}", + offset, + data.len() + )), Self::Stream { stream_id, offset, fill, data, fin, - } => format!( + } => Some(format!( "Stream {{ stream_id: {}, offset: {}, len: {}{}, fin: {} }}", stream_id.as_u64(), offset, if *fill { ">>" } else { "" }, data.len(), fin, - ), - Self::Padding(length) => format!("Padding {{ len: {length} }}"), - Self::Datagram { data, .. } => format!("Datagram {{ len: {} }}", data.len()), - _ => format!("{self:?}"), + )), + Self::Padding => None, + Self::Datagram { data, .. } => Some(format!("Datagram {{ len: {} }}", data.len())), + _ => Some(format!("{self:?}")), } } - #[must_use] pub fn is_allowed(&self, pt: PacketType) -> bool { match self { - Self::Padding { .. } | Self::Ping => true, + Self::Padding | Self::Ping => true, Self::Crypto { .. } | Self::Ack { .. } | Self::ConnectionClose { @@ -403,9 +388,6 @@ impl<'a> Frame<'a> { } } - /// # Errors - /// - /// Returns an error if the frame cannot be decoded. #[allow(clippy::too_many_lines)] // Yeah, but it's a nice match statement. pub fn decode(dec: &mut Decoder<'a>) -> Res { /// Maximum ACK Range Count in ACK Frame @@ -427,23 +409,13 @@ impl<'a> Frame<'a> { } // TODO(ekr@rtfm.com): check for minimal encoding - let t = dv(dec)?; + let t = d(dec.decode_varint())?; match t { - FRAME_TYPE_PADDING => { - let mut length: u16 = 1; - while let Some(b) = dec.peek_byte() { - if u64::from(b) != FRAME_TYPE_PADDING { - break; - } - length += 1; - dec.skip(1); - } - Ok(Self::Padding(length)) - } + FRAME_TYPE_PADDING => Ok(Self::Padding), FRAME_TYPE_PING => Ok(Self::Ping), FRAME_TYPE_RESET_STREAM => Ok(Self::ResetStream { stream_id: StreamId::from(dv(dec)?), - application_error_code: dv(dec)?, + application_error_code: d(dec.decode_varint())?, final_size: match dec.decode_varint() { Some(v) => v, _ => return Err(Error::NoMoreData), @@ -485,12 +457,12 @@ impl<'a> Frame<'a> { } FRAME_TYPE_STOP_SENDING => Ok(Self::StopSending { stream_id: StreamId::from(dv(dec)?), - application_error_code: dv(dec)?, + application_error_code: d(dec.decode_varint())?, }), FRAME_TYPE_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()).unwrap() > ((1 << 62) - 1) { return Err(Error::FrameEncodingError); } Ok(Self::Crypto { offset, data }) @@ -517,7 +489,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()).unwrap() > ((1 << 62) - 1) { return Err(Error::FrameEncodingError); } Ok(Self::Stream { @@ -566,7 +538,7 @@ impl<'a> Frame<'a> { return Err(Error::DecodingFrame); } let srt = d(dec.decode(16))?; - let stateless_reset_token = <&[_; 16]>::try_from(srt)?; + let stateless_reset_token = <&[_; 16]>::try_from(srt).unwrap(); Ok(Self::NewConnectionId { sequence_number, @@ -591,7 +563,7 @@ impl<'a> Frame<'a> { Ok(Self::PathResponse { data: datav }) } FRAME_TYPE_CONNECTION_CLOSE_TRANSPORT | FRAME_TYPE_CONNECTION_CLOSE_APPLICATION => { - let error_code = CloseError::from_type_bit(t, dv(dec)?); + let error_code = CloseError::from_type_bit(t, d(dec.decode_varint())?); let frame_type = if t == FRAME_TYPE_CONNECTION_CLOSE_TRANSPORT { dv(dec)? } else { @@ -659,10 +631,8 @@ mod tests { #[test] fn padding() { - let f = Frame::Padding(1); + let f = Frame::Padding; just_dec(&f, "00"); - let f = Frame::Padding(2); - just_dec(&f, "0000"); } #[test] @@ -918,8 +888,8 @@ mod tests { #[test] fn test_compare() { - let f1 = Frame::Padding(1); - let f2 = Frame::Padding(1); + let f1 = Frame::Padding; + let f2 = Frame::Padding; let f3 = Frame::Crypto { offset: 0, data: &[1, 2, 3], diff --git a/third_party/rust/neqo-transport/src/lib.rs b/third_party/rust/neqo-transport/src/lib.rs index 8fabbeb9a3e0..be482c466fec 100644 --- a/third_party/rust/neqo-transport/src/lib.rs +++ b/third_party/rust/neqo-transport/src/lib.rs @@ -6,7 +6,7 @@ #![allow(clippy::module_name_repetitions)] // This lint doesn't work here. -use neqo_common::qwarn; +use neqo_common::qinfo; use neqo_crypto::Error as CryptoError; mod ackrate; @@ -165,7 +165,7 @@ impl Error { impl From for Error { fn from(err: CryptoError) -> Self { - qwarn!("Crypto operation failed {:?}", err); + qinfo!("Crypto operation failed {:?}", err); match err { CryptoError::EchRetry(config) => Self::EchRetry(config), _ => Self::CryptoError(err), diff --git a/third_party/rust/neqo-transport/src/packet/mod.rs b/third_party/rust/neqo-transport/src/packet/mod.rs index d435ac0dd86d..8458f69779dd 100644 --- a/third_party/rust/neqo-transport/src/packet/mod.rs +++ b/third_party/rust/neqo-transport/src/packet/mod.rs @@ -18,7 +18,6 @@ use neqo_crypto::random; use crate::{ cid::{ConnectionId, ConnectionIdDecoder, ConnectionIdRef, MAX_CONNECTION_ID_LEN}, crypto::{CryptoDxState, CryptoSpace, CryptoStates}, - frame::FRAME_TYPE_PADDING, version::{Version, WireVersion}, Error, Res, }; @@ -256,14 +255,9 @@ impl PacketBuilder { /// Maybe pad with "PADDING" frames. /// Only does so if padding was needed and this is a short packet. /// Returns true if padding was added. - /// - /// # Panics - /// - /// Cannot happen. pub fn pad(&mut self) -> bool { if self.padding && !self.is_long() { - self.encoder - .pad_to(self.limit, FRAME_TYPE_PADDING.try_into().unwrap()); + self.encoder.pad_to(self.limit, 0); true } else { false @@ -294,10 +288,6 @@ impl PacketBuilder { /// The length is filled in after calling `build`. /// Does nothing if there isn't 4 bytes available other than render this builder /// unusable; if `remaining()` returns 0 at any point, call `abort()`. - /// - /// # Panics - /// - /// This will panic if the packet number length is too large. pub fn pn(&mut self, pn: PacketNumber, pn_len: usize) { if self.remaining() < 4 { self.limit = 0; @@ -362,10 +352,6 @@ impl PacketBuilder { } /// Build the packet and return the encoder. - /// - /// # Errors - /// - /// This will return an error if the packet is too large. pub fn build(mut self, crypto: &mut CryptoDxState) -> Res { if self.len() > self.limit { qwarn!("Packet contents are more than the limit"); @@ -390,9 +376,7 @@ impl PacketBuilder { // Calculate the mask. let offset = SAMPLE_OFFSET - self.offsets.pn.len(); - if offset + SAMPLE_SIZE > ciphertext.len() { - return Err(Error::InternalError); - } + assert!(offset + SAMPLE_SIZE <= ciphertext.len()); let sample = &ciphertext[offset..offset + SAMPLE_SIZE]; let mask = crypto.compute_mask(sample)?; @@ -426,10 +410,6 @@ impl PacketBuilder { /// As this is a simple packet, this is just an associated function. /// As Retry is odd (it has to be constructed with leading bytes), /// this returns a [`Vec`] rather than building on an encoder. - /// - /// # Errors - /// - /// This will return an error if AEAD encrypt fails. #[allow(clippy::similar_names)] // scid and dcid are fine here. pub fn retry( version: Version, @@ -463,7 +443,6 @@ impl PacketBuilder { /// Make a Version Negotiation packet. #[allow(clippy::similar_names)] // scid and dcid are fine here. - #[must_use] pub fn version_negotiation( dcid: &[u8], scid: &[u8], @@ -575,10 +554,6 @@ impl<'a> PublicPacket<'a> { /// Decode the common parts of a packet. This provides minimal parsing and validation. /// Returns a tuple of a `PublicPacket` and a slice with any remainder from the datagram. - /// - /// # Errors - /// - /// This will return an error if the packet could not be decoded. #[allow(clippy::similar_names)] // For dcid and scid, which are fine. pub fn decode(data: &'a [u8], dcid_decoder: &dyn ConnectionIdDecoder) -> Res<(Self, &'a [u8])> { let mut decoder = Decoder::new(data); @@ -610,7 +585,7 @@ impl<'a> PublicPacket<'a> { } // Generic long header. - let version = WireVersion::try_from(Self::opt(decoder.decode_uint(4))?)?; + let version = WireVersion::try_from(Self::opt(decoder.decode_uint(4))?).unwrap(); let dcid = ConnectionIdRef::from(Self::opt(decoder.decode_vec(1))?); let scid = ConnectionIdRef::from(Self::opt(decoder.decode_vec(1))?); @@ -670,14 +645,11 @@ impl<'a> PublicPacket<'a> { } /// Validate the given packet as though it were a retry. - #[must_use] pub fn is_valid_retry(&self, odcid: &ConnectionId) -> bool { if self.packet_type != PacketType::Retry { return false; } - let Some(version) = self.version() else { - return false; - }; + let version = self.version().unwrap(); let expansion = retry::expansion(version); if self.data.len() <= expansion { return false; @@ -693,7 +665,6 @@ impl<'a> PublicPacket<'a> { .unwrap_or(false) } - #[must_use] pub fn is_valid_initial(&self) -> bool { // Packet has to be an initial, with a DCID of 8 bytes, or a token. // Note: the Server class validates the token and checks the length. @@ -701,42 +672,32 @@ impl<'a> PublicPacket<'a> { && (self.dcid().len() >= 8 || !self.token.is_empty()) } - #[must_use] pub fn packet_type(&self) -> PacketType { self.packet_type } - #[must_use] pub fn dcid(&self) -> ConnectionIdRef<'a> { self.dcid } - /// # Panics - /// - /// This will panic if called for a short header packet. - #[must_use] pub fn scid(&self) -> ConnectionIdRef<'a> { self.scid .expect("should only be called for long header packets") } - #[must_use] pub fn token(&self) -> &'a [u8] { self.token } - #[must_use] pub fn version(&self) -> Option { self.version.and_then(|v| Version::try_from(v).ok()) } - #[must_use] pub fn wire_version(&self) -> WireVersion { debug_assert!(self.version.is_some()); self.version.unwrap_or(0) } - #[must_use] pub fn len(&self) -> usize { self.data.len() } @@ -764,10 +725,14 @@ impl<'a> PublicPacket<'a> { assert_ne!(self.packet_type, PacketType::Retry); assert_ne!(self.packet_type, PacketType::VersionNegotiation); + qtrace!( + "unmask hdr={}", + hex(&self.data[..self.header_len + SAMPLE_OFFSET]) + ); + let sample_offset = self.header_len + SAMPLE_OFFSET; let mask = if let Some(sample) = self.data.get(sample_offset..(sample_offset + SAMPLE_SIZE)) { - qtrace!("unmask hdr={}", hex(&self.data[..sample_offset])); crypto.compute_mask(sample) } else { Err(Error::NoMoreData) @@ -811,9 +776,6 @@ impl<'a> PublicPacket<'a> { )) } - /// # Errors - /// - /// This will return an error if the packet cannot be decrypted. pub fn decrypt(&self, crypto: &mut CryptoStates, release_at: Instant) -> Res { let cspace: CryptoSpace = self.packet_type.into(); // When we don't have a version, the crypto code doesn't need a version @@ -828,9 +790,7 @@ impl<'a> PublicPacket<'a> { // too small (which is public information). let (key_phase, pn, header, body) = self.decrypt_header(rx)?; qtrace!([rx], "decoded header: {:?}", header); - let Some(rx) = crypto.rx(version, cspace, key_phase) else { - return Err(Error::DecryptError); - }; + let rx = crypto.rx(version, cspace, key_phase).unwrap(); let version = rx.version(); // Version fixup; see above. let d = rx.decrypt(pn, &header, body)?; // If this is the first packet ever successfully decrypted @@ -853,14 +813,8 @@ impl<'a> PublicPacket<'a> { } } - /// # Errors - /// - /// This will return an error if the packet is not a version negotiation packet - /// or if the versions cannot be decoded. pub fn supported_versions(&self) -> Res> { - if self.packet_type != PacketType::VersionNegotiation { - return Err(Error::InvalidPacket); - } + assert_eq!(self.packet_type, PacketType::VersionNegotiation); let mut decoder = Decoder::new(&self.data[self.header_len..]); let mut res = Vec::new(); while decoder.remaining() > 0 { @@ -891,17 +845,14 @@ pub struct DecryptedPacket { } impl DecryptedPacket { - #[must_use] pub fn version(&self) -> Version { self.version } - #[must_use] pub fn packet_type(&self) -> PacketType { self.pt } - #[must_use] pub fn pn(&self) -> PacketNumber { self.pn } @@ -915,7 +866,7 @@ impl Deref for DecryptedPacket { } } -#[cfg(all(test, not(feature = "disable-encryption")))] +#[cfg(all(test, not(feature = "fuzzing")))] mod tests { use neqo_common::Encoder; use test_fixture::{fixture_init, now}; diff --git a/third_party/rust/neqo-transport/src/packet/retry.rs b/third_party/rust/neqo-transport/src/packet/retry.rs index 71193b9100ce..72036d3b49bf 100644 --- a/third_party/rust/neqo-transport/src/packet/retry.rs +++ b/third_party/rust/neqo-transport/src/packet/retry.rs @@ -18,6 +18,7 @@ fn make_aead(version: Version) -> Aead { let secret = hkdf::import_key(TLS_VERSION_1_3, version.retry_secret()).unwrap(); Aead::new( + false, TLS_VERSION_1_3, TLS_AES_128_GCM_SHA256, &secret, diff --git a/third_party/rust/neqo-transport/src/path.rs b/third_party/rust/neqo-transport/src/path.rs index 50e458ff361c..4e8d9958abe1 100644 --- a/third_party/rust/neqo-transport/src/path.rs +++ b/third_party/rust/neqo-transport/src/path.rs @@ -216,7 +216,7 @@ impl Paths { /// to a migration from a peer, in which case the old path needs to be probed. #[must_use] fn select_primary(&mut self, path: &PathRef) -> Option { - qdebug!([path.borrow()], "set as primary path"); + qinfo!([path.borrow()], "set as primary path"); let old_path = self.primary.replace(Rc::clone(path)).map(|old| { old.borrow_mut().set_primary(false); old diff --git a/third_party/rust/neqo-transport/src/qlog.rs b/third_party/rust/neqo-transport/src/qlog.rs index a8ad986d2a8d..2572966104b7 100644 --- a/third_party/rust/neqo-transport/src/qlog.rs +++ b/third_party/rust/neqo-transport/src/qlog.rs @@ -195,7 +195,7 @@ pub fn packet_sent( ) { qlog.add_event_with_stream(|stream| { let mut d = Decoder::from(body); - let header = PacketHeader::with_type(pt.into(), Some(pn), None, None, None); + let header = PacketHeader::with_type(to_qlog_pkt_type(pt), Some(pn), None, None, None); let raw = RawInfo { length: Some(plen as u64), payload_length: None, @@ -205,7 +205,7 @@ pub fn packet_sent( let mut frames = SmallVec::new(); while d.remaining() > 0 { if let Ok(f) = Frame::decode(&mut d) { - frames.push(QuicFrame::from(&f)); + frames.push(frame_to_qlogframe(&f)); } else { qinfo!("qlog: invalid frame"); break; @@ -231,8 +231,13 @@ pub fn packet_sent( pub fn packet_dropped(qlog: &mut NeqoQlog, public_packet: &PublicPacket) { qlog.add_event_data(|| { - let header = - PacketHeader::with_type(public_packet.packet_type().into(), None, None, None, None); + let header = PacketHeader::with_type( + to_qlog_pkt_type(public_packet.packet_type()), + None, + None, + None, + None, + ); let raw = RawInfo { length: Some(public_packet.len() as u64), payload_length: None, @@ -254,7 +259,8 @@ pub fn packet_dropped(qlog: &mut NeqoQlog, public_packet: &PublicPacket) { pub fn packets_lost(qlog: &mut NeqoQlog, pkts: &[SentPacket]) { qlog.add_event_with_stream(|stream| { for pkt in pkts { - let header = PacketHeader::with_type(pkt.pt.into(), Some(pkt.pn), None, None, None); + let header = + PacketHeader::with_type(to_qlog_pkt_type(pkt.pt), Some(pkt.pn), None, None, None); let ev_data = EventData::PacketLost(PacketLost { header: Some(header), @@ -277,7 +283,7 @@ pub fn packet_received( let mut d = Decoder::from(&payload[..]); let header = PacketHeader::with_type( - public_packet.packet_type().into(), + to_qlog_pkt_type(public_packet.packet_type()), Some(payload.pn()), None, None, @@ -293,7 +299,7 @@ pub fn packet_received( while d.remaining() > 0 { if let Ok(f) = Frame::decode(&mut d) { - frames.push(QuicFrame::from(&f)); + frames.push(frame_to_qlogframe(&f)); } else { qinfo!("qlog: invalid frame"); break; @@ -387,180 +393,173 @@ pub fn metrics_updated(qlog: &mut NeqoQlog, updated_metrics: &[QlogMetric]) { #[allow(clippy::too_many_lines)] // Yeah, but it's a nice match. #[allow(clippy::cast_possible_truncation, clippy::cast_precision_loss)] // No choice here. -impl From<&Frame<'_>> for QuicFrame { - fn from(frame: &Frame) -> Self { - match frame { - // TODO: Add payload length to `QuicFrame::Padding` once - // https://github.com/cloudflare/quiche/pull/1745 is available via the qlog crate. - Frame::Padding { .. } => QuicFrame::Padding, - Frame::Ping => QuicFrame::Ping, - Frame::Ack { - largest_acknowledged, - ack_delay, - first_ack_range, - ack_ranges, - } => { - let ranges = - Frame::decode_ack_frame(*largest_acknowledged, *first_ack_range, ack_ranges) - .ok(); - - let acked_ranges = ranges.map(|all| { - AckedRanges::Double( - all.into_iter() - .map(RangeInclusive::into_inner) - .collect::>(), - ) - }); - - QuicFrame::Ack { - ack_delay: Some(*ack_delay as f32 / 1000.0), - acked_ranges, - ect1: None, - ect0: None, - ce: None, - } +fn frame_to_qlogframe(frame: &Frame) -> QuicFrame { + match frame { + Frame::Padding => QuicFrame::Padding, + Frame::Ping => QuicFrame::Ping, + Frame::Ack { + largest_acknowledged, + ack_delay, + first_ack_range, + ack_ranges, + } => { + let ranges = + Frame::decode_ack_frame(*largest_acknowledged, *first_ack_range, ack_ranges).ok(); + + let acked_ranges = ranges.map(|all| { + AckedRanges::Double( + all.into_iter() + .map(RangeInclusive::into_inner) + .collect::>(), + ) + }); + + QuicFrame::Ack { + ack_delay: Some(*ack_delay as f32 / 1000.0), + acked_ranges, + ect1: None, + ect0: None, + ce: None, } - Frame::ResetStream { - stream_id, - application_error_code, - final_size, - } => QuicFrame::ResetStream { - stream_id: stream_id.as_u64(), - error_code: *application_error_code, - final_size: *final_size, - }, - Frame::StopSending { - stream_id, - application_error_code, - } => QuicFrame::StopSending { - stream_id: stream_id.as_u64(), - error_code: *application_error_code, - }, - Frame::Crypto { offset, data } => QuicFrame::Crypto { - offset: *offset, - length: data.len() as u64, - }, - Frame::NewToken { token } => QuicFrame::NewToken { - token: qlog::Token { - ty: Some(qlog::TokenType::Retry), - details: None, - raw: Some(RawInfo { - data: Some(hex(token)), - length: Some(token.len() as u64), - payload_length: None, - }), - }, - }, - Frame::Stream { - fin, - stream_id, - offset, - data, - .. - } => QuicFrame::Stream { - stream_id: stream_id.as_u64(), - offset: *offset, - length: data.len() as u64, - fin: Some(*fin), - raw: None, - }, - Frame::MaxData { maximum_data } => QuicFrame::MaxData { - maximum: *maximum_data, - }, - Frame::MaxStreamData { - stream_id, - maximum_stream_data, - } => QuicFrame::MaxStreamData { - stream_id: stream_id.as_u64(), - maximum: *maximum_stream_data, - }, - Frame::MaxStreams { - stream_type, - maximum_streams, - } => QuicFrame::MaxStreams { - stream_type: match stream_type { - NeqoStreamType::BiDi => StreamType::Bidirectional, - NeqoStreamType::UniDi => StreamType::Unidirectional, - }, - maximum: *maximum_streams, - }, - Frame::DataBlocked { data_limit } => QuicFrame::DataBlocked { limit: *data_limit }, - Frame::StreamDataBlocked { - stream_id, - stream_data_limit, - } => QuicFrame::StreamDataBlocked { - stream_id: stream_id.as_u64(), - limit: *stream_data_limit, - }, - Frame::StreamsBlocked { - stream_type, - stream_limit, - } => QuicFrame::StreamsBlocked { - stream_type: match stream_type { - NeqoStreamType::BiDi => StreamType::Bidirectional, - NeqoStreamType::UniDi => StreamType::Unidirectional, - }, - limit: *stream_limit, - }, - Frame::NewConnectionId { - sequence_number, - retire_prior, - connection_id, - stateless_reset_token, - } => QuicFrame::NewConnectionId { - sequence_number: *sequence_number as u32, - retire_prior_to: *retire_prior as u32, - connection_id_length: Some(connection_id.len() as u8), - connection_id: hex(connection_id), - stateless_reset_token: Some(hex(stateless_reset_token)), - }, - Frame::RetireConnectionId { sequence_number } => QuicFrame::RetireConnectionId { - sequence_number: *sequence_number as u32, - }, - Frame::PathChallenge { data } => QuicFrame::PathChallenge { - data: Some(hex(data)), + } + Frame::ResetStream { + stream_id, + application_error_code, + final_size, + } => QuicFrame::ResetStream { + stream_id: stream_id.as_u64(), + error_code: *application_error_code, + final_size: *final_size, + }, + Frame::StopSending { + stream_id, + application_error_code, + } => QuicFrame::StopSending { + stream_id: stream_id.as_u64(), + error_code: *application_error_code, + }, + Frame::Crypto { offset, data } => QuicFrame::Crypto { + offset: *offset, + length: data.len() as u64, + }, + Frame::NewToken { token } => QuicFrame::NewToken { + token: qlog::Token { + ty: Some(qlog::TokenType::Retry), + details: None, + raw: Some(RawInfo { + data: Some(hex(token)), + length: Some(token.len() as u64), + payload_length: None, + }), }, - Frame::PathResponse { data } => QuicFrame::PathResponse { - data: Some(hex(data)), + }, + Frame::Stream { + fin, + stream_id, + offset, + data, + .. + } => QuicFrame::Stream { + stream_id: stream_id.as_u64(), + offset: *offset, + length: data.len() as u64, + fin: Some(*fin), + raw: None, + }, + Frame::MaxData { maximum_data } => QuicFrame::MaxData { + maximum: *maximum_data, + }, + Frame::MaxStreamData { + stream_id, + maximum_stream_data, + } => QuicFrame::MaxStreamData { + stream_id: stream_id.as_u64(), + maximum: *maximum_stream_data, + }, + Frame::MaxStreams { + stream_type, + maximum_streams, + } => QuicFrame::MaxStreams { + stream_type: match stream_type { + NeqoStreamType::BiDi => StreamType::Bidirectional, + NeqoStreamType::UniDi => StreamType::Unidirectional, }, - Frame::ConnectionClose { - error_code, - frame_type, - reason_phrase, - } => QuicFrame::ConnectionClose { - error_space: match error_code { - CloseError::Transport(_) => Some(ErrorSpace::TransportError), - CloseError::Application(_) => Some(ErrorSpace::ApplicationError), - }, - error_code: Some(error_code.code()), - error_code_value: Some(0), - reason: Some(String::from_utf8_lossy(reason_phrase).to_string()), - trigger_frame_type: Some(*frame_type), + maximum: *maximum_streams, + }, + Frame::DataBlocked { data_limit } => QuicFrame::DataBlocked { limit: *data_limit }, + Frame::StreamDataBlocked { + stream_id, + stream_data_limit, + } => QuicFrame::StreamDataBlocked { + stream_id: stream_id.as_u64(), + limit: *stream_data_limit, + }, + Frame::StreamsBlocked { + stream_type, + stream_limit, + } => QuicFrame::StreamsBlocked { + stream_type: match stream_type { + NeqoStreamType::BiDi => StreamType::Bidirectional, + NeqoStreamType::UniDi => StreamType::Unidirectional, }, - Frame::HandshakeDone => QuicFrame::HandshakeDone, - Frame::AckFrequency { .. } => QuicFrame::Unknown { - frame_type_value: None, - raw_frame_type: frame.get_type(), - raw: None, + limit: *stream_limit, + }, + Frame::NewConnectionId { + sequence_number, + retire_prior, + connection_id, + stateless_reset_token, + } => QuicFrame::NewConnectionId { + sequence_number: *sequence_number as u32, + retire_prior_to: *retire_prior as u32, + connection_id_length: Some(connection_id.len() as u8), + connection_id: hex(connection_id), + stateless_reset_token: Some(hex(stateless_reset_token)), + }, + Frame::RetireConnectionId { sequence_number } => QuicFrame::RetireConnectionId { + sequence_number: *sequence_number as u32, + }, + Frame::PathChallenge { data } => QuicFrame::PathChallenge { + data: Some(hex(data)), + }, + Frame::PathResponse { data } => QuicFrame::PathResponse { + data: Some(hex(data)), + }, + Frame::ConnectionClose { + error_code, + frame_type, + reason_phrase, + } => QuicFrame::ConnectionClose { + error_space: match error_code { + CloseError::Transport(_) => Some(ErrorSpace::TransportError), + CloseError::Application(_) => Some(ErrorSpace::ApplicationError), }, - Frame::Datagram { data, .. } => QuicFrame::Datagram { - length: data.len() as u64, - raw: None, - }, - } + error_code: Some(error_code.code()), + error_code_value: Some(0), + reason: Some(String::from_utf8_lossy(reason_phrase).to_string()), + trigger_frame_type: Some(*frame_type), + }, + Frame::HandshakeDone => QuicFrame::HandshakeDone, + Frame::AckFrequency { .. } => QuicFrame::Unknown { + frame_type_value: None, + raw_frame_type: frame.get_type(), + raw: None, + }, + Frame::Datagram { data, .. } => QuicFrame::Datagram { + length: data.len() as u64, + raw: None, + }, } } -impl From for qlog::events::quic::PacketType { - fn from(value: PacketType) -> Self { - match value { - PacketType::Initial => qlog::events::quic::PacketType::Initial, - PacketType::Handshake => qlog::events::quic::PacketType::Handshake, - PacketType::ZeroRtt => qlog::events::quic::PacketType::ZeroRtt, - PacketType::Short => qlog::events::quic::PacketType::OneRtt, - PacketType::Retry => qlog::events::quic::PacketType::Retry, - PacketType::VersionNegotiation => qlog::events::quic::PacketType::VersionNegotiation, - PacketType::OtherVersion => qlog::events::quic::PacketType::Unknown, - } +fn to_qlog_pkt_type(ptype: PacketType) -> qlog::events::quic::PacketType { + match ptype { + PacketType::Initial => qlog::events::quic::PacketType::Initial, + PacketType::Handshake => qlog::events::quic::PacketType::Handshake, + PacketType::ZeroRtt => qlog::events::quic::PacketType::ZeroRtt, + PacketType::Short => qlog::events::quic::PacketType::OneRtt, + PacketType::Retry => qlog::events::quic::PacketType::Retry, + PacketType::VersionNegotiation => qlog::events::quic::PacketType::VersionNegotiation, + PacketType::OtherVersion => qlog::events::quic::PacketType::Unknown, } } diff --git a/third_party/rust/neqo-transport/src/server.rs b/third_party/rust/neqo-transport/src/server.rs index 7d3d144a0908..96a6244ef158 100644 --- a/third_party/rust/neqo-transport/src/server.rs +++ b/third_party/rust/neqo-transport/src/server.rs @@ -15,12 +15,12 @@ use std::{ ops::{Deref, DerefMut}, path::PathBuf, rc::{Rc, Weak}, - time::Instant, + time::{Duration, Instant}, }; use neqo_common::{ self as common, event::Provider, hex, qdebug, qerror, qinfo, qlog::NeqoQlog, qtrace, qwarn, - Datagram, Decoder, Role, + timer::Timer, Datagram, Decoder, Role, }; use neqo_crypto::{ encode_ech_config, AntiReplay, Cipher, PrivateKey, PublicKey, ZeroRttCheckResult, @@ -46,6 +46,13 @@ pub enum InitialResult { /// `MIN_INITIAL_PACKET_SIZE` is the smallest packet that can be used to establish /// a new connection across all QUIC versions this server supports. const MIN_INITIAL_PACKET_SIZE: usize = 1200; +/// The size of timer buckets. This is higher than the actual timer granularity +/// as this depends on there being some distribution of events. +const TIMER_GRANULARITY: Duration = Duration::from_millis(4); +/// The number of buckets in the timer. As mentioned in the definition of `Timer`, +/// the granularity and capacity need to multiply to be larger than the largest +/// delay that might be used. That's the idle timeout (currently 30s). +const TIMER_CAPACITY: usize = 16384; type StateRef = Rc>; type ConnectionTableRef = Rc>>; @@ -54,21 +61,7 @@ type ConnectionTableRef = Rc>>; pub struct ServerConnectionState { c: Connection, active_attempt: Option, - wake_at: Option, -} - -impl ServerConnectionState { - fn set_wake_at(&mut self, at: Instant) { - self.wake_at = Some(at); - } - - fn needs_waking(&self, now: Instant) -> bool { - self.wake_at.map_or(false, |t| t <= now) - } - - fn woken(&mut self) { - self.wake_at = None; - } + last_timer: Instant, } impl Deref for ServerConnectionState { @@ -181,8 +174,8 @@ pub struct Server { active: HashSet, /// The set of connections that need immediate processing. waiting: VecDeque, - /// The latest [`Output::Callback`] returned from [`Server::process`]. - wake_at: Option, + /// Outstanding timers for connections. + timers: Timer, /// Address validation logic, which determines whether we send a Retry. address_validation: Rc>, /// Directory to create qlog traces in @@ -226,10 +219,10 @@ impl Server { connections: Rc::default(), active: HashSet::default(), waiting: VecDeque::default(), + timers: Timer::new(now, TIMER_GRANULARITY, TIMER_CAPACITY), address_validation: Rc::new(RefCell::new(validation)), qlog_dir: None, ech_config: None, - wake_at: None, }) } @@ -267,6 +260,11 @@ impl Server { self.ech_config.as_ref().map_or(&[], |cfg| &cfg.encoded) } + fn remove_timer(&mut self, c: &StateRef) { + let last = c.borrow().last_timer; + self.timers.remove(last, |t| Rc::ptr_eq(t, c)); + } + fn process_connection( &mut self, c: &StateRef, @@ -282,12 +280,16 @@ impl Server { } Output::Callback(delay) => { let next = now + delay; - c.borrow_mut().set_wake_at(next); - if self.wake_at.map_or(true, |c| c > next) { - self.wake_at = Some(next); + if next != c.borrow().last_timer { + qtrace!([self], "Change timer to {:?}", next); + self.remove_timer(c); + c.borrow_mut().last_timer = next; + self.timers.add(next, Rc::clone(c)); } } - Output::None => {} + Output::None => { + self.remove_timer(c); + } } if c.borrow().has_events() { qtrace!([self], "Connection active: {:?}", c); @@ -505,7 +507,7 @@ impl Server { self.setup_connection(&mut c, &attempt_key, initial, orig_dcid); let c = Rc::new(RefCell::new(ServerConnectionState { c, - wake_at: None, + last_timer: now, active_attempt: Some(attempt_key.clone()), })); cid_mgr.borrow_mut().set_connection(&c); @@ -644,28 +646,24 @@ impl Server { return Some(d); } } - - qtrace!([self], "No packet to send still, check wake up times"); - loop { - let connection = self - .connections - .borrow() - .values() - .find(|c| c.borrow().needs_waking(now)) - .cloned()?; - let datagram = self.process_connection(&connection, None, now); - connection.borrow_mut().woken(); - if datagram.is_some() { - return datagram; + qtrace!([self], "No packet to send still, run timers"); + while let Some(c) = self.timers.take_next(now) { + if let Some(d) = self.process_connection(&c, None, now) { + return Some(d); } } + None } - pub fn process(&mut self, dgram: Option<&Datagram>, now: Instant) -> Output { - if self.wake_at.map_or(false, |c| c <= now) { - self.wake_at = None; + fn next_time(&mut self, now: Instant) -> Option { + if self.waiting.is_empty() { + self.timers.next_time().map(|x| x - now) + } else { + Some(Duration::new(0, 0)) } + } + pub fn process(&mut self, dgram: Option<&Datagram>, now: Instant) -> Output { dgram .and_then(|d| self.process_input(d, now)) .or_else(|| self.process_next_output(now)) @@ -673,7 +671,12 @@ impl Server { qtrace!([self], "Send packet: {:?}", d); Output::Datagram(d) }) - .or_else(|| self.wake_at.take().map(|c| Output::Callback(c - now))) + .or_else(|| { + self.next_time(now).map(|delay| { + qtrace!([self], "Wait: {:?}", delay); + Output::Callback(delay) + }) + }) .unwrap_or_else(|| { qtrace!([self], "Go dormant"); Output::None diff --git a/third_party/rust/neqo-transport/src/stats.rs b/third_party/rust/neqo-transport/src/stats.rs index 0a61097010ba..9eff503dcfa0 100644 --- a/third_party/rust/neqo-transport/src/stats.rs +++ b/third_party/rust/neqo-transport/src/stats.rs @@ -14,7 +14,7 @@ use std::{ time::Duration, }; -use neqo_common::qwarn; +use neqo_common::qinfo; use crate::packet::PacketNumber; @@ -168,7 +168,7 @@ impl Stats { pub fn pkt_dropped(&mut self, reason: impl AsRef) { self.dropped_rx += 1; - qwarn!( + qinfo!( [self.info], "Dropped received packet: {}; Total: {}", reason.as_ref(), @@ -206,7 +206,7 @@ impl Debug for Stats { " tx: {} lost {} lateack {} ptoack {}", self.packets_tx, self.lost, self.late_ack, self.pto_ack )?; - writeln!(f, " resumed: {}", self.resumed)?; + writeln!(f, " resumed: {} ", self.resumed)?; writeln!(f, " frames rx:")?; self.frame_rx.fmt(f)?; writeln!(f, " frames tx:")?; diff --git a/third_party/rust/neqo-transport/tests/common/mod.rs b/third_party/rust/neqo-transport/tests/common/mod.rs index e36e66f753d2..faff216eb9fb 100644 --- a/third_party/rust/neqo-transport/tests/common/mod.rs +++ b/third_party/rust/neqo-transport/tests/common/mod.rs @@ -146,7 +146,14 @@ pub fn initial_aead_and_hp(dcid: &[u8], role: Role) -> (Aead, HpKey) { ) .unwrap(); ( - Aead::new(TLS_VERSION_1_3, TLS_AES_128_GCM_SHA256, &secret, "quic ").unwrap(), + Aead::new( + false, + TLS_VERSION_1_3, + TLS_AES_128_GCM_SHA256, + &secret, + "quic ", + ) + .unwrap(), HpKey::extract(TLS_VERSION_1_3, TLS_AES_128_GCM_SHA256, &secret, "quic hp").unwrap(), ) } diff --git a/third_party/rust/neqo-transport/tests/conn_vectors.rs b/third_party/rust/neqo-transport/tests/conn_vectors.rs index 86fe9d36fcc2..f47888307550 100644 --- a/third_party/rust/neqo-transport/tests/conn_vectors.rs +++ b/third_party/rust/neqo-transport/tests/conn_vectors.rs @@ -6,7 +6,7 @@ // Tests with the test vectors from the spec. -#![cfg(not(feature = "disable-encryption"))] +#![cfg(not(feature = "fuzzing"))] use std::{cell::RefCell, rc::Rc}; diff --git a/third_party/rust/neqo-transport/tests/connection.rs b/third_party/rust/neqo-transport/tests/connection.rs index b8877b946d01..0b91fcf306dc 100644 --- a/third_party/rust/neqo-transport/tests/connection.rs +++ b/third_party/rust/neqo-transport/tests/connection.rs @@ -127,76 +127,6 @@ fn reorder_server_initial() { assert_eq!(*client.state(), State::Confirmed); } -fn set_payload(server_packet: &Option, client_dcid: &[u8], payload: &[u8]) -> Datagram { - let (server_initial, _server_hs) = split_datagram(server_packet.as_ref().unwrap()); - let (protected_header, _, _, orig_payload) = - decode_initial_header(&server_initial, Role::Server); - - // Now decrypt the packet. - let (aead, hp) = initial_aead_and_hp(client_dcid, Role::Server); - let (mut header, pn) = remove_header_protection(&hp, protected_header, orig_payload); - assert_eq!(pn, 0); - // Re-encode the packet number as four bytes, so we have enough material for the header - // protection sample if payload is empty. - let pn_pos = header.len() - 2; - header[pn_pos] = u8::try_from(4 + aead.expansion()).unwrap(); - header.resize(header.len() + 3, 0); - header[0] |= 0b0000_0011; // Set the packet number length to 4. - - // And build a packet containing the given payload. - let mut packet = header.clone(); - packet.resize(header.len() + payload.len() + aead.expansion(), 0); - aead.encrypt(pn, &header, payload, &mut packet[header.len()..]) - .unwrap(); - apply_header_protection(&hp, &mut packet, protected_header.len()..header.len()); - Datagram::new( - server_initial.source(), - server_initial.destination(), - server_initial.tos(), - server_initial.ttl(), - packet, - ) -} - -/// Test that the stack treats a packet without any frames as a protocol violation. -#[test] -fn packet_without_frames() { - let mut client = new_client( - ConnectionParameters::default().versions(Version::Version1, vec![Version::Version1]), - ); - let mut server = default_server(); - - let client_initial = client.process_output(now()); - let (_, client_dcid, _, _) = - decode_initial_header(client_initial.as_dgram_ref().unwrap(), Role::Client); - - let server_packet = server.process(client_initial.as_dgram_ref(), now()).dgram(); - let modified = set_payload(&server_packet, client_dcid, &[]); - client.process_input(&modified, now()); - assert_eq!( - client.state(), - &State::Closed(ConnectionError::Transport(Error::ProtocolViolation)) - ); -} - -/// Test that the stack permits a packet containing only padding. -#[test] -fn packet_with_only_padding() { - let mut client = new_client( - ConnectionParameters::default().versions(Version::Version1, vec![Version::Version1]), - ); - let mut server = default_server(); - - let client_initial = client.process_output(now()); - let (_, client_dcid, _, _) = - decode_initial_header(client_initial.as_dgram_ref().unwrap(), Role::Client); - - let server_packet = server.process(client_initial.as_dgram_ref(), now()).dgram(); - let modified = set_payload(&server_packet, client_dcid, &[0]); - client.process_input(&modified, now()); - assert_eq!(client.state(), &State::WaitInitial); -} - /// Overflow the crypto buffer. #[allow(clippy::similar_names)] // For ..._scid and ..._dcid, which are fine. #[test] diff --git a/third_party/rust/neqo-transport/tests/retry.rs b/third_party/rust/neqo-transport/tests/retry.rs index 36eff71e7bfd..e583fcae0fe1 100644 --- a/third_party/rust/neqo-transport/tests/retry.rs +++ b/third_party/rust/neqo-transport/tests/retry.rs @@ -4,7 +4,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![cfg(not(feature = "disable-encryption"))] +#![cfg(not(feature = "fuzzing"))] mod common; -- 2.11.4.GIT