Bug 1596069 - Update neqo to version 0.1.6 r=agrover

Differential Revision: https://phabricator.services.mozilla.com/D53327

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Dragana Damjanovic 2019-11-17 03:30:04 +00:00
Родитель 441a0d7087
Коммит 808438384e
44 изменённых файлов: 1300 добавлений и 861 удалений

Просмотреть файл

@ -15,7 +15,7 @@ rev = "6a866fdad2ca880df9b87fcbc9921abac1e91914"
[source."https://github.com/mozilla/neqo"]
git = "https://github.com/mozilla/neqo"
replace-with = "vendored-sources"
rev = "a17c1e83"
tag = "v0.1.6"
[source."https://github.com/kvark/spirv_cross"]
branch = "wgpu"

60
Cargo.lock сгенерированный
Просмотреть файл

@ -2301,8 +2301,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "neqo-common"
version = "0.1.4"
source = "git+https://github.com/mozilla/neqo?rev=a17c1e83#a17c1e83bb44ed923eb16a4c675ffe569b3a08f3"
version = "0.1.6"
source = "git+https://github.com/mozilla/neqo?tag=v0.1.6#c110c2e09a36707934271d95a4bf5f44d6753dd5"
dependencies = [
"env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2312,12 +2312,12 @@ dependencies = [
[[package]]
name = "neqo-crypto"
version = "0.1.4"
source = "git+https://github.com/mozilla/neqo?rev=a17c1e83#a17c1e83bb44ed923eb16a4c675ffe569b3a08f3"
version = "0.1.6"
source = "git+https://github.com/mozilla/neqo?tag=v0.1.6#c110c2e09a36707934271d95a4bf5f44d6753dd5"
dependencies = [
"bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"neqo-common 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
"neqo-common 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2325,39 +2325,39 @@ dependencies = [
[[package]]
name = "neqo-http3"
version = "0.1.4"
source = "git+https://github.com/mozilla/neqo?rev=a17c1e83#a17c1e83bb44ed923eb16a4c675ffe569b3a08f3"
version = "0.1.6"
source = "git+https://github.com/mozilla/neqo?tag=v0.1.6#c110c2e09a36707934271d95a4bf5f44d6753dd5"
dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"neqo-common 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
"neqo-crypto 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
"neqo-qpack 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
"neqo-transport 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
"neqo-common 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
"neqo-crypto 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
"neqo-qpack 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
"neqo-transport 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "neqo-qpack"
version = "0.1.4"
source = "git+https://github.com/mozilla/neqo?rev=a17c1e83#a17c1e83bb44ed923eb16a4c675ffe569b3a08f3"
version = "0.1.6"
source = "git+https://github.com/mozilla/neqo?tag=v0.1.6#c110c2e09a36707934271d95a4bf5f44d6753dd5"
dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"neqo-common 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
"neqo-crypto 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
"neqo-transport 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
"neqo-common 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
"neqo-crypto 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
"neqo-transport 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
]
[[package]]
name = "neqo-transport"
version = "0.1.4"
source = "git+https://github.com/mozilla/neqo?rev=a17c1e83#a17c1e83bb44ed923eb16a4c675ffe569b3a08f3"
version = "0.1.6"
source = "git+https://github.com/mozilla/neqo?tag=v0.1.6#c110c2e09a36707934271d95a4bf5f44d6753dd5"
dependencies = [
"derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"neqo-common 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
"neqo-crypto 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
"neqo-common 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
"neqo-crypto 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"slice-deque 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2367,10 +2367,10 @@ dependencies = [
name = "neqo_glue"
version = "0.1.0"
dependencies = [
"neqo-common 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
"neqo-crypto 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
"neqo-http3 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
"neqo-transport 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
"neqo-common 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
"neqo-crypto 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
"neqo-http3 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
"neqo-transport 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
"nserror 0.1.0",
"nsstring 0.1.0",
"thin-vec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3170,7 +3170,7 @@ dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"murmurhash3 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -4675,11 +4675,11 @@ dependencies = [
"checksum mp4parse_fallible 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6626c2aef76eb8f984eef02e475883d3fe9112e114720446c5810fc5f045cd30"
"checksum msdos_time 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aad9dfe950c057b1bfe9c1f2aa51583a8468ef2a5baba2ebbe06d775efeb7729"
"checksum murmurhash3 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a2983372caf4480544083767bf2d27defafe32af49ab4df3a0b7fc90793a3664"
"checksum neqo-common 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)" = "<none>"
"checksum neqo-crypto 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)" = "<none>"
"checksum neqo-http3 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)" = "<none>"
"checksum neqo-qpack 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)" = "<none>"
"checksum neqo-transport 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)" = "<none>"
"checksum neqo-common 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)" = "<none>"
"checksum neqo-crypto 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)" = "<none>"
"checksum neqo-http3 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)" = "<none>"
"checksum neqo-qpack 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)" = "<none>"
"checksum neqo-transport 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)" = "<none>"
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
"checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"
"checksum nix 0.13.1 (git+https://github.com/shravanrn/nix/?branch=r0.13.1)" = "<none>"

Просмотреть файл

@ -8,16 +8,16 @@ edition = "2018"
name = "neqo_glue"
[dependencies]
neqo-http3 = { rev = "a17c1e83", git = "https://github.com/mozilla/neqo" }
neqo-transport = { rev = "a17c1e83", git = "https://github.com/mozilla/neqo" }
neqo-common = { rev = "a17c1e83", git = "https://github.com/mozilla/neqo" }
neqo-http3 = { tag = "v0.1.6", git = "https://github.com/mozilla/neqo" }
neqo-transport = { tag = "v0.1.6", git = "https://github.com/mozilla/neqo" }
neqo-common = { tag = "v0.1.6", git = "https://github.com/mozilla/neqo" }
nserror = { path = "../../../xpcom/rust/nserror" }
nsstring = { path = "../../../xpcom/rust/nsstring" }
xpcom = { path = "../../../xpcom/rust/xpcom" }
thin-vec = { version = "0.1.0", features = ["gecko-ffi"] }
[dependencies.neqo-crypto]
rev = "a17c1e83"
tag = "v0.1.6"
git = "https://github.com/mozilla/neqo"
default-features = false
features = ["gecko"]

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"6791b2f6143d31a8b2511e995a1ca902e0827f8cefdd966a477ad11068602e80","src/codec.rs":"6c619c42d1293297fd1e1763213033a82723bfa97938f5dd9fde6745f965940e","src/datagram.rs":"47d69797b66108cec997375818cb43ba9575b89f8730277047c6889de09b12aa","src/incrdecoder.rs":"4d55c9d992a4c409e4b4e37a8c04d3741d2ba260f46d5385cb3eff5121db03de","src/lib.rs":"7204f3eb32908563ffd50e615534326509be781cb5afd111f3bccdd6cf04249c","src/log.rs":"68a0a30344edcfad6c222eed62f5810fb9aa896fea7ec782b6ca2b2fc9a0bd4b","src/once.rs":"ad0d1ac0233dda75e294b5ccab65caceaec66d277659e22b1236aceea0c53ede","src/timer.rs":"13fb2ad4ef435d57895c61c291aca82a261c93c0f2cae2634929fb6ca5fdac85","tests/log.rs":"79e01eeef039d1abb17aadb2212256ad064c53e6d72bbebe254230119a623510"},"package":null}
{"files":{"Cargo.toml":"0132063e21304df128d64381c01694c31d7775c1f3d72f169ea9d4547d7024cf","src/codec.rs":"6c619c42d1293297fd1e1763213033a82723bfa97938f5dd9fde6745f965940e","src/datagram.rs":"47d69797b66108cec997375818cb43ba9575b89f8730277047c6889de09b12aa","src/incrdecoder.rs":"4d55c9d992a4c409e4b4e37a8c04d3741d2ba260f46d5385cb3eff5121db03de","src/lib.rs":"7204f3eb32908563ffd50e615534326509be781cb5afd111f3bccdd6cf04249c","src/log.rs":"943e4e332400d94805d60f965d1d0ae7aad180f6d5b50936d0bd9e085bbc1502","src/once.rs":"ad0d1ac0233dda75e294b5ccab65caceaec66d277659e22b1236aceea0c53ede","src/timer.rs":"13fb2ad4ef435d57895c61c291aca82a261c93c0f2cae2634929fb6ca5fdac85","tests/log.rs":"1c7ae6cb43047877fff27f3d01abc8ac456ea0907e88473d0179215342391d5d"},"package":null}

2
third_party/rust/neqo-common/Cargo.toml поставляемый
Просмотреть файл

@ -1,6 +1,6 @@
[package]
name = "neqo-common"
version = "0.1.4"
version = "0.1.6"
authors = ["Bobby Holley <bobbyholley@gmail.com>"]
edition = "2018"
license = "MIT/Apache-2.0"

5
third_party/rust/neqo-common/src/log.rs поставляемый
Просмотреть файл

@ -47,30 +47,25 @@ macro_rules! qlog {
#[macro_export]
macro_rules! qerror {
([$ctx:expr], $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Error, $ctx, $($arg)*););
([$ctx:expr] $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Error, $ctx, $($arg)*););
($($arg:tt)*) => ( { ::neqo_common::log::init(); ::log::log!(::log::Level::Error, $($arg)*); } );
}
#[macro_export]
macro_rules! qwarn {
([$ctx:expr], $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Warn, $ctx, $($arg)*););
([$ctx:expr] $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Warn, $ctx, $($arg)*););
($($arg:tt)*) => ( { ::neqo_common::log::init(); ::log::log!(::log::Level::Warn, $($arg)*); } );
}
#[macro_export]
macro_rules! qinfo {
([$ctx:expr], $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Info, $ctx, $($arg)*););
([$ctx:expr] $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Info, $ctx, $($arg)*););
($($arg:tt)*) => ( { ::neqo_common::log::init(); ::log::log!(::log::Level::Info, $($arg)*); } );
}
#[macro_export]
macro_rules! qdebug {
([$ctx:expr], $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Debug, $ctx, $($arg)*););
([$ctx:expr] $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Debug, $ctx, $($arg)*););
($($arg:tt)*) => ( { ::neqo_common::log::init(); ::log::log!(::log::Level::Debug, $($arg)*); } );
}
#[macro_export]
macro_rules! qtrace {
([$ctx:expr], $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Trace, $ctx, $($arg)*););
([$ctx:expr] $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Trace, $ctx, $($arg)*););
($($arg:tt)*) => ( { ::neqo_common::log::init(); ::log::log!(::log::Level::Trace, $($arg)*); } );
}

10
third_party/rust/neqo-common/tests/log.rs поставляемый
Просмотреть файл

@ -31,11 +31,11 @@ fn args() {
#[test]
fn context() {
let context = "context";
qerror!([context] "error");
qwarn!([context] "warn");
qinfo!([context] "info");
qdebug!([context] "debug");
qtrace!([context] "trace");
qerror!([context], "error");
qwarn!([context], "warn");
qinfo!([context], "info");
qdebug!([context], "debug");
qtrace!([context], "trace");
}
#[test]

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"d7afc57115b1915c379e45550e58e5b09245db87affd7a55b8b733a852a542a0","TODO":"ac0f1c2ebcca03f5b3c0cc56c5aedbb030a4b511e438bc07a57361c789f91e9f","bindings/bindings.toml":"0f305bda9513e7fb4b521df79912ad5ba21784377b84f4b531895619e561f356","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":"ebb685e47de005413d8e24370ba22576b45b0273aaf0a5116af96dcdc48d32c0","src/aead.rs":"bfbd4b72354fb7103ff31a2a600dd457e10fdc14ad670a5de1f5bb0f9b6e1504","src/agent.rs":"b8f59b2f1d3432db0b810383c2ae6d17a79b89819b90da50eecc3370cae77398","src/agentio.rs":"615a805e0f27970755daa5bfe864b2e9b3b09309dfa4178b85f38a13ae6f7131","src/auth.rs":"846a4954186f0bcabc4084214ae216819215f3bccc33cc08d93abb9c5fefb7f2","src/cert.rs":"fd3fd2bbb38754bdcee3898549feae412943c9f719032531c1ad6e61783b5394","src/constants.rs":"75dec8e3c74326f492a115a0e7a487daba32eba30bcbd64d2223333b3caa4008","src/err.rs":"81d5c9b75457d4367607d0a456c276fa037c0f66a1c8df40af58ff42426c9890","src/exp.rs":"61586662407359c1ecb8ed4987bc3c702f26ba2e203a091a51b6d6363cbd510f","src/ext.rs":"f3cc5bfdd96d46affff43653258d91eb447251f83da19b37dd415129052413e3","src/hkdf.rs":"6d44f63493f0c558a23339f88fe766f8afdb0bda3dc11a79e8a99d3c8d0b6acb","src/hp.rs":"854ce7b9d44892fbb01ac4078b84266771a9254cebfea5b94e7f4b4a7fb1b946","src/lib.rs":"6c3540b4e54510f6a298f04093f44f6d957f30f475214fd3ec9e39fa4d98e386","src/p11.rs":"89df482ae683646add0f46333991f31fe996fdce67859a1ff37c090a4166ce6e","src/prio.rs":"0e213056f6bf0c797c2cfe13c6d14dbb64a64b1218fff21cbf36fb3309b852f9","src/replay.rs":"01eae2accfefbc26719fcccd4bcb8c1ea6400ab96fbb696ecdb8f32164f931a2","src/result.rs":"d76c7bc5e99c80a5a124909ab586cdb91d894856e52f5146430da43584a6d6c1","src/secrets.rs":"e929b69927d93b4bde3bd490c0ed9a4e1e4c5a047492259ab1dae7fbad885c22","src/selfencrypt.rs":"9bffad6af2f186f606bd7305a8528d76e66471a71f7103c7498b90507fb031e1","src/ssl.rs":"4c7c850777a1b4b7b66ad765e24a25780e64f24da08175b5cc722a840d35f693","src/time.rs":"4dffa6f4ac9cfc8db240c370fb04a7d7241c80793ecf6acda2d41d0bc94b0236","tests/aead.rs":"bedf985ba0b95a9c6db6a84f870d15062d821f3b24cb3cb9dfa89445be795d50","tests/agent.rs":"8b9ca3c182cf065b7668fd9c7e5885b1cde8bb1d0ea3afbb5fb7a3186d7a9d2e","tests/ext.rs":"b1d2f9d68d18e24df5f246e4ad6f80a0a0d98f824094a9fa447a580b02486d90","tests/handshake.rs":"2752bd6c575e7d28db2bce8484aa08ba08846f30aa0bb9aa07153d1763dab830","tests/hkdf.rs":"83300020a18d5485a1adcd3b806aed64fd008072589875112145f401340f3602","tests/hp.rs":"83f453a792ef17eb51a20b2764407c28a60620f5d3b917c8e237a121b32988df","tests/init.rs":"abb08d3d5d9610d62dc94535230ed4f52743d90b7059224b152caa8cf7cf43d7","tests/selfencrypt.rs":"365bc96be63d2e970bab7cf0134a59526513e1c1c3b854c34fa44fc8ed8c10d3"},"package":null}
{"files":{"Cargo.toml":"f238c080977551a9301b25aa52362b19dae1ad1fdeda2b3f47d21752e13e37bf","TODO":"ac0f1c2ebcca03f5b3c0cc56c5aedbb030a4b511e438bc07a57361c789f91e9f","bindings/bindings.toml":"0f305bda9513e7fb4b521df79912ad5ba21784377b84f4b531895619e561f356","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":"0a4eaffefed2e190286a0de3eb69cd860ed4aea215d58a7135331b1850a5f82d","src/aead.rs":"bfbd4b72354fb7103ff31a2a600dd457e10fdc14ad670a5de1f5bb0f9b6e1504","src/agent.rs":"2539f4d1c471457208af0597c61a30e7abb1295d1442e6ed8fbbd83811c3dff6","src/agentio.rs":"25b87af28366d32671770900bed3bf093b141cc92c5193be71e4f748eea2a313","src/auth.rs":"846a4954186f0bcabc4084214ae216819215f3bccc33cc08d93abb9c5fefb7f2","src/cert.rs":"fd3fd2bbb38754bdcee3898549feae412943c9f719032531c1ad6e61783b5394","src/constants.rs":"75dec8e3c74326f492a115a0e7a487daba32eba30bcbd64d2223333b3caa4008","src/err.rs":"d2ee7e2e024acb8894fe0a9e028e6627dad19368808df1d52d321f1b8a159dca","src/exp.rs":"61586662407359c1ecb8ed4987bc3c702f26ba2e203a091a51b6d6363cbd510f","src/ext.rs":"f3cc5bfdd96d46affff43653258d91eb447251f83da19b37dd415129052413e3","src/hkdf.rs":"6d44f63493f0c558a23339f88fe766f8afdb0bda3dc11a79e8a99d3c8d0b6acb","src/hp.rs":"854ce7b9d44892fbb01ac4078b84266771a9254cebfea5b94e7f4b4a7fb1b946","src/lib.rs":"6c3540b4e54510f6a298f04093f44f6d957f30f475214fd3ec9e39fa4d98e386","src/p11.rs":"89df482ae683646add0f46333991f31fe996fdce67859a1ff37c090a4166ce6e","src/prio.rs":"0e213056f6bf0c797c2cfe13c6d14dbb64a64b1218fff21cbf36fb3309b852f9","src/replay.rs":"01eae2accfefbc26719fcccd4bcb8c1ea6400ab96fbb696ecdb8f32164f931a2","src/result.rs":"d76c7bc5e99c80a5a124909ab586cdb91d894856e52f5146430da43584a6d6c1","src/secrets.rs":"e929b69927d93b4bde3bd490c0ed9a4e1e4c5a047492259ab1dae7fbad885c22","src/selfencrypt.rs":"9bffad6af2f186f606bd7305a8528d76e66471a71f7103c7498b90507fb031e1","src/ssl.rs":"4c7c850777a1b4b7b66ad765e24a25780e64f24da08175b5cc722a840d35f693","src/time.rs":"4dffa6f4ac9cfc8db240c370fb04a7d7241c80793ecf6acda2d41d0bc94b0236","tests/aead.rs":"bedf985ba0b95a9c6db6a84f870d15062d821f3b24cb3cb9dfa89445be795d50","tests/agent.rs":"8b9ca3c182cf065b7668fd9c7e5885b1cde8bb1d0ea3afbb5fb7a3186d7a9d2e","tests/ext.rs":"b1d2f9d68d18e24df5f246e4ad6f80a0a0d98f824094a9fa447a580b02486d90","tests/handshake.rs":"2752bd6c575e7d28db2bce8484aa08ba08846f30aa0bb9aa07153d1763dab830","tests/hkdf.rs":"83300020a18d5485a1adcd3b806aed64fd008072589875112145f401340f3602","tests/hp.rs":"83f453a792ef17eb51a20b2764407c28a60620f5d3b917c8e237a121b32988df","tests/init.rs":"abb08d3d5d9610d62dc94535230ed4f52743d90b7059224b152caa8cf7cf43d7","tests/selfencrypt.rs":"365bc96be63d2e970bab7cf0134a59526513e1c1c3b854c34fa44fc8ed8c10d3"},"package":null}

2
third_party/rust/neqo-crypto/Cargo.toml поставляемый
Просмотреть файл

@ -1,6 +1,6 @@
[package]
name = "neqo-crypto"
version = "0.1.4"
version = "0.1.6"
authors = ["Martin Thomson <mt@lowentropy.net>"]
edition = "2018"
build = "build.rs"

4
third_party/rust/neqo-crypto/build.rs поставляемый
Просмотреть файл

@ -231,7 +231,9 @@ fn build_bindings(base: &str, bindings: &Bindings, flags: &[String], gecko: bool
println!("cargo:rerun-if-changed={}", header);
let mut builder = Builder::default().header(header).generate_comments(false);
let mut builder = Builder::default().header(header);
builder = builder.generate_comments(false);
builder = builder.derive_debug(false); // https://github.com/rust-lang/rust-bindgen/issues/372
builder = builder.clang_arg("-v");

18
third_party/rust/neqo-crypto/src/agent.rs поставляемый
Просмотреть файл

@ -75,7 +75,7 @@ fn get_alpn(fd: *mut ssl::PRFileDesc, pre: bool) -> Res<Option<String>> {
}
_ => None,
};
qinfo!([format!("{:p}", fd)] "got ALPN {:?}", alpn);
qinfo!([format!("{:p}", fd)], "got ALPN {:?}", alpn);
Ok(alpn)
}
@ -290,7 +290,11 @@ impl SecretAgent {
if st.is_none() {
*st = Some(alert.description);
} else {
qwarn!([format!("{:p}", fd)] "duplicate alert {}", alert.description);
qwarn!(
[format!("{:p}", fd)],
"duplicate alert {}",
alert.description
);
}
}
}
@ -510,7 +514,7 @@ impl SecretAgent {
fn capture_error<T>(&mut self, res: Res<T>) -> Res<T> {
if let Err(e) = &res {
qwarn!([self] "error: {:?}", e);
qwarn!([self], "error: {:?}", e);
self.state = HandshakeState::Failed(e.clone());
}
res
@ -528,7 +532,7 @@ impl SecretAgent {
let info = self.capture_error(SecretAgentInfo::new(self.fd))?;
HandshakeState::Complete(info)
};
qinfo!([self] "state -> {:?}", self.state);
qinfo!([self], "state -> {:?}", self.state);
Ok(())
}
@ -582,9 +586,9 @@ impl SecretAgent {
// Note that this is the test that ensures that we only do this for the server.
let eoed = Record::new(1, 22, END_OF_EARLY_DATA);
self.capture_error(eoed.write(self.fd))?;
self.no_eoed = false;
}
}
self.no_eoed = false;
Ok(())
}
@ -602,7 +606,7 @@ impl SecretAgent {
if let HandshakeState::Authenticated(ref err) = self.state {
let result =
secstatus_to_res(unsafe { ssl::SSL_AuthCertificateComplete(self.fd, *err) });
qdebug!([self] "SSL_AuthCertificateComplete: {:?}", result);
qdebug!([self], "SSL_AuthCertificateComplete: {:?}", result);
// This should return SECSuccess, so don't use update_state().
self.capture_error(result)?;
}
@ -679,7 +683,7 @@ impl Client {
let resumption = resumption_ptr.as_mut().unwrap();
let mut v = Vec::with_capacity(len as usize);
v.extend_from_slice(std::slice::from_raw_parts(token, len as usize));
qdebug!([format!("{:p}", fd)] "Got resumption token");
qdebug!([format!("{:p}", fd)], "Got resumption token");
*resumption = Some(v);
ssl::SECSuccess
}

8
third_party/rust/neqo-crypto/src/agentio.rs поставляемый
Просмотреть файл

@ -177,7 +177,7 @@ impl AgentIoInput {
}
let src = unsafe { std::slice::from_raw_parts(self.input, amount) };
qtrace!([self] "read {}", hex(src));
qtrace!([self], "read {}", hex(src));
let dst = unsafe { std::slice::from_raw_parts_mut(buf, amount) };
dst.copy_from_slice(&src);
self.input = self.input.wrapping_add(amount);
@ -186,7 +186,7 @@ impl AgentIoInput {
}
fn reset(&mut self) {
qtrace!([self] "reset");
qtrace!([self], "reset");
self.input = null();
self.available = 0;
}
@ -232,12 +232,12 @@ impl AgentIo {
// Stage output from TLS into the output buffer.
fn save_output(&mut self, buf: *const u8, count: usize) {
let slice = unsafe { std::slice::from_raw_parts(buf, count) };
qtrace!([self] "save output {}", hex(slice));
qtrace!([self], "save output {}", hex(slice));
self.output.extend_from_slice(slice);
}
pub fn take_output(&mut self) -> Vec<u8> {
qtrace!([self] "take output");
qtrace!([self], "take output");
mem::replace(&mut self.output, Vec::new())
}
}

1
third_party/rust/neqo-crypto/src/err.rs поставляемый
Просмотреть файл

@ -188,5 +188,4 @@ mod tests {
_ => panic!("bad error type"),
}
}
}

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"bde1a1af255191ae9785b8f438fe72addc291496e4fa7d140437de5828aa6d8c","src/client_events.rs":"c7022955c4c7c1257204948a0a2a88ccd895dfdb64b62ff76e56bc989d066277","src/connection.rs":"5a3003fad10db9c92ae5c4728e6944e3fc3433555cd210300908f4bf55eabe4f","src/connection_client.rs":"96395301b0b82aa09f3684b6f8571cab9261a1590565ad67209b71b40f610d81","src/connection_server.rs":"ec6c6182f4522b2c8bddbd441790bc8f07f122c35292dc227779c7a7574d8a43","src/control_stream_local.rs":"8b685d5236ea59914ca91f6bd9613586ede581ca400e54e8f429f9e51580774b","src/control_stream_remote.rs":"94ba2cdeeb1e76e7bab7ed19ef02b9516fb4c13f496a4c8066f92230c62cf083","src/hframe.rs":"15dce78028666c12dbc99e252f3db8e87659da9260fc7bf0d2d182cb9e6d3081","src/lib.rs":"8b5607f7dee014e11771ea05b4ed52fcd1eafe146ee8ebee75da742921867b57","src/server_events.rs":"374b40c645443eae19a0a039f74e3f5353b1a6373c7a3089e9f270db9609596e","src/stream_type_reader.rs":"e96f55f9e1df4e894d4d93250a79a4a46db1669d8c17353b94525db0a75c774e","src/transaction_client.rs":"d2664b0eb6505c6de9ec86d5c422d30576c42896e6bbbf5c907a9fd7e01caecd","src/transaction_server.rs":"9c1eb5a7cc81269a063fa891aeae0fc93bf773f23ead8a177452ea2dc425ff09","tests/httpconn.rs":"7a78d258bb940c88b3b935e4e3c76c103fb4d400ddfad14107b17a15759eb3e9"},"package":null}
{"files":{"Cargo.toml":"2c3a091954d90040b9d2bc7df2e2e2e2457da21186d69d4fe30fcf4cf3888a66","src/client_events.rs":"c7022955c4c7c1257204948a0a2a88ccd895dfdb64b62ff76e56bc989d066277","src/connection.rs":"30a79c660e6945fd193ab0eb27bf22014c4d246a5ee361aad5a5586e3c03b39f","src/connection_client.rs":"362f4774003c5c3b51eda02e9975943de15d3f244178c208407c62115942e867","src/control_stream_local.rs":"319f8277fc4765b31a4a094bfd663e681d71831532925b0043bae5da96202e64","src/control_stream_remote.rs":"1b96316d6eecc582436382517fcffdb2bb4f9d73194301bc3e2e253d3322e95e","src/hframe.rs":"6e65670cfe5944e88a0631e39d077c8e9d225fde650c978405816f1b2028c9a1","src/lib.rs":"908cb880d6b68c35085b768b67e866d1db0d3212d3bd0e6a76daf0d670b79d1c","src/server.rs":"4819dcfe998f036501b4900ce489c03cc3e24c45ca8825354daff826f7157316","src/server_connection_events.rs":"6ae07ca2c54a8b733a2e4cdd5594838f530224e7bb8233ecd9d7ad0838842bf2","src/server_events.rs":"e0a19bfc88b91d0584c1ec08da3005aae192471cbc37809a977dd6098f4e7dcc","src/stream_type_reader.rs":"be1ea1f553292b5447f0d6d89bdfa73732189db236ce34b4067cda0276229540","src/transaction_client.rs":"2e4a2ca83bdc6583697ab5b6e8c2767b4fd46fd4215f4fe9cf79891ad5523bd6","src/transaction_server.rs":"98ba7522fb20936e056cce2bbd1098ee94e748a58e7b4609772c87c349b12d85","tests/httpconn.rs":"7955f6ac4406b5d770e0fb10258aff529a1c01020374dfc5f85d8608abb68f6f"},"package":null}

2
third_party/rust/neqo-http3/Cargo.toml поставляемый
Просмотреть файл

@ -1,6 +1,6 @@
[package]
name = "neqo-http3"
version = "0.1.4"
version = "0.1.6"
authors = ["draganadamjanovic"]
edition = "2018"
license = "MIT/Apache-2.0"

367
third_party/rust/neqo-http3/src/connection.rs поставляемый
Просмотреть файл

@ -8,24 +8,17 @@ use crate::client_events::Http3ClientEvents;
use crate::control_stream_local::{ControlStreamLocal, HTTP3_UNI_STREAM_TYPE_CONTROL};
use crate::control_stream_remote::ControlStreamRemote;
use crate::hframe::{HFrame, HSettingType};
use crate::server_events::Http3ServerEvents;
use crate::server_connection_events::Http3ServerConnEvents;
use crate::stream_type_reader::NewStreamTypeReader;
use crate::transaction_client::TransactionClient;
use crate::transaction_server::TransactionServer;
use neqo_common::{matches, qdebug, qerror, qinfo, qtrace, qwarn, Datagram};
use neqo_crypto::AntiReplay;
use neqo_common::{matches, qdebug, qerror, qinfo, qtrace, qwarn};
use neqo_qpack::decoder::{QPackDecoder, QPACK_UNI_STREAM_TYPE_DECODER};
use neqo_qpack::encoder::{QPackEncoder, QPACK_UNI_STREAM_TYPE_ENCODER};
use neqo_transport::{
AppError, CloseError, Connection, ConnectionEvent, ConnectionIdManager, Output, Role, State,
StreamType,
};
use std::cell::RefCell;
use neqo_transport::{AppError, CloseError, Connection, ConnectionEvent, State, StreamType};
use std::collections::{BTreeSet, HashMap};
use std::fmt::Debug;
use std::mem;
use std::net::SocketAddr;
use std::rc::Rc;
use std::time::Instant;
use crate::{Error, Res};
@ -95,9 +88,9 @@ pub enum Http3State {
Closed(CloseError),
}
#[derive(Debug)]
pub struct Http3Connection<E: Http3Events, T: Http3Transaction, H: Http3Handler<E, T>> {
pub state: Http3State,
pub conn: Connection,
max_header_list_size: u64,
control_stream_local: ControlStreamLocal,
control_stream_remote: ControlStreamRemote,
@ -115,41 +108,19 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>> ::std
for Http3Connection<E, T, H>
{
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "Http3 connection {:?}", self.role())
write!(f, "Http3 connection")
}
}
impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
Http3Connection<E, T, H>
{
pub fn new_client(
server_name: &str,
protocols: &[impl AsRef<str>],
cid_manager: Rc<RefCell<dyn ConnectionIdManager>>,
local_addr: SocketAddr,
remote_addr: SocketAddr,
max_table_size: u32,
max_blocked_streams: u16,
) -> Res<Self> {
pub fn new(max_table_size: u32, max_blocked_streams: u16) -> Self {
if max_table_size > (1 << 30) - 1 {
panic!("Wrong max_table_size");
}
let conn =
Connection::new_client(server_name, protocols, cid_manager, local_addr, remote_addr)?;
Http3Connection::new_client_with_conn(conn, max_table_size, max_blocked_streams)
}
pub fn new_client_with_conn(
c: Connection,
max_table_size: u32,
max_blocked_streams: u16,
) -> Res<Self> {
if max_table_size > (1 << 30) - 1 {
panic!("Wrong max_table_size");
}
Ok(Http3Connection {
Http3Connection {
state: Http3State::Initializing,
conn: c,
max_header_list_size: MAX_HEADER_LIST_SIZE_DEFAULT,
control_stream_local: ControlStreamLocal::default(),
control_stream_remote: ControlStreamRemote::new(),
@ -161,47 +132,20 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
events: E::default(),
transactions: HashMap::new(),
handler: H::new(),
})
}
pub fn new_server(
certs: &[impl AsRef<str>],
protocols: &[impl AsRef<str>],
anti_replay: &AntiReplay,
cid_manager: Rc<RefCell<dyn ConnectionIdManager>>,
max_table_size: u32,
max_blocked_streams: u16,
) -> Res<Self> {
if max_table_size > (1 << 30) - 1 {
panic!("Wrong max_table_size");
}
Ok(Http3Connection {
state: Http3State::Initializing,
conn: Connection::new_server(certs, protocols, anti_replay, cid_manager)?,
max_header_list_size: MAX_HEADER_LIST_SIZE_DEFAULT,
control_stream_local: ControlStreamLocal::default(),
control_stream_remote: ControlStreamRemote::new(),
new_streams: HashMap::new(),
qpack_encoder: QPackEncoder::new(true),
qpack_decoder: QPackDecoder::new(max_table_size, max_blocked_streams),
settings_received: false,
streams_have_data_to_send: BTreeSet::new(),
events: E::default(),
transactions: HashMap::new(),
handler: H::new(),
})
}
fn initialize_http3_connection(&mut self) -> Res<()> {
qinfo!([self] "Initialize the http3 connection.");
self.control_stream_local.create(&mut self.conn)?;
fn initialize_http3_connection(&mut self, conn: &mut Connection) -> Res<()> {
qinfo!([self], "Initialize the http3 connection.");
self.control_stream_local.create(conn)?;
self.send_settings();
self.create_qpack_streams()?;
self.create_qpack_streams(conn)?;
Ok(())
}
fn send_settings(&mut self) {
qdebug!([self] "Send settings.");
qdebug!([self], "Send settings.");
self.control_stream_local.queue_frame(HFrame::Settings {
settings: vec![
(
@ -216,116 +160,87 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
});
}
fn create_qpack_streams(&mut self) -> Res<()> {
qdebug!([self] "create_qpack_streams.");
fn create_qpack_streams(&mut self, conn: &mut Connection) -> Res<()> {
qdebug!([self], "create_qpack_streams.");
self.qpack_encoder
.add_send_stream(self.conn.stream_create(StreamType::UniDi)?);
.add_send_stream(conn.stream_create(StreamType::UniDi)?);
self.qpack_decoder
.add_send_stream(self.conn.stream_create(StreamType::UniDi)?);
.add_send_stream(conn.stream_create(StreamType::UniDi)?);
Ok(())
}
// This function takes the provided result and check for an error.
// An error results in closing the connection.
fn check_result<ERR>(&mut self, now: Instant, res: Res<ERR>) -> bool {
fn check_result<ERR>(&mut self, conn: &mut Connection, now: Instant, res: Res<ERR>) -> bool {
match &res {
Err(e) => {
qinfo!([self] "Connection error: {}.", e);
self.close(now, e.code(), &format!("{}", e));
qinfo!([self], "Connection error: {}.", e);
self.close(conn, now, e.code(), &format!("{}", e));
self.events
.connection_state_change(Http3State::Closing(CloseError::Application(
e.code(),
)));
true
}
_ => false,
}
}
pub fn role(&self) -> Role {
self.conn.role()
}
pub fn process(&mut self, dgram: Option<Datagram>, now: Instant) -> Output {
qtrace!([self] "Process.");
if let Some(d) = dgram {
self.process_input(d, now);
}
self.process_http3(now);
self.process_output(now)
}
pub fn process_input(&mut self, dgram: Datagram, now: Instant) {
qtrace!([self] "Process input.");
self.conn.process_input(dgram, now);
}
pub fn process_timer(&mut self, now: Instant) {
qtrace!([self] "Process timer.");
self.conn.process_timer(now);
}
pub fn conn(&mut self) -> &mut Connection {
&mut self.conn
}
pub fn process_http3(&mut self, now: Instant) {
qtrace!([self] "Process http3 internal.");
pub fn process_http3(&mut self, conn: &mut Connection, now: Instant) {
qtrace!([self], "Process http3 internal.");
match self.state {
Http3State::Connected | Http3State::GoingAway => {
let res = self.check_connection_events();
if self.check_result(now, res) {
let res = self.check_connection_events(conn);
if self.check_result(conn, now, res) {
return;
}
let res = self.process_sending();
self.check_result(now, res);
let res = self.process_sending(conn);
self.check_result(conn, now, res);
}
Http3State::Closed { .. } => {}
_ => {
let res = self.check_connection_events();
let _ = self.check_result(now, res);
let res = self.check_connection_events(conn);
let _ = self.check_result(conn, now, res);
}
}
}
pub fn process_output(&mut self, now: Instant) -> Output {
qtrace!([self] "Process output.");
self.conn.process_output(now)
}
pub fn stream_stop_sending(&mut self, stream_id: u64, app_error: AppError) -> Res<()> {
self.conn.stream_stop_sending(stream_id, app_error)?;
Ok(())
}
pub fn insert_streams_have_data_to_send(&mut self, stream_id: u64) {
self.streams_have_data_to_send.insert(stream_id);
}
fn process_sending(&mut self) -> Res<()> {
pub fn has_data_to_send(&self) -> bool {
!self.streams_have_data_to_send.is_empty()
}
fn process_sending(&mut self, conn: &mut Connection) -> Res<()> {
// check if control stream has data to send.
self.control_stream_local.send(&mut self.conn)?;
self.control_stream_local.send(conn)?;
let to_send = mem::replace(&mut self.streams_have_data_to_send, BTreeSet::new());
for stream_id in to_send {
if let Some(t) = &mut self.transactions.get_mut(&stream_id) {
t.send(&mut self.conn, &mut self.qpack_encoder)?;
t.send(conn, &mut self.qpack_encoder)?;
if t.has_data_to_send() {
self.streams_have_data_to_send.insert(stream_id);
}
}
}
self.qpack_decoder.send(&mut self.conn)?;
self.qpack_encoder.send(&mut self.conn)?;
self.qpack_decoder.send(conn)?;
self.qpack_encoder.send(conn)?;
Ok(())
}
// If this return an error the connection must be closed.
fn check_connection_events(&mut self) -> Res<()> {
qtrace!([self] "Check connection events.");
while let Some(e) = self.conn.next_event() {
qdebug!([self] "check_connection_events - event {:?}.", e);
fn check_connection_events(&mut self, conn: &mut Connection) -> Res<()> {
qtrace!([self], "Check connection events.");
while let Some(e) = conn.next_event() {
qdebug!([self], "check_connection_events - event {:?}.", e);
match e {
ConnectionEvent::NewStream {
stream_id,
stream_type,
} => self.handle_new_stream(stream_id, stream_type)?,
} => self.handle_new_stream(conn, stream_id, stream_type)?,
ConnectionEvent::SendStreamWritable { stream_id } => {
self.handler.handle_send_stream_writable(
&mut self.transactions,
@ -334,19 +249,19 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
)?
}
ConnectionEvent::RecvStreamReadable { stream_id } => {
self.handle_stream_readable(stream_id)?
self.handle_stream_readable(conn, stream_id)?
}
ConnectionEvent::RecvStreamReset {
stream_id,
app_error,
} => self.handle_stream_reset(stream_id, app_error)?,
} => self.handle_stream_reset(conn, stream_id, app_error)?,
ConnectionEvent::SendStreamStopSending {
stream_id,
app_error,
} => self.handler.handle_stream_stop_sending(
&mut self.transactions,
&mut self.events,
&mut self.conn,
conn,
stream_id,
app_error,
)?,
@ -361,7 +276,7 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
.handle_authentication_needed(&mut self.events)?,
ConnectionEvent::StateChange(state) => {
match state {
State::Connected => self.handle_connection_connected()?,
State::Connected => self.handle_connection_connected(conn)?,
State::Closing { error, .. } => {
self.handle_connection_closing(error.clone().into())?
}
@ -380,8 +295,13 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
Ok(())
}
fn handle_new_stream(&mut self, stream_id: u64, stream_type: StreamType) -> Res<()> {
qinfo!([self] "A new stream: {:?} {}.", stream_type, stream_id);
fn handle_new_stream(
&mut self,
conn: &mut Connection,
stream_id: u64,
stream_type: StreamType,
) -> Res<()> {
qinfo!([self], "A new stream: {:?} {}.", stream_type, stream_id);
assert!(self.state_active());
match stream_type {
StreamType::BiDi => self.handler.handle_new_bidi_stream(
@ -397,7 +317,7 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
.new_streams
.entry(stream_id)
.or_insert_with(NewStreamTypeReader::new);
stream_type = ns.get_type(&mut self.conn, stream_id);
stream_type = ns.get_type(conn, stream_id);
fin = ns.fin();
}
@ -405,7 +325,7 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
self.new_streams.remove(&stream_id);
Ok(())
} else if let Some(t) = stream_type {
self.decode_new_stream(t, stream_id)?;
self.decode_new_stream(conn, t, stream_id)?;
self.new_streams.remove(&stream_id);
Ok(())
} else {
@ -415,8 +335,8 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
}
}
fn handle_stream_readable(&mut self, stream_id: u64) -> Res<()> {
qtrace!([self] "Readable stream {}.", stream_id);
fn handle_stream_readable(&mut self, conn: &mut Connection, stream_id: u64) -> Res<()> {
qtrace!([self], "Readable stream {}.", stream_id);
assert!(self.state_active());
@ -427,14 +347,14 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
};
let mut unblocked_streams: Vec<u64> = Vec::new();
if self.handle_read_stream(stream_id)? {
qdebug!([label] "Request/response stream {} read.", stream_id);
if self.handle_read_stream(conn, stream_id)? {
qdebug!([label], "Request/response stream {} read.", stream_id);
} else if self
.control_stream_remote
.receive_if_this_stream(&mut self.conn, stream_id)?
.receive_if_this_stream(conn, stream_id)?
{
qdebug!(
[self]
[self],
"The remote control stream ({}) is readable.",
stream_id
);
@ -443,32 +363,29 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
{
self.handle_control_frame()?;
self.control_stream_remote
.receive_if_this_stream(&mut self.conn, stream_id)?;
.receive_if_this_stream(conn, stream_id)?;
}
} else if self
.qpack_encoder
.recv_if_encoder_stream(&mut self.conn, stream_id)?
{
} else if self.qpack_encoder.recv_if_encoder_stream(conn, stream_id)? {
qdebug!(
[self]
[self],
"The qpack encoder stream ({}) is readable.",
stream_id
);
} else if self.qpack_decoder.is_recv_stream(stream_id) {
qdebug!(
[self]
[self],
"The qpack decoder stream ({}) is readable.",
stream_id
);
unblocked_streams = self.qpack_decoder.receive(&mut self.conn, stream_id)?;
unblocked_streams = self.qpack_decoder.receive(conn, stream_id)?;
} else if let Some(ns) = self.new_streams.get_mut(&stream_id) {
let stream_type = ns.get_type(&mut self.conn, stream_id);
let stream_type = ns.get_type(conn, stream_id);
let fin = ns.fin();
if fin {
self.new_streams.remove(&stream_id);
}
if let Some(t) = stream_type {
self.decode_new_stream(t, stream_id)?;
self.decode_new_stream(conn, t, stream_id)?;
self.new_streams.remove(&stream_id);
}
} else {
@ -482,14 +399,24 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
}
for stream_id in unblocked_streams {
qinfo!([self] "Stream {} is unblocked", stream_id);
self.handle_read_stream(stream_id)?;
qinfo!([self], "Stream {} is unblocked", stream_id);
self.handle_read_stream(conn, stream_id)?;
}
Ok(())
}
fn handle_stream_reset(&mut self, stream_id: u64, app_err: AppError) -> Res<()> {
qinfo!([self] "Handle a stream reset stream_id={} app_err={}", stream_id, app_err);
fn handle_stream_reset(
&mut self,
conn: &mut Connection,
stream_id: u64,
app_err: AppError,
) -> Res<()> {
qinfo!(
[self],
"Handle a stream reset stream_id={} app_err={}",
stream_id,
app_err
);
assert!(self.state_active());
@ -501,7 +428,7 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
t.stop_sending();
// close sending side of the transport stream as well. The server may have done
// it se well, but just to be sure.
let _ = self.conn.stream_reset_send(stream_id, app_err);
let _ = conn.stream_reset_send(stream_id, app_err);
// remove the stream
self.transactions.remove(&stream_id);
}
@ -512,11 +439,11 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
Ok(())
}
fn handle_connection_connected(&mut self) -> Res<()> {
fn handle_connection_connected(&mut self, conn: &mut Connection) -> Res<()> {
assert_eq!(self.state, Http3State::Initializing);
self.events.connection_state_change(Http3State::Connected);
self.state = Http3State::Connected;
self.initialize_http3_connection()
self.initialize_http3_connection(conn)
}
fn handle_connection_closing(&mut self, error_code: CloseError) -> Res<()> {
@ -534,7 +461,7 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
Ok(())
}
fn handle_read_stream(&mut self, stream_id: u64) -> Res<bool> {
fn handle_read_stream(&mut self, conn: &mut Connection, stream_id: u64) -> Res<bool> {
let label = if ::log::log_enabled!(::log::Level::Debug) {
format!("{}", self)
} else {
@ -544,10 +471,14 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
assert!(self.state_active());
if let Some(transaction) = &mut self.transactions.get_mut(&stream_id) {
qinfo!([label] "Request/response stream {} is readable.", stream_id);
match transaction.receive(&mut self.conn, &mut self.qpack_decoder) {
qinfo!(
[label],
"Request/response stream {} is readable.",
stream_id
);
match transaction.receive(conn, &mut self.qpack_decoder) {
Err(e) => {
qerror!([label] "Error {} ocurred", e);
qerror!([label], "Error {} ocurred", e);
return Err(e);
}
Ok(()) => {
@ -562,7 +493,12 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
}
}
fn decode_new_stream(&mut self, stream_type: u64, stream_id: u64) -> Res<()> {
fn decode_new_stream(
&mut self,
conn: &mut Connection,
stream_type: u64,
stream_id: u64,
) -> Res<()> {
match stream_type {
HTTP3_UNI_STREAM_TYPE_CONTROL => {
self.control_stream_remote.add_remote_stream(stream_id)?;
@ -570,43 +506,48 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
}
HTTP3_UNI_STREAM_TYPE_PUSH => {
qinfo!([self] "A new push stream {}.", stream_id);
qinfo!([self], "A new push stream {}.", stream_id);
self.handler.handle_new_push_stream()
}
QPACK_UNI_STREAM_TYPE_ENCODER => {
qinfo!([self] "A new remote qpack encoder stream {}", stream_id);
qinfo!([self], "A new remote qpack encoder stream {}", stream_id);
self.qpack_decoder
.add_recv_stream(stream_id)
.map_err(|_| Error::HttpStreamCreationError)
}
QPACK_UNI_STREAM_TYPE_DECODER => {
qinfo!([self] "A new remote qpack decoder stream {}", stream_id);
qinfo!([self], "A new remote qpack decoder stream {}", stream_id);
self.qpack_encoder
.add_recv_stream(stream_id)
.map_err(|_| Error::HttpStreamCreationError)
}
// TODO reserved stream types
_ => {
self.conn
.stream_stop_sending(stream_id, Error::HttpStreamCreationError.code())?;
conn.stream_stop_sending(stream_id, Error::HttpStreamCreationError.code())?;
Ok(())
}
}
}
pub fn close(&mut self, now: Instant, error: AppError, msg: &str) {
qinfo!([self] "Close connection error {:?} msg={}.", error, msg);
assert!(self.state_active());
self.state = Http3State::Closing(CloseError::Application(error));
if !self.transactions.is_empty() && (error == 0) {
qwarn!("close() called when streams still active");
pub fn close(&mut self, conn: &mut Connection, now: Instant, error: AppError, msg: &str) {
qinfo!([self], "Close connection error {:?} msg={}.", error, msg);
if !matches!(self.state, Http3State::Closing(_) | Http3State::Closed(_)) {
self.state = Http3State::Closing(CloseError::Application(error));
if !self.transactions.is_empty() && (error == 0) {
qwarn!("close() called when streams still active");
}
self.transactions.clear();
conn.close(now, error, msg);
}
self.transactions.clear();
self.conn.close(now, error, msg);
}
pub fn stream_reset(&mut self, stream_id: u64, error: AppError) -> Res<()> {
qinfo!([self] "Reset stream {} error={}.", stream_id, error);
pub fn stream_reset(
&mut self,
conn: &mut Connection,
stream_id: u64,
error: AppError,
) -> Res<()> {
qinfo!([self], "Reset stream {} error={}.", stream_id, error);
assert!(self.state_active());
let mut transaction = self
.transactions
@ -614,22 +555,22 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
.ok_or(Error::InvalidStreamId)?;
transaction.stop_sending();
// Stream maybe already be closed and we may get an error here, but we do not care.
let _ = self.conn.stream_reset_send(stream_id, error);
let _ = conn.stream_reset_send(stream_id, error);
transaction.reset_receiving_side();
// Stream maybe already be closed and we may get an error here, but we do not care.
self.conn.stream_stop_sending(stream_id, error)?;
conn.stream_stop_sending(stream_id, error)?;
self.events.remove_events_for_stream_id(stream_id);
Ok(())
}
pub fn stream_close_send(&mut self, stream_id: u64) -> Res<()> {
qinfo!([self] "Close sending side for stream {}.", stream_id);
pub fn stream_close_send(&mut self, conn: &mut Connection, stream_id: u64) -> Res<()> {
qinfo!([self], "Close sending side for stream {}.", stream_id);
assert!(self.state_active());
let transaction = self
.transactions
.get_mut(&stream_id)
.ok_or(Error::InvalidStreamId)?;
transaction.close_send(&mut self.conn)?;
transaction.close_send(conn)?;
if transaction.done() {
self.transactions.remove(&stream_id);
}
@ -642,15 +583,15 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
}
if self.control_stream_remote.frame_reader_done() {
let f = self.control_stream_remote.get_frame()?;
qinfo!([self] "Handle a control frame {:?}", f);
qinfo!([self], "Handle a control frame {:?}", f);
if let HFrame::Settings { .. } = f {
if self.settings_received {
qerror!([self] "SETTINGS frame already received");
qerror!([self], "SETTINGS frame already received");
return Err(Error::HttpFrameUnexpected);
}
self.settings_received = true;
} else if !self.settings_received {
qerror!([self] "SETTINGS frame not received");
qerror!([self], "SETTINGS frame not received");
return Err(Error::HttpMissingSettings);
}
return match f {
@ -673,9 +614,9 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
}
fn handle_settings(&mut self, s: &[(HSettingType, u64)]) -> Res<()> {
qinfo!([self] "Handle SETTINGS frame.");
qinfo!([self], "Handle SETTINGS frame.");
for (t, v) in s {
qinfo!([self] " {:?} = {:?}", t, v);
qinfo!([self], " {:?} = {:?}", t, v);
match t {
HSettingType::MaxHeaderListSize => {
self.max_header_list_size = *v;
@ -690,10 +631,7 @@ impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
}
fn state_active(&self) -> bool {
match self.state {
Http3State::Connected | Http3State::GoingAway => true,
_ => false,
}
matches!(self.state, Http3State::Connected | Http3State::GoingAway)
}
fn state_closing(&self) -> bool {
@ -731,7 +669,7 @@ impl Http3Handler<Http3ClientEvents, TransactionClient> for Http3ClientHandler {
fn handle_new_push_stream(&mut self) -> Res<()> {
// TODO implement PUSH
qerror!([self] "PUSH is not implemented!");
qerror!([self], "PUSH is not implemented!");
Err(Error::HttpIdError)
}
@ -751,7 +689,7 @@ impl Http3Handler<Http3ClientEvents, TransactionClient> for Http3ClientHandler {
events: &mut Http3ClientEvents,
stream_id: u64,
) -> Res<()> {
qtrace!([self] "Writable stream {}.", stream_id);
qtrace!([self], "Writable stream {}.", stream_id);
if let Some(t) = transactions.get_mut(&stream_id) {
if t.is_state_sending_data() {
@ -769,7 +707,12 @@ impl Http3Handler<Http3ClientEvents, TransactionClient> for Http3ClientHandler {
stop_stream_id: u64,
app_err: AppError,
) -> Res<()> {
qinfo!([self] "Handle stream_stop_sending stream_id={} app_err={}", stop_stream_id, app_err);
qinfo!(
[self],
"Handle stream_stop_sending stream_id={} app_err={}",
stop_stream_id,
app_err
);
if let Some(t) = transactions.get_mut(&stop_stream_id) {
// close sending side.
@ -802,7 +745,7 @@ impl Http3Handler<Http3ClientEvents, TransactionClient> for Http3ClientHandler {
state: &mut Http3State,
goaway_stream_id: u64,
) -> Res<()> {
qinfo!([self] "handle_goaway");
qinfo!([self], "handle_goaway");
// Issue reset events for streams >= goaway stream id
for id in transactions
.iter()
@ -823,7 +766,7 @@ impl Http3Handler<Http3ClientEvents, TransactionClient> for Http3ClientHandler {
}
fn handle_max_push_id(&mut self, stream_id: u64) -> Res<()> {
qerror!([self] "handle_max_push_id={}.", stream_id);
qerror!([self], "handle_max_push_id={}.", stream_id);
Err(Error::HttpFrameUnexpected)
}
@ -839,31 +782,31 @@ impl ::std::fmt::Display for Http3ClientHandler {
}
}
#[derive(Default)]
#[derive(Default, Debug)]
pub struct Http3ServerHandler {}
impl Http3Handler<Http3ServerEvents, TransactionServer> for Http3ServerHandler {
impl Http3Handler<Http3ServerConnEvents, TransactionServer> for Http3ServerHandler {
fn new() -> Self {
Http3ServerHandler::default()
}
fn handle_stream_creatable(
&mut self,
_events: &mut Http3ServerEvents,
_events: &mut Http3ServerConnEvents,
_stream_type: StreamType,
) -> Res<()> {
Ok(())
}
fn handle_new_push_stream(&mut self) -> Res<()> {
qerror!([self] "Error: server receives a push stream!");
qerror!([self], "Error: server receives a push stream!");
Err(Error::HttpStreamCreationError)
}
fn handle_new_bidi_stream(
&mut self,
transactions: &mut HashMap<u64, TransactionServer>,
events: &mut Http3ServerEvents,
events: &mut Http3ServerConnEvents,
stream_id: u64,
) -> Res<()> {
transactions.insert(stream_id, TransactionServer::new(stream_id, events.clone()));
@ -873,7 +816,7 @@ impl Http3Handler<Http3ServerEvents, TransactionServer> for Http3ServerHandler {
fn handle_send_stream_writable(
&mut self,
_transactions: &mut HashMap<u64, TransactionServer>,
_events: &mut Http3ServerEvents,
_events: &mut Http3ServerConnEvents,
_stream_id: u64,
) -> Res<()> {
Ok(())
@ -882,18 +825,18 @@ impl Http3Handler<Http3ServerEvents, TransactionServer> for Http3ServerHandler {
fn handle_goaway(
&mut self,
_transactions: &mut HashMap<u64, TransactionServer>,
_events: &mut Http3ServerEvents,
_events: &mut Http3ServerConnEvents,
_state: &mut Http3State,
_goaway_stream_id: u64,
) -> Res<()> {
qerror!([self] "handle_goaway");
qerror!([self], "handle_goaway");
Err(Error::HttpFrameUnexpected)
}
fn handle_stream_stop_sending(
&mut self,
_transactions: &mut HashMap<u64, TransactionServer>,
_events: &mut Http3ServerEvents,
_events: &mut Http3ServerConnEvents,
_conn: &mut Connection,
_stop_stream_id: u64,
_app_err: AppError,
@ -902,12 +845,12 @@ impl Http3Handler<Http3ServerEvents, TransactionServer> for Http3ServerHandler {
}
fn handle_max_push_id(&mut self, stream_id: u64) -> Res<()> {
qinfo!([self] "handle_max_push_id={}.", stream_id);
qinfo!([self], "handle_max_push_id={}.", stream_id);
// TODO
Ok(())
}
fn handle_authentication_needed(&self, _events: &mut Http3ServerEvents) -> Res<()> {
fn handle_authentication_needed(&self, _events: &mut Http3ServerConnEvents) -> Res<()> {
Err(Error::HttpInternalError)
}
}

Просмотреть файл

@ -20,12 +20,13 @@ use std::time::Instant;
use crate::{Error, Res};
pub struct Http3Client {
conn: Connection,
base_handler: Http3Connection<Http3ClientEvents, TransactionClient, Http3ClientHandler>,
}
impl ::std::fmt::Display for Http3Client {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "Http3 connection {:?}", self.role())
write!(f, "Http3 client")
}
}
@ -40,15 +41,14 @@ impl Http3Client {
max_blocked_streams: u16,
) -> Res<Http3Client> {
Ok(Http3Client {
base_handler: Http3Connection::new_client(
conn: Connection::new_client(
server_name,
protocols,
cid_manager,
local_addr,
remote_addr,
max_table_size,
max_blocked_streams,
)?,
base_handler: Http3Connection::new(max_table_size, max_blocked_streams),
})
}
@ -58,16 +58,13 @@ impl Http3Client {
max_blocked_streams: u16,
) -> Res<Http3Client> {
Ok(Http3Client {
base_handler: Http3Connection::new_client_with_conn(
c,
max_table_size,
max_blocked_streams,
)?,
conn: c,
base_handler: Http3Connection::new(max_table_size, max_blocked_streams),
})
}
pub fn role(&self) -> Role {
self.base_handler.role()
self.conn.role()
}
pub fn state(&self) -> Http3State {
@ -75,21 +72,21 @@ impl Http3Client {
}
pub fn tls_info(&self) -> Option<&SecretAgentInfo> {
self.base_handler.conn.tls_info()
self.conn.tls_info()
}
/// Get the peer's certificate.
pub fn peer_certificate(&self) -> Option<CertificateInfo> {
self.base_handler.conn.peer_certificate()
self.conn.peer_certificate()
}
pub fn authenticated(&mut self, status: AuthenticationStatus, now: Instant) {
self.base_handler.conn.authenticated(status, now);
self.conn.authenticated(status, now);
}
pub fn close(&mut self, now: Instant, error: AppError, msg: &str) {
qinfo!([self] "Close the connection error={} msg={}.", error, msg);
self.base_handler.close(now, error, msg);
qinfo!([self], "Close the connection error={} msg={}.", error, msg);
self.base_handler.close(&mut self.conn, now, error, msg);
}
pub fn fetch(
@ -101,14 +98,14 @@ impl Http3Client {
headers: &[Header],
) -> Res<u64> {
qinfo!(
[self]
[self],
"Fetch method={}, scheme={}, host={}, path={}",
method,
scheme,
host,
path
);
let id = self.base_handler.conn().stream_create(StreamType::BiDi)?;
let id = self.conn.stream_create(StreamType::BiDi)?;
self.base_handler.add_transaction(
id,
TransactionClient::new(
@ -125,26 +122,33 @@ impl Http3Client {
}
pub fn stream_reset(&mut self, stream_id: u64, error: AppError) -> Res<()> {
qinfo!([self] "reset_stream {} error={}.", stream_id, error);
self.base_handler.stream_reset(stream_id, error)
qinfo!([self], "reset_stream {} error={}.", stream_id, error);
self.base_handler
.stream_reset(&mut self.conn, stream_id, error)
}
pub fn stream_close_send(&mut self, stream_id: u64) -> Res<()> {
qinfo!([self] "Close senidng side stream={}.", stream_id);
self.base_handler.stream_close_send(stream_id)
qinfo!([self], "Close senidng side stream={}.", stream_id);
self.base_handler
.stream_close_send(&mut self.conn, stream_id)
}
pub fn send_request_body(&mut self, stream_id: u64, buf: &[u8]) -> Res<usize> {
qinfo!([self] "send_request_body from stream {} sending {} bytes.", stream_id, buf.len());
qinfo!(
[self],
"send_request_body from stream {} sending {} bytes.",
stream_id,
buf.len()
);
self.base_handler
.transactions
.get_mut(&stream_id)
.ok_or(Error::InvalidStreamId)?
.send_request_body(&mut self.base_handler.conn, buf)
.send_request_body(&mut self.conn, buf)
}
pub fn read_response_headers(&mut self, stream_id: u64) -> Res<(Vec<Header>, bool)> {
qinfo!([self] "read_response_headers from stream {}.", stream_id);
qinfo!([self], "read_response_headers from stream {}.", stream_id);
let transaction = self
.base_handler
.transactions
@ -167,14 +171,14 @@ impl Http3Client {
stream_id: u64,
buf: &mut [u8],
) -> Res<(usize, bool)> {
qinfo!([self] "read_data from stream {}.", stream_id);
qinfo!([self], "read_data from stream {}.", stream_id);
let transaction = self
.base_handler
.transactions
.get_mut(&stream_id)
.ok_or(Error::InvalidStreamId)?;
match transaction.read_response_data(&mut self.base_handler.conn, buf) {
match transaction.read_response_data(&mut self.conn, buf) {
Ok((amount, fin)) => {
if fin {
self.base_handler.transactions.remove(&stream_id);
@ -184,10 +188,7 @@ impl Http3Client {
// pick up subsequent already-received data frames in
// the stream even if no new packets arrive to cause
// process_http3() to run.
transaction.receive(
&mut self.base_handler.conn,
&mut self.base_handler.qpack_decoder,
)?;
transaction.receive(&mut self.conn, &mut self.base_handler.qpack_decoder)?;
}
Ok((amount, fin))
}
@ -219,33 +220,37 @@ impl Http3Client {
}
pub fn process(&mut self, dgram: Option<Datagram>, now: Instant) -> Output {
qtrace!([self] "Process.");
self.base_handler.process(dgram, now)
qtrace!([self], "Process.");
if let Some(d) = dgram {
self.process_input(d, now);
}
self.process_http3(now);
self.process_output(now)
}
pub fn process_input(&mut self, dgram: Datagram, now: Instant) {
qtrace!([self] "Process input.");
self.base_handler.process_input(dgram, now);
qtrace!([self], "Process input.");
self.conn.process_input(dgram, now);
}
pub fn process_timer(&mut self, now: Instant) {
qtrace!([self] "Process timer.");
self.base_handler.process_timer(now);
qtrace!([self], "Process timer.");
self.conn.process_timer(now);
}
pub fn conn(&mut self) -> &mut Connection {
&mut self.base_handler.conn
&mut self.conn
}
pub fn process_http3(&mut self, now: Instant) {
qtrace!([self] "Process http3 internal.");
qtrace!([self], "Process http3 internal.");
self.base_handler.process_http3(now);
self.base_handler.process_http3(&mut self.conn, now);
}
pub fn process_output(&mut self, now: Instant) -> Output {
qtrace!([self] "Process output.");
self.base_handler.process_output(now)
qtrace!([self], "Process output.");
self.conn.process_output(now)
}
}

Просмотреть файл

@ -34,7 +34,7 @@ impl ControlStreamLocal {
pub fn send(&mut self, conn: &mut Connection) -> Res<()> {
if let Some(stream_id) = self.stream_id {
if !self.buf.is_empty() {
qtrace!([self] "sending data.");
qtrace!([self], "sending data.");
let sent = conn.stream_send(stream_id, &self.buf[..])?;
if sent == self.buf.len() {
self.buf.clear();
@ -48,7 +48,7 @@ impl ControlStreamLocal {
}
pub fn create(&mut self, conn: &mut Connection) -> Res<()> {
qtrace!([self] "Create a control stream.");
qtrace!([self], "Create a control stream.");
self.stream_id = Some(conn.stream_create(StreamType::UniDi)?);
let mut enc = Encoder::default();
enc.encode_varint(HTTP3_UNI_STREAM_TYPE_CONTROL as u64);

Просмотреть файл

@ -33,9 +33,9 @@ impl ControlStreamRemote {
}
pub fn add_remote_stream(&mut self, stream_id: u64) -> Res<()> {
qinfo!([self] "A new control stream {}.", stream_id);
qinfo!([self], "A new control stream {}.", stream_id);
if self.stream_id.is_some() {
qdebug!([self] "A control stream already exists");
qdebug!([self], "A control stream already exists");
return Err(Error::HttpStreamCreationError);
}
self.stream_id = Some(stream_id);
@ -45,7 +45,7 @@ impl ControlStreamRemote {
pub fn receive_if_this_stream(&mut self, conn: &mut Connection, stream_id: u64) -> Res<bool> {
if let Some(id) = self.stream_id {
if id == stream_id {
qdebug!([self] "Receiving data.");
qdebug!([self], "Receiving data.");
self.fin = self.frame_reader.receive(conn, stream_id)?;
return Ok(true);
}

32
third_party/rust/neqo-http3/src/hframe.rs поставляемый
Просмотреть файл

@ -213,7 +213,7 @@ impl HFrameReader {
let fin;
let mut input = match conn.stream_recv(stream_id, &mut buf[..]) {
Ok((0, true)) => {
qtrace!([conn] "HFrameReader::receive: stream has been closed");
qtrace!([conn], "HFrameReader::receive: stream has been closed");
break match self.state {
HFrameReaderState::BeforeFrame => Ok(true),
_ => Err(Error::HttpFrameError),
@ -221,12 +221,22 @@ impl HFrameReader {
}
Ok((0, false)) => break Ok(false),
Ok((amount, f)) => {
qtrace!([conn] "HFrameReader::receive: reading {} byte, fin={}", amount, f);
qtrace!(
[conn],
"HFrameReader::receive: reading {} byte, fin={}",
amount,
f
);
fin = f;
Decoder::from(&buf[..amount])
}
Err(e) => {
qdebug!([conn] "HFrameReader::receive: error reading data from stream {}: {:?}", stream_id, e);
qdebug!(
[conn],
"HFrameReader::receive: error reading data from stream {}: {:?}",
stream_id,
e
);
break Err(e.into());
}
};
@ -238,7 +248,7 @@ impl HFrameReader {
match self.state {
HFrameReaderState::BeforeFrame | HFrameReaderState::GetType => match progress {
IncrementalDecoderResult::Uint(v) => {
qtrace!([conn] "HFrameReader::receive: read frame type {}", v);
qtrace!([conn], "HFrameReader::receive: read frame type {}", v);
self.hframe_type = v;
self.decoder = IncrementalDecoder::decode_varint();
self.state = HFrameReaderState::GetLength;
@ -252,7 +262,12 @@ impl HFrameReader {
HFrameReaderState::GetLength => {
match progress {
IncrementalDecoderResult::Uint(len) => {
qtrace!([conn] "HFrameReader::receive: frame type {} length {}", self.hframe_type, len);
qtrace!(
[conn],
"HFrameReader::receive: frame type {} length {}",
self.hframe_type,
len
);
self.hframe_len = len;
self.state = match self.hframe_type {
// DATA and HEADERS payload are left on the quic stream and picked up separately
@ -310,7 +325,12 @@ impl HFrameReader {
HFrameReaderState::GetData => {
match progress {
IncrementalDecoderResult::Buffer(data) => {
qtrace!([conn] "received frame {}: {}", self.hframe_type, hex(&data[..]));
qtrace!(
[conn],
"received frame {}: {}",
self.hframe_type,
hex(&data[..])
);
self.payload = data;
self.state = HFrameReaderState::Done;
}

6
third_party/rust/neqo-http3/src/lib.rs поставляемый
Просмотреть файл

@ -9,14 +9,16 @@
mod client_events;
mod connection;
pub mod connection_client;
pub mod connection_server;
mod control_stream_local;
mod control_stream_remote;
pub mod hframe;
pub mod server;
mod server_connection_events;
mod server_events;
mod stream_type_reader;
mod transaction_client;
pub mod transaction_server;
//pub mod server;
use neqo_qpack;
use neqo_transport;
@ -25,8 +27,8 @@ pub use neqo_transport::Output;
pub use client_events::Http3ClientEvent;
pub use connection::Http3State;
pub use connection_client::Http3Client;
pub use connection_server::Http3Server;
pub use neqo_qpack::Header;
pub use server::Http3Server;
pub use server_events::Http3ServerEvent;
pub use transaction_server::TransactionServer;

Просмотреть файл

@ -4,139 +4,169 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use crate::connection::{Http3Connection, Http3ServerHandler, Http3State};
use crate::server_events::{Http3ServerEvent, Http3ServerEvents};
use crate::transaction_server::TransactionServer;
use crate::{Error, Header, Res};
use neqo_common::{qdebug, qinfo, qtrace, Datagram};
use crate::connection::Http3State;
use crate::server_connection_events::Http3ServerConnEvent;
use crate::server_events::{
ClientRequestStream, Http3Handler, Http3ServerEvent, Http3ServerEvents,
};
use crate::Res;
use neqo_common::{qtrace, Datagram};
use neqo_crypto::AntiReplay;
use neqo_transport::{AppError, Connection, ConnectionIdManager, Output, Role};
use neqo_transport::server::{ActiveConnectionRef, Server};
use neqo_transport::{ConnectionIdManager, Output};
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use std::time::Instant;
type HandlerRef = Rc<RefCell<Http3Handler>>;
pub struct Http3Server {
base_handler: Http3Connection<Http3ServerEvents, TransactionServer, Http3ServerHandler>,
server: Server,
max_table_size: u32,
max_blocked_streams: u16,
connections: HashMap<ActiveConnectionRef, HandlerRef>,
events: Http3ServerEvents,
}
impl ::std::fmt::Display for Http3Server {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "Http3 connection {:?}", self.role())
write!(f, "Http3 server ")
}
}
impl Http3Server {
pub fn new(
now: Instant,
certs: &[impl AsRef<str>],
protocols: &[impl AsRef<str>],
anti_replay: &AntiReplay,
anti_replay: AntiReplay,
cid_manager: Rc<RefCell<dyn ConnectionIdManager>>,
max_table_size: u32,
max_blocked_streams: u16,
) -> Res<Http3Server> {
Ok(Http3Server {
base_handler: Http3Connection::new_server(
certs,
protocols,
anti_replay,
cid_manager,
max_table_size,
max_blocked_streams,
)?,
server: Server::new(now, certs, protocols, anti_replay, cid_manager)?,
max_table_size,
max_blocked_streams,
connections: HashMap::new(),
events: Http3ServerEvents::default(),
})
}
fn role(&self) -> Role {
self.base_handler.role()
}
pub fn process(&mut self, dgram: Option<Datagram>, now: Instant) -> Output {
qtrace!([self] "Process.");
self.base_handler.process(dgram, now)
}
pub fn process_input(&mut self, dgram: Datagram, now: Instant) {
qtrace!([self] "Process input.");
self.base_handler.process_input(dgram, now);
}
pub fn process_timer(&mut self, now: Instant) {
qtrace!([self] "Process timer.");
self.base_handler.process_timer(now);
}
pub fn conn(&mut self) -> &mut Connection {
&mut self.base_handler.conn
qtrace!([self], "Process.");
let out = self.server.process(dgram, now);
self.process_http3(now);
// If we do not that a dgram already try again after process_http3.
match out {
Output::Datagram(d) => {
qtrace!([self], "Send packet: {:?}", d);
Output::Datagram(d)
}
_ => self.server.process(None, now),
}
}
pub fn process_http3(&mut self, now: Instant) {
qtrace!([self] "Process http3 internal.");
self.base_handler.process_http3(now);
}
qtrace!([self], "Process http3 internal.");
let mut active_conns = self.server.active_connections();
pub fn process_output(&mut self, now: Instant) -> Output {
qtrace!([self] "Process output.");
self.base_handler.process_output(now)
}
// We need to find connections that needs to be process on http3 level.
let mut http3_active: Vec<ActiveConnectionRef> = self
.connections
.iter()
.filter(|(conn, handler)| {
handler.borrow().should_be_processed() && !active_conns.contains(&conn)
})
.map(|(conn, _)| conn)
.cloned()
.collect();
// For http_active connection we need to put them in neqo-transport's server
// waiting queue.
http3_active
.iter()
.for_each(|conn| self.server.add_to_waiting(conn.clone()));
active_conns.append(&mut http3_active);
active_conns.dedup();
let max_table_size = self.max_table_size;
let max_blocked_streams = self.max_blocked_streams;
for mut conn in active_conns {
let handler = self.connections.entry(conn.clone()).or_insert_with(|| {
Rc::new(RefCell::new(Http3Handler::new(
max_table_size,
max_blocked_streams,
)))
});
pub fn close(&mut self, now: Instant, error: AppError, msg: &str) {
qinfo!([self] "Close connection.");
self.base_handler.close(now, error, msg);
}
pub fn state(&self) -> Http3State {
self.base_handler.state.clone()
handler
.borrow_mut()
.process_http3(&mut conn.borrow_mut(), now);
let mut remove = false;
while let Some(e) = handler.borrow_mut().next_event() {
match e {
Http3ServerConnEvent::Headers {
stream_id,
headers,
fin,
} => self.events.headers(
ClientRequestStream::new(conn.clone(), handler.clone(), stream_id),
headers,
fin,
),
Http3ServerConnEvent::Data {
stream_id,
data,
fin,
} => self.events.data(
ClientRequestStream::new(conn.clone(), handler.clone(), stream_id),
data,
fin,
),
Http3ServerConnEvent::StateChange(state) => {
self.events
.connection_state_change(conn.clone(), state.clone());
if let Http3State::Closed { .. } = state {
remove = true;
}
}
_ => {}
}
}
if remove {
self.connections.remove(&conn.clone());
}
}
}
/// Get all current events. Best used just in debug/testing code, use
/// next_event() instead.
pub fn events(&mut self) -> impl Iterator<Item = Http3ServerEvent> {
self.base_handler.events.events()
self.events.events()
}
/// Return true if there are outstanding events.
pub fn has_events(&self) -> bool {
self.base_handler.events.has_events()
self.events.has_events()
}
/// Get events that indicate state changes on the connection. This method
/// correctly handles cases where handling one event can obsolete
/// previously-queued events, or cause new events to be generated.
pub fn next_event(&mut self) -> Option<Http3ServerEvent> {
self.base_handler.events.next_event()
}
pub fn set_response(&mut self, stream_id: u64, headers: &[Header], data: Vec<u8>) -> Res<()> {
qinfo!([self] "Set new respons for stream {}.", stream_id);
self.base_handler
.transactions
.get_mut(&stream_id)
.ok_or(Error::InvalidStreamId)?
.set_response(headers, data, &mut self.base_handler.qpack_encoder);
self.base_handler
.insert_streams_have_data_to_send(stream_id);
Ok(())
}
pub fn stream_stop_sending(&mut self, stream_id: u64, app_error: AppError) -> Res<()> {
qdebug!([self] "stop sending stream_id:{} error:{}.", stream_id, app_error);
self.base_handler.stream_stop_sending(stream_id, app_error)
}
pub fn stream_reset(&mut self, stream_id: u64, app_error: AppError) -> Res<()> {
qdebug!([self] "reset stream_id:{} error:{}.", stream_id, app_error);
self.base_handler.stream_reset(stream_id, app_error)
self.events.next_event()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Error;
use neqo_common::matches;
use neqo_crypto::AuthenticationStatus;
use neqo_qpack::encoder::QPackEncoder;
use neqo_transport::{
CloseError, ConnectionEvent, FixedConnectionIdManager, State, StreamType,
CloseError, Connection, ConnectionEvent, FixedConnectionIdManager, State, StreamType,
};
use test_fixture::*;
@ -144,9 +174,10 @@ mod tests {
pub fn default_http3_server() -> Http3Server {
fixture_init();
Http3Server::new(
now(),
DEFAULT_KEYS,
DEFAULT_ALPN,
&anti_replay(),
anti_replay(),
Rc::new(RefCell::new(FixedConnectionIdManager::new(5))),
100,
100,
@ -154,13 +185,29 @@ mod tests {
.expect("create a default server")
}
fn assert_closed(hconn: &Http3Server, expected: Error) {
match hconn.state() {
Http3State::Closing(err) | Http3State::Closed(err) => {
assert_eq!(err, CloseError::Application(expected.code()))
}
_ => panic!("Wrong state {:?}", hconn.state()),
fn assert_closed(hconn: &mut Http3Server, expected: Error) {
let err = CloseError::Application(expected.code());
let closed = |e| {
matches!(e,
Http3ServerEvent::StateChange{ state: Http3State::Closing(e), .. }
| Http3ServerEvent::StateChange{ state: Http3State::Closed(e), .. }
if e == err)
};
assert!(hconn.events().any(closed));
}
fn assert_connected(hconn: &mut Http3Server) {
let connected =
|e| matches!(e, Http3ServerEvent::StateChange{ state: Http3State::Connected, ..} );
assert!(hconn.events().any(connected));
}
fn assert_not_closed(hconn: &mut Http3Server) {
let closed = |e| {
matches!(e,
Http3ServerEvent::StateChange{ state: Http3State::Closing(..), .. })
};
assert!(!hconn.events().any(closed));
}
// Start a client/server and check setting frame.
@ -176,7 +223,6 @@ mod tests {
let mut hconn = default_http3_server();
let mut neqo_trans_conn = default_client();
assert_eq!(hconn.state(), Http3State::Initializing);
let out = neqo_trans_conn.process(None, now());
let out = hconn.process(out.dgram(), now());
let out = neqo_trans_conn.process(out.dgram(), now());
@ -186,7 +232,7 @@ mod tests {
neqo_trans_conn.authenticated(AuthenticationStatus::Ok, now());
let out = neqo_trans_conn.process(None, now());
let out = hconn.process(out.dgram(), now());
assert_eq!(hconn.state(), Http3State::Connected);
assert_connected(&mut hconn);
neqo_trans_conn.process(out.dgram(), now());
let mut connected = false;
@ -271,7 +317,7 @@ mod tests {
hconn.process(out.dgram(), now());
// assert no error occured.
assert_eq!(hconn.state(), Http3State::Connected);
assert_not_closed(&mut hconn);
(
hconn,
PeerConnection {
@ -298,7 +344,7 @@ mod tests {
.unwrap();
let out = peer_conn.conn.process(None, now());
hconn.process(out.dgram(), now());
assert_closed(&hconn, Error::HttpClosedCriticalStream);
assert_closed(&mut hconn, Error::HttpClosedCriticalStream);
}
// Server: test missing SETTINGS frame
@ -313,7 +359,7 @@ mod tests {
assert_eq!(sent, Ok(4));
let out = neqo_trans_conn.process(None, now());
hconn.process(out.dgram(), now());
assert_closed(&hconn, Error::HttpMissingSettings);
assert_closed(&mut hconn, Error::HttpMissingSettings);
}
// Server: receiving SETTINGS frame twice causes connection close
@ -329,7 +375,7 @@ mod tests {
assert_eq!(sent, Ok(8));
let out = peer_conn.conn.process(None, now());
hconn.process(out.dgram(), now());
assert_closed(&hconn, Error::HttpFrameUnexpected);
assert_closed(&mut hconn, Error::HttpFrameUnexpected);
}
fn test_wrong_frame_on_control_stream(v: &[u8]) {
@ -340,8 +386,7 @@ mod tests {
let out = peer_conn.conn.process(None, now());
hconn.process(out.dgram(), now());
assert_closed(&hconn, Error::HttpFrameUnexpected);
assert_closed(&mut hconn, Error::HttpFrameUnexpected);
}
// send DATA frame on a cortrol stream
@ -382,6 +427,8 @@ mod tests {
let out = peer_conn.conn.process(None, now());
let out = hconn.process(out.dgram(), now());
peer_conn.conn.process(out.dgram(), now());
let out = hconn.process(None, now());
peer_conn.conn.process(out.dgram(), now());
// check for stop-sending with Error::HttpStreamCreationError.
let mut stop_sending_event_found = false;
@ -397,7 +444,7 @@ mod tests {
}
}
assert!(stop_sending_event_found);
assert_eq!(hconn.state(), Http3State::Connected);
assert_not_closed(&mut hconn);
}
// Server: receiving a push stream on a server should cause WrongStreamDirection
@ -411,7 +458,7 @@ mod tests {
let out = peer_conn.conn.process(None, now());
let out = hconn.process(out.dgram(), now());
peer_conn.conn.process(out.dgram(), now());
assert_closed(&hconn, Error::HttpStreamCreationError);
assert_closed(&mut hconn, Error::HttpStreamCreationError);
}
//// Test reading of a slowly streamed frame. bytes are received one by one
@ -459,7 +506,7 @@ mod tests {
let out = peer_conn.process(None, now());
hconn.process(out.dgram(), now());
assert_eq!(hconn.state(), Http3State::Connected);
assert_not_closed(&mut hconn);
// Now test PushPromise
sent = peer_conn.stream_send(control_stream, &[0x5]);
@ -478,7 +525,7 @@ mod tests {
hconn.process(out.dgram(), now());
// PUSH_PROMISE on a control stream will cause an error
assert_closed(&hconn, Error::HttpFrameUnexpected);
assert_closed(&mut hconn, Error::HttpFrameUnexpected);
}
// Test reading of a slowly streamed frame. bytes are received one by one
@ -493,7 +540,7 @@ mod tests {
let out = peer_conn.process(None, now());
hconn.process(out.dgram(), now());
assert_closed(&hconn, Error::HttpFrameError);
assert_closed(&mut hconn, Error::HttpFrameError);
}
const REQUEST_WITH_BODY: &[u8] = &[
@ -554,7 +601,7 @@ mod tests {
headers_frames += 1;
}
Http3ServerEvent::Data {
stream_id,
mut request,
data,
fin,
} => {
@ -563,9 +610,8 @@ mod tests {
} else {
assert_eq!(data, &REQUEST_WITH_BODY[25..]);
assert_eq!(fin, true);
hconn
request
.set_response(
stream_id,
&[
(String::from(":status"), String::from("200")),
(String::from("content-length"), String::from("3")),
@ -602,7 +648,7 @@ mod tests {
while let Some(event) = hconn.next_event() {
match event {
Http3ServerEvent::Headers {
stream_id,
mut request,
headers,
fin,
} => {
@ -617,12 +663,11 @@ mod tests {
);
assert_eq!(fin, false);
headers_frames += 1;
hconn
.stream_stop_sending(stream_id, Error::HttpEarlyResponse.code())
request
.stream_stop_sending(Error::HttpEarlyResponse.code())
.unwrap();
hconn
request
.set_response(
stream_id,
&[
(String::from(":status"), String::from("200")),
(String::from("content-length"), String::from("3")),
@ -683,11 +728,10 @@ mod tests {
while let Some(event) = hconn.next_event() {
match event {
Http3ServerEvent::Headers {
stream_id,
mut request,
headers,
fin,
} => {
assert_eq!(request_stream_id, stream_id);
assert_eq!(
headers,
vec![
@ -699,8 +743,8 @@ mod tests {
);
assert_eq!(fin, false);
headers_frames += 1;
hconn
.stream_reset(stream_id, Error::HttpRequestRejected.code())
request
.stream_reset(Error::HttpRequestRejected.code())
.unwrap();
}
Http3ServerEvent::Data { .. } => {

97
third_party/rust/neqo-http3/src/server_connection_events.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,97 @@
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use crate::connection::{Http3Events, Http3State};
use crate::Header;
use neqo_common::matches;
use neqo_transport::AppError;
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)]
pub enum Http3ServerConnEvent {
/// Headers are ready.
Headers {
stream_id: u64,
headers: Vec<Header>,
fin: bool,
},
/// Request data is ready.
Data {
stream_id: u64,
data: Vec<u8>,
fin: bool,
},
/// Peer reset the stream.
Reset { stream_id: u64, error: AppError },
/// Connection state change.
StateChange(Http3State),
}
#[derive(Debug, Default, Clone)]
pub struct Http3ServerConnEvents {
events: Rc<RefCell<VecDeque<Http3ServerConnEvent>>>,
}
impl Http3ServerConnEvents {
fn insert(&self, event: Http3ServerConnEvent) {
self.events.borrow_mut().push_back(event);
}
fn remove<F>(&self, f: F)
where
F: Fn(&Http3ServerConnEvent) -> bool,
{
self.events.borrow_mut().retain(|evt| !f(evt))
}
pub fn events(&self) -> impl Iterator<Item = Http3ServerConnEvent> {
self.events.replace(VecDeque::new()).into_iter()
}
pub fn has_events(&self) -> bool {
!self.events.borrow().is_empty()
}
pub fn next_event(&self) -> Option<Http3ServerConnEvent> {
self.events.borrow_mut().pop_front()
}
pub fn headers(&self, stream_id: u64, headers: Vec<Header>, fin: bool) {
self.insert(Http3ServerConnEvent::Headers {
stream_id,
headers,
fin,
});
}
pub fn data(&self, stream_id: u64, data: Vec<u8>, fin: bool) {
self.insert(Http3ServerConnEvent::Data {
stream_id,
data,
fin,
});
}
}
impl Http3Events for Http3ServerConnEvents {
fn reset(&self, stream_id: u64, error: AppError) {
self.insert(Http3ServerConnEvent::Reset { stream_id, error });
}
fn connection_state_change(&self, state: Http3State) {
self.insert(Http3ServerConnEvent::StateChange(state));
}
fn remove_events_for_stream_id(&self, stream_id: u64) {
self.remove(|evt| {
matches!(evt,
Http3ServerConnEvent::Reset { stream_id: x, .. } if *x == stream_id)
});
}
}

Просмотреть файл

@ -4,33 +4,144 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use crate::connection::{Http3Events, Http3State};
use crate::Header;
use neqo_common::matches;
use neqo_transport::AppError;
use crate::connection::{Http3Connection, Http3ServerHandler, Http3State};
use crate::server_connection_events::{Http3ServerConnEvent, Http3ServerConnEvents};
use crate::transaction_server::TransactionServer;
use crate::{Error, Header, Res};
use neqo_common::{qdebug, qinfo};
use neqo_transport::server::ActiveConnectionRef;
use neqo_transport::{AppError, Connection};
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;
use std::time::Instant;
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)]
pub type Http3ServerConnection =
Http3Connection<Http3ServerConnEvents, TransactionServer, Http3ServerHandler>;
#[derive(Debug)]
pub struct Http3Handler {
handler: Http3ServerConnection,
}
impl Http3Handler {
pub fn new(max_table_size: u32, max_blocked_streams: u16) -> Self {
Http3Handler {
handler: Http3Connection::new(max_table_size, max_blocked_streams),
}
}
pub fn set_response(&mut self, stream_id: u64, headers: &[Header], data: Vec<u8>) -> Res<()> {
self.handler
.transactions
.get_mut(&stream_id)
.ok_or(Error::InvalidStreamId)?
.set_response(headers, data, &mut self.handler.qpack_encoder);
self.handler.insert_streams_have_data_to_send(stream_id);
Ok(())
}
pub fn stream_reset(
&mut self,
conn: &mut Connection,
stream_id: u64,
app_error: AppError,
) -> Res<()> {
self.handler.stream_reset(conn, stream_id, app_error)
}
pub fn process_http3(&mut self, conn: &mut Connection, now: Instant) {
self.handler.process_http3(conn, now);
}
pub fn next_event(&mut self) -> Option<Http3ServerConnEvent> {
self.handler.events.next_event()
}
pub fn should_be_processed(&self) -> bool {
self.handler.has_data_to_send() | self.handler.events.has_events()
}
}
#[derive(Debug, Clone)]
pub struct ClientRequestStream {
conn: ActiveConnectionRef,
handler: Rc<RefCell<Http3Handler>>,
stream_id: u64,
}
impl ::std::fmt::Display for ClientRequestStream {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
let conn: &Connection = &self.conn.borrow();
write!(
f,
"Http3 server conn={:?} stream_id={}",
conn, self.stream_id
)
}
}
impl ClientRequestStream {
pub fn new(
conn: ActiveConnectionRef,
handler: Rc<RefCell<Http3Handler>>,
stream_id: u64,
) -> Self {
ClientRequestStream {
conn,
handler,
stream_id,
}
}
pub fn set_response(&mut self, headers: &[Header], data: Vec<u8>) -> Res<()> {
qinfo!([self], "Set new response.");
self.handler
.borrow_mut()
.set_response(self.stream_id, headers, data)
}
pub fn stream_stop_sending(&mut self, app_error: AppError) -> Res<()> {
qdebug!(
[self],
"stop sending stream_id:{} error:{}.",
self.stream_id,
app_error
);
self.conn
.borrow_mut()
.stream_stop_sending(self.stream_id, app_error)?;
Ok(())
}
pub fn stream_reset(&mut self, app_error: AppError) -> Res<()> {
qdebug!([self], "reset error:{}.", app_error);
self.handler.borrow_mut().stream_reset(
&mut self.conn.borrow_mut(),
self.stream_id,
app_error,
)
}
}
#[derive(Debug, Clone)]
pub enum Http3ServerEvent {
/// Headers are ready.
Headers {
stream_id: u64,
request: ClientRequestStream,
headers: Vec<Header>,
fin: bool,
},
/// Request data is ready.
Data {
stream_id: u64,
request: ClientRequestStream,
data: Vec<u8>,
fin: bool,
},
/// Peer reset the stream.
Reset { stream_id: u64, error: AppError },
/// Connection state change.
StateChange(Http3State),
/// When individual connection change state. It is only used for tests.
StateChange {
conn: ActiveConnectionRef,
state: Http3State,
},
}
#[derive(Debug, Default, Clone)]
@ -43,13 +154,6 @@ impl Http3ServerEvents {
self.events.borrow_mut().push_back(event);
}
fn remove<F>(&self, f: F)
where
F: Fn(&Http3ServerEvent) -> bool,
{
self.events.borrow_mut().retain(|evt| !f(evt))
}
pub fn events(&self) -> impl Iterator<Item = Http3ServerEvent> {
self.events.replace(VecDeque::new()).into_iter()
}
@ -62,36 +166,19 @@ impl Http3ServerEvents {
self.events.borrow_mut().pop_front()
}
pub fn headers(&self, stream_id: u64, headers: Vec<Header>, fin: bool) {
pub fn headers(&self, request: ClientRequestStream, headers: Vec<Header>, fin: bool) {
self.insert(Http3ServerEvent::Headers {
stream_id,
request,
headers,
fin,
});
}
pub fn data(&self, stream_id: u64, data: Vec<u8>, fin: bool) {
self.insert(Http3ServerEvent::Data {
stream_id,
data,
fin,
});
}
}
impl Http3Events for Http3ServerEvents {
fn reset(&self, stream_id: u64, error: AppError) {
self.insert(Http3ServerEvent::Reset { stream_id, error });
}
fn connection_state_change(&self, state: Http3State) {
self.insert(Http3ServerEvent::StateChange(state));
}
fn remove_events_for_stream_id(&self, stream_id: u64) {
self.remove(|evt| {
matches!(evt,
Http3ServerEvent::Reset { stream_id: x, .. } if *x == stream_id)
});
pub fn connection_state_change(&self, conn: ActiveConnectionRef, state: Http3State) {
self.insert(Http3ServerEvent::StateChange { conn, state });
}
pub fn data(&self, request: ClientRequestStream, data: Vec<u8>, fin: bool) {
self.insert(Http3ServerEvent::Data { request, data, fin });
}
}

Просмотреть файл

@ -46,7 +46,12 @@ impl NewStreamTypeReader {
}
}
Err(e) => {
qdebug!([conn] "Error reading stream type for stream {}: {:?}", stream_id, e);
qdebug!(
[conn],
"Error reading stream type for stream {}: {:?}",
stream_id,
e
);
self.fin = true;
return None;
}

Просмотреть файл

@ -58,7 +58,7 @@ impl Request {
return;
}
qinfo!([self] "Encoding headers for {}/{}", self.host, self.path);
qinfo!([self], "Encoding headers for {}/{}", self.host, self.path);
let encoded_headers = encoder.encode_header_block(&self.headers, stream_id);
let f = HFrame::Headers {
len: encoded_headers.len() as u64,
@ -83,10 +83,10 @@ impl Request {
self.ensure_encoded(encoder, stream_id);
if let Some(buf) = &mut self.buf {
let sent = conn.stream_send(stream_id, &buf)?;
qinfo!([label] "{} bytes sent", sent);
qinfo!([label], "{} bytes sent", sent);
if sent == buf.len() {
qinfo!([label] "done sending request");
qinfo!([label], "done sending request");
Ok(true)
} else {
let b = buf.split_off(sent);
@ -196,7 +196,12 @@ impl TransactionClient {
}
pub fn send_request_body(&mut self, conn: &mut Connection, buf: &[u8]) -> Res<usize> {
qinfo!([self] "send_request_body: send_state={:?} len={}", self.send_state, buf.len());
qinfo!(
[self],
"send_request_body: send_state={:?} len={}",
self.send_state,
buf.len()
);
match self.send_state {
TransactionSendState::SendingHeaders { .. } => Ok(0),
TransactionSendState::SendingData => {
@ -218,7 +223,12 @@ impl TransactionClient {
to_send = min(buf.len(), available - 9);
}
qinfo!([self] "send_request_body: available={} to_send={}.", available, to_send);
qinfo!(
[self],
"send_request_body: available={} to_send={}.",
available,
to_send
);
let data_frame = HFrame::Data {
len: to_send as u64,
@ -241,7 +251,12 @@ impl TransactionClient {
}
fn handle_frame_in_state_waiting_for_headers(&mut self, frame: HFrame, fin: bool) -> Res<()> {
qinfo!([self] "A new frame has been received: {:?}; state={:?}", frame, self.recv_state);
qinfo!(
[self],
"A new frame has been received: {:?}; state={:?}",
frame,
self.recv_state
);
match frame {
HFrame::Headers { len } => self.handle_headers_frame(len, fin),
HFrame::PushPromise { .. } => Err(Error::HttpIdError),
@ -265,7 +280,12 @@ impl TransactionClient {
}
fn handle_frame_in_state_waiting_for_data(&mut self, frame: HFrame, fin: bool) -> Res<()> {
qinfo!([self] "A new frame has been received: {:?}; state={:?}", frame, self.recv_state);
qinfo!(
[self],
"A new frame has been received: {:?}; state={:?}",
frame,
self.recv_state
);
match frame {
HFrame::Data { len } => self.handle_data_frame(len, fin),
HFrame::PushPromise { .. } => Err(Error::HttpIdError),
@ -302,7 +322,11 @@ impl TransactionClient {
fn set_state_to_close_pending(&mut self) {
// Stream has received fin. Depending on headers state set header_ready
// or data_readable event so that app can pick up the fin.
qdebug!([self] "set_state_to_close_pending: response_headers_state={:?}", self.response_headers_state);
qdebug!(
[self],
"set_state_to_close_pending: response_headers_state={:?}",
self.response_headers_state
);
match self.response_headers_state {
ResponseHeadersState::NoHeaders => {
self.conn_events.header_ready(self.stream_id);
@ -317,7 +341,7 @@ impl TransactionClient {
}
fn recv_frame_header(&mut self, conn: &mut Connection) -> Res<Option<(HFrame, bool)>> {
qtrace!([self] "receiving frame header");
qtrace!([self], "receiving frame header");
let fin = self.frame_reader.receive(conn, self.stream_id)?;
if !self.frame_reader.done() {
if fin {
@ -329,7 +353,7 @@ impl TransactionClient {
}
Ok(None)
} else {
qdebug!([self] "A new frame has been received.");
qdebug!([self], "A new frame has been received.");
Ok(Some((self.frame_reader.get_frame()?, fin)))
}
}
@ -350,7 +374,7 @@ impl TransactionClient {
} = self.recv_state
{
let (amount, fin) = conn.stream_recv(self.stream_id, &mut buf[*offset..])?;
qdebug!([label] "read_headers: read {} bytes fin={}.", amount, fin);
qdebug!([label], "read_headers: read {} bytes fin={}.", amount, fin);
*offset += amount as usize;
if *offset < buf.len() {
if fin {
@ -361,7 +385,10 @@ impl TransactionClient {
}
// we have read the headers, try decoding them.
qinfo!([label] "read_headers: read all headers, try decoding them.");
qinfo!(
[label],
"read_headers: read all headers, try decoding them."
);
match decoder.decode_header_block(buf, self.stream_id)? {
Some(headers) => {
self.add_headers(Some(headers))?;
@ -469,11 +496,11 @@ impl Http3Transaction for TransactionClient {
if fin {
conn.stream_close_send(self.stream_id)?;
self.send_state = TransactionSendState::Closed;
qinfo!([label] "done sending request");
qinfo!([label], "done sending request");
} else {
self.send_state = TransactionSendState::SendingData;
self.conn_events.data_writable(self.stream_id);
qinfo!([label] "change to state SendingData");
qinfo!([label], "change to state SendingData");
}
}
}
@ -487,7 +514,12 @@ impl Http3Transaction for TransactionClient {
String::new()
};
loop {
qdebug!([label] "send_state={:?} recv_state={:?}.", self.send_state, self.recv_state);
qdebug!(
[label],
"send_state={:?} recv_state={:?}.",
self.send_state,
self.recv_state
);
match self.recv_state {
TransactionRecvState::WaitingForResponseHeaders => {
match self.recv_frame_header(conn)? {
@ -516,7 +548,7 @@ impl Http3Transaction for TransactionClient {
}
}
None => {
qinfo!([self] "decoding header is blocked.");
qinfo!([self], "decoding header is blocked.");
break Ok(());
}
}

Просмотреть файл

@ -6,10 +6,10 @@
use crate::connection::Http3Transaction;
use crate::hframe::{HFrame, HFrameReader};
use crate::server_events::Http3ServerEvents;
use crate::server_connection_events::Http3ServerConnEvents;
use crate::Header;
use crate::{Error, Res};
use neqo_common::{qdebug, qinfo, qtrace, Encoder};
use neqo_common::{matches, qdebug, qinfo, qtrace, Encoder};
use neqo_qpack::decoder::QPackDecoder;
use neqo_qpack::encoder::QPackEncoder;
use neqo_transport::Connection;
@ -38,11 +38,11 @@ pub struct TransactionServer {
send_state: TransactionSendState,
stream_id: u64,
frame_reader: HFrameReader,
conn_events: Http3ServerEvents,
conn_events: Http3ServerConnEvents,
}
impl TransactionServer {
pub fn new(stream_id: u64, conn_events: Http3ServerEvents) -> TransactionServer {
pub fn new(stream_id: u64, conn_events: Http3ServerConnEvents) -> TransactionServer {
qinfo!("Create a request stream_id={}", stream_id);
TransactionServer {
recv_state: TransactionRecvState::WaitingForHeaders,
@ -54,7 +54,7 @@ impl TransactionServer {
}
pub fn set_response(&mut self, headers: &[Header], data: Vec<u8>, encoder: &mut QPackEncoder) {
qdebug!([self] "Encoding headers");
qdebug!([self], "Encoding headers");
let encoded_headers = encoder.encode_header_block(&headers, self.stream_id);
let hframe = HFrame::Headers {
len: encoded_headers.len() as u64,
@ -63,7 +63,7 @@ impl TransactionServer {
hframe.encode(&mut d);
d.encode(&encoded_headers);
if !data.is_empty() {
qdebug!([self] "Encoding data");
qdebug!([self], "Encoding data");
let d_frame = HFrame::Data {
len: data.len() as u64,
};
@ -75,12 +75,12 @@ impl TransactionServer {
}
fn recv_frame_header(&mut self, conn: &mut Connection) -> Res<(Option<HFrame>, bool)> {
qtrace!([self] "receiving frame header");
qtrace!([self], "receiving frame header");
let fin = self.frame_reader.receive(conn, self.stream_id)?;
if !self.frame_reader.done() {
Ok((None, fin))
} else {
qinfo!([self] "A new frame has been received.");
qinfo!([self], "A new frame has been received.");
Ok((Some(self.frame_reader.get_frame()?), fin))
}
}
@ -101,7 +101,7 @@ impl TransactionServer {
} = self.recv_state
{
let (amount, fin) = conn.stream_recv(self.stream_id, &mut buf[*offset..])?;
qdebug!([label] "read_headers: read {} bytes fin={}.", amount, fin);
qdebug!([label], "read_headers: read {} bytes fin={}.", amount, fin);
*offset += amount as usize;
if *offset < buf.len() {
if fin {
@ -112,7 +112,10 @@ impl TransactionServer {
}
// we have read the headers, try decoding them.
qinfo!([label] "read_headers: read all headers, try decoding them.");
qinfo!(
[label],
"read_headers: read all headers, try decoding them."
);
match decoder.decode_header_block(buf, self.stream_id)? {
Some(headers) => {
self.conn_events.headers(self.stream_id, headers, fin);
@ -137,7 +140,7 @@ impl TransactionServer {
}
fn handle_frame_in_state_waiting_for_headers(&mut self, frame: HFrame, fin: bool) -> Res<()> {
qdebug!([self] "A new frame has been received: {:?}", frame);
qdebug!([self], "A new frame has been received: {:?}", frame);
match frame {
HFrame::Headers { len } => self.handle_headers_frame(len, fin),
_ => Err(Error::HttpFrameUnexpected),
@ -145,7 +148,7 @@ impl TransactionServer {
}
fn handle_frame_in_state_waiting_for_data(&mut self, frame: HFrame, fin: bool) -> Res<()> {
qdebug!([self] "A new frame has been received: {:?}", frame);
qdebug!([self], "A new frame has been received: {:?}", frame);
match frame {
HFrame::Data { len } => self.handle_data_frame(len, fin),
_ => Err(Error::HttpFrameUnexpected),
@ -153,7 +156,7 @@ impl TransactionServer {
}
fn handle_headers_frame(&mut self, len: u64, fin: bool) -> Res<()> {
qinfo!([self] "A new header frame len={} fin={}", len, fin);
qinfo!([self], "A new header frame len={} fin={}", len, fin);
if len == 0 {
self.conn_events.headers(self.stream_id, Vec::new(), fin);
} else {
@ -169,7 +172,7 @@ impl TransactionServer {
}
fn handle_data_frame(&mut self, len: u64, fin: bool) -> Res<()> {
qinfo!([self] "A new data frame len={} fin={}", len, fin);
qinfo!([self], "A new data frame len={} fin={}", len, fin);
if len > 0 {
if fin {
return Err(Error::HttpFrameError);
@ -193,7 +196,7 @@ impl ::std::fmt::Display for TransactionServer {
impl Http3Transaction for TransactionServer {
fn send(&mut self, conn: &mut Connection, _encoder: &mut QPackEncoder) -> Res<()> {
qtrace!([self] "Sending response.");
qtrace!([self], "Sending response.");
let label = if ::log::log_enabled!(::log::Level::Debug) {
format!("{}", self)
} else {
@ -201,11 +204,11 @@ impl Http3Transaction for TransactionServer {
};
if let TransactionSendState::SendingResponse { ref mut buf } = self.send_state {
let sent = conn.stream_send(self.stream_id, &buf[..])?;
qinfo!([label] "{} bytes sent", sent);
qinfo!([label], "{} bytes sent", sent);
if sent == buf.len() {
conn.stream_close_send(self.stream_id)?;
self.send_state = TransactionSendState::Closed;
qinfo!([label] "done sending request");
qinfo!([label], "done sending request");
} else {
let mut b = buf.split_off(sent);
mem::swap(buf, &mut b);
@ -223,7 +226,11 @@ impl Http3Transaction for TransactionServer {
};
loop {
qtrace!([label] "[recv_state={:?}] receiving data.", self.recv_state);
qtrace!(
[label],
"[recv_state={:?}] receiving data.",
self.recv_state
);
match self.recv_state {
TransactionRecvState::WaitingForHeaders => {
let (f, fin) = self.recv_frame_header(conn)?;
@ -258,7 +265,7 @@ impl Http3Transaction for TransactionServer {
}
}
None => {
qinfo!([self] "decoding header is blocked.");
qinfo!([self], "decoding header is blocked.");
return Ok(());
}
}
@ -323,11 +330,7 @@ impl Http3Transaction for TransactionServer {
}
fn has_data_to_send(&self) -> bool {
if let TransactionSendState::SendingResponse { .. } = self.send_state {
true
} else {
false
}
matches!(self.send_state, TransactionSendState::SendingResponse { .. })
}
fn is_state_sending_data(&self) -> bool {

28
third_party/rust/neqo-http3/tests/httpconn.rs поставляемый
Просмотреть файл

@ -13,11 +13,11 @@ use test_fixture::*;
const RESPONSE_DATA: &[u8] = &[0x61, 0x62, 0x63];
fn process_server_events(conn: &mut Http3Server) {
fn process_server_events(server: &mut Http3Server) {
let mut request_found = false;
while let Some(event) = conn.next_event() {
while let Some(event) = server.next_event() {
if let Http3ServerEvent::Headers {
stream_id,
mut request,
headers,
fin,
} = event
@ -32,15 +32,15 @@ fn process_server_events(conn: &mut Http3Server) {
]
);
assert_eq!(fin, true);
conn.set_response(
stream_id,
&[
(String::from(":status"), String::from("200")),
(String::from("content-length"), String::from("3")),
],
RESPONSE_DATA.to_vec(),
)
.unwrap();
request
.set_response(
&[
(String::from(":status"), String::from("200")),
(String::from("content-length"), String::from("3")),
],
RESPONSE_DATA.to_vec(),
)
.unwrap();
request_found = true;
}
}
@ -86,7 +86,6 @@ fn connect() -> (Http3Client, Http3Server, Option<Datagram>) {
let mut hconn_s = default_http3_server();
assert_eq!(hconn_c.state(), Http3State::Initializing);
assert_eq!(hconn_s.state(), Http3State::Initializing);
let out = hconn_c.process(None, now()); // Initial
let out = hconn_s.process(out.dgram(), now()); // Initial + Handshake
let out = hconn_c.process(out.dgram(), now()); // ACK
@ -97,7 +96,6 @@ fn connect() -> (Http3Client, Http3Server, Option<Datagram>) {
let out = hconn_c.process(None, now()); // Handshake
assert_eq!(hconn_c.state(), Http3State::Connected);
let out = hconn_s.process(out.dgram(), now()); // Handshake
assert_eq!(hconn_s.state(), Http3State::Connected);
let out = hconn_c.process(out.dgram(), now());
let out = hconn_s.process(out.dgram(), now());
// assert_eq!(hconn_s.settings_received, true);
@ -131,5 +129,7 @@ fn test_fetch() {
eprintln!("-----client");
let _ = hconn_c.process(out.dgram(), now());
let out = hconn_s.process(None, now());
let _ = hconn_c.process(out.dgram(), now());
process_client_events(&mut hconn_c);
}

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"1b0641ab11933da85b807fc64e9b9c19d49a53602359e8b51722d80ac3774a63","src/decoder.rs":"bbbeae34f8d1d42d51fd344a4d558aec1ddaa3c3bb41b0428796c316c160a778","src/encoder.rs":"854864b93d63b127659c5ed85822fe9452eb5f40a362cb2a19dc8273a7c2e81e","src/huffman.rs":"720eedace45205098a0b2210c876906ce15b7be469a799e75e70baafac8adee8","src/huffman_decode_helper.rs":"e4734353591770dfe9a9047b0be5d9068150433e9cea8cad029444b42b0afa39","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"b223e4a709a9cc144d36777d2bcf78d81780bdbc09e9f2f09c7bffa110a098da","src/qpack_helper.rs":"200ab8bcb60728e3bcacf25b7006fa54b544458bfee5e66e09fa472a614347fc","src/qpack_send_buf.rs":"471e3b0af9f8783aa1bfe11a1959bf5694e62bc2d8e1cf783c933af81e3f3cf9","src/static_table.rs":"fda9d5c6f38f94b0bf92d3afdf8432dce6e27e189736596e16727090c77b78ec","src/table.rs":"f4f09692bf6ec863b0f066c88837d99f59a1fc4a8ca61bee4ed76d45a77c3cc4"},"package":null}
{"files":{"Cargo.toml":"96d0220db0a96108e39ca9d277a4979bd387e4d9d6ac92da7bbd590a86b2fa12","src/decoder.rs":"18f08a510d8a63012146eb0bb063218bf691a720624f521a29dc8cc3b1e52237","src/encoder.rs":"78da509611b5869d320795c42bef944b6499c0f207c73818c1908f1a1cf001fc","src/huffman.rs":"720eedace45205098a0b2210c876906ce15b7be469a799e75e70baafac8adee8","src/huffman_decode_helper.rs":"e4734353591770dfe9a9047b0be5d9068150433e9cea8cad029444b42b0afa39","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"b223e4a709a9cc144d36777d2bcf78d81780bdbc09e9f2f09c7bffa110a098da","src/qpack_helper.rs":"200ab8bcb60728e3bcacf25b7006fa54b544458bfee5e66e09fa472a614347fc","src/qpack_send_buf.rs":"471e3b0af9f8783aa1bfe11a1959bf5694e62bc2d8e1cf783c933af81e3f3cf9","src/static_table.rs":"fda9d5c6f38f94b0bf92d3afdf8432dce6e27e189736596e16727090c77b78ec","src/table.rs":"f4f09692bf6ec863b0f066c88837d99f59a1fc4a8ca61bee4ed76d45a77c3cc4"},"package":null}

2
third_party/rust/neqo-qpack/Cargo.toml поставляемый
Просмотреть файл

@ -1,6 +1,6 @@
[package]
name = "neqo-qpack"
version = "0.1.4"
version = "0.1.6"
authors = ["Dragana Damjanovic <dragana.damjano@gmail.com>"]
edition = "2018"
license = "MIT/Apache-2.0"

38
third_party/rust/neqo-qpack/src/decoder.rs поставляемый
Просмотреть файл

@ -133,7 +133,7 @@ impl QPackDecoder {
#[allow(clippy::useless_let_if_seq)]
fn read_instructions(&mut self, conn: &mut Connection, stream_id: u64) -> Res<()> {
let label = self.to_string();
qdebug!([self] "reading instructions");
qdebug!([self], "reading instructions");
loop {
match self.state {
QPackDecoderState::ReadInstruction => {
@ -209,7 +209,7 @@ impl QPackDecoder {
conn, stream_id, &mut v, &mut cnt, 3, b[0], true,
)?;
if done {
qdebug!([label] "received instruction - duplicate index={}", v);
qdebug!([label], "received instruction - duplicate index={}", v);
self.table.duplicate(v)?;
self.total_num_of_inserts += 1;
self.increment += 1;
@ -310,7 +310,7 @@ impl QPackDecoder {
} else {
mem::swap(&mut value_to_insert, value);
}
qdebug!([label] "received instruction - insert with name ref index={} static={} value={:x?}", name_index, name_static_table, value_to_insert);
qdebug!([label], "received instruction - insert with name ref index={} static={} value={:x?}", name_index, name_static_table, value_to_insert);
self.table.insert_with_name_ref(
*name_static_table,
*name_index,
@ -430,7 +430,7 @@ impl QPackDecoder {
} else {
mem::swap(&mut value_to_insert, value);
}
qdebug!([label] "received instruction - insert with name literal name={:x?} value={:x?}", name_to_insert, value_to_insert);
qdebug!([label], "received instruction - insert with name literal name={:x?} value={:x?}", name_to_insert, value_to_insert);
self.table.insert(name_to_insert, value_to_insert)?;
self.total_num_of_inserts += 1;
self.increment += 1;
@ -450,7 +450,7 @@ impl QPackDecoder {
conn, stream_id, index, cnt, 0, 0x0, false,
)?;
if done {
qdebug!([label] "received instruction - duplicate index={}", index);
qdebug!([label], "received instruction - duplicate index={}", index);
self.table.duplicate(*index)?;
self.total_num_of_inserts += 1;
self.increment += 1;
@ -481,7 +481,7 @@ impl QPackDecoder {
}
pub fn set_capacity(&mut self, cap: u64) -> Res<()> {
qdebug!([self] "received instruction capacity cap={}", cap);
qdebug!([self], "received instruction capacity cap={}", cap);
if cap > u64::from(self.max_table_size) {
return Err(Error::EncoderStreamError);
}
@ -512,7 +512,7 @@ impl QPackDecoder {
match conn.stream_send(stream_id, &self.send_buf[..]) {
Err(_) => Err(Error::DecoderStreamError),
Ok(r) => {
qdebug!([self] "{} bytes sent.", r);
qdebug!([self], "{} bytes sent.", r);
self.send_buf.read(r as usize);
Ok(())
}
@ -524,19 +524,19 @@ impl QPackDecoder {
// this function returns None if the stream is blocked waiting for table insertions.
pub fn decode_header_block(&mut self, buf: &[u8], stream_id: u64) -> Res<Option<Vec<Header>>> {
qdebug!([self] "decode header block.");
qdebug!([self], "decode header block.");
let mut reader = BufWrapper { buf, offset: 0 };
let (req_inserts, base) = self.read_base(&mut reader)?;
qdebug!(
[self]
[self],
"requested inserts count is {} and base is {}",
req_inserts,
base
);
if self.table.base() < req_inserts {
qdebug!(
[self]
[self],
"stream is blocked stream_id={} requested inserts count={}",
stream_id,
req_inserts
@ -555,7 +555,7 @@ impl QPackDecoder {
if req_inserts != 0 {
self.header_ack(stream_id);
}
qdebug!([self] "done decoding header block.");
qdebug!([self], "done decoding header block.");
break Ok(Some(h));
}
@ -594,7 +594,7 @@ impl QPackDecoder {
fn read_indexed(&self, buf: &mut BufWrapper, base: u64) -> Res<Header> {
let static_table = buf.peek()? & 0x40 != 0;
let index = read_prefixed_encoded_int_slice(buf, 2)?;
qdebug!([self] "decoder indexed {} static={}.", index, static_table);
qdebug!([self], "decoder indexed {} static={}.", index, static_table);
if static_table {
match self.table.get_static(index) {
Ok(entry) => Ok((to_string(entry.name())?, to_string(entry.value())?)),
@ -609,7 +609,7 @@ impl QPackDecoder {
fn read_post_base_index(&self, buf: &mut BufWrapper, base: u64) -> Res<Header> {
let index = read_prefixed_encoded_int_slice(buf, 4)?;
qdebug!([self] "decode post-based {}.", index);
qdebug!([self], "decode post-based {}.", index);
if let Ok(entry) = self.table.get_dynamic(index, base, true) {
Ok((to_string(entry.name())?, to_string(entry.value())?))
} else {
@ -618,7 +618,7 @@ impl QPackDecoder {
}
fn read_literal_with_name_ref(&self, buf: &mut BufWrapper, base: u64) -> Res<Header> {
qdebug!([self] "read literal with name reference.");
qdebug!([self], "read literal with name reference.");
// ignore n bit.
let static_table = buf.peek()? & 0x10 != 0;
let index = read_prefixed_encoded_int_slice(buf, 4)?;
@ -645,7 +645,7 @@ impl QPackDecoder {
buf.slice(value_len)?.to_vec()
};
qdebug!(
[self]
[self],
"name index={} static={} value={:x?}.",
index,
static_table,
@ -655,7 +655,7 @@ impl QPackDecoder {
}
fn read_literal_with_post_base_name_ref(&self, buf: &mut BufWrapper, base: u64) -> Res<Header> {
qdebug!([self] "decoder literal with post-based index.");
qdebug!([self], "decoder literal with post-based index.");
// ignore n bit.
let index = read_prefixed_encoded_int_slice(buf, 5)?;
let name: Vec<u8>;
@ -674,12 +674,12 @@ impl QPackDecoder {
buf.slice(value_len)?.to_vec()
};
qdebug!([self] "name={:x?} value={:x?}.", name, value);
qdebug!([self], "name={:x?} value={:x?}.", name, value);
Ok((to_string(&name)?, to_string(&value)?))
}
fn read_literal_with_name_literal(&self, buf: &mut BufWrapper) -> Res<Header> {
qdebug!([self] "decode literal with name literal.");
qdebug!([self], "decode literal with name literal.");
// ignore n bit.
let name_is_huffman = buf.peek()? & 0x08 != 0;
@ -700,7 +700,7 @@ impl QPackDecoder {
buf.slice(value_len)?.to_vec()
};
qdebug!([self] "name={:x?} value={:x?}.", name, value);
qdebug!([self], "name={:x?} value={:x?}.", name, value);
Ok((to_string(&name)?, to_string(&value)?))
}

36
third_party/rust/neqo-qpack/src/encoder.rs поставляемый
Просмотреть файл

@ -72,7 +72,7 @@ impl QPackEncoder {
// TODO dragana check wat is the correct error.
return Err(Error::EncoderStreamError);
}
qdebug!([self] "Set max capacity to {}.", cap);
qdebug!([self], "Set max capacity to {}.", cap);
self.max_entries = (cap as f64 / 32.0).floor() as u64;
// we also set our table to the max allowed. TODO we may not want to use max allowed.
self.change_capacity(cap);
@ -83,7 +83,7 @@ impl QPackEncoder {
if blocked_streams > (1 << 16) - 1 {
return Err(Error::EncoderStreamError);
}
qdebug!([self] "Set max blocked streams to {}.", blocked_streams);
qdebug!([self], "Set max blocked streams to {}.", blocked_streams);
self.max_blocked_streams = blocked_streams as u16;
Ok(())
}
@ -103,7 +103,7 @@ impl QPackEncoder {
}
fn read_instructions(&mut self, conn: &mut Connection, stream_id: u64) -> Res<()> {
qdebug!([self] "read a new instraction");
qdebug!([self], "read a new instraction");
loop {
match self.instruction_reader_current_inst {
None => {
@ -174,7 +174,7 @@ impl QPackEncoder {
fn call_instruction(&mut self) {
if let Some(inst) = &self.instruction_reader_current_inst {
qdebug!([self] "call intruction {:?}", inst);
qdebug!([self], "call intruction {:?}", inst);
match inst {
DecoderInstructions::InsertCountIncrement => {
self.table.increment_acked(self.instruction_reader_value);
@ -203,7 +203,7 @@ impl QPackEncoder {
value: Vec<u8>,
) -> Res<()> {
qdebug!(
[self]
[self],
"insert with name reference {} from {} value={:x?}.",
name_index,
if name_static_table {
@ -226,7 +226,7 @@ impl QPackEncoder {
}
pub fn insert_with_name_literal(&mut self, name: Vec<u8>, value: Vec<u8>) -> Res<()> {
qdebug!([self] "insert name {:x?}, value={:x?}.", name, value);
qdebug!([self], "insert name {:x?}, value={:x?}.", name, value);
// try to insert a new entry
self.table.insert(name, value)?;
@ -239,14 +239,14 @@ impl QPackEncoder {
}
pub fn duplicate(&mut self, index: u64) -> Res<()> {
qdebug!([self] "duplicate entry {}.", index);
qdebug!([self], "duplicate entry {}.", index);
self.table.duplicate(index)?;
self.send_buf.encode_prefixed_encoded_int(0x00, 3, index);
Ok(())
}
pub fn change_capacity(&mut self, cap: u64) {
qdebug!([self] "change capacity: {}", cap);
qdebug!([self], "change capacity: {}", cap);
self.table.set_capacity(cap);
self.send_buf.encode_prefixed_encoded_int(0x20, 3, cap);
}
@ -258,7 +258,7 @@ impl QPackEncoder {
match conn.stream_send(stream_id, &self.send_buf[..]) {
Err(_) => Err(Error::EncoderStreamError),
Ok(r) => {
qdebug!([self] "{} bytes sent.", r);
qdebug!([self], "{} bytes sent.", r);
self.send_buf.read(r as usize);
Ok(())
}
@ -269,7 +269,7 @@ impl QPackEncoder {
}
pub fn encode_header_block(&mut self, h: &[Header], stream_id: u64) -> QPData {
qdebug!([self] "encoding headers.");
qdebug!([self], "encoding headers.");
let mut encoded_h = QPData::default();
let base = self.table.base();
let mut req_insert_cnt = 0;
@ -290,7 +290,7 @@ impl QPackEncoder {
// this is done in this way because otherwise it is complaining about mut borrow. TODO: look if we can do this better
let (e_s, e_d, found_value) = self.table.lookup(&name, &value);
if let Some(entry) = e_s {
qtrace!([label] "found a static entry, value-match={}", found_value);
qtrace!([label], "found a static entry, value-match={}", found_value);
can_use = true;
index = entry.index();
value_as_well = found_value;
@ -300,7 +300,7 @@ impl QPackEncoder {
index = entry.index();
can_use = index < acked_inserts_cnt || can_be_blocked;
qtrace!(
[label]
[label],
"found a dynamic entry - can_use={} value-match={},",
can_use,
found_value
@ -385,7 +385,7 @@ impl QPackEncoder {
positive: bool,
) {
qdebug!(
[self]
[self],
"encode header block prefix req_insert_cnt={} delta={} (fix={}).",
req_insert_cnt,
delta,
@ -435,7 +435,7 @@ impl QPackEncoder {
}
fn encode_indexed(&self, buf: &mut QPData, is_static: bool, index: u64) {
qdebug!([self] "encode index {} (static={}).", index, is_static);
qdebug!([self], "encode index {} (static={}).", index, is_static);
let prefix = if is_static { 0xc0 } else { 0x80 };
buf.encode_prefixed_encoded_int(prefix, 2, index);
}
@ -448,7 +448,7 @@ impl QPackEncoder {
value: &[u8],
) {
qdebug!(
[self]
[self],
"encode literal with name ref - index={}, static={}, value={:x?}",
index,
is_static,
@ -460,13 +460,13 @@ impl QPackEncoder {
}
fn encode_post_base_index(&self, buf: &mut QPData, index: u64) {
qdebug!([self] "encode post base index {}.", index);
qdebug!([self], "encode post base index {}.", index);
buf.encode_prefixed_encoded_int(0x10, 4, index);
}
fn encode_literal_with_post_based_name_ref(&self, buf: &mut QPData, index: u64, value: &[u8]) {
qdebug!(
[self]
[self],
"encode literal with post base index - index={}, value={:x?}.",
index,
value
@ -477,7 +477,7 @@ impl QPackEncoder {
fn encode_literal_with_name_literal(&self, buf: &mut QPData, name: &[u8], value: &[u8]) {
qdebug!(
[self]
[self],
"encode literal with name literal - name={:x?}, value={:x?}.",
name,
value

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"82faeea7483f4181d323f7e6889d336606c52dd52d9e7cb900b9e51e6f3e3a83","TODO":"d759cb804b32fa9d96ea8d3574a3c4073da9fe6a0b02b708a0e22cce5a5b4a0f","src/connection.rs":"ced6150694f2bfda6f7ff1799087a52dabe07155401919fe84cbb3cdbf5ef307","src/crypto.rs":"2eccba8925d74b199f524686c70de3c6715fab95af7654e0657e58cfd338b640","src/dump.rs":"d3c327d303c1257094687f750b3d468eedf945b06166484bee75dc4cab7ca001","src/events.rs":"07b1fa18efc538b96736ebfedba929b4854dffd460e1250ae02dc79cc86bb310","src/flow_mgr.rs":"9ced2d8f9a8747a960795c80aad384bde7a9a25ed4ac3ebf4ea0ebf1133d8e7a","src/frame.rs":"97fc6b83a71e51106d5f947ca9855892bae657d50c7f3aa55e18c67c1bf71359","src/lib.rs":"784bc483e981c92a9f2301ed67cee62654405c6bdb854dadb1f2464b8e3ac5a5","src/packet.rs":"7fa31e596082d577397853b2043b4e0ac534218a7fdc6cfc52eeba1224948970","src/recovery.rs":"5fea4291a54ef6693ed7d2022b6e0574f94224421015714e090e38132b1f7cff","src/recv_stream.rs":"f092be0c94655938461d69cdbb146200681341145f15c57817873c64bc25c538","src/send_stream.rs":"f778f0904d1a944c934198af9138dc872912c45662338ae8562093f648735b3e","src/server.rs":"a3b44025a9ee5f1071ca75f5ae8f8e7e5070ae7b9c053737d1e090e7855907c1","src/stats.rs":"dca5afcb6252f3f32f494513f76964cffb945afd6d18b8669dea98a7aeed1689","src/stream_id.rs":"b3158cf2c6072da79bf6e77a31f71f2f3b970429221142a9ff1dd6cd07df2442","src/tparams.rs":"d35e2ec14958de74c315710bce80d8a72262f2437ddd1121fe28e752a1b4244d","src/tracking.rs":"9ce66170fa240db42a8c596f70846cc8e62925c30be6e622bc40b1a8f1ec73f2","tests/conn_vectors.rs":"5c381c8f1e0d126cb675bea302d1d118ea2ae988ec9c1536db2b18552074d845","tests/connection.rs":"195f52a876b9bd92f4368f301c98169a36438b5c9c1bb9ebaab146c7f8e0bb24","tests/server.rs":"8126ee12424487ee723d062169295e20858b041284a66c019173d39a7eaaa066"},"package":null}
{"files":{"Cargo.toml":"aa4e0d0fe520b00cca715828f066d6827c039f5127b1db9a3514318b53f36c51","TODO":"d759cb804b32fa9d96ea8d3574a3c4073da9fe6a0b02b708a0e22cce5a5b4a0f","src/connection.rs":"1994a978b6e6a970bb4d6870d0b932c92067f1288b81a871b6bdb7933c212211","src/crypto.rs":"dca8ce0a92f2ae12d87fcaa903cfd69048d6867eadd0eaf71670d000a23343de","src/dump.rs":"e4058d89acf50c3dea7e9f067e6fa1d8abfe0a65a77acf187f5012b53ed2568d","src/events.rs":"07b1fa18efc538b96736ebfedba929b4854dffd460e1250ae02dc79cc86bb310","src/flow_mgr.rs":"acd567f932be71ac4d342308369dd1620f6498fdb1c9a35a7325725702575c41","src/frame.rs":"17b85f48d20752dabaa2cd529ee65294ab0d37c4498134bb844958c9d901f2b0","src/lib.rs":"784bc483e981c92a9f2301ed67cee62654405c6bdb854dadb1f2464b8e3ac5a5","src/packet.rs":"7fa31e596082d577397853b2043b4e0ac534218a7fdc6cfc52eeba1224948970","src/recovery.rs":"f7bfbc605a03ba5c60a403fecbf843129d2868cb77e6378aa17c7c27c3dc6003","src/recv_stream.rs":"e3f8339aa8152587ec093ed426618a37a3b836fac56417fdf7822270bb5e87de","src/send_stream.rs":"69ee5867aa66a6d838dfc16e79b75d6fa9e0074d54229ccfc2e770f9f7deba57","src/server.rs":"d391a1d585bb1e45d025cdd1adb25f986128302178926b71e17dce8105346dda","src/stats.rs":"dca5afcb6252f3f32f494513f76964cffb945afd6d18b8669dea98a7aeed1689","src/stream_id.rs":"b3158cf2c6072da79bf6e77a31f71f2f3b970429221142a9ff1dd6cd07df2442","src/tparams.rs":"d35e2ec14958de74c315710bce80d8a72262f2437ddd1121fe28e752a1b4244d","src/tracking.rs":"49d2ca42ade8c2f9d119a0b96c25106a657f5e15022a1a19ddababb097944aea","tests/conn_vectors.rs":"5c381c8f1e0d126cb675bea302d1d118ea2ae988ec9c1536db2b18552074d845","tests/connection.rs":"195f52a876b9bd92f4368f301c98169a36438b5c9c1bb9ebaab146c7f8e0bb24","tests/server.rs":"8126ee12424487ee723d062169295e20858b041284a66c019173d39a7eaaa066"},"package":null}

2
third_party/rust/neqo-transport/Cargo.toml поставляемый
Просмотреть файл

@ -1,6 +1,6 @@
[package]
name = "neqo-transport"
version = "0.1.4"
version = "0.1.6"
authors = ["EKR <ekr@rtfm.com>"]
edition = "2018"
license = "MIT/Apache-2.0"

Просмотреть файл

@ -6,13 +6,11 @@
// The class implementing a QUIC connection.
#![allow(dead_code)]
use std::cell::RefCell;
use std::cmp::{max, Ordering};
use std::collections::HashMap;
use std::convert::TryInto;
use std::fmt::{self, Debug};
use std::mem;
use std::net::SocketAddr;
use std::rc::Rc;
use std::time::{Duration, Instant};
@ -22,11 +20,11 @@ use smallvec::SmallVec;
use neqo_common::{hex, matches, qdebug, qerror, qinfo, qtrace, qwarn, Datagram, Decoder, Encoder};
use neqo_crypto::agent::CertificateInfo;
use neqo_crypto::{
Agent, AntiReplay, AuthenticationStatus, Client, Epoch, HandshakeState, Record, RecordList,
Agent, AntiReplay, AuthenticationStatus, Client, Epoch, HandshakeState, Record,
SecretAgentInfo, Server,
};
use crate::crypto::Crypto;
use crate::crypto::{Crypto, CryptoState};
use crate::dump::*;
use crate::events::{ConnectionEvent, ConnectionEvents};
use crate::flow_mgr::FlowMgr;
@ -155,6 +153,14 @@ impl Path {
pub fn received_on(&self, d: &Datagram) -> bool {
self.local == d.destination() && self.remote == d.source()
}
fn mtu(&self) -> usize {
if self.local.is_ipv4() {
1252
} else {
1232 // IPv6
}
}
}
#[derive(Clone, Debug, PartialEq)]
@ -349,7 +355,7 @@ impl Connection {
remote_cid: dcid.clone(),
}),
);
c.crypto.states[0] = Some(c.crypto.create_initial_state(Role::Client, &dcid));
c.crypto.create_initial_state(Role::Client, &dcid);
Ok(c)
}
@ -437,14 +443,6 @@ impl Connection {
self.tps.borrow_mut().local.set(key, value)
}
fn pmtu(&self) -> usize {
match &self.path {
Some(path) if path.local.is_ipv4() => 1252,
Some(_) => 1232, // IPv6
None => 1280,
}
}
/// Set the connection ID that was originally chosen by the client.
pub(crate) fn original_connection_id(&mut self, odcid: &ConnectionId) {
assert_eq!(self.role, Role::Server);
@ -495,21 +493,21 @@ impl Connection {
/// if the token supports that.
pub fn set_resumption_token(&mut self, now: Instant, token: &[u8]) -> Res<()> {
if self.state != State::Init {
qerror!([self] "set token in state {:?}", self.state);
qerror!([self], "set token in state {:?}", self.state);
return Err(Error::ConnectionState);
}
qinfo!([self] "resumption token {}", hex(token));
qinfo!([self], "resumption token {}", hex(token));
let mut dec = Decoder::from(token);
let tp_slice = match dec.decode_vvec() {
Some(v) => v,
_ => return Err(Error::InvalidResumptionToken),
};
qtrace!([self] " transport parameters {}", hex(&tp_slice));
qtrace!([self], " transport parameters {}", hex(&tp_slice));
let mut dec_tp = Decoder::from(tp_slice);
let tp = TransportParameters::decode(&mut dec_tp)?;
let tok = dec.decode_remainder();
qtrace!([self] " TLS token {}", hex(&tok));
qtrace!([self], " TLS token {}", hex(&tok));
match self.crypto.tls {
Agent::Client(ref mut c) => c.set_resumption_token(&tok)?,
Agent::Server(_) => return Err(Error::WrongRole),
@ -533,8 +531,8 @@ impl Connection {
});
enc.encode(extra);
let records = s.send_ticket(now, &enc)?;
qinfo!([self] "send session ticket {}", hex(&enc));
self.buffer_crypto_records(records);
qinfo!([self], "send session ticket {}", hex(&enc));
self.crypto.buffer_records(records);
Ok(())
}
Agent::Client(_) => Err(Error::WrongRole),
@ -581,7 +579,7 @@ impl Connection {
#[cfg(not(debug_assertions))]
let msg = String::from("");
if let State::Closed(err) | State::Closing { error: err, .. } = &self.state {
qwarn!([self] "Closing again after error {:?}", err);
qwarn!([self], "Closing again after error {:?}", err);
} else {
self.set_state(State::Closing {
error: ConnectionError::Transport(v.clone()),
@ -626,7 +624,7 @@ impl Connection {
/// Get the time that we next need to be called back, relative to `now`.
fn next_delay(&mut self, now: Instant) -> Duration {
self.loss_recovery_state = self.loss_recovery.get_timer(&self.state);
self.loss_recovery_state = self.loss_recovery.get_timer();
let mut delays = SmallVec::<[_; 4]>::new();
@ -705,10 +703,10 @@ impl Connection {
// assume that the DCID is OK.
if hdr.dcid.len() < 8 {
if token.is_empty() {
qinfo!([self] "Drop Initial with short DCID");
qinfo!([self], "Drop Initial with short DCID");
false
} else {
qinfo!([self] "Initial received with token, assuming OK");
qinfo!([self], "Initial received with token, assuming OK");
true
}
} else {
@ -716,31 +714,34 @@ impl Connection {
true
}
} else {
qdebug!([self] "Dropping non-Initial packet");
qdebug!([self], "Dropping non-Initial packet");
false
}
}
fn handle_retry(&mut self, scid: &ConnectionId, odcid: &ConnectionId, token: &[u8]) -> Res<()> {
qdebug!([self] "received Retry");
qdebug!([self], "received Retry");
if self.retry_info.is_some() {
qinfo!([self] "Dropping extra Retry");
qinfo!([self], "Dropping extra Retry");
return Ok(());
}
if token.is_empty() {
qinfo!([self] "Dropping Retry without a token");
qinfo!([self], "Dropping Retry without a token");
return Ok(());
}
match self.path.iter_mut().find(|p| p.remote_cid == *odcid) {
None => {
qinfo!([self] "Ignoring Retry with mismatched ODCID");
qinfo!([self], "Ignoring Retry with mismatched ODCID");
return Ok(());
}
Some(path) => {
path.remote_cid = scid.clone();
}
}
qinfo!([self] "Valid Retry received, restarting with provided token");
qinfo!(
[self],
"Valid Retry received, restarting with provided token"
);
self.retry_info = Some(RetryInfo {
token: token.to_vec(),
odcid: odcid.clone(),
@ -750,14 +751,14 @@ impl Connection {
// Switching crypto state here might not happen eventually.
// https://github.com/quicwg/base-drafts/issues/2823
self.crypto.states[0] = Some(self.crypto.create_initial_state(self.role, scid));
self.crypto.create_initial_state(self.role, scid);
Ok(())
}
fn input(&mut self, d: Datagram, now: Instant) -> Res<()> {
let mut slc = &d[..];
qinfo!([self] "input {}", hex( &**d));
qinfo!([self], "input {}", hex(&**d));
// Handle each packet in the datagram
while !slc.is_empty() {
@ -765,7 +766,12 @@ impl Connection {
let mut hdr = match res {
Ok(h) => h,
Err(e) => {
qinfo!([self] "Received indecipherable packet header {} {}", hex(slc), e);
qinfo!(
[self],
"Received indecipherable packet header {} {}",
hex(slc),
e
);
return Ok(()); // Drop the remainder of the datagram.
}
};
@ -800,22 +806,21 @@ impl Connection {
match self.state {
State::Init => {
qinfo!([self] "Received message while in Init state");
qinfo!([self], "Received message while in Init state");
return Ok(());
}
State::WaitInitial => {
qinfo!([self] "Received packet in WaitInitial");
qinfo!([self], "Received packet in WaitInitial");
if self.role == Role::Server {
if !self.is_valid_initial(&hdr) {
return Ok(());
}
self.crypto.states[0] =
Some(self.crypto.create_initial_state(self.role, &hdr.dcid));
self.crypto.create_initial_state(self.role, &hdr.dcid);
}
}
State::Handshaking | State::Connected => {
if !self.is_valid_cid(&hdr.dcid) {
qinfo!([self] "Ignoring packet with CID {:?}", hdr.dcid);
qinfo!([self], "Ignoring packet with CID {:?}", hdr.dcid);
return Ok(());
}
}
@ -831,7 +836,7 @@ impl Connection {
}
}
qdebug!([self] "Received unverified packet {:?}", hdr);
qdebug!([self], "Received unverified packet {:?}", hdr);
let body = self.decrypt_body(&mut hdr, slc);
slc = &slc[hdr.hdr_len + hdr.body_len()..];
@ -841,7 +846,7 @@ impl Connection {
// on the assert for doesn't exist.
// OK, we have a valid packet.
self.idle_timeout.on_packet_received(now);
dump_packet(self, "<- RX", &hdr, &body);
dump_packet(self, "-> RX", &hdr, &body);
if self.process_packet(&hdr, body, now)? {
continue;
}
@ -858,15 +863,17 @@ impl Connection {
// the rest of the datagram on the floor, but don't generate an error.
let largest_acknowledged = self
.loss_recovery
.largest_acknowledged(PNSpace::from(hdr.epoch));
.largest_acknowledged_pn(PNSpace::from(hdr.epoch));
if (self.state == State::Handshaking) && (hdr.epoch == 3) {
// Server has keys for epoch 3 but it is still in state Handshaking -> discharge packet.
debug_assert_eq!(self.role(), Role::Server);
return None;
}
match self.crypto.obtain_crypto_state(self.role, hdr.epoch) {
Ok(cs) => match cs.rx.as_ref() {
Some(rx) => {
let pn_decoder = PacketNumberDecoder::new(largest_acknowledged);
decrypt_packet(rx, pn_decoder, &mut hdr, slc).ok()
}
_ => None,
},
Ok(CryptoState { rx: Some(rx), .. }) => {
let pn_decoder = PacketNumberDecoder::new(largest_acknowledged);
decrypt_packet(rx, pn_decoder, &mut hdr, slc).ok()
}
_ => None,
}
}
@ -883,7 +890,12 @@ impl Connection {
let ack_eliciting = self.input_packet(hdr.epoch, Decoder::from(&body[..]), now)?;
let space = PNSpace::from(hdr.epoch);
if self.acks[space].is_duplicate(hdr.pn) {
qdebug!([self] "Received duplicate packet epoch={} pn={}", hdr.epoch, hdr.pn);
qdebug!(
[self],
"Received duplicate packet epoch={} pn={}",
hdr.epoch,
hdr.pn
);
self.stats.dups_rx += 1;
Ok(true)
} else {
@ -916,7 +928,11 @@ impl Connection {
ZeroRttState::Rejected
};
} else {
qdebug!([self] "Changing to use Server CID={}", hdr.scid.as_ref().unwrap());
qdebug!(
[self],
"Changing to use Server CID={}",
hdr.scid.as_ref().unwrap()
);
let p = self
.path
.iter_mut()
@ -939,7 +955,7 @@ impl Connection {
}
// Return whether the packet had ack-eliciting frames.
fn input_packet(&mut self, epoch: Epoch, mut d: Decoder, now: Instant) -> Res<(bool)> {
fn input_packet(&mut self, epoch: Epoch, mut d: Decoder, now: Instant) -> Res<bool> {
let mut ack_eliciting = false;
// Handle each frame in the packet
@ -956,41 +972,40 @@ impl Connection {
fn output(&mut self, now: Instant) -> Option<Datagram> {
let mut out = None;
// Can't call a method on self while iterating over self.paths
let paths = mem::replace(&mut self.path, Default::default());
for p in &paths {
match self.output_path(&p, now) {
Ok(Some(dgram)) => {
out = Some(dgram);
break;
if self.path.is_some() {
match self.output_pkt_for_path(now) {
Ok(res) => {
out = res;
}
Err(e) => {
if !matches!(self.state, State::Closing{..}) {
// An error here causes us to transition to closing.
self.absorb_error(now, Err(e));
// Rerun to give a chance to send a CONNECTION_CLOSE.
out = match self.output_path(&p, now) {
out = match self.output_pkt_for_path(now) {
Ok(x) => x,
Err(e) => {
qwarn!([self] "two output_path errors in a row: {:?}", e);
qwarn!([self], "two output_path errors in a row: {:?}", e);
None
}
};
break;
}
}
_ => (),
};
}
self.path = paths;
out
}
#[allow(clippy::cognitive_complexity)]
/// Build a datagram, possibly from multiple packets (for different PN
/// spaces) and each containing 1+ frames.
fn output_path(&mut self, path: &Path, now: Instant) -> Res<Option<Datagram>> {
fn output_pkt_for_path(&mut self, now: Instant) -> Res<Option<Datagram>> {
let mut out_bytes = Vec::new();
let mut needs_padding = false;
let path = self
.path
.take()
.expect("we know we have a path because calling fn checked");
// Frames for different epochs must go in different packets, but then these
// packets can go in a single datagram
@ -999,21 +1014,19 @@ impl Connection {
let mut encoder = Encoder::default();
let mut tokens = Vec::new();
// Try to make our own crypo state and if we can't, skip this epoch.
match self.crypto.obtain_crypto_state(self.role, epoch) {
Ok(cs) => {
if cs.tx.is_none() {
continue;
}
}
_ => continue,
// Ensure we have tx crypto state for this epoch, or skip it.
if !matches!(
self.crypto.obtain_crypto_state(self.role, epoch),
Ok(CryptoState { tx: Some(_), .. })
) {
continue;
}
let mut ack_eliciting = false;
match &self.state {
State::Init | State::WaitInitial | State::Handshaking | State::Connected => {
loop {
let remaining = self.pmtu() - out_bytes.len() - encoder.len();
let remaining = path.mtu() - out_bytes.len() - encoder.len();
// Check sources in turn for available frames
if let Some((frame, token)) = self
@ -1031,8 +1044,7 @@ impl Connection {
if let Some(t) = token {
tokens.push(t);
}
assert!(encoder.len() <= self.pmtu());
if out_bytes.len() + encoder.len() == self.pmtu() {
if out_bytes.len() + encoder.len() == path.mtu() {
// No more space for frames.
break;
}
@ -1069,7 +1081,7 @@ impl Connection {
continue;
}
qdebug!([self] "Need to send a packet");
qdebug!([self], "Need to send a packet");
match epoch {
// Packets containing Initial packets need padding.
0 => needs_padding = true,
@ -1118,29 +1130,32 @@ impl Connection {
let mut packet = encode_packet(tx, &hdr, &encoder);
dump_packet(self, "TX ->", &hdr, &encoder);
out_bytes.append(&mut packet);
if out_bytes.len() >= self.pmtu() {
if out_bytes.len() >= path.mtu() {
break;
}
}
if out_bytes.is_empty() {
self.path = Some(path);
return Ok(None);
}
// Pad Initial packets sent by the client to 1200 bytes.
if self.role == Role::Client && needs_padding {
qdebug!([self] "pad Initial to 1200");
qdebug!([self], "pad Initial to 1200");
out_bytes.resize(1200, 0);
}
Ok(Some(Datagram::new(path.local, path.remote, out_bytes)))
let dgram = Some(Datagram::new(path.local, path.remote, out_bytes));
self.path = Some(path);
Ok(dgram)
}
fn client_start(&mut self, now: Instant) -> Res<()> {
qinfo!([self] "client_start");
qinfo!([self], "client_start");
self.handshake(now, 0, None)?;
self.set_state(State::WaitInitial);
if self.crypto.tls.preinfo()?.early_data() {
qdebug!([self] "Enabling 0-RTT");
qdebug!([self], "Enabling 0-RTT");
self.zero_rtt_state = ZeroRttState::Enabled;
}
Ok(())
@ -1161,15 +1176,6 @@ impl Connection {
});
}
/// Buffer crypto records for sending.
fn buffer_crypto_records(&mut self, records: RecordList) {
for r in records {
assert_eq!(r.ct, 22);
qdebug!([self] "Adding CRYPTO data {:?}", r);
self.crypto.streams[r.epoch as usize].tx.send(&r.data);
}
}
fn set_initial_limits(&mut self) {
let tps = self.tps.borrow();
let remote = tps.remote();
@ -1202,37 +1208,36 @@ impl Connection {
fn handshake(&mut self, now: Instant, epoch: u16, data: Option<&[u8]>) -> Res<()> {
qdebug!("Handshake epoch={} data={:0x?}", epoch, data);
let mut rec: Option<Record> = None;
if let Some(d) = data {
qdebug!([self] "Handshake received {:0x?} ", d);
rec = Some(Record {
ct: 22, // TODO(ekr@rtfm.com): Symbolic constants for CT. This is handshake.
epoch,
data: d.to_vec(),
});
}
let rec = data
.map(|d| {
qdebug!([self], "Handshake received {:0x?} ", d);
Some(Record {
ct: 22, // TODO(ekr@rtfm.com): Symbolic constants for CT. This is handshake.
epoch,
data: d.to_vec(),
})
})
.unwrap_or(None);
let m = self.crypto.tls.handshake_raw(now, rec);
if *self.crypto.tls.state() == HandshakeState::AuthenticationPending {
self.events.authentication_needed();
}
match m {
match self.crypto.tls.handshake_raw(now, rec) {
Err(e) => {
qwarn!([self] "Handshake failed");
qwarn!([self], "Handshake failed");
return Err(match self.crypto.tls.alert() {
Some(a) => Error::CryptoAlert(*a),
_ => Error::CryptoError(e),
});
}
Ok(msgs) => self.buffer_crypto_records(msgs),
Ok(msgs) => self.crypto.buffer_records(msgs),
}
if self.crypto.tls.state().connected() {
qinfo!([self] "TLS handshake completed");
if *self.crypto.tls.state() == HandshakeState::AuthenticationPending {
self.events.authentication_needed();
} else if matches!(self.crypto.tls.state(), HandshakeState::Complete(_)) {
qinfo!([self], "TLS handshake completed");
if self.crypto.tls.info().map(SecretAgentInfo::alpn).is_none() {
qwarn!([self] "No ALPN. Closing connection.");
qwarn!([self], "No ALPN. Closing connection.");
// 120 = no_application_protocol
return Err(Error::CryptoAlert(120));
}
@ -1263,6 +1268,9 @@ impl Connection {
}
fn input_frame(&mut self, epoch: Epoch, frame: Frame, now: Instant) -> Res<()> {
if !frame.is_allowed(epoch) {
return Err(Error::ProtocolViolation);
}
match frame {
Frame::Padding => {
// Ignore
@ -1307,7 +1315,7 @@ impl Connection {
}
Frame::Crypto { offset, data } => {
qdebug!(
[self]
[self],
"Crypto frame on epoch={} offset={}, data={:0x?}",
epoch,
offset,
@ -1328,6 +1336,7 @@ impl Connection {
stream_id,
offset,
data,
..
} => {
if let (_, Some(rs)) = self.obtain_stream(stream_id.into())? {
rs.inbound_stream_frame(fin, offset, data)?;
@ -1358,7 +1367,11 @@ impl Connection {
}
Frame::DataBlocked { data_limit } => {
// Should never happen since we set data limit to 2^62-1
qwarn!([self] "Received DataBlocked with data limit {}", data_limit);
qwarn!(
[self],
"Received DataBlocked with data limit {}",
data_limit
);
}
Frame::StreamDataBlocked { stream_id, .. } => {
// TODO(agrover@mozilla.com): how should we be using
@ -1402,7 +1415,7 @@ impl Connection {
Frame::PathResponse { .. } => {
// Should never see this, we don't support migration atm and
// do not send path challenges
qwarn!([self] "Received Path Response");
qwarn!([self], "Received Path Response");
}
Frame::ConnectionClose {
error_code,
@ -1410,11 +1423,13 @@ impl Connection {
reason_phrase,
} => {
let reason_phrase = String::from_utf8_lossy(&reason_phrase);
qinfo!([self]
"ConnectionClose received. Error code: {:?} frame type {:x} reason {}",
error_code,
frame_type,
reason_phrase);
qinfo!(
[self],
"ConnectionClose received. Error code: {:?} frame type {:x} reason {}",
error_code,
frame_type,
reason_phrase
);
self.set_state(State::Closed(error_code.into()));
}
};
@ -1434,7 +1449,7 @@ impl Connection {
RecoveryToken::Stream(st) => self.send_streams.lost(&st),
RecoveryToken::Crypto(ct) => self.crypto.lost(ct),
RecoveryToken::Flow(ft) => self.flow_mgr.borrow_mut().lost(
ft,
&ft,
&mut self.send_streams,
&mut self.recv_streams,
&mut self.indexes,
@ -1454,7 +1469,7 @@ impl Connection {
now: Instant,
) -> Res<()> {
qinfo!(
[self]
[self],
"Rx ACK epoch={}, largest_acked={}, first_ack_range={}, ranges={:?}",
epoch,
largest_acknowledged,
@ -1503,7 +1518,7 @@ impl Connection {
RecoveryToken::Stream(st) => self.send_streams.lost(&st),
RecoveryToken::Crypto(ct) => self.crypto.lost(ct),
RecoveryToken::Flow(ft) => self.flow_mgr.borrow_mut().lost(
ft,
&ft,
&mut self.send_streams,
&mut self.recv_streams,
&mut self.indexes,
@ -1518,7 +1533,7 @@ impl Connection {
fn set_state(&mut self, state: State) {
if state > self.state {
qinfo!([self] "State change from {:?} -> {:?}", self.state, state);
qinfo!([self], "State change from {:?} -> {:?}", self.state, state);
self.state = state.clone();
match &self.state {
State::Connected => {
@ -1615,9 +1630,12 @@ impl Connection {
if stream_idx >= *next_stream_idx {
let recv_initial_max_stream_data = if stream_id.is_bidi() {
if stream_idx > self.indexes.local_max_stream_bidi {
qwarn!([self] "remote bidi stream create blocked, next={:?} max={:?}",
stream_idx,
self.indexes.local_max_stream_bidi);
qwarn!(
[self],
"remote bidi stream create blocked, next={:?} max={:?}",
stream_idx,
self.indexes.local_max_stream_bidi
);
return Err(Error::StreamLimitError);
}
self.tps
@ -1626,9 +1644,12 @@ impl Connection {
.get_integer(tp_const::INITIAL_MAX_STREAM_DATA_BIDI_REMOTE)
} else {
if stream_idx > self.indexes.local_max_stream_uni {
qwarn!([self] "remote uni stream create blocked, next={:?} max={:?}",
stream_idx,
self.indexes.local_max_stream_uni);
qwarn!(
[self],
"remote uni stream create blocked, next={:?} max={:?}",
stream_idx,
self.indexes.local_max_stream_uni
);
return Err(Error::StreamLimitError);
}
self.tps
@ -1710,9 +1731,12 @@ impl Connection {
self.flow_mgr
.borrow_mut()
.streams_blocked(self.indexes.remote_max_stream_uni, StreamType::UniDi);
qwarn!([self] "local uni stream create blocked, next={:?} max={:?}",
self.indexes.remote_next_stream_uni,
self.indexes.remote_max_stream_uni);
qwarn!(
[self],
"local uni stream create blocked, next={:?} max={:?}",
self.indexes.remote_next_stream_uni,
self.indexes.remote_max_stream_uni
);
return Err(Error::StreamLimitError);
}
let new_id = self
@ -1742,9 +1766,12 @@ impl Connection {
self.flow_mgr
.borrow_mut()
.streams_blocked(self.indexes.remote_max_stream_bidi, StreamType::BiDi);
qwarn!([self] "local bidi stream create blocked, next={:?} max={:?}",
self.indexes.remote_next_stream_bidi,
self.indexes.remote_max_stream_bidi);
qwarn!(
[self],
"local bidi stream create blocked, next={:?} max={:?}",
self.indexes.remote_next_stream_bidi,
self.indexes.remote_max_stream_bidi
);
return Err(Error::StreamLimitError);
}
let new_id = self
@ -1856,7 +1883,7 @@ impl Connection {
}
fn check_loss_detection_timeout(&mut self, now: Instant) {
qdebug!([self] "check_loss_timeouts");
qdebug!([self], "check_loss_timeouts");
if matches!(self.loss_recovery_state.mode(), LossRecoveryMode::None) {
// LR not the active timer
@ -1887,7 +1914,7 @@ impl Connection {
RecoveryToken::Stream(st) => self.send_streams.lost(&st),
RecoveryToken::Crypto(ct) => self.crypto.lost(ct),
RecoveryToken::Flow(ft) => self.flow_mgr.borrow_mut().lost(
ft,
&ft,
&mut self.send_streams,
&mut self.recv_streams,
&mut self.indexes,
@ -1898,7 +1925,7 @@ impl Connection {
}
LossRecoveryMode::PTO => {
qinfo!(
[self]
[self],
"check_loss_detection_timeout -send_one_or_two_packets"
);
self.loss_recovery.increment_pto_count();
@ -1930,6 +1957,7 @@ impl ::std::fmt::Display for Connection {
mod tests {
use super::*;
use crate::frame::StreamType;
use std::mem;
use test_fixture::{self, assertions, fixture_init, loopback, now};
// This is fabulous: because test_fixture uses the public API for Connection,
@ -2815,4 +2843,42 @@ mod tests {
client.stream_send(stream_id, &[0x00])
);
}
#[test]
fn test_client_fin_reorder() {
let mut client = default_client();
let mut server = default_server();
// Send ClientHello.
let client_hs = client.process(None, now());
assert!(client_hs.as_dgram_ref().is_some());
let server_hs = server.process(client_hs.dgram(), now());
assert!(server_hs.as_dgram_ref().is_some()); // ServerHello, etc...
let client_ack = client.process(server_hs.dgram(), now());
assert!(client_ack.as_dgram_ref().is_some());
let server_out = server.process(client_ack.dgram(), now());
assert!(server_out.as_dgram_ref().is_none());
assert!(maybe_authenticate(&mut client));
assert_eq!(*client.state(), State::Connected);
let client_fin = client.process(None, now());
assert!(client_fin.as_dgram_ref().is_some());
let client_stream_id = client.stream_create(StreamType::UniDi).unwrap();
client.stream_send(client_stream_id, &[1, 2, 3]).unwrap();
let client_stream_data = client.process(None, now());
assert!(client_stream_data.as_dgram_ref().is_some());
// Now stream data gets before client_fin
let server_out = server.process(client_stream_data.dgram(), now());
assert!(server_out.as_dgram_ref().is_none()); // the packet will be discarded
assert_eq!(*server.state(), State::Handshaking);
let server_out = server.process(client_fin.dgram(), now());
assert!(server_out.as_dgram_ref().is_some());
}
}

41
third_party/rust/neqo-transport/src/crypto.rs поставляемый
Просмотреть файл

@ -5,19 +5,18 @@
// except according to those terms.
use std::cell::RefCell;
use std::cmp::min;
use std::rc::Rc;
use neqo_common::{hex, qdebug, qinfo, qtrace};
use neqo_crypto::aead::Aead;
use neqo_crypto::hp::HpKey;
use neqo_crypto::{
hkdf, Agent, AntiReplay, Cipher, Epoch, SymKey, TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384,
TLS_VERSION_1_3,
hkdf, Agent, AntiReplay, Cipher, Epoch, RecordList, SymKey, TLS_AES_128_GCM_SHA256,
TLS_AES_256_GCM_SHA384, TLS_VERSION_1_3,
};
use crate::connection::Role;
use crate::frame::{crypto_frame_hdr_len, Frame, TxMode};
use crate::frame::{Frame, TxMode};
use crate::packet::{CryptoCtx, PacketNumber};
use crate::recovery::RecoveryToken;
use crate::recv_stream::RxStreamOrderer;
@ -62,12 +61,12 @@ impl Crypto {
}
// Create the initial crypto state.
pub fn create_initial_state(&mut self, role: Role, dcid: &[u8]) -> CryptoState {
pub fn create_initial_state(&mut self, role: Role, dcid: &[u8]) {
const CLIENT_INITIAL_LABEL: &str = "client in";
const SERVER_INITIAL_LABEL: &str = "server in";
qinfo!(
[self]
[self],
"Creating initial cipher state role={:?} dcid={}",
role,
hex(dcid)
@ -78,10 +77,19 @@ impl Crypto {
Role::Server => (SERVER_INITIAL_LABEL, CLIENT_INITIAL_LABEL),
};
CryptoState {
self.states[0] = Some(CryptoState {
epoch: 0,
tx: CryptoDxState::new_initial(CryptoDxDirection::Write, write_label, dcid),
rx: CryptoDxState::new_initial(CryptoDxDirection::Read, read_label, dcid),
});
}
/// Buffer crypto records for sending.
pub fn buffer_records(&mut self, records: RecordList) {
for r in records {
assert_eq!(r.ct, 22);
qdebug!([self], "Adding CRYPTO data {:?}", r);
self.streams[r.epoch as usize].tx.send(&r.data);
}
}
@ -94,7 +102,7 @@ impl Crypto {
let cs = &mut self.states[epoch as usize];
if cs.is_none() {
qtrace!([label] "Build crypto state for epoch {}", epoch);
qtrace!([label], "Build crypto state for epoch {}", epoch);
assert!(epoch != 0); // This state is made directly.
let cipher = match (epoch, self.tls.info()) {
@ -103,7 +111,7 @@ impl Crypto {
(_, Some(info)) => Some(info.cipher_suite()),
};
if cipher.is_none() {
qdebug!([label] "cipher info not available yet");
qdebug!([label], "cipher info not available yet");
return Err(Error::KeysNotFound);
}
let cipher = cipher.unwrap();
@ -123,7 +131,7 @@ impl Crypto {
| (Some(_), None, Role::Server, 1)
| (Some(_), Some(_), _, _) => {}
(None, None, _, _) => {
qdebug!([label] "Keying material not available for epoch {}", epoch);
qdebug!([label], "Keying material not available for epoch {}", epoch);
return Err(Error::KeysNotFound);
}
_ => panic!("bad configuration of keys"),
@ -167,12 +175,7 @@ impl Crypto {
) -> Option<(Frame, Option<RecoveryToken>)> {
let tx_stream = &mut self.streams[epoch as usize].tx;
if let Some((offset, data)) = tx_stream.next_bytes(mode) {
let frame_hdr_len = crypto_frame_hdr_len(offset, remaining);
let length = min(data.len(), remaining - frame_hdr_len);
let frame = Frame::Crypto {
offset,
data: data[..length].to_vec(),
};
let (frame, length) = Frame::new_crypto(offset, data, remaining);
tx_stream.mark_as_sent(offset, length);
qdebug!(
@ -276,7 +279,7 @@ impl CryptoCtx for CryptoDxState {
fn aead_decrypt(&self, pn: PacketNumber, hdr: &[u8], body: &[u8]) -> Res<Vec<u8>> {
qinfo!(
[self]
[self],
"aead_decrypt pn={} hdr={} body={}",
pn,
hex(hdr),
@ -289,7 +292,7 @@ impl CryptoCtx for CryptoDxState {
fn aead_encrypt(&self, pn: PacketNumber, hdr: &[u8], body: &[u8]) -> Res<Vec<u8>> {
qdebug!(
[self]
[self],
"aead_encrypt pn={} hdr={} body={}",
pn,
hex(hdr),
@ -300,7 +303,7 @@ impl CryptoCtx for CryptoDxState {
let mut out = vec![0; size];
let res = self.aead.encrypt(pn, hdr, body, &mut out)?;
qdebug!([self] "aead_encrypt ct={}", hex(res),);
qdebug!([self], "aead_encrypt ct={}", hex(res),);
Ok(res.to_vec())
}

2
third_party/rust/neqo-transport/src/dump.rs поставляемый
Просмотреть файл

@ -28,5 +28,5 @@ pub fn dump_packet(conn: &Connection, dir: &str, hdr: &PacketHdr, payload: &[u8]
s.push_str(&format!("\n {} {}", dir, &x));
}
}
qdebug!([conn] "pn={} type={:?}{}", hdr.pn, hdr.tipe, s);
qdebug!([conn], "pn={} type={:?}{}", hdr.pn, hdr.tipe, s);
}

Просмотреть файл

@ -51,10 +51,16 @@ impl FlowMgr {
assert!(self.used_data <= self.max_data)
}
// Dummy DataBlocked frame for discriminant use below
/// Returns whether max credit was actually increased.
pub fn conn_increase_max_credit(&mut self, new: u64) -> bool {
if new > self.max_data {
self.max_data = new;
const DB_FRAME: Frame = Frame::DataBlocked { data_limit: 0 };
self.from_conn.remove(&mem::discriminant(&DB_FRAME));
true
} else {
false
@ -75,6 +81,11 @@ impl FlowMgr {
self.from_conn.insert(mem::discriminant(&frame), frame);
}
pub fn max_data(&mut self, maximum_data: u64) {
let frame = Frame::MaxData { maximum_data };
self.from_conn.insert(mem::discriminant(&frame), frame);
}
// -- frames scoped on stream --
/// Indicate to receiving remote the stream is reset
@ -205,12 +216,12 @@ impl FlowMgr {
pub(crate) fn lost(
&mut self,
token: FlowControlRecoveryToken,
token: &FlowControlRecoveryToken,
send_streams: &mut SendStreams,
recv_streams: &mut RecvStreams,
indexes: &mut StreamIndexes,
) {
match token {
match *token {
// Always resend ResetStream if lost
Frame::ResetStream {
stream_id,

140
third_party/rust/neqo-transport/src/frame.rs поставляемый
Просмотреть файл

@ -6,12 +6,16 @@
// Directly relating to QUIC frames.
use neqo_common::{qdebug, Decoder, Encoder};
use neqo_common::{matches, qdebug, Decoder, Encoder};
use neqo_crypto::Epoch;
use crate::stream_id::StreamIndex;
use crate::{AppError, TransportError};
use crate::{ConnectionError, Error, Res};
use std::cmp::min;
use std::convert::TryFrom;
#[allow(clippy::module_name_repetitions)]
pub type FrameType = u64;
@ -142,6 +146,7 @@ pub enum Frame {
stream_id: u64,
offset: u64,
data: Vec<u8>,
fill: bool,
},
MaxData {
maximum_data: u64,
@ -197,7 +202,9 @@ impl Frame {
Frame::StopSending { .. } => FRAME_TYPE_STOP_SENDING,
Frame::Crypto { .. } => FRAME_TYPE_CRYPTO,
Frame::NewToken { .. } => FRAME_TYPE_NEW_TOKEN,
Frame::Stream { fin, offset, .. } => {
Frame::Stream {
fin, offset, fill, ..
} => {
let mut t = FRAME_TYPE_STREAM;
if *fin {
t |= STREAM_FRAME_BIT_FIN;
@ -205,7 +212,9 @@ impl Frame {
if *offset > 0 {
t |= STREAM_FRAME_BIT_OFF;
}
t |= STREAM_FRAME_BIT_LEN;
if !*fill {
t |= STREAM_FRAME_BIT_LEN;
}
t
}
Frame::MaxData { .. } => FRAME_TYPE_MAX_DATA,
@ -228,6 +237,68 @@ impl Frame {
}
}
/// Create a CRYPTO frame that fits the available space and its length.
pub fn new_crypto(offset: u64, data: &[u8], space: usize) -> (Frame, usize) {
// Subtract the frame type and offset from available space.
let mut remaining = space - 1 - Encoder::varint_len(offset);
// Then subtract space for the length field.
let data_len = min(remaining - 1, data.len());
remaining -= Encoder::varint_len(u64::try_from(data_len).unwrap());
remaining = min(data.len(), remaining);
(
Frame::Crypto {
offset,
data: data[..remaining].to_vec(),
},
remaining,
)
}
/// Create a STREAM frame that fits the available space.
/// Return a tuple of a frame and the amount of data it carries.
pub fn new_stream(
stream_id: u64,
offset: u64,
data: &[u8],
fin: bool,
space: usize,
) -> (Frame, usize) {
let mut remaining = space - 1 - Encoder::varint_len(stream_id);
if offset > 0 {
remaining -= Encoder::varint_len(offset);
}
let (fin, fill) = if data.len() > remaining {
// More data than fits, fill the packet and negate |fin|.
(false, true)
} else if data.len() == remaining {
// Exact fit, fill the packet, keep |fin|.
(fin, true)
} else {
// Too small, so include a length.
let data_len = min(remaining - 1, data.len());
remaining -= Encoder::varint_len(u64::try_from(data_len).unwrap());
remaining = min(data.len(), remaining);
// In case the added length causes this to spill over, check |fin| again.
(fin && remaining == data.len(), false)
};
qdebug!(
"Frame::new_stream fill {} fin {} data {}",
fill,
fin,
remaining
);
(
Frame::Stream {
stream_id,
offset,
data: data[..remaining].to_vec(),
fin,
fill,
},
remaining,
)
}
pub fn marshal(&self, enc: &mut Encoder) {
enc.encode_varint(self.get_type());
@ -275,13 +346,18 @@ impl Frame {
stream_id,
offset,
data,
fill,
..
} => {
enc.encode_varint(*stream_id);
if *offset > 0 {
enc.encode_varint(*offset);
}
enc.encode_vvec(&data);
if *fill {
enc.encode(&data);
} else {
enc.encode_vvec(&data);
}
}
Frame::MaxData { maximum_data } => {
enc.encode_varint(*maximum_data);
@ -345,10 +421,7 @@ impl Frame {
}
pub fn ack_eliciting(&self) -> bool {
match self {
Frame::Ack { .. } | Frame::Padding => false,
_ => true,
}
!matches!(self, Frame::Ack { .. } | Frame::Padding | Frame::ConnectionClose { .. })
}
/// Converts AckRanges as encoded in a ACK frame (see -transport
@ -404,12 +477,14 @@ impl Frame {
Frame::Stream {
stream_id,
offset,
fill,
data,
fin,
} => Some(format!(
"Stream {{ stream_id: {}, offset: {}, len: {} fin: {} }}",
"Stream {{ stream_id: {}, offset: {}, len: {}{} fin: {} }}",
stream_id,
offset,
if *fill { ">>" } else { "" },
data.len(),
fin,
)),
@ -417,13 +492,20 @@ impl Frame {
_ => Some(format!("{:?}", self)),
}
}
}
/// Calculate the crypto frame header size so we know how much data we can fit
pub fn crypto_frame_hdr_len(offset: u64, remaining: usize) -> usize {
let mut hdr_len = 1; // for frame type
hdr_len += Encoder::varint_len(offset);
hdr_len + Encoder::varint_len(remaining as u64)
pub fn is_allowed(&self, epoch: Epoch) -> bool {
qdebug!("is_allowed {:?} {}", self, epoch);
if matches!(self, Frame::Padding | Frame::Ping) {
true
} else if matches!(self, Frame::Crypto {..} | Frame::Ack {..} | Frame::ConnectionClose { error_code: CloseError::Transport(_), .. })
{
epoch != 1
} else if matches!(self, Frame::NewToken {..} | Frame::ConnectionClose {..}) {
epoch >= 3
} else {
epoch == 1 || epoch >= 3 // Application data
}
}
}
#[allow(clippy::module_name_repetitions)]
@ -508,7 +590,8 @@ pub fn decode_frame(dec: &mut Decoder) -> Res<Frame> {
dv!(dec)
};
qdebug!("STREAM {}", t);
let data = if (t & STREAM_FRAME_BIT_LEN) == 0 {
let fill = (t & STREAM_FRAME_BIT_LEN) == 0;
let data = if fill {
qdebug!("STREAM frame extends to the end of the packet");
dec.decode_remainder()
} else {
@ -520,6 +603,7 @@ pub fn decode_frame(dec: &mut Decoder) -> Res<Frame> {
stream_id: s,
offset: o,
data: data.to_vec(), // TODO(mt) unnecessary copy.
fill,
})
}
FRAME_TYPE_MAX_DATA => Ok(Frame::MaxData {
@ -591,7 +675,6 @@ pub fn decode_frame(dec: &mut Decoder) -> Res<Frame> {
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum TxMode {
Normal,
#[allow(dead_code)]
Pto,
}
@ -689,30 +772,35 @@ mod tests {
#[test]
fn test_stream() {
// First, just set the length bit.
let mut f = Frame::Stream {
let f = Frame::Stream {
fin: false,
stream_id: 5,
offset: 0,
data: vec![1, 2, 3],
fill: false,
};
enc_dec(&f, "0a0503010203");
// Now verify that we can parse without the length
// bit, because we never generate this.
let enc = Encoder::from_hex("0805010203");
let mut dec = enc.as_decoder();
let f2 = decode_frame(&mut dec).unwrap();
assert_eq!(f, f2);
// Now with offset != 0 and FIN
f = Frame::Stream {
let f = Frame::Stream {
fin: true,
stream_id: 5,
offset: 1,
data: vec![1, 2, 3],
fill: false,
};
enc_dec(&f, "0f050103010203");
// Now to fill the packet.
let f = Frame::Stream {
fin: true,
stream_id: 5,
offset: 0,
data: vec![1, 2, 3],
fill: true,
};
enc_dec(&f, "0905010203");
}
#[test]

Просмотреть файл

@ -19,7 +19,6 @@ use crate::crypto::CryptoRecoveryToken;
use crate::flow_mgr::FlowControlRecoveryToken;
use crate::send_stream::StreamRecoveryToken;
use crate::tracking::{AckToken, PNSpace};
use crate::State;
const GRANULARITY: Duration = Duration::from_millis(20);
// Defined in -recovery 6.2 as 500ms but using lower value until we have RTT
@ -244,7 +243,7 @@ impl LossRecovery {
self.pto_count += 1;
}
pub fn largest_acknowledged(&self, pn_space: PNSpace) -> Option<u64> {
pub fn largest_acknowledged_pn(&self, pn_space: PNSpace) -> Option<u64> {
self.spaces[pn_space].largest_acked
}
@ -264,7 +263,7 @@ impl LossRecovery {
tokens: Vec<RecoveryToken>,
now: Instant,
) {
qdebug!([self] "packet {:?}-{} sent.", pn_space, packet_number);
qdebug!([self], "packet {:?}-{} sent.", pn_space, packet_number);
self.spaces[pn_space].sent_packets.insert(
packet_number,
SentPacket {
@ -290,8 +289,12 @@ impl LossRecovery {
ack_delay: Duration,
now: Instant,
) -> (Vec<SentPacket>, Vec<SentPacket>) {
qdebug!([self] "ack received for {:?} - largest_acked={}.",
pn_space, largest_acked);
qdebug!(
[self],
"ack received for {:?} - largest_acked={}.",
pn_space,
largest_acked
);
let (acked_packets, any_ack_eliciting) = self.spaces[pn_space].remove_acked(acked_ranges);
if acked_packets.is_empty() {
@ -354,9 +357,12 @@ impl LossRecovery {
// Packets sent before this time are deemed lost.
let lost_deadline = now - loss_delay;
qdebug!([self]
qdebug!(
[self],
"detect lost packets = now {:?} loss delay {:?} lost_deadline {:?}",
now, loss_delay, lost_deadline
now,
loss_delay,
lost_deadline
);
let packet_space = &mut self.spaces[pn_space];
@ -436,8 +442,8 @@ impl LossRecovery {
lost_packets
}
pub fn get_timer(&mut self, conn_state: &State) -> LossRecoveryState {
qdebug!([self] "get_loss_detection_timer.");
pub fn get_timer(&mut self) -> LossRecoveryState {
qdebug!([self], "get_loss_detection_timer.");
let has_ack_eliciting_out = self
.spaces
@ -445,17 +451,14 @@ impl LossRecovery {
.flat_map(|spc| spc.sent_packets.values())
.any(|sp| sp.ack_eliciting);
qdebug!(
[self]
"has_ack_eliciting_out={}",
has_ack_eliciting_out,
);
qdebug!([self], "has_ack_eliciting_out={}", has_ack_eliciting_out,);
if !has_ack_eliciting_out && *conn_state == State::Connected {
if !has_ack_eliciting_out {
return LossRecoveryState::new(LossRecoveryMode::None, None);
}
qinfo!([self]
qinfo!(
[self],
"sent packets {} {} {}",
self.spaces[PNSpace::Initial].sent_packets.len(),
self.spaces[PNSpace::Handshake].sent_packets.len(),
@ -478,7 +481,12 @@ impl LossRecovery {
)
};
qdebug!([self] "loss_detection_timer mode={:?} timer={:?}", mode, maybe_timer);
qdebug!(
[self],
"loss_detection_timer mode={:?} timer={:?}",
mode,
maybe_timer
);
LossRecoveryState::new(mode, maybe_timer)
}
@ -743,7 +751,7 @@ mod tests {
assert_sent_times(&lr, None, None, Some(pn1_sent_time));
// After time elapses, pn 1 is marked lost.
let lr_state = lr.get_timer(&State::Connected);
let lr_state = lr.get_timer();
let pn1_lost_time = pn1_sent_time + (INITIAL_RTT * 9 / 8);
assert_eq!(lr_state.callback_time, Some(pn1_lost_time));
match lr_state.mode {

Просмотреть файл

@ -21,7 +21,7 @@ use crate::events::ConnectionEvents;
use crate::flow_mgr::FlowMgr;
use crate::stream_id::StreamId;
use crate::{AppError, Error, Res};
use neqo_common::qtrace;
use neqo_common::{matches, qtrace};
pub const RX_STREAM_DATA_WINDOW: u64 = 0xFFFF; // 64 KiB
@ -464,18 +464,15 @@ impl RecvStream {
}
pub fn is_terminal(&self) -> bool {
match self.state {
RecvStreamState::ResetRecvd | RecvStreamState::DataRead => true,
_ => false,
}
matches!(
self.state,
RecvStreamState::ResetRecvd | RecvStreamState::DataRead
)
}
// App got all data but did not get the fin signal.
fn needs_to_inform_app_about_fin(&self) -> bool {
match self.state {
RecvStreamState::DataRecvd { .. } => true,
_ => false,
}
matches!(self.state, RecvStreamState::DataRecvd { .. })
}
fn data_ready(&self) -> bool {
@ -751,5 +748,4 @@ mod tests {
assert_eq!(rx_ord.buffered(), 15);
assert_eq!(rx_ord.retired(), 2);
}
}

Просмотреть файл

@ -16,7 +16,7 @@ use std::rc::Rc;
use slice_deque::SliceDeque;
use smallvec::SmallVec;
use neqo_common::{matches, qerror, qinfo, qtrace, qwarn, Encoder};
use neqo_common::{matches, qdebug, qerror, qinfo, qtrace, qwarn};
use crate::events::ConnectionEvents;
use crate::flow_mgr::FlowMgr;
@ -299,20 +299,31 @@ impl TxBuffer {
can_buffer
}
pub fn next_bytes(&self, _mode: TxMode) -> Option<(u64, &[u8])> {
let (start, maybe_len) = self.ranges.first_unmarked_range();
pub fn next_bytes(&self, mode: TxMode) -> Option<(u64, &[u8])> {
match mode {
TxMode::Normal => {
let (start, maybe_len) = self.ranges.first_unmarked_range();
if start == self.retired + u64::try_from(self.buffered()).unwrap() {
return None;
}
if start == self.retired + u64::try_from(self.buffered()).unwrap() {
return None;
}
let buff_off = usize::try_from(start - self.retired).unwrap();
match maybe_len {
Some(len) => Some((
start,
&self.send_buf[buff_off..buff_off + usize::try_from(len).unwrap()],
)),
None => Some((start, &self.send_buf[buff_off..])),
let buff_off = usize::try_from(start - self.retired).unwrap();
match maybe_len {
Some(len) => Some((
start,
&self.send_buf[buff_off..buff_off + usize::try_from(len).unwrap()],
)),
None => Some((start, &self.send_buf[buff_off..])),
}
}
TxMode::Pto => {
if self.buffered() == 0 {
None
} else {
Some((self.retired, &self.send_buf))
}
}
}
}
@ -606,10 +617,7 @@ impl SendStream {
}
pub fn is_terminal(&self) -> bool {
match self.state {
SendStreamState::DataRecvd { .. } | SendStreamState::ResetRecvd => true,
_ => false,
}
matches!(self.state, SendStreamState::DataRecvd { .. } | SendStreamState::ResetRecvd)
}
pub fn send(&mut self, buf: &[u8]) -> Res<usize> {
@ -759,30 +767,22 @@ impl SendStreams {
}
for (stream_id, stream) in self {
let fin = stream.final_size();
let complete = stream.final_size().is_some();
if let Some((offset, data)) = stream.next_bytes(mode) {
qtrace!(
"Stream {} sending bytes {}-{}, epoch {}, mode {:?}, remaining {}",
let (frame, length) =
Frame::new_stream(stream_id.as_u64(), offset, data, complete, remaining);
qdebug!(
"Stream {} sending bytes {}-{}, epoch {}, mode {:?}",
stream_id.as_u64(),
offset,
offset + data.len() as u64,
offset + length as u64,
epoch,
mode,
remaining
);
let frame_hdr_len = stream_frame_hdr_len(*stream_id, offset, remaining);
let length = min(data.len(), remaining - frame_hdr_len);
let fin = match fin {
None => false,
Some(fin) => fin == offset + length as u64,
};
let frame = Frame::Stream {
fin,
stream_id: stream_id.as_u64(),
offset,
data: data[..length].to_vec(),
};
let fin = complete && length == data.len();
debug_assert!(!fin || matches!(frame, Frame::Stream{fin: true, .. }));
stream.mark_as_sent(offset, length, fin);
return Some((
frame,
Some(RecoveryToken::Stream(StreamRecoveryToken {
@ -807,18 +807,6 @@ impl<'a> IntoIterator for &'a mut SendStreams {
}
}
/// Calculate the frame header size so we know how much data we can fit
fn stream_frame_hdr_len(stream_id: StreamId, offset: u64, remaining: usize) -> usize {
let mut hdr_len = 1; // for frame type
hdr_len += Encoder::varint_len(stream_id.as_u64());
if offset > 0 {
hdr_len += Encoder::varint_len(offset);
}
// We always include a length field.
hdr_len + Encoder::varint_len(remaining as u64)
}
#[derive(Debug, Clone)]
pub struct StreamRecoveryToken {
pub(crate) id: StreamId,
@ -882,6 +870,15 @@ mod tests {
let res = rt.first_unmarked_range();
assert_eq!(res, (0, Some(5)));
assert_eq!(
rt.used.iter().nth(0).unwrap(),
(&5, &(5, RangeState::Acked))
);
assert_eq!(
rt.used.iter().nth(1).unwrap(),
(&13, &(2, RangeState::Sent))
);
assert!(rt.used.iter().nth(2).is_none());
rt.mark_range(0, 5, RangeState::Sent);
let res = rt.first_unmarked_range();

41
third_party/rust/neqo-transport/src/server.rs поставляемый
Просмотреть файл

@ -48,7 +48,7 @@ type CidMgr = Rc<RefCell<dyn ConnectionIdManager>>;
type ConnectionTableRef = Rc<RefCell<HashMap<ConnectionId, StateRef>>>;
#[derive(Debug)]
struct ServerConnectionState {
pub struct ServerConnectionState {
c: Connection,
last_timer: Instant,
}
@ -264,17 +264,17 @@ impl Server {
dgram: Option<Datagram>,
now: Instant,
) -> Option<Datagram> {
qtrace!([self] "Process connection {:?}", c);
qtrace!([self], "Process connection {:?}", c);
let out = c.borrow_mut().process(dgram, now);
match out {
Output::Datagram(_) => {
qtrace!([self] "Sending packet, added to waiting connections");
qtrace!([self], "Sending packet, added to waiting connections");
self.waiting.push_back(c.clone());
}
Output::Callback(delay) => {
let next = now + delay;
if next != c.borrow().last_timer {
qtrace!([self] "Change timer to {:?}", next);
qtrace!([self], "Change timer to {:?}", next);
self.remove_timer(&c);
c.borrow_mut().last_timer = next;
self.timers.add(next, c.clone());
@ -285,7 +285,7 @@ impl Server {
}
}
if c.borrow().has_events() {
qtrace!([self] "Connection active: {:?}", c);
qtrace!([self], "Connection active: {:?}", c);
self.active.insert(ActiveConnectionRef { c: c.clone() });
}
if matches!(c.borrow().state(), State::Closed(_)) {
@ -315,7 +315,7 @@ impl Server {
RetryTokenResult::Pass => self.accept_connection(None, dgram, now),
RetryTokenResult::Valid(dcid) => self.accept_connection(Some(dcid), dgram, now),
RetryTokenResult::Validate => {
qinfo!([self] "Send retry for {:?}", hdr.dcid);
qinfo!([self], "Send retry for {:?}", hdr.dcid);
let res = self.retry.generate_token(&hdr.dcid, dgram.source(), now);
let token = if let Ok(t) = res {
@ -348,7 +348,7 @@ impl Server {
dgram: Datagram,
now: Instant,
) -> Option<Datagram> {
qinfo!([self] "Accept connection");
qinfo!([self], "Accept connection");
// The internal connection ID manager that we use is not used directly.
// Instead, wrap it so that we can save connection IDs.
let cid_mgr = Rc::new(RefCell::new(ServerConnectionIdManager {
@ -370,7 +370,7 @@ impl Server {
cid_mgr.borrow_mut().c = Some(c.clone());
self.process_connection(c, Some(dgram), now)
} else {
qwarn!([self] "Unable to create connection");
qwarn!([self], "Unable to create connection");
None
}
}
@ -384,7 +384,7 @@ impl Server {
let hdr = match res {
Ok(h) => h,
_ => {
qtrace!([self] "Discarding {:?}", dgram);
qtrace!([self], "Discarding {:?}", dgram);
return None;
}
};
@ -396,12 +396,12 @@ impl Server {
if hdr.tipe == PacketType::Short {
// TODO send a stateless reset here.
qtrace!([self] "Short header packet for an unknown connection");
qtrace!([self], "Short header packet for an unknown connection");
return None;
}
if dgram.len() < MIN_INITIAL_PACKET_SIZE {
qtrace!([self] "Bogus packet: too short");
qtrace!([self], "Bogus packet: too short");
return None;
}
@ -415,13 +415,13 @@ impl Server {
/// Iterate through the pending connections looking for any that might want
/// to send a datagram. Stop at the first one that does.
fn process_next_output(&mut self, now: Instant) -> Option<Datagram> {
qtrace!([self] "No packet to send, look at waiting connections");
qtrace!([self], "No packet to send, look at waiting connections");
while let Some(c) = self.waiting.pop_front() {
if let Some(d) = self.process_connection(c, None, now) {
return Some(d);
}
}
qtrace!([self] "No packet to send still, run timers");
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);
@ -447,16 +447,16 @@ impl Server {
let out = out.or_else(|| self.process_next_output(now));
match out {
Some(d) => {
qtrace!([self] "Send packet: {:?}", d);
qtrace!([self], "Send packet: {:?}", d);
Output::Datagram(d)
}
_ => match self.next_time(now) {
Some(delay) => {
qtrace!([self] "Wait: {:?}", delay);
qtrace!([self], "Wait: {:?}", delay);
Output::Callback(delay)
}
_ => {
qtrace!([self] "Go dormant");
qtrace!([self], "Go dormant");
Output::None
}
},
@ -470,6 +470,10 @@ impl Server {
.into_iter()
.collect()
}
pub fn add_to_waiting(&mut self, c: ActiveConnectionRef) {
self.waiting.push_back(c.connection());
}
}
#[derive(Clone, Debug)]
@ -485,6 +489,10 @@ impl ActiveConnectionRef {
pub fn borrow_mut<'a>(&'a mut self) -> impl DerefMut<Target = Connection> + 'a {
std::cell::RefMut::map(self.c.borrow_mut(), |c| &mut c.c)
}
pub fn connection(&self) -> StateRef {
self.c.clone()
}
}
impl std::hash::Hash for ActiveConnectionRef {
@ -499,6 +507,7 @@ impl PartialEq for ActiveConnectionRef {
Rc::ptr_eq(&self.c, &other.c)
}
}
impl Eq for ActiveConnectionRef {}
struct ServerConnectionIdManager {

Просмотреть файл

@ -84,12 +84,12 @@ impl PacketRange {
assert!(!self.contains(pn));
// Only insert if this is adjacent the current range.
if (self.largest + 1) == pn {
qtrace!([self] "Adding largest {}", pn);
qtrace!([self], "Adding largest {}", pn);
self.largest += 1;
self.ack_needed = true;
true
} else if self.smallest == (pn + 1) {
qtrace!([self] "Adding smallest {}", pn);
qtrace!([self], "Adding smallest {}", pn);
self.smallest -= 1;
self.ack_needed = true;
true
@ -100,7 +100,7 @@ impl PacketRange {
/// Maybe merge a lower-numbered range into this.
pub fn merge_smaller(&mut self, other: &Self) {
qinfo!([self] "Merging {}", other);
qinfo!([self], "Merging {}", other);
// This only works if they are immediately adjacent.
assert_eq!(self.smallest - 1, other.largest);
@ -113,7 +113,7 @@ impl PacketRange {
/// Requires that other is equal to this, or a larger range.
pub fn acknowledged(&mut self, other: &Self) {
if (other.smallest <= self.smallest) && (other.largest >= self.largest) {
qinfo!([self] "Acknowledged");
qinfo!([self], "Acknowledged");
self.ack_needed = false;
}
}
@ -201,6 +201,8 @@ impl RecvdPackets {
/// Add the packet to the tracked set.
pub fn set_received(&mut self, now: Instant, pn: u64, ack_eliciting: bool) {
let next_in_order_pn = self.ranges.get(0).map(|pr| pr.largest + 1).unwrap_or(0);
qdebug!("next in order pn: {}", next_in_order_pn);
let i = self.add(pn);
// The new addition was the largest, so update the time we use for calculating ACK delay.
@ -212,18 +214,21 @@ impl RecvdPackets {
if self.ranges.len() > MAX_TRACKED_RANGES {
let oldest = self.ranges.pop_back().unwrap();
if oldest.ack_needed {
qwarn!([self] "Dropping unacknowledged ACK range: {}", oldest);
qwarn!([self], "Dropping unacknowledged ACK range: {}", oldest);
// TODO(mt) Record some statistics about this so we can tune MAX_TRACKED_RANGES.
} else {
qdebug!([self] "Drop ACK range: {}", oldest);
qdebug!([self], "Drop ACK range: {}", oldest);
}
self.min_tracked = oldest.largest + 1;
}
if ack_eliciting {
// On the first ack-eliciting packet since sending an ACK, set a delay.
// On the second, remove that delay.
if self.ack_time.is_none() && self.space == PNSpace::ApplicationData {
// Send ACK right away if out-of-order
// On the first in-order ack-eliciting packet since sending an ACK,
// set a delay. On the second, remove that delay.
if pn != next_in_order_pn {
self.ack_time = Some(now);
} else if self.ack_time.is_none() && self.space == PNSpace::ApplicationData {
self.ack_time = Some(now + ACK_DELAY);
} else {
self.ack_time = Some(now);
@ -507,6 +512,24 @@ mod tests {
}
}
#[test]
fn ooo_no_ack_delay() {
for space in &[
PNSpace::Initial,
PNSpace::Handshake,
PNSpace::ApplicationData,
] {
let mut rp = RecvdPackets::new(*space);
assert!(rp.ack_time().is_none());
assert!(!rp.ack_now(now()));
// Any OoO packet will be acknowledged straight away.
rp.set_received(now(), 3, true);
assert_eq!(Some(now()), rp.ack_time());
assert!(rp.ack_now(now()));
}
}
#[test]
fn aggregate_ack_time() {
let mut tracker = AckTracker::default();