Bug 1647769 - Update to Neqo 0.4.4 r=dragana,necko-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D80687
This commit is contained in:
Andy Grover 2020-06-23 18:51:19 +00:00
Родитель a6bb2f24f2
Коммит 70c8aeee0b
37 изменённых файлов: 1211 добавлений и 561 удалений

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

@ -15,7 +15,7 @@ rev = "e3c3388e6632cf55e08d773b32e58b1cab9b2731"
[source."https://github.com/mozilla/neqo"] [source."https://github.com/mozilla/neqo"]
git = "https://github.com/mozilla/neqo" git = "https://github.com/mozilla/neqo"
replace-with = "vendored-sources" replace-with = "vendored-sources"
tag = "v0.4.3" tag = "v0.4.4"
[source."https://github.com/mozilla/mp4parse-rust"] [source."https://github.com/mozilla/mp4parse-rust"]
git = "https://github.com/mozilla/mp4parse-rust" git = "https://github.com/mozilla/mp4parse-rust"

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

@ -3065,8 +3065,8 @@ dependencies = [
[[package]] [[package]]
name = "neqo-common" name = "neqo-common"
version = "0.4.3" version = "0.4.4"
source = "git+https://github.com/mozilla/neqo?tag=v0.4.3#7406cc1798ed5274cd8540b93bb3443ff4cc26e5" source = "git+https://github.com/mozilla/neqo?tag=v0.4.4#0d1cef1b8fe42e4e73085c2f940b16ce00a29f73"
dependencies = [ dependencies = [
"chrono", "chrono",
"env_logger", "env_logger",
@ -3078,8 +3078,8 @@ dependencies = [
[[package]] [[package]]
name = "neqo-crypto" name = "neqo-crypto"
version = "0.4.3" version = "0.4.4"
source = "git+https://github.com/mozilla/neqo?tag=v0.4.3#7406cc1798ed5274cd8540b93bb3443ff4cc26e5" source = "git+https://github.com/mozilla/neqo?tag=v0.4.4#0d1cef1b8fe42e4e73085c2f940b16ce00a29f73"
dependencies = [ dependencies = [
"bindgen", "bindgen",
"log", "log",
@ -3091,8 +3091,8 @@ dependencies = [
[[package]] [[package]]
name = "neqo-http3" name = "neqo-http3"
version = "0.4.3" version = "0.4.4"
source = "git+https://github.com/mozilla/neqo?tag=v0.4.3#7406cc1798ed5274cd8540b93bb3443ff4cc26e5" source = "git+https://github.com/mozilla/neqo?tag=v0.4.4#0d1cef1b8fe42e4e73085c2f940b16ce00a29f73"
dependencies = [ dependencies = [
"log", "log",
"neqo-common", "neqo-common",
@ -3105,8 +3105,8 @@ dependencies = [
[[package]] [[package]]
name = "neqo-qpack" name = "neqo-qpack"
version = "0.4.3" version = "0.4.4"
source = "git+https://github.com/mozilla/neqo?tag=v0.4.3#7406cc1798ed5274cd8540b93bb3443ff4cc26e5" source = "git+https://github.com/mozilla/neqo?tag=v0.4.4#0d1cef1b8fe42e4e73085c2f940b16ce00a29f73"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"log", "log",
@ -3120,8 +3120,8 @@ dependencies = [
[[package]] [[package]]
name = "neqo-transport" name = "neqo-transport"
version = "0.4.3" version = "0.4.4"
source = "git+https://github.com/mozilla/neqo?tag=v0.4.3#7406cc1798ed5274cd8540b93bb3443ff4cc26e5" source = "git+https://github.com/mozilla/neqo?tag=v0.4.4#0d1cef1b8fe42e4e73085c2f940b16ce00a29f73"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"log", "log",

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

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

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

@ -5,16 +5,16 @@ authors = ["Dragana Damjanovic <dragana.damjano@gmail.com>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
neqo-transport = { tag = "v0.4.3", git = "https://github.com/mozilla/neqo" } neqo-transport = { tag = "v0.4.4", git = "https://github.com/mozilla/neqo" }
neqo-common = { tag = "v0.4.3", git = "https://github.com/mozilla/neqo" } neqo-common = { tag = "v0.4.4", git = "https://github.com/mozilla/neqo" }
neqo-http3 = { tag = "v0.4.3", git = "https://github.com/mozilla/neqo" } neqo-http3 = { tag = "v0.4.4", git = "https://github.com/mozilla/neqo" }
neqo-qpack = { tag = "v0.4.3", git = "https://github.com/mozilla/neqo" } neqo-qpack = { tag = "v0.4.4", git = "https://github.com/mozilla/neqo" }
mio = "0.6.17" mio = "0.6.17"
mio-extras = "2.0.5" mio-extras = "2.0.5"
log = "0.4.0" log = "0.4.0"
[dependencies.neqo-crypto] [dependencies.neqo-crypto]
tag = "v0.4.3" tag = "v0.4.4"
git = "https://github.com/mozilla/neqo" git = "https://github.com/mozilla/neqo"
default-features = false default-features = false
features = ["gecko"] features = ["gecko"]

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

@ -1 +1 @@
{"files":{"Cargo.toml":"38f530fd1164e97530bdc353b8561b79ea3c16faea4d0cb164261e8a81d6e148","src/codec.rs":"6ec44d7fbc4c2a4db39da4530e3a463e1608256528d5c68fc59ea90752b2d94a","src/datagram.rs":"569f8d9e34d7ee17144bf63d34136ecd9778da0d337e513f338738c50284615e","src/incrdecoder.rs":"8d44c4437461cae023448312cab4045ad6e3f0c9eb8af2383f7132be40a9d917","src/lib.rs":"72dbf367239ab7f057d59d23cd8ce6ae2b29a2d3362a9ccb162619d80992da9a","src/log.rs":"b8da388073f72a21128d52b0d0c963e07a3d3cf3368438ae3a50be34b8add3a4","src/qlog.rs":"4f131c7e4c2bb5862b33a0d1746348a4f63f9b57cfa7a85dce1b59f80ecfaa7b","src/timer.rs":"706333bf1b07f65df9d18904b1cb269e4b80dee93a9b239dd8cb128b293955ae","tests/log.rs":"480b165b7907ec642c508b303d63005eee1427115d6973a349eaf6b2242ed18d"},"package":null} {"files":{"Cargo.toml":"1950a6e43e499c2594ec8eeeefc6d5bee79ec624a736fb044bac87dcaa674270","src/codec.rs":"6ec44d7fbc4c2a4db39da4530e3a463e1608256528d5c68fc59ea90752b2d94a","src/datagram.rs":"569f8d9e34d7ee17144bf63d34136ecd9778da0d337e513f338738c50284615e","src/incrdecoder.rs":"8d44c4437461cae023448312cab4045ad6e3f0c9eb8af2383f7132be40a9d917","src/lib.rs":"72dbf367239ab7f057d59d23cd8ce6ae2b29a2d3362a9ccb162619d80992da9a","src/log.rs":"b8da388073f72a21128d52b0d0c963e07a3d3cf3368438ae3a50be34b8add3a4","src/qlog.rs":"4f131c7e4c2bb5862b33a0d1746348a4f63f9b57cfa7a85dce1b59f80ecfaa7b","src/timer.rs":"706333bf1b07f65df9d18904b1cb269e4b80dee93a9b239dd8cb128b293955ae","tests/log.rs":"480b165b7907ec642c508b303d63005eee1427115d6973a349eaf6b2242ed18d"},"package":null}

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

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

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

@ -1 +1 @@
{"files":{"Cargo.toml":"9cf24ef2dd52419b4e3f222fd68a4548fac5b46184fea89afe2d4305cacc27b8","TODO":"ac0f1c2ebcca03f5b3c0cc56c5aedbb030a4b511e438bc07a57361c789f91e9f","bindings/bindings.toml":"0ae7922bb20f2b8cf54b307cd642303e65b00cfbc3e681877e2a7a86f7b22530","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":"0be611e6b25a18d5ed724071a3a471c2c5b584649b5fe36de28a56ed8caaf800","src/aead.rs":"b0ed05d399a32e4c923d4d385e4ae72d675d24c6cc86471f59a4edbe5cb2159a","src/agent.rs":"9ba921199282efaaf7d194c8279921fe75fd76bd34dd0c6ce1a7d71821dd8bac","src/agentio.rs":"2ab0ad6349276a8c94dfd85bfaedcad24c8fff464b82f7369c1bd45038f79cfd","src/auth.rs":"71ac7e297a5f872d26cf67b6bbd96e4548ea38374bdd84c1094f76a5de4ed1cb","src/cert.rs":"fd3fd2bbb38754bdcee3898549feae412943c9f719032531c1ad6e61783b5394","src/constants.rs":"c39ee506a10d685fda77c1d2ddf691b595b067b4e1044ac7a21e360119d6002b","src/err.rs":"04f38831ca62d29d8aadfe9daf95fd29e68ece184e6d3e00bfb9ee1d12744033","src/exp.rs":"61586662407359c1ecb8ed4987bc3c702f26ba2e203a091a51b6d6363cbd510f","src/ext.rs":"97cba23247e5f9656f27587214f7d7370a69174bae5960a012ce3e6fc99f9116","src/hkdf.rs":"40e44f4280497ef525c2b4c465f14f06d241150851668b264ee958f74321cfbe","src/hp.rs":"7fce64e0cc3a6a7e744bc797886bcfaa39679f0a81853b2e55ea0f54fb6bf700","src/lib.rs":"5f3c4c05c0a5ecb4e4cfc6c4d242e7603566f287bdb0f0ca46f6a773aa7714e9","src/once.rs":"b9850384899a1a016e839743d3489c0d4d916e1973746ef8c89872105d7d9736","src/p11.rs":"0b62ee5938aefb82e8faee5aa14e990a00442cc9744e8ba22eda80b32030c42c","src/prio.rs":"bc4e97049563b136cb7b39f5171e7909d56a77ed46690aaacb781eeb4a4743e0","src/replay.rs":"40924865994396441a68e6009ecbdf352d6a02fdf539aa65604124e26bffb4d3","src/result.rs":"cef34dfcb907723e195b56501132e4560e250b327783cb5e41201da5b63e9b5c","src/secrets.rs":"acb5befa74e06281c6f80d7298efc58f568bb4e6d949b4225c335e3f392be741","src/selfencrypt.rs":"f8d04728353fcbbdd50ad19217c9fd34974ffa8872c0d9d5d6d896d05f04baa5","src/ssl.rs":"d64c20ed2a0b63c5fa3aee674a622408a89a764ee225098f18d0c61ce6c6df29","src/time.rs":"5b2ab4028b04b6245c666f33f1c1449816d3d1eb8141f723f5773f21f8fe4388","tests/aead.rs":"a1d8eb69f5672e064f84dce3d214b347a396718e3de56d57ccc108ee87f1cbc1","tests/agent.rs":"89c21e97bf9c8d893380c1d4ab91f4e12526e1a51acc0f19159e643ef8da2a4f","tests/ext.rs":"5f5de777599cbe1295a4461b32c249de74666edb0a13173f76948f2939963dfd","tests/handshake.rs":"6f12fb9a02d36f64254ffe49385de69fce8bc95b73af80be011f0e065d65a5a3","tests/hkdf.rs":"539235e9dcf2a56b72961a9a04f0080409adf6bf465bfad7c30026421b2d4326","tests/hp.rs":"e52a7d2f4387f2dfe8bfe1da5867e8e0d3eb51e171c6904e18b18c4343536af8","tests/init.rs":"20aad800ac793aaf83059cf860593750509fdedeeff0c08a648e7a5cb398dae0","tests/selfencrypt.rs":"46e9a1a09c2ae577eb106d23a5cdacf762575c0dea1948aedab06ef7389ce713"},"package":null} {"files":{"Cargo.toml":"5fd46db41f0e46a4f02431cf6072ef5394a1387b744ec67d64247e793df47df0","TODO":"ac0f1c2ebcca03f5b3c0cc56c5aedbb030a4b511e438bc07a57361c789f91e9f","bindings/bindings.toml":"0ae7922bb20f2b8cf54b307cd642303e65b00cfbc3e681877e2a7a86f7b22530","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":"0be611e6b25a18d5ed724071a3a471c2c5b584649b5fe36de28a56ed8caaf800","src/aead.rs":"b0ed05d399a32e4c923d4d385e4ae72d675d24c6cc86471f59a4edbe5cb2159a","src/agent.rs":"6f6cbe5a977587d2cfdea07793c9dca0345994854f395a7ca8bb2e978f19e90e","src/agentio.rs":"2ab0ad6349276a8c94dfd85bfaedcad24c8fff464b82f7369c1bd45038f79cfd","src/auth.rs":"71ac7e297a5f872d26cf67b6bbd96e4548ea38374bdd84c1094f76a5de4ed1cb","src/cert.rs":"fd3fd2bbb38754bdcee3898549feae412943c9f719032531c1ad6e61783b5394","src/constants.rs":"c39ee506a10d685fda77c1d2ddf691b595b067b4e1044ac7a21e360119d6002b","src/err.rs":"04f38831ca62d29d8aadfe9daf95fd29e68ece184e6d3e00bfb9ee1d12744033","src/exp.rs":"61586662407359c1ecb8ed4987bc3c702f26ba2e203a091a51b6d6363cbd510f","src/ext.rs":"97cba23247e5f9656f27587214f7d7370a69174bae5960a012ce3e6fc99f9116","src/hkdf.rs":"40e44f4280497ef525c2b4c465f14f06d241150851668b264ee958f74321cfbe","src/hp.rs":"7fce64e0cc3a6a7e744bc797886bcfaa39679f0a81853b2e55ea0f54fb6bf700","src/lib.rs":"5f3c4c05c0a5ecb4e4cfc6c4d242e7603566f287bdb0f0ca46f6a773aa7714e9","src/once.rs":"b9850384899a1a016e839743d3489c0d4d916e1973746ef8c89872105d7d9736","src/p11.rs":"0b62ee5938aefb82e8faee5aa14e990a00442cc9744e8ba22eda80b32030c42c","src/prio.rs":"bc4e97049563b136cb7b39f5171e7909d56a77ed46690aaacb781eeb4a4743e0","src/replay.rs":"40924865994396441a68e6009ecbdf352d6a02fdf539aa65604124e26bffb4d3","src/result.rs":"cef34dfcb907723e195b56501132e4560e250b327783cb5e41201da5b63e9b5c","src/secrets.rs":"acb5befa74e06281c6f80d7298efc58f568bb4e6d949b4225c335e3f392be741","src/selfencrypt.rs":"f8d04728353fcbbdd50ad19217c9fd34974ffa8872c0d9d5d6d896d05f04baa5","src/ssl.rs":"d64c20ed2a0b63c5fa3aee674a622408a89a764ee225098f18d0c61ce6c6df29","src/time.rs":"5b2ab4028b04b6245c666f33f1c1449816d3d1eb8141f723f5773f21f8fe4388","tests/aead.rs":"a1d8eb69f5672e064f84dce3d214b347a396718e3de56d57ccc108ee87f1cbc1","tests/agent.rs":"2312590910dc3cba4c446c0dee844773779d8a3870cf543fcc863821fcee50dd","tests/ext.rs":"5f5de777599cbe1295a4461b32c249de74666edb0a13173f76948f2939963dfd","tests/handshake.rs":"6f12fb9a02d36f64254ffe49385de69fce8bc95b73af80be011f0e065d65a5a3","tests/hkdf.rs":"539235e9dcf2a56b72961a9a04f0080409adf6bf465bfad7c30026421b2d4326","tests/hp.rs":"e52a7d2f4387f2dfe8bfe1da5867e8e0d3eb51e171c6904e18b18c4343536af8","tests/init.rs":"20aad800ac793aaf83059cf860593750509fdedeeff0c08a648e7a5cb398dae0","tests/selfencrypt.rs":"46e9a1a09c2ae577eb106d23a5cdacf762575c0dea1948aedab06ef7389ce713"},"package":null}

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

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

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

@ -354,7 +354,7 @@ impl SecretAgent {
/// ///
/// # Errors /// # Errors
/// If NSS can't enable or disable ciphers. /// If NSS can't enable or disable ciphers.
pub fn enable_ciphers(&mut self, ciphers: &[Cipher]) -> Res<()> { pub fn set_ciphers(&mut self, ciphers: &[Cipher]) -> Res<()> {
if self.state != HandshakeState::New { if self.state != HandshakeState::New {
qwarn!([self], "Cannot enable ciphers in state {:?}", self.state); qwarn!([self], "Cannot enable ciphers in state {:?}", self.state);
return Err(Error::InternalError); return Err(Error::InternalError);

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

@ -141,7 +141,7 @@ fn chacha_client() {
let mut client = Client::new("server.example").expect("should create client"); let mut client = Client::new("server.example").expect("should create client");
let mut server = Server::new(&["key"]).expect("should create server"); let mut server = Server::new(&["key"]).expect("should create server");
client client
.enable_ciphers(&[TLS_CHACHA20_POLY1305_SHA256]) .set_ciphers(&[TLS_CHACHA20_POLY1305_SHA256])
.expect("ciphers set"); .expect("ciphers set");
connect(&mut client, &mut server); connect(&mut client, &mut server);

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

@ -1 +1 @@
{"files":{"Cargo.toml":"09ebcb8eb486484a561a328f40d00de26723d3c9dc6afd4f1effb4b68cc3c353","src/client_events.rs":"8c19986b7372b36d1265d4a848b07b5c334511cbdfc02f313c54e551523c08f5","src/connection.rs":"cebdb535151ec5598161091c6b709c38852aa32f32855cee8f2c6129a2bcb5a0","src/connection_client.rs":"6ec91fe9f32f092f681f2a1463ecfb635019910919dd1df759447e2865bec3b4","src/connection_server.rs":"c96e347cbc53a6abb12ef86f548cac52526069884ee97d384aa91a1ae3cd43aa","src/control_stream_local.rs":"03d6259599543da2154388d5e48efbc06271e079429d3d946278c4c58c0521c7","src/control_stream_remote.rs":"121ac329dafc43efbfa3a0d26ab42b164d6a467523bc34193d03b7a0597ffd21","src/hframe.rs":"16bed02bec406f897ca847e0e2e060fa4e0e03d0397fab40e640c24679652228","src/hsettings_frame.rs":"f7cd5dc349c4e3d77b35effae620578492631cf33e7db9c93418a119b90cadc3","src/lib.rs":"fc76582370c384294d08e55f9e3d026ca2645b4418b1e989328f61d2f280ffff","src/push_controller.rs":"36e70602887fe685986cbe7960ec5270feda61b7f5a87474f585248fe13104fd","src/recv_message.rs":"d651428ed86cdea0f54102c3218eb4c7f99aac6fcad739b5538f6fb8fee9c918","src/send_message.rs":"4aa03879c64e9382fc8e6fcdda5c7674878e61a374e99af58139408eaf520c0f","src/server.rs":"b8e815be0e297aa422fe9067e2ff62c55e948258710b605ec82d4f8ea6b95698","src/server_connection_events.rs":"d95c9c441b278d9cc7577e5a2d8c1b00cf2e20f43a538d8c34db39629b415b01","src/server_events.rs":"27f23dc49f649fb66113c5a71345d9af30e7de04f791d4e1928d32c66b47d3f1","src/stream_type_reader.rs":"9eadcdf4ea223258f6a115c3c7e8c37228e4d7baee8eb8eb944175ed91a5cf36","tests/httpconn.rs":"32b5162ad8963a7079704858d537f9d7f3ba40d428620e5bc80fe1845908ce75"},"package":null} {"files":{"Cargo.toml":"08e5dbc1d05fabf34a58ea82b091031198d02ff28044408ba183aca7da842013","src/client_events.rs":"8c19986b7372b36d1265d4a848b07b5c334511cbdfc02f313c54e551523c08f5","src/connection.rs":"c9cf4772d5a2db0589beeca3fd52a030ebe8f8b265cf9396980098e129e5ed34","src/connection_client.rs":"a504a57a48b07ee83de9ac647fbd4a39fc5a9408e173d54bbbaca90f96e2e3ae","src/connection_server.rs":"4de7cda18ef946440c89bafb5c5c61714f145d6373dd9a9d8e1d57d7569e3e47","src/control_stream_local.rs":"03d6259599543da2154388d5e48efbc06271e079429d3d946278c4c58c0521c7","src/control_stream_remote.rs":"fc21b25c44aa851ff0b1789b84aadac7e93728939bedbcb76d1019469b410da8","src/hframe.rs":"a422af189ede7bdc664947563bc8cd87f70c3d8a17665dd91698f403d960caab","src/hsettings_frame.rs":"f7cd5dc349c4e3d77b35effae620578492631cf33e7db9c93418a119b90cadc3","src/lib.rs":"fc76582370c384294d08e55f9e3d026ca2645b4418b1e989328f61d2f280ffff","src/push_controller.rs":"36e70602887fe685986cbe7960ec5270feda61b7f5a87474f585248fe13104fd","src/recv_message.rs":"d651428ed86cdea0f54102c3218eb4c7f99aac6fcad739b5538f6fb8fee9c918","src/send_message.rs":"4aa03879c64e9382fc8e6fcdda5c7674878e61a374e99af58139408eaf520c0f","src/server.rs":"8d681bd1e52aa692db0e781254592c10bb8e89ebc4e9d238cf4c0db9cfd0644e","src/server_connection_events.rs":"d95c9c441b278d9cc7577e5a2d8c1b00cf2e20f43a538d8c34db39629b415b01","src/server_events.rs":"27f23dc49f649fb66113c5a71345d9af30e7de04f791d4e1928d32c66b47d3f1","src/stream_type_reader.rs":"9eadcdf4ea223258f6a115c3c7e8c37228e4d7baee8eb8eb944175ed91a5cf36","tests/httpconn.rs":"32b5162ad8963a7079704858d537f9d7f3ba40d428620e5bc80fe1845908ce75"},"package":null}

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

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

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

@ -214,24 +214,26 @@ impl Http3Connection {
} }
} }
/// This function handles reading from all streams, i.e. control, qpack, request/response fn recv_decoder(&mut self, conn: &mut Connection, stream_id: u64) -> Res<bool> {
/// stream and unidi stream that are still do not have a type. if self.qpack_decoder.is_recv_stream(stream_id) {
/// The function cannot handle: qdebug!(
/// 1) a Push stream (if an unknown unidi stream is decoded to be a push stream) [self],
/// 2) frames `MaxPushId` or `Goaway` must be handled by `Http3Client`/`Server`. "The qpack decoder stream ({}) is readable.",
/// The function returns `HandleReadableOutput`. stream_id
pub fn handle_stream_readable( );
&mut self, let unblocked_streams = self.qpack_decoder.receive(conn, stream_id)?;
conn: &mut Connection, for stream_id in unblocked_streams {
stream_id: u64, qdebug!([self], "Stream {} is unblocked", stream_id);
) -> Res<HandleReadableOutput> { self.handle_read_stream(conn, stream_id)?;
qtrace!([self], "Readable stream {}.", stream_id); }
Ok(true)
} else {
Ok(false)
}
}
let label = ::neqo_common::log_subject!(::log::Level::Debug, self); fn recv_control(&mut self, conn: &mut Connection, stream_id: u64) -> Res<HandleReadableOutput> {
if self.handle_read_stream(conn, stream_id)? { if self
qdebug!([label], "Request/response stream {} read.", stream_id);
Ok(HandleReadableOutput::NoOutput)
} else if self
.control_stream_remote .control_stream_remote
.receive_if_this_stream(conn, stream_id)? .receive_if_this_stream(conn, stream_id)?
{ {
@ -257,6 +259,31 @@ impl Http3Connection {
} else { } else {
Ok(HandleReadableOutput::ControlFrames(control_frames)) Ok(HandleReadableOutput::ControlFrames(control_frames))
} }
} else {
debug_assert!(false, "Must be a control stream");
Ok(HandleReadableOutput::NoOutput)
}
}
/// This function handles reading from all streams, i.e. control, qpack, request/response
/// stream and unidi stream that are still do not have a type.
/// The function cannot handle:
/// 1) a Push stream (if an unknown unidi stream is decoded to be a push stream)
/// 2) frames `MaxPushId` or `Goaway` must be handled by `Http3Client`/`Server`.
/// The function returns `HandleReadableOutput`.
pub fn handle_stream_readable(
&mut self,
conn: &mut Connection,
stream_id: u64,
) -> Res<HandleReadableOutput> {
qtrace!([self], "Readable stream {}.", stream_id);
let label = ::neqo_common::log_subject!(::log::Level::Debug, self);
if self.handle_read_stream(conn, stream_id)? {
qdebug!([label], "Request/response stream {} read.", stream_id);
Ok(HandleReadableOutput::NoOutput)
} else if self.control_stream_remote.is_recv_stream(stream_id) {
self.recv_control(conn, stream_id)
} else if self.qpack_encoder.recv_if_encoder_stream(conn, stream_id)? { } else if self.qpack_encoder.recv_if_encoder_stream(conn, stream_id)? {
qdebug!( qdebug!(
[self], [self],
@ -264,17 +291,7 @@ impl Http3Connection {
stream_id stream_id
); );
Ok(HandleReadableOutput::NoOutput) Ok(HandleReadableOutput::NoOutput)
} else if self.qpack_decoder.is_recv_stream(stream_id) { } else if self.recv_decoder(conn, stream_id)? {
qdebug!(
[self],
"The qpack decoder stream ({}) is readable.",
stream_id
);
let unblocked_streams = self.qpack_decoder.receive(conn, stream_id)?;
for stream_id in unblocked_streams {
qinfo!([self], "Stream {} is unblocked", stream_id);
self.handle_read_stream(conn, stream_id)?;
}
Ok(HandleReadableOutput::NoOutput) Ok(HandleReadableOutput::NoOutput)
} else if let Some(ns) = self.new_streams.get_mut(&stream_id) { } else if let Some(ns) = self.new_streams.get_mut(&stream_id) {
let stream_type = ns.get_type(conn, stream_id); let stream_type = ns.get_type(conn, stream_id);
@ -284,10 +301,21 @@ impl Http3Connection {
} }
if let Some(t) = stream_type { if let Some(t) = stream_type {
self.new_streams.remove(&stream_id); self.new_streams.remove(&stream_id);
let push = self.decode_new_stream(conn, t, stream_id)?; self.decode_new_stream(conn, t, stream_id)?;
if push { // Make sure to read from this stream because DataReadable will not be set again.
return Ok(HandleReadableOutput::PushStream); return match t {
} HTTP3_UNI_STREAM_TYPE_CONTROL => self.recv_control(conn, stream_id),
QPACK_UNI_STREAM_TYPE_DECODER => {
self.qpack_encoder.recv_if_encoder_stream(conn, stream_id)?;
Ok(HandleReadableOutput::NoOutput)
}
QPACK_UNI_STREAM_TYPE_ENCODER => {
self.recv_decoder(conn, stream_id)?;
Ok(HandleReadableOutput::NoOutput)
}
HTTP3_UNI_STREAM_TYPE_PUSH => Ok(HandleReadableOutput::PushStream),
_ => Ok(HandleReadableOutput::NoOutput),
};
} }
Ok(HandleReadableOutput::NoOutput) Ok(HandleReadableOutput::NoOutput)

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

@ -17,7 +17,7 @@ use neqo_common::{
Role, Role,
}; };
use neqo_crypto::{agent::CertificateInfo, AuthenticationStatus, SecretAgentInfo}; use neqo_crypto::{agent::CertificateInfo, AuthenticationStatus, SecretAgentInfo};
use neqo_qpack::QpackSettings; use neqo_qpack::{stats::Stats, QpackSettings};
use neqo_transport::{ use neqo_transport::{
AppError, Connection, ConnectionEvent, ConnectionIdManager, Output, QuicVersion, StreamId, AppError, Connection, ConnectionEvent, ConnectionIdManager, Output, QuicVersion, StreamId,
StreamType, ZeroRttState, StreamType, ZeroRttState,
@ -408,24 +408,21 @@ impl Http3Client {
while let Some(e) = self.conn.next_event() { while let Some(e) = self.conn.next_event() {
qdebug!([self], "check_connection_events - event {:?}.", e); qdebug!([self], "check_connection_events - event {:?}.", e);
match e { match e {
ConnectionEvent::NewStream { ConnectionEvent::NewStream { stream_id } => match stream_id.stream_type() {
stream_id,
stream_type,
} => match stream_type {
StreamType::BiDi => return Err(Error::HttpStreamCreation), StreamType::BiDi => return Err(Error::HttpStreamCreation),
StreamType::UniDi => { StreamType::UniDi => {
if self if self
.base_handler .base_handler
.handle_new_unidi_stream(&mut self.conn, stream_id)? .handle_new_unidi_stream(&mut self.conn, stream_id.as_u64())?
{ {
return Err(Error::HttpId); return Err(Error::HttpId);
} }
} }
}, },
ConnectionEvent::SendStreamWritable { stream_id } => { ConnectionEvent::SendStreamWritable { stream_id } => {
if let Some(s) = self.base_handler.send_streams.get_mut(&stream_id) { if let Some(s) = self.base_handler.send_streams.get_mut(&stream_id.as_u64()) {
if s.is_state_sending_data() { if s.is_state_sending_data() {
self.events.data_writable(stream_id); self.events.data_writable(stream_id.as_u64());
} }
} }
} }
@ -590,6 +587,16 @@ impl Http3Client {
Ok(()) Ok(())
} }
#[must_use]
pub fn qpack_decoder_stats(&self) -> &Stats {
self.base_handler.qpack_decoder.stats()
}
#[must_use]
pub fn qpack_encoder_stats(&self) -> &Stats {
self.base_handler.qpack_encoder.stats()
}
} }
#[cfg(test)] #[cfg(test)]
@ -662,6 +669,10 @@ mod tests {
const PUSH_STREAM_DATA: &[u8] = &[0x1]; const PUSH_STREAM_DATA: &[u8] = &[0x1];
const CLIENT_SIDE_CONTROL_STREAM_ID: u64 = 2;
const CLIENT_SIDE_ENCODER_STREAM_ID: u64 = 6;
const CLIENT_SIDE_DECODER_STREAM_ID: u64 = 10;
struct TestServer { struct TestServer {
settings: HFrame, settings: HFrame,
conn: Connection, conn: Connection,
@ -671,33 +682,186 @@ mod tests {
decoder_stream_id: Option<u64>, decoder_stream_id: Option<u64>,
} }
fn make_server(server_settings: &[HSetting]) -> TestServer { impl TestServer {
fixture_init(); pub fn new() -> Self {
TestServer { Self::new_with_settings(&[
settings: HFrame::Settings { HSetting::new(HSettingType::MaxTableCapacity, 100),
settings: HSettings::new(server_settings), HSetting::new(HSettingType::BlockedStreams, 100),
}, HSetting::new(HSettingType::MaxHeaderListSize, 10000),
conn: default_server(), ])
control_stream_id: None,
encoder: QPackEncoder::new(
QpackSettings {
max_table_size_encoder: 128,
max_table_size_decoder: 0,
max_blocked_streams: 0,
},
true,
),
encoder_stream_id: None,
decoder_stream_id: None,
} }
}
fn make_default_server() -> TestServer { pub fn new_with_settings(server_settings: &[HSetting]) -> Self {
make_server(&[ fixture_init();
HSetting::new(HSettingType::MaxTableCapacity, 100), Self {
HSetting::new(HSettingType::BlockedStreams, 100), settings: HFrame::Settings {
HSetting::new(HSettingType::MaxHeaderListSize, 10000), settings: HSettings::new(server_settings),
]) },
conn: default_server(),
control_stream_id: None,
encoder: QPackEncoder::new(
QpackSettings {
max_table_size_encoder: 128,
max_table_size_decoder: 0,
max_blocked_streams: 0,
},
true,
),
encoder_stream_id: None,
decoder_stream_id: None,
}
}
pub fn new_with_conn(conn: Connection) -> Self {
Self {
settings: HFrame::Settings {
settings: HSettings::new(&[]),
},
conn,
control_stream_id: None,
encoder: QPackEncoder::new(
QpackSettings {
max_table_size_encoder: 128,
max_table_size_decoder: 0,
max_blocked_streams: 0,
},
true,
),
encoder_stream_id: None,
decoder_stream_id: None,
}
}
pub fn create_qpack_streams(&mut self) {
// Create a QPACK encoder stream
self.encoder_stream_id = Some(self.conn.stream_create(StreamType::UniDi).unwrap());
self.encoder
.add_send_stream(self.encoder_stream_id.unwrap());
self.encoder.send(&mut self.conn).unwrap();
// Create decoder stream
self.decoder_stream_id = Some(self.conn.stream_create(StreamType::UniDi).unwrap());
assert_eq!(
self.conn
.stream_send(self.decoder_stream_id.unwrap(), DECODER_STREAM_DATA)
.unwrap(),
1
);
}
pub fn create_control_stream(&mut self) {
// Create control stream
self.control_stream_id = Some(self.conn.stream_create(StreamType::UniDi).unwrap());
// Send stream type on the control stream.
assert_eq!(
self.conn
.stream_send(self.control_stream_id.unwrap(), CONTROL_STREAM_TYPE)
.unwrap(),
1
);
// Encode a settings frame and send it.
let mut enc = Encoder::default();
self.settings.encode(&mut enc);
assert_eq!(
self.conn
.stream_send(self.control_stream_id.unwrap(), &enc[..])
.unwrap(),
enc[..].len()
);
}
pub fn check_client_control_qpack_streams_no_resumption(&mut self) {
self.check_client_control_qpack_streams(ENCODER_STREAM_DATA, false, true);
}
pub fn check_control_qpack_request_streams_resumption(
&mut self,
expect_encoder_stream_data: &[u8],
expect_request: bool,
) {
self.check_client_control_qpack_streams(
expect_encoder_stream_data,
expect_request,
false,
);
}
// Check that server has received correct settings and qpack streams.
pub fn check_client_control_qpack_streams(
&mut self,
expect_encoder_stream_data: &[u8],
expect_request: bool,
expect_connected: bool,
) {
let mut connected = false;
let mut control_stream = false;
let mut qpack_decoder_stream = false;
let mut qpack_encoder_stream = false;
let mut request = false;
while let Some(e) = self.conn.next_event() {
match e {
ConnectionEvent::NewStream { stream_id }
| ConnectionEvent::SendStreamWritable { stream_id } => {
if expect_request {
assert!(matches!(stream_id.as_u64(), 2 | 6 | 10 | 0));
} else {
assert!(matches!(stream_id.as_u64(), 2 | 6 | 10));
}
}
ConnectionEvent::RecvStreamReadable { stream_id } => {
if stream_id == CLIENT_SIDE_CONTROL_STREAM_ID {
// the control stream
self.read_and_check_stream_data(stream_id, CONTROL_STREAM_DATA, false);
control_stream = true;
} else if stream_id == CLIENT_SIDE_ENCODER_STREAM_ID {
// the qpack encoder stream
self.read_and_check_stream_data(
stream_id,
expect_encoder_stream_data,
false,
);
qpack_encoder_stream = true;
} else if stream_id == CLIENT_SIDE_DECODER_STREAM_ID {
// the qpack decoder stream
self.read_and_check_stream_data(stream_id, DECODER_STREAM_DATA, false);
qpack_decoder_stream = true;
} else if stream_id == 0 {
assert!(expect_request);
self.read_and_check_stream_data(
stream_id,
EXPECTED_REQUEST_HEADER_FRAME,
true,
);
request = true;
} else {
panic!("unexpected event");
}
}
ConnectionEvent::StateChange(State::Connected) => connected = true,
ConnectionEvent::StateChange(_) => {}
_ => panic!("unexpected event"),
}
}
assert_eq!(connected, expect_connected);
assert!(control_stream);
assert!(qpack_encoder_stream);
assert!(qpack_decoder_stream);
assert_eq!(request, expect_request);
}
pub fn read_and_check_stream_data(
&mut self,
stream_id: u64,
expected_data: &[u8],
expected_fin: bool,
) {
let mut buf = [0_u8; 100];
let (amount, fin) = self.conn.stream_recv(stream_id, &mut buf).unwrap();
assert_eq!(fin, expected_fin);
assert_eq!(amount, expected_data.len());
assert_eq!(&buf[..amount], expected_data);
}
} }
// Perform only Quic transport handshake. // Perform only Quic transport handshake.
@ -730,52 +894,28 @@ mod tests {
// Perform only Quic transport handshake. // Perform only Quic transport handshake.
fn connect_only_transport() -> (Http3Client, TestServer) { fn connect_only_transport() -> (Http3Client, TestServer) {
let mut client = default_http3_client(); let mut client = default_http3_client();
let mut server = make_default_server(); let mut server = TestServer::new();
connect_only_transport_with(&mut client, &mut server); connect_only_transport_with(&mut client, &mut server);
(client, server) (client, server)
} }
fn send_and_receive_client_settings(client: &mut Http3Client, server: &mut TestServer) {
// send and receive client settings
let out = client.process(None, now());
let _ = server.conn.process(out.dgram(), now());
server.check_client_control_qpack_streams_no_resumption();
}
// Perform Quic transport handshake and exchange Http3 settings. // Perform Quic transport handshake and exchange Http3 settings.
fn connect_with(client: &mut Http3Client, server: &mut TestServer) { fn connect_with(client: &mut Http3Client, server: &mut TestServer) {
connect_only_transport_with(client, server); connect_only_transport_with(client, server);
// send and receive client settings send_and_receive_client_settings(client, server);
let out = client.process(None, now());
server.conn.process(out.dgram(), now());
check_control_qpack_streams(&mut server.conn);
// send and receive server settings server.create_control_stream();
// Create control stream server.create_qpack_streams();
server.control_stream_id = Some(server.conn.stream_create(StreamType::UniDi).unwrap()); // Send the server's control and qpack streams data.
let mut enc = Encoder::default();
server.settings.encode(&mut enc);
// Send stream type on the control stream.
let mut sent = server
.conn
.stream_send(server.control_stream_id.unwrap(), CONTROL_STREAM_TYPE);
assert_eq!(sent.unwrap(), 1);
// Encode a settings frame and send it.
let mut enc = Encoder::default();
server.settings.encode(&mut enc);
sent = server
.conn
.stream_send(server.control_stream_id.unwrap(), &enc[..]);
assert_eq!(sent.unwrap(), enc[..].len());
// Create a QPACK encoder stream
server.encoder_stream_id = Some(server.conn.stream_create(StreamType::UniDi).unwrap());
server
.encoder
.add_send_stream(server.encoder_stream_id.unwrap());
server.encoder.send(&mut server.conn).unwrap();
// Create decoder stream
server.decoder_stream_id = Some(server.conn.stream_create(StreamType::UniDi).unwrap());
sent = server
.conn
.stream_send(server.decoder_stream_id.unwrap(), DECODER_STREAM_DATA);
assert_eq!(sent, Ok(1));
// Actually send all above data
let out = server.conn.process(None, now()); let out = server.conn.process(None, now());
client.process(out.dgram(), now()); client.process(out.dgram(), now());
@ -786,74 +926,11 @@ mod tests {
// Perform Quic transport handshake and exchange Http3 settings. // Perform Quic transport handshake and exchange Http3 settings.
fn connect() -> (Http3Client, TestServer) { fn connect() -> (Http3Client, TestServer) {
let mut client = default_http3_client(); let mut client = default_http3_client();
let mut server = make_default_server(); let mut server = TestServer::new();
connect_with(&mut client, &mut server); connect_with(&mut client, &mut server);
(client, server) (client, server)
} }
fn read_and_check_stream_data(
server: &mut Connection,
stream_id: u64,
expected_data: &[u8],
expected_fin: bool,
) {
let mut buf = [0_u8; 100];
let (amount, fin) = server.stream_recv(stream_id, &mut buf).unwrap();
assert_eq!(fin, expected_fin);
assert_eq!(amount, expected_data.len());
assert_eq!(&buf[..amount], expected_data);
}
const CLIENT_SIDE_CONTROL_STREAM_ID: u64 = 2;
const CLIENT_SIDE_ENCODER_STREAM_ID: u64 = 6;
const CLIENT_SIDE_DECODER_STREAM_ID: u64 = 10;
// Check that server has received correct settings and qpack streams.
fn check_control_qpack_streams(server: &mut Connection) {
let mut connected = false;
let mut control_stream = false;
let mut qpack_decoder_stream = false;
let mut qpack_encoder_stream = false;
while let Some(e) = server.next_event() {
match e {
ConnectionEvent::NewStream {
stream_id,
stream_type,
} => {
assert!(matches!(stream_id, 2 | 6 | 10));
assert_eq!(stream_type, StreamType::UniDi);
}
ConnectionEvent::RecvStreamReadable { stream_id } => {
if stream_id == CLIENT_SIDE_CONTROL_STREAM_ID {
// the control stream
read_and_check_stream_data(server, stream_id, CONTROL_STREAM_DATA, false);
control_stream = true;
} else if stream_id == CLIENT_SIDE_ENCODER_STREAM_ID {
// the qpack encoder stream
read_and_check_stream_data(server, stream_id, ENCODER_STREAM_DATA, false);
qpack_encoder_stream = true;
} else if stream_id == CLIENT_SIDE_DECODER_STREAM_ID {
// the qpack decoder stream
read_and_check_stream_data(server, stream_id, DECODER_STREAM_DATA, false);
qpack_decoder_stream = true;
} else {
panic!("unexpected event");
}
}
ConnectionEvent::SendStreamWritable { stream_id } => {
assert!(matches!(stream_id, 2 | 6 | 10));
}
ConnectionEvent::StateChange(State::Connected) => connected = true,
ConnectionEvent::StateChange(_) => {}
_ => panic!("unexpected event"),
}
}
assert!(connected);
assert!(control_stream);
assert!(qpack_encoder_stream);
assert!(qpack_decoder_stream);
}
// Fetch request fetch("GET", "https", "something.com", "/", &[]). // Fetch request fetch("GET", "https", "something.com", "/", &[]).
fn make_request(client: &mut Http3Client, close_sending_side: bool) -> u64 { fn make_request(client: &mut Http3Client, close_sending_side: bool) -> u64 {
let request_stream_id = client let request_stream_id = client
@ -933,22 +1010,18 @@ mod tests {
assert_eq!(request_stream_id, 0); assert_eq!(request_stream_id, 0);
let out = client.process(None, now()); let out = client.process(None, now());
server.conn.process(out.dgram(), now()); let _ = server.conn.process(out.dgram(), now());
// find the new request/response stream and send frame v on it. // find the new request/response stream and send frame v on it.
while let Some(e) = server.conn.next_event() { while let Some(e) = server.conn.next_event() {
match e { match e {
ConnectionEvent::NewStream { ConnectionEvent::NewStream { stream_id } => {
stream_id, assert_eq!(stream_id.as_u64(), request_stream_id);
stream_type, assert_eq!(stream_id.stream_type(), StreamType::BiDi);
} => {
assert_eq!(stream_id, request_stream_id);
assert_eq!(stream_type, StreamType::BiDi);
} }
ConnectionEvent::RecvStreamReadable { stream_id } => { ConnectionEvent::RecvStreamReadable { stream_id } => {
assert_eq!(stream_id, request_stream_id); assert_eq!(stream_id, request_stream_id);
read_and_check_stream_data( server.read_and_check_stream_data(
&mut server.conn,
stream_id, stream_id,
EXPECTED_REQUEST_HEADER_FRAME, EXPECTED_REQUEST_HEADER_FRAME,
close_sending_side, close_sending_side,
@ -1145,7 +1218,7 @@ mod tests {
.stream_send(new_stream_id, &[0x41, 0x19, 0x4, 0x4, 0x6, 0x0, 0x8, 0x0]); .stream_send(new_stream_id, &[0x41, 0x19, 0x4, 0x4, 0x6, 0x0, 0x8, 0x0]);
let out = server.conn.process(None, now()); let out = server.conn.process(None, now());
let out = client.process(out.dgram(), now()); let out = client.process(out.dgram(), now());
server.conn.process(out.dgram(), now()); let _ = server.conn.process(out.dgram(), now());
// check for stop-sending with Error::HttpStreamCreation. // check for stop-sending with Error::HttpStreamCreation.
let mut stop_sending_event_found = false; let mut stop_sending_event_found = false;
@ -1174,7 +1247,7 @@ mod tests {
let _ = server.conn.stream_send(push_stream_id, PUSH_STREAM_DATA); let _ = server.conn.stream_send(push_stream_id, PUSH_STREAM_DATA);
let out = server.conn.process(None, now()); let out = server.conn.process(None, now());
let out = client.process(out.dgram(), now()); let out = client.process(out.dgram(), now());
server.conn.process(out.dgram(), now()); let _ = server.conn.process(out.dgram(), now());
assert_closed(&client, &Error::HttpId); assert_closed(&client, &Error::HttpId);
} }
@ -1411,17 +1484,14 @@ mod tests {
let _ = client.stream_close_send(request_stream_id); let _ = client.stream_close_send(request_stream_id);
let out = client.process(None, now()); let out = client.process(None, now());
server.conn.process(out.dgram(), now()); let _ = server.conn.process(out.dgram(), now());
// find the new request/response stream and send response on it. // find the new request/response stream and send response on it.
while let Some(e) = server.conn.next_event() { while let Some(e) = server.conn.next_event() {
match e { match e {
ConnectionEvent::NewStream { ConnectionEvent::NewStream { stream_id } => {
stream_id, assert_eq!(stream_id.as_u64(), request_stream_id);
stream_type, assert_eq!(stream_id.stream_type(), StreamType::BiDi);
} => {
assert_eq!(stream_id, request_stream_id);
assert_eq!(stream_type, StreamType::BiDi);
} }
ConnectionEvent::RecvStreamReadable { stream_id } => { ConnectionEvent::RecvStreamReadable { stream_id } => {
assert_eq!(stream_id, request_stream_id); assert_eq!(stream_id, request_stream_id);
@ -2086,7 +2156,7 @@ mod tests {
assert_eq!(request_stream_id_3, 8); assert_eq!(request_stream_id_3, 8);
let out = client.process(None, now()); let out = client.process(None, now());
server.conn.process(out.dgram(), now()); let _ = server.conn.process(out.dgram(), now());
let _ = server let _ = server
.conn .conn
@ -2160,7 +2230,7 @@ mod tests {
assert_eq!(request_stream_id_3, 8); assert_eq!(request_stream_id_3, 8);
let out = client.process(None, now()); let out = client.process(None, now());
server.conn.process(out.dgram(), now()); let _ = server.conn.process(out.dgram(), now());
// First send a Goaway frame with an higher number // First send a Goaway frame with an higher number
let _ = server let _ = server
@ -2792,73 +2862,6 @@ mod tests {
assert!(recv_header); assert!(recv_header);
} }
fn check_control_qpack_request_streams_resumption(
server: &mut Connection,
expect_encoder_stream_data: &[u8],
expect_request: bool,
) {
let mut control_stream = false;
let mut qpack_decoder_stream = false;
let mut qpack_encoder_stream = false;
let mut request = false;
while let Some(e) = server.next_event() {
match e {
ConnectionEvent::NewStream {
stream_id,
stream_type,
} => {
assert!(matches!(stream_id, 2 | 6 | 10 | 0));
if stream_id == 0 {
assert_eq!(stream_type, StreamType::BiDi);
} else {
assert_eq!(stream_type, StreamType::UniDi);
}
}
ConnectionEvent::RecvStreamReadable { stream_id } => {
if stream_id == 2 {
// the control stream
read_and_check_stream_data(server, stream_id, CONTROL_STREAM_DATA, false);
control_stream = true;
} else if stream_id == 6 {
let mut buf = [0_u8; 100];
let (amount, fin) = server.stream_recv(stream_id, &mut buf).unwrap();
assert_eq!(fin, false);
assert_eq!(amount, expect_encoder_stream_data.len());
assert_eq!(&buf[..amount], expect_encoder_stream_data);
qpack_encoder_stream = true;
} else if stream_id == 10 {
let mut buf = [0_u8; 100];
let (amount, fin) = server.stream_recv(stream_id, &mut buf).unwrap();
assert_eq!(fin, false);
assert_eq!(amount, DECODER_STREAM_DATA.len());
assert_eq!(&buf[..amount], DECODER_STREAM_DATA);
qpack_decoder_stream = true;
} else if stream_id == 0 {
assert!(expect_request);
read_and_check_stream_data(
server,
stream_id,
EXPECTED_REQUEST_HEADER_FRAME,
true,
);
request = true;
} else {
panic!("unexpected event");
}
}
ConnectionEvent::SendStreamWritable { stream_id } => {
assert!(matches!(stream_id, 2 | 6 | 10));
}
ConnectionEvent::StateChange(_) => (),
_ => panic!("unexpected event"),
}
}
assert!(control_stream);
assert!(qpack_encoder_stream);
assert!(qpack_decoder_stream);
assert_eq!(request, expect_request);
}
fn exchange_token(client: &mut Http3Client, server: &mut Connection) -> Vec<u8> { fn exchange_token(client: &mut Http3Client, server: &mut Connection) -> Vec<u8> {
server.send_ticket(now(), &[]).expect("can send ticket"); server.send_ticket(now(), &[]).expect("can send ticket");
let out = server.process_output(now()); let out = server.process_output(now());
@ -2874,7 +2877,7 @@ mod tests {
let mut client = default_http3_client(); let mut client = default_http3_client();
let server = make_default_server(); let server = TestServer::new();
assert_eq!(client.state(), Http3State::Initializing); assert_eq!(client.state(), Http3State::Initializing);
client client
@ -2900,8 +2903,7 @@ mod tests {
// SETTINGS frame has been received. // SETTINGS frame has been received.
// Also qpack encoder stream will send "change capacity" instruction because it has // Also qpack encoder stream will send "change capacity" instruction because it has
// the peer settings already. // the peer settings already.
check_control_qpack_request_streams_resumption( server.check_control_qpack_request_streams_resumption(
&mut server.conn,
ENCODER_STREAM_DATA_WITH_CAP_INSTRUCTION, ENCODER_STREAM_DATA_WITH_CAP_INSTRUCTION,
false, false,
); );
@ -2934,8 +2936,7 @@ mod tests {
// SETTINGS frame has been received. // SETTINGS frame has been received.
// Also qpack encoder stream will send "change capacity" instruction because it has // Also qpack encoder stream will send "change capacity" instruction because it has
// the peer settings already. // the peer settings already.
check_control_qpack_request_streams_resumption( server.check_control_qpack_request_streams_resumption(
&mut server.conn,
ENCODER_STREAM_DATA_WITH_CAP_INSTRUCTION, ENCODER_STREAM_DATA_WITH_CAP_INSTRUCTION,
true, true,
); );
@ -3026,7 +3027,7 @@ mod tests {
// Client will send Setting frame and open new qpack streams. // Client will send Setting frame and open new qpack streams.
let _ = server.process(client_out.dgram(), now()); let _ = server.process(client_out.dgram(), now());
check_control_qpack_streams(&mut server); TestServer::new_with_conn(server).check_client_control_qpack_streams_no_resumption();
// Check that we can send a request and that the stream_id starts again from 0. // Check that we can send a request and that the stream_id starts again from 0.
assert_eq!(make_request(&mut client, false), 0); assert_eq!(make_request(&mut client, false), 0);
@ -3040,13 +3041,13 @@ mod tests {
expected_encoder_stream_data: &[u8], expected_encoder_stream_data: &[u8],
) { ) {
let mut client = default_http3_client(); let mut client = default_http3_client();
let mut server = make_server(original_settings); let mut server = TestServer::new_with_settings(original_settings);
// Connect and get a token // Connect and get a token
connect_with(&mut client, &mut server); connect_with(&mut client, &mut server);
let token = exchange_token(&mut client, &mut server.conn); let token = exchange_token(&mut client, &mut server.conn);
let mut client = default_http3_client(); let mut client = default_http3_client();
let mut server = make_server(resumption_settings); let mut server = TestServer::new_with_settings(resumption_settings);
assert_eq!(client.state(), Http3State::Initializing); assert_eq!(client.state(), Http3State::Initializing);
client client
.set_resumption_token(now(), &token) .set_resumption_token(now(), &token)
@ -3061,11 +3062,7 @@ mod tests {
// Check that control and qpack streams anda SETTINGS frame are received. // Check that control and qpack streams anda SETTINGS frame are received.
// Also qpack encoder stream will send "change capacity" instruction because it has // Also qpack encoder stream will send "change capacity" instruction because it has
// the peer settings already. // the peer settings already.
check_control_qpack_request_streams_resumption( server.check_control_qpack_request_streams_resumption(expected_encoder_stream_data, false);
&mut server.conn,
expected_encoder_stream_data,
false,
);
assert_eq!(*server.conn.state(), State::Handshaking); assert_eq!(*server.conn.state(), State::Handshaking);
let out = client.process(out.dgram(), now()); let out = client.process(out.dgram(), now());
@ -3621,4 +3618,65 @@ mod tests {
); );
assert!(!client.events().any(data_readable_event)); assert!(!client.events().any(data_readable_event));
} }
#[test]
fn stream_blocked_no_remote_encoder_stream() {
let (mut client, mut server) = connect_only_transport();
send_and_receive_client_settings(&mut client, &mut server);
server.create_control_stream();
// Send the server's control stream data.
let out = server.conn.process(None, now());
client.process(out.dgram(), now());
server.create_qpack_streams();
let qpack_pkt1 = server.conn.process(None, now());
// delay delivery of this packet.
let request_stream_id = make_request(&mut client, true);
let out = client.process(None, now());
let _ = server.conn.process(out.dgram(), now());
server.encoder.set_max_capacity(100).unwrap();
server.encoder.set_max_blocked_streams(100).unwrap();
server.encoder.send(&mut server.conn).unwrap();
let headers = vec![
(String::from(":status"), String::from("200")),
(String::from("my-header"), String::from("my-header")),
(String::from("content-length"), String::from("3")),
];
let encoded_headers = server
.encoder
.encode_header_block(&mut server.conn, &headers, request_stream_id)
.unwrap();
let hframe = HFrame::Headers {
header_block: encoded_headers.to_vec(),
};
// Send the encoder instructions,
let out = server.conn.process(None, now());
client.process(out.dgram(), now());
// Send response
let mut d = Encoder::default();
hframe.encode(&mut d);
let d_frame = HFrame::Data { len: 3 };
d_frame.encode(&mut d);
d.encode(&[0x61, 0x62, 0x63]);
let _ = server.conn.stream_send(request_stream_id, &d[..]);
server.conn.stream_close_send(request_stream_id).unwrap();
let out = server.conn.process(None, now());
let _out = client.process(out.dgram(), now());
let header_ready_event = |e| matches!(e, Http3ClientEvent::HeaderReady { .. });
assert!(!client.events().any(header_ready_event));
// Let client receive the encoder instructions.
let _out = client.process(qpack_pkt1.dgram(), now());
assert!(client.events().any(header_ready_event));
}
} }

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

@ -121,17 +121,17 @@ impl Http3ServerHandler {
while let Some(e) = conn.next_event() { while let Some(e) = conn.next_event() {
qdebug!([self], "check_connection_events - event {:?}.", e); qdebug!([self], "check_connection_events - event {:?}.", e);
match e { match e {
ConnectionEvent::NewStream { ConnectionEvent::NewStream { stream_id } => match stream_id.stream_type() {
stream_id,
stream_type,
} => match stream_type {
StreamType::BiDi => self.base_handler.add_streams( StreamType::BiDi => self.base_handler.add_streams(
stream_id, stream_id.as_u64(),
SendMessage::new(stream_id, Box::new(self.events.clone())), SendMessage::new(stream_id.as_u64(), Box::new(self.events.clone())),
RecvMessage::new(stream_id, Box::new(self.events.clone()), None), RecvMessage::new(stream_id.as_u64(), Box::new(self.events.clone()), None),
), ),
StreamType::UniDi => { StreamType::UniDi => {
if self.base_handler.handle_new_unidi_stream(conn, stream_id)? { if self
.base_handler
.handle_new_unidi_stream(conn, stream_id.as_u64())?
{
return Err(Error::HttpStreamCreation); return Err(Error::HttpStreamCreation);
} }
} }

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

@ -6,7 +6,7 @@
use crate::hframe::{HFrame, HFrameReader}; use crate::hframe::{HFrame, HFrameReader};
use crate::{Error, Res}; use crate::{Error, Res};
use neqo_common::{qdebug, qinfo}; use neqo_common::{matches, qdebug, qinfo};
use neqo_transport::Connection; use neqo_transport::Connection;
/// The remote control stream is responsible only for reading frames. The frames are handled by `Http3Connection`. /// The remote control stream is responsible only for reading frames. The frames are handled by `Http3Connection`.
@ -43,6 +43,11 @@ impl ControlStreamRemote {
Ok(()) Ok(())
} }
/// Check if `stream_id` is the remote control stream.
pub fn is_recv_stream(&self, stream_id: u64) -> bool {
matches!(self.stream_id, Some(id) if id == stream_id)
}
/// Check if a stream is the control stream and read received data. /// Check if a stream is the control stream and read received data.
pub fn receive_if_this_stream(&mut self, conn: &mut Connection, stream_id: u64) -> Res<bool> { pub fn receive_if_this_stream(&mut self, conn: &mut Connection, stream_id: u64) -> Res<bool> {
if let Some(id) = self.stream_id { if let Some(id) = self.stream_id {

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

@ -377,10 +377,10 @@ mod tests {
let out = conn_c.process(None, now()); let out = conn_c.process(None, now());
let out = conn_s.process(out.dgram(), now()); let out = conn_s.process(out.dgram(), now());
let out = conn_c.process(out.dgram(), now()); let out = conn_c.process(out.dgram(), now());
conn_s.process(out.dgram(), now()); let _ = conn_s.process(out.dgram(), now());
conn_c.authenticated(AuthenticationStatus::Ok, now()); conn_c.authenticated(AuthenticationStatus::Ok, now());
let out = conn_c.process(None, now()); let out = conn_c.process(None, now());
conn_s.process(out.dgram(), now()); let _ = conn_s.process(out.dgram(), now());
// create a stream // create a stream
let stream_id = conn_s.stream_create(StreamType::BiDi).unwrap(); let stream_id = conn_s.stream_create(StreamType::BiDi).unwrap();
@ -399,7 +399,7 @@ mod tests {
} }
conn_s.stream_send(stream_id, &buf).unwrap(); conn_s.stream_send(stream_id, &buf).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
@ -482,32 +482,32 @@ mod tests {
// Send and read settings frame 040406040804 // Send and read settings frame 040406040804
conn_s.stream_send(stream_id, &[0x4]).unwrap(); conn_s.stream_send(stream_id, &[0x4]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
conn_s.stream_send(stream_id, &[0x4]).unwrap(); conn_s.stream_send(stream_id, &[0x4]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
conn_s.stream_send(stream_id, &[0x6]).unwrap(); conn_s.stream_send(stream_id, &[0x6]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
conn_s.stream_send(stream_id, &[0x4]).unwrap(); conn_s.stream_send(stream_id, &[0x4]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
conn_s.stream_send(stream_id, &[0x8]).unwrap(); conn_s.stream_send(stream_id, &[0x8]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
conn_s.stream_send(stream_id, &[0x4]).unwrap(); conn_s.stream_send(stream_id, &[0x4]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
assert!(fr.done()); assert!(fr.done());
@ -534,47 +534,47 @@ mod tests {
// Read settings frame 400406064004084100 // Read settings frame 400406064004084100
conn_s.stream_send(stream_id, &[0x40]).unwrap(); conn_s.stream_send(stream_id, &[0x40]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
conn_s.stream_send(stream_id, &[0x4]).unwrap(); conn_s.stream_send(stream_id, &[0x4]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
conn_s.stream_send(stream_id, &[0x6]).unwrap(); conn_s.stream_send(stream_id, &[0x6]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
conn_s.stream_send(stream_id, &[0x6]).unwrap(); conn_s.stream_send(stream_id, &[0x6]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
conn_s.stream_send(stream_id, &[0x40]).unwrap(); conn_s.stream_send(stream_id, &[0x40]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
conn_s.stream_send(stream_id, &[0x4]).unwrap(); conn_s.stream_send(stream_id, &[0x4]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
conn_s.stream_send(stream_id, &[0x8]).unwrap(); conn_s.stream_send(stream_id, &[0x8]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
conn_s.stream_send(stream_id, &[0x41]).unwrap(); conn_s.stream_send(stream_id, &[0x41]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
conn_s.stream_send(stream_id, &[0x0]).unwrap(); conn_s.stream_send(stream_id, &[0x0]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
assert!(fr.done()); assert!(fr.done());
@ -601,24 +601,24 @@ mod tests {
// Read pushpromise frame 05054101010203 // Read pushpromise frame 05054101010203
conn_s.stream_send(stream_id, &[0x5]).unwrap(); conn_s.stream_send(stream_id, &[0x5]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
conn_s.stream_send(stream_id, &[0x5]).unwrap(); conn_s.stream_send(stream_id, &[0x5]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
conn_s.stream_send(stream_id, &[0x41]).unwrap(); conn_s.stream_send(stream_id, &[0x41]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
conn_s conn_s
.stream_send(stream_id, &[0x1, 0x1, 0x2, 0x3]) .stream_send(stream_id, &[0x1, 0x1, 0x2, 0x3])
.unwrap(); .unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
// headers are still on the stream. // headers are still on the stream.
@ -657,7 +657,7 @@ mod tests {
.stream_send(stream_id, &[0x0, 0x3, 0x1, 0x2, 0x3]) .stream_send(stream_id, &[0x0, 0x3, 0x1, 0x2, 0x3])
.unwrap(); .unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
// payloead is still on the stream. // payloead is still on the stream.
@ -696,13 +696,13 @@ mod tests {
buf.resize(UNKNOWN_FRAME_LEN + buf.len(), 0); buf.resize(UNKNOWN_FRAME_LEN + buf.len(), 0);
conn_s.stream_send(stream_id, &buf).unwrap(); conn_s.stream_send(stream_id, &buf).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
// now receive a CANCEL_PUSH fram to see that frame reader is ok. // now receive a CANCEL_PUSH fram to see that frame reader is ok.
conn_s.stream_send(stream_id, &[0x03, 0x01, 0x05]).unwrap(); conn_s.stream_send(stream_id, &[0x03, 0x01, 0x05]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id)); assert_eq!(Ok(false), fr.receive(&mut conn_c, stream_id));
assert!(fr.done()); assert!(fr.done());
@ -745,12 +745,12 @@ mod tests {
} }
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
if let FrameReadingTestSend::DataThenFin = test_to_send { if let FrameReadingTestSend::DataThenFin = test_to_send {
conn_s.stream_close_send(stream_id).unwrap(); conn_s.stream_close_send(stream_id).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
} }
let mut fr = HFrameReader::new(); let mut fr = HFrameReader::new();
@ -973,12 +973,12 @@ mod tests {
let stream_id = conn_s.stream_create(StreamType::BiDi).unwrap(); let stream_id = conn_s.stream_create(StreamType::BiDi).unwrap();
conn_s.stream_send(stream_id, &[0x00]).unwrap(); conn_s.stream_send(stream_id, &[0x00]).unwrap();
let out = conn_s.process(None, now()); let out = conn_s.process(None, now());
conn_c.process(out.dgram(), now()); let _ = conn_c.process(out.dgram(), now());
let mut fr: HFrameReader = HFrameReader::new(); let mut fr: HFrameReader = HFrameReader::new();
assert_eq!(Ok(()), conn_c.stream_close_send(stream_id)); assert_eq!(Ok(()), conn_c.stream_close_send(stream_id));
let out = conn_c.process(None, now()); let out = conn_c.process(None, now());
conn_s.process(out.dgram(), now()); let _ = conn_s.process(out.dgram(), now());
assert_eq!(Ok(true), fr.receive(&mut conn_s, stream_id)); assert_eq!(Ok(true), fr.receive(&mut conn_s, stream_id));
} }
} }

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

@ -296,21 +296,18 @@ mod tests {
let out = neqo_trans_conn.process(None, now()); let out = neqo_trans_conn.process(None, now());
let out = hconn.process(out.dgram(), now()); let out = hconn.process(out.dgram(), now());
assert_connected(&mut hconn); assert_connected(&mut hconn);
neqo_trans_conn.process(out.dgram(), now()); let _ = neqo_trans_conn.process(out.dgram(), now());
let mut connected = false; let mut connected = false;
while let Some(e) = neqo_trans_conn.next_event() { while let Some(e) = neqo_trans_conn.next_event() {
match e { match e {
ConnectionEvent::NewStream { ConnectionEvent::NewStream { stream_id } => {
stream_id,
stream_type,
} => {
assert!( assert!(
(stream_id == SERVER_SIDE_CONTROL_STREAM_ID) (stream_id.as_u64() == SERVER_SIDE_CONTROL_STREAM_ID)
|| (stream_id == SERVER_SIDE_ENCODER_STREAM_ID) || (stream_id.as_u64() == SERVER_SIDE_ENCODER_STREAM_ID)
|| (stream_id == SERVER_SIDE_DECODER_STREAM_ID) || (stream_id.as_u64() == SERVER_SIDE_DECODER_STREAM_ID)
); );
assert_eq!(stream_type, StreamType::UniDi); assert_eq!(stream_id.stream_type(), StreamType::UniDi);
} }
ConnectionEvent::RecvStreamReadable { stream_id } => { ConnectionEvent::RecvStreamReadable { stream_id } => {
if stream_id == CLIENT_SIDE_CONTROL_STREAM_ID if stream_id == CLIENT_SIDE_CONTROL_STREAM_ID
@ -397,7 +394,7 @@ mod tests {
assert_eq!(sent, Ok(1)); assert_eq!(sent, Ok(1));
let out1 = neqo_trans_conn.process(None, now()); let out1 = neqo_trans_conn.process(None, now());
let out2 = hconn.process(out1.dgram(), now()); let out2 = hconn.process(out1.dgram(), now());
neqo_trans_conn.process(out2.dgram(), now()); let _ = neqo_trans_conn.process(out2.dgram(), now());
// assert no error occured. // assert no error occured.
assert_not_closed(&mut hconn); assert_not_closed(&mut hconn);
@ -503,9 +500,9 @@ mod tests {
.stream_send(new_stream_id, &[0x41, 0x19, 0x4, 0x4, 0x6, 0x0, 0x8, 0x0]); .stream_send(new_stream_id, &[0x41, 0x19, 0x4, 0x4, 0x6, 0x0, 0x8, 0x0]);
let out = peer_conn.conn.process(None, now()); let out = peer_conn.conn.process(None, now());
let out = hconn.process(out.dgram(), now()); let out = hconn.process(out.dgram(), now());
peer_conn.conn.process(out.dgram(), now()); let _ = peer_conn.conn.process(out.dgram(), now());
let out = hconn.process(None, now()); let out = hconn.process(None, now());
peer_conn.conn.process(out.dgram(), now()); let _ = peer_conn.conn.process(out.dgram(), now());
// check for stop-sending with Error::HttpStreamCreation. // check for stop-sending with Error::HttpStreamCreation.
let mut stop_sending_event_found = false; let mut stop_sending_event_found = false;
@ -534,7 +531,7 @@ mod tests {
let _ = peer_conn.conn.stream_send(push_stream_id, &[0x1]); let _ = peer_conn.conn.stream_send(push_stream_id, &[0x1]);
let out = peer_conn.conn.process(None, now()); let out = peer_conn.conn.process(None, now());
let out = hconn.process(out.dgram(), now()); let out = hconn.process(out.dgram(), now());
peer_conn.conn.process(out.dgram(), now()); let _ = peer_conn.conn.process(out.dgram(), now());
assert_closed(&mut hconn, &Error::HttpStreamCreation); assert_closed(&mut hconn, &Error::HttpStreamCreation);
} }

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

@ -1 +1 @@
{"files":{"Cargo.toml":"8fb2753d93e78302c9193171c98725b9a96fd0e66944ed1feaa4bafac6c1209c","src/decoder.rs":"468b51d03aee3363d7998bb9e8a70d998a8279eb0089702a9fe4423f8c577f1e","src/decoder_instructions.rs":"a8e04dff5fc4c658322a10daadab947dc2e41932c00c3f8d387671a86d0516af","src/encoder.rs":"03cc95df1c57972cd8a19ffb77920f8daac52b4e220eac6182d05671d04e9d58","src/encoder_instructions.rs":"4fab8d6a86482139275f81fd30f9f8c462d6312faf0cdb9143fed1a1a514623f","src/header_block.rs":"8e4b7483319883bb87661d9835b5570d22baae4aecce804f387d7a27584fb53e","src/huffman.rs":"68fa0bada0c35d20f793980596accdcc548970214841f71789290fc334e51fc1","src/huffman_decode_helper.rs":"2970c57f052878b727c2f764490c54184f5c2608e1d6aa961c3b01509e290122","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"4413c57c8707c5fe47cdc4f40b6e2e9baa4f18fae9cecd895c11e509973ccc2a","src/prefix.rs":"8807126dbf4e7aff9afe164072c523b8fbfa0be5d4c57bb8291b510c8f0e8ca5","src/qlog.rs":"ee4eb799cadcd31e2569690ab1f7cbfb22179033ee7aec7ed217749eb0210fc9","src/qpack_send_buf.rs":"cf64e247e57076c8971e2b87e6c81b895d7bc2a671792b839e7a241d78e8a875","src/reader.rs":"4bcea0de1d7dc09ec0cdff364d8f62da54bbbe1f6db55a495f943f31369b4074","src/static_table.rs":"fda9d5c6f38f94b0bf92d3afdf8432dce6e27e189736596e16727090c77b78ec","src/table.rs":"fc927a57c02a7556b0ea7152c713cfd84825b14343f809c7ed0cc2a2a011482f"},"package":null} {"files":{"Cargo.toml":"46efba4d086b74b091a4ca9b2dac2cbaef19429e181da90569bc7c44b0ae1740","src/decoder.rs":"55988899298bc05e7a59d974e48c7d4cd50414496d28a0fbaf30ab581c1a7c18","src/decoder_instructions.rs":"a8e04dff5fc4c658322a10daadab947dc2e41932c00c3f8d387671a86d0516af","src/encoder.rs":"900b5c0947f61f0c88cc8bd2e6ca67d31e92b2261ebdecb8c9d34091c5f79668","src/encoder_instructions.rs":"4fab8d6a86482139275f81fd30f9f8c462d6312faf0cdb9143fed1a1a514623f","src/header_block.rs":"135898d30d2c50d018d500ffe51dc2d553b4b391f6085ae7ff1afc6bdf300cae","src/huffman.rs":"68fa0bada0c35d20f793980596accdcc548970214841f71789290fc334e51fc1","src/huffman_decode_helper.rs":"2970c57f052878b727c2f764490c54184f5c2608e1d6aa961c3b01509e290122","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"1963fa642f178ffe5cb5d57ef908bbb0622b28c8c984148f8c53886e7e8bd031","src/prefix.rs":"8807126dbf4e7aff9afe164072c523b8fbfa0be5d4c57bb8291b510c8f0e8ca5","src/qlog.rs":"ee4eb799cadcd31e2569690ab1f7cbfb22179033ee7aec7ed217749eb0210fc9","src/qpack_send_buf.rs":"cf64e247e57076c8971e2b87e6c81b895d7bc2a671792b839e7a241d78e8a875","src/reader.rs":"4bcea0de1d7dc09ec0cdff364d8f62da54bbbe1f6db55a495f943f31369b4074","src/static_table.rs":"fda9d5c6f38f94b0bf92d3afdf8432dce6e27e189736596e16727090c77b78ec","src/stats.rs":"39b8bb0af37c7f05e9db40f74dfec2f6be4a3f112c2347dd235c2488403eb03c","src/table.rs":"fc927a57c02a7556b0ea7152c713cfd84825b14343f809c7ed0cc2a2a011482f"},"package":null}

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

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

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

@ -9,6 +9,7 @@ use crate::encoder_instructions::{DecodedEncoderInstruction, EncoderInstructionR
use crate::header_block::{HeaderDecoder, HeaderDecoderResult}; use crate::header_block::{HeaderDecoder, HeaderDecoderResult};
use crate::qpack_send_buf::QPData; use crate::qpack_send_buf::QPData;
use crate::reader::ReceiverConnWrapper; use crate::reader::ReceiverConnWrapper;
use crate::stats::Stats;
use crate::table::HeaderTable; use crate::table::HeaderTable;
use crate::{Error, Header, QpackSettings, Res}; use crate::{Error, Header, QpackSettings, Res};
use neqo_common::qdebug; use neqo_common::qdebug;
@ -29,6 +30,7 @@ pub struct QPackDecoder {
max_table_size: u64, max_table_size: u64,
max_blocked_streams: usize, max_blocked_streams: usize,
blocked_streams: Vec<(u64, u64)>, //stream_id and requested inserts count. blocked_streams: Vec<(u64, u64)>, //stream_id and requested inserts count.
stats: Stats,
} }
impl QPackDecoder { impl QPackDecoder {
@ -46,6 +48,7 @@ impl QPackDecoder {
max_table_size: qpack_settings.max_table_size_decoder, max_table_size: qpack_settings.max_table_size_decoder,
max_blocked_streams: qpack_settings.max_blocked_streams.try_into().unwrap(), max_blocked_streams: qpack_settings.max_blocked_streams.try_into().unwrap(),
blocked_streams: Vec::new(), blocked_streams: Vec::new(),
stats: Stats::default(),
} }
} }
@ -104,22 +107,26 @@ impl QPackDecoder {
self.table self.table
.insert_with_name_ref(true, index, &value) .insert_with_name_ref(true, index, &value)
.map_err(|_| Error::EncoderStream)?; .map_err(|_| Error::EncoderStream)?;
self.stats.dynamic_table_inserts += 1;
} }
DecodedEncoderInstruction::InsertWithNameRefDynamic { index, value } => { DecodedEncoderInstruction::InsertWithNameRefDynamic { index, value } => {
self.table self.table
.insert_with_name_ref(false, index, &value) .insert_with_name_ref(false, index, &value)
.map_err(|_| Error::EncoderStream)?; .map_err(|_| Error::EncoderStream)?;
self.stats.dynamic_table_inserts += 1;
} }
DecodedEncoderInstruction::InsertWithNameLiteral { name, value } => { DecodedEncoderInstruction::InsertWithNameLiteral { name, value } => {
self.table self.table
.insert(&name, &value) .insert(&name, &value)
.map(|_| ()) .map(|_| ())
.map_err(|_| Error::EncoderStream)?; .map_err(|_| Error::EncoderStream)?;
self.stats.dynamic_table_inserts += 1;
} }
DecodedEncoderInstruction::Duplicate { index } => { DecodedEncoderInstruction::Duplicate { index } => {
self.table self.table
.duplicate(index) .duplicate(index)
.map_err(|_| Error::EncoderStream)?; .map_err(|_| Error::EncoderStream)?;
self.stats.dynamic_table_inserts += 1;
} }
DecodedEncoderInstruction::NoInstruction => { DecodedEncoderInstruction::NoInstruction => {
unreachable!("This can be call only with an instruction.") unreachable!("This can be call only with an instruction.")
@ -186,6 +193,7 @@ impl QPackDecoder {
Ok(HeaderDecoderResult::Headers(h)) => { Ok(HeaderDecoderResult::Headers(h)) => {
if decoder.get_req_insert_cnt() != 0 { if decoder.get_req_insert_cnt() != 0 {
self.header_ack(stream_id, decoder.get_req_insert_cnt()); self.header_ack(stream_id, decoder.get_req_insert_cnt());
self.stats.dynamic_table_references += 1;
} }
Ok(Some(h)) Ok(Some(h))
} }
@ -229,6 +237,11 @@ impl QPackDecoder {
pub fn remote_stream_id(&self) -> Option<u64> { pub fn remote_stream_id(&self) -> Option<u64> {
self.remote_stream_id self.remote_stream_id
} }
#[must_use]
pub fn stats(&self) -> &Stats {
&self.stats
}
} }
impl ::std::fmt::Display for QPackDecoder { impl ::std::fmt::Display for QPackDecoder {
@ -290,7 +303,7 @@ mod tests {
.peer_conn .peer_conn
.stream_send(decoder.recv_stream_id, encoder_instruction); .stream_send(decoder.recv_stream_id, encoder_instruction);
let out = decoder.peer_conn.process(None, now()); let out = decoder.peer_conn.process(None, now());
decoder.conn.process(out.dgram(), now()); let _ = decoder.conn.process(out.dgram(), now());
assert_eq!( assert_eq!(
decoder decoder
.decoder .decoder
@ -302,7 +315,7 @@ mod tests {
fn send_instructions_and_check(decoder: &mut TestDecoder, decoder_instruction: &[u8]) { fn send_instructions_and_check(decoder: &mut TestDecoder, decoder_instruction: &[u8]) {
decoder.decoder.send(&mut decoder.conn).unwrap(); decoder.decoder.send(&mut decoder.conn).unwrap();
let out = decoder.conn.process(None, now()); let out = decoder.conn.process(None, now());
decoder.peer_conn.process(out.dgram(), now()); let _ = decoder.peer_conn.process(out.dgram(), now());
let mut buf = [0_u8; 100]; let mut buf = [0_u8; 100];
let (amount, fin) = decoder let (amount, fin) = decoder
.peer_conn .peer_conn

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

@ -10,6 +10,7 @@ use crate::header_block::HeaderEncoder;
use crate::qlog; use crate::qlog;
use crate::qpack_send_buf::QPData; use crate::qpack_send_buf::QPData;
use crate::reader::ReceiverConnWrapper; use crate::reader::ReceiverConnWrapper;
use crate::stats::Stats;
use crate::table::{HeaderTable, LookupResult, ADDITIONAL_TABLE_ENTRY_SIZE}; use crate::table::{HeaderTable, LookupResult, ADDITIONAL_TABLE_ENTRY_SIZE};
use crate::Header; use crate::Header;
use crate::{Error, QpackSettings, Res}; use crate::{Error, QpackSettings, Res};
@ -37,6 +38,7 @@ pub struct QPackEncoder {
unacked_header_blocks: HashMap<u64, VecDeque<HashSet<u64>>>, unacked_header_blocks: HashMap<u64, VecDeque<HashSet<u64>>>,
blocked_stream_cnt: u16, blocked_stream_cnt: u16,
use_huffman: bool, use_huffman: bool,
stats: Stats,
} }
impl QPackEncoder { impl QPackEncoder {
@ -54,6 +56,7 @@ impl QPackEncoder {
unacked_header_blocks: HashMap::new(), unacked_header_blocks: HashMap::new(),
blocked_stream_cnt: 0, blocked_stream_cnt: 0,
use_huffman, use_huffman,
stats: Stats::default(),
} }
} }
@ -248,6 +251,8 @@ impl QPackEncoder {
return Err(Error::EncoderStreamBlocked); return Err(Error::EncoderStreamBlocked);
} }
self.stats.dynamic_table_inserts += 1;
match self.table.insert(name, value) { match self.table.insert(name, value) {
Ok(inx) => Ok(inx), Ok(inx) => Ok(inx),
Err(e) => { Err(e) => {
@ -387,6 +392,7 @@ impl QPackEncoder {
.entry(stream_id) .entry(stream_id)
.or_insert_with(VecDeque::new) .or_insert_with(VecDeque::new)
.push_front(ref_entries); .push_front(ref_entries);
self.stats.dynamic_table_references += 1;
} }
Ok(encoded_h) Ok(encoded_h)
} }
@ -412,6 +418,11 @@ impl QPackEncoder {
} }
} }
#[must_use]
pub fn stats(&self) -> &Stats {
&self.stats
}
#[must_use] #[must_use]
pub fn local_stream_id(&self) -> Option<u64> { pub fn local_stream_id(&self) -> Option<u64> {
self.local_stream_id self.local_stream_id
@ -513,7 +524,7 @@ mod tests {
encoder.encoder.send(&mut encoder.conn).unwrap(); encoder.encoder.send(&mut encoder.conn).unwrap();
let out = encoder.conn.process(None, now()); let out = encoder.conn.process(None, now());
let out2 = encoder.peer_conn.process(out.dgram(), now()); let out2 = encoder.peer_conn.process(out.dgram(), now());
encoder.conn.process(out2.dgram(), now()); let _ = encoder.conn.process(out2.dgram(), now());
let mut buf = [0_u8; 100]; let mut buf = [0_u8; 100];
let (amount, fin) = encoder let (amount, fin) = encoder
.peer_conn .peer_conn
@ -529,7 +540,7 @@ mod tests {
.stream_send(encoder.recv_stream_id, decoder_instruction) .stream_send(encoder.recv_stream_id, decoder_instruction)
.unwrap(); .unwrap();
let out = encoder.peer_conn.process(None, now()); let out = encoder.peer_conn.process(None, now());
encoder.conn.process(out.dgram(), now()); let _ = encoder.conn.process(out.dgram(), now());
assert!(encoder assert!(encoder
.encoder .encoder
.read_instructions(&mut encoder.conn, encoder.recv_stream_id) .read_instructions(&mut encoder.conn, encoder.recv_stream_id)
@ -1578,7 +1589,7 @@ mod tests {
encoder.encoder.send(&mut encoder.conn).unwrap(); encoder.encoder.send(&mut encoder.conn).unwrap();
let out = encoder.conn.process(None, now()); let out = encoder.conn.process(None, now());
encoder.peer_conn.process(out.dgram(), now()); let _ = encoder.peer_conn.process(out.dgram(), now());
// receive an insert count increment. // receive an insert count increment.
recv_instruction(&mut encoder, &[0x01]); recv_instruction(&mut encoder, &[0x01]);

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

@ -422,30 +422,30 @@ impl<'a> HeaderDecoder<'a> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{Deref, HeaderDecoder, HeaderDecoderResult, HeaderEncoder, HeaderTable}; use super::{HeaderDecoder, HeaderDecoderResult, HeaderEncoder, HeaderTable};
const INDEX_STATIC_TEST: [(u64, &[u8], &str, &str); 4] = [ const INDEX_STATIC_TEST: &[(u64, &[u8], &str, &str)] = &[
(0, &[0x0, 0x0, 0xc0], ":authority", ""), (0, &[0x0, 0x0, 0xc0], ":authority", ""),
(10, &[0x0, 0x0, 0xca], "last-modified", ""), (10, &[0x0, 0x0, 0xca], "last-modified", ""),
(15, &[0x0, 0x0, 0xcf], ":method", "CONNECT"), (15, &[0x0, 0x0, 0xcf], ":method", "CONNECT"),
(65, &[0x0, 0x0, 0xff, 0x02], ":status", "206"), (65, &[0x0, 0x0, 0xff, 0x02], ":status", "206"),
]; ];
const INDEX_DYNAMIC_TEST: [(u64, &[u8], &str, &str); 4] = [ const INDEX_DYNAMIC_TEST: &[(u64, &[u8], &str, &str)] = &[
(0, &[0x02, 0x41, 0xbf, 0x2], "header0", "0"), (0, &[0x02, 0x41, 0xbf, 0x2], "header0", "0"),
(10, &[0x0c, 0x37, 0xb7], "header10", "10"), (10, &[0x0c, 0x37, 0xb7], "header10", "10"),
(15, &[0x11, 0x32, 0xb2], "header15", "15"), (15, &[0x11, 0x32, 0xb2], "header15", "15"),
(65, &[0x43, 0x0, 0x80], "header65", "65"), (65, &[0x43, 0x0, 0x80], "header65", "65"),
]; ];
const INDEX_DYNAMIC_POST_TEST: [(u64, &[u8], &str, &str); 4] = [ const INDEX_DYNAMIC_POST_TEST: &[(u64, &[u8], &str, &str)] = &[
(0, &[0x02, 0x80, 0x10], "header0", "0"), (0, &[0x02, 0x80, 0x10], "header0", "0"),
(10, &[0x0c, 0x8a, 0x1a], "header10", "10"), (10, &[0x0c, 0x8a, 0x1a], "header10", "10"),
(15, &[0x11, 0x8f, 0x1f, 0x00], "header15", "15"), (15, &[0x11, 0x8f, 0x1f, 0x00], "header15", "15"),
(65, &[0x43, 0xc1, 0x1f, 0x32], "header65", "65"), (65, &[0x43, 0xc1, 0x1f, 0x32], "header65", "65"),
]; ];
const NAME_REF_STATIC: [(u64, &[u8], &str, &str); 4] = [ const NAME_REF_STATIC: &[(u64, &[u8], &str, &str)] = &[
( (
0, 0,
&[ &[
@ -482,7 +482,7 @@ mod tests {
), ),
]; ];
const NAME_REF_DYNAMIC: [(u64, &[u8], &str, &str); 4] = [ const NAME_REF_DYNAMIC: &[(u64, &[u8], &str, &str)] = &[
( (
0, 0,
&[ &[
@ -520,7 +520,7 @@ mod tests {
), ),
]; ];
const NAME_REF_DYNAMIC_POST: [(u64, &[u8], &str, &str); 4] = [ const NAME_REF_DYNAMIC_POST: &[(u64, &[u8], &str, &str)] = &[
( (
0, 0,
&[ &[
@ -558,7 +558,7 @@ mod tests {
), ),
]; ];
const NAME_REF_DYNAMIC_HUFFMAN: [(u64, &[u8], &str, &str); 4] = [ const NAME_REF_DYNAMIC_HUFFMAN: &[(u64, &[u8], &str, &str)] = &[
( (
0, 0,
&[ &[
@ -606,107 +606,73 @@ mod tests {
const LITERAL_VALUE: &str = "custom-key"; const LITERAL_VALUE: &str = "custom-key";
const TEST_N_BIT: [(&[u8], &str, &str); 4] = [
(
&[
0x02, 0x41, 0x6f, 0x32, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65,
0x79,
],
"header0",
"custom-key",
),
(
&[
0x02, 0x80, 0x08, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65, 0x79,
],
"header0",
"custom-key",
),
(
&[
0x0, 0x42, 0x37, 0x03, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65, 0x79,
0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65, 0x79,
],
"custom-key",
"custom-key",
),
(
&[
0x0, 0x42, 0x3f, 0x01, 0x25, 0xa8, 0x49, 0xe9, 0x5b, 0xa9, 0x7d, 0x7f, 0x88, 0x25,
0xa8, 0x49, 0xe9, 0x5b, 0xa9, 0x7d, 0x7f,
],
"custom-key",
"custom-key",
),
];
#[test] #[test]
fn test_encode_indexed_static() { fn test_encode_indexed_static() {
for (index, result, _, _) in &INDEX_STATIC_TEST { for (index, result, _, _) in INDEX_STATIC_TEST {
let mut encoded_h = HeaderEncoder::new(0, true, 1000); let mut encoded_h = HeaderEncoder::new(0, true, 1000);
encoded_h.encode_indexed_static(*index); encoded_h.encode_indexed_static(*index);
encoded_h.fix_header_block_prefix(); encoded_h.fix_header_block_prefix();
assert_eq!(&&encoded_h[..], result); assert_eq!(&&*encoded_h, result);
} }
} }
#[test] #[test]
fn test_encode_indexed_dynamic() { fn test_encode_indexed_dynamic() {
for (index, result, _, _) in &INDEX_DYNAMIC_TEST { for (index, result, _, _) in INDEX_DYNAMIC_TEST {
let mut encoded_h = HeaderEncoder::new(66, true, 1000); let mut encoded_h = HeaderEncoder::new(66, true, 1000);
encoded_h.encode_indexed_dynamic(*index); encoded_h.encode_indexed_dynamic(*index);
encoded_h.fix_header_block_prefix(); encoded_h.fix_header_block_prefix();
assert_eq!(&encoded_h.deref(), result); assert_eq!(&&*encoded_h, result);
} }
} }
#[test] #[test]
fn test_encode_indexed_dynamic_post() { fn test_encode_indexed_dynamic_post() {
for (index, result, _, _) in &INDEX_DYNAMIC_POST_TEST { for (index, result, _, _) in INDEX_DYNAMIC_POST_TEST {
let mut encoded_h = HeaderEncoder::new(0, true, 1000); let mut encoded_h = HeaderEncoder::new(0, true, 1000);
encoded_h.encode_indexed_dynamic(*index); encoded_h.encode_indexed_dynamic(*index);
encoded_h.fix_header_block_prefix(); encoded_h.fix_header_block_prefix();
assert_eq!(&encoded_h.deref(), result); assert_eq!(&&*encoded_h, result);
} }
} }
#[test] #[test]
fn test_encode_literal_with_name_ref_static() { fn test_encode_literal_with_name_ref_static() {
for (index, result, _, _) in &NAME_REF_STATIC { for (index, result, _, _) in NAME_REF_STATIC {
let mut encoded_h = HeaderEncoder::new(0, false, 1000); let mut encoded_h = HeaderEncoder::new(0, false, 1000);
encoded_h.encode_literal_with_name_ref(true, *index, VALUE); encoded_h.encode_literal_with_name_ref(true, *index, VALUE);
encoded_h.fix_header_block_prefix(); encoded_h.fix_header_block_prefix();
assert_eq!(&encoded_h.deref(), result); assert_eq!(&&*encoded_h, result);
} }
} }
#[test] #[test]
fn test_encode_literal_with_name_ref_dynamic() { fn test_encode_literal_with_name_ref_dynamic() {
for (index, result, _, _) in &NAME_REF_DYNAMIC { for (index, result, _, _) in NAME_REF_DYNAMIC {
let mut encoded_h = HeaderEncoder::new(66, false, 1000); let mut encoded_h = HeaderEncoder::new(66, false, 1000);
encoded_h.encode_literal_with_name_ref(false, *index, VALUE); encoded_h.encode_literal_with_name_ref(false, *index, VALUE);
encoded_h.fix_header_block_prefix(); encoded_h.fix_header_block_prefix();
assert_eq!(&encoded_h.deref(), result); assert_eq!(&&*encoded_h, result);
} }
} }
#[test] #[test]
fn test_encode_literal_with_name_ref_dynamic_post() { fn test_encode_literal_with_name_ref_dynamic_post() {
for (index, result, _, _) in &NAME_REF_DYNAMIC_POST { for (index, result, _, _) in NAME_REF_DYNAMIC_POST {
let mut encoded_h = HeaderEncoder::new(0, false, 1000); let mut encoded_h = HeaderEncoder::new(0, false, 1000);
encoded_h.encode_literal_with_name_ref(false, *index, VALUE); encoded_h.encode_literal_with_name_ref(false, *index, VALUE);
encoded_h.fix_header_block_prefix(); encoded_h.fix_header_block_prefix();
assert_eq!(&encoded_h.deref(), result); assert_eq!(&&*encoded_h, result);
} }
} }
#[test] #[test]
fn test_encode_literal_with_name_ref_dynamic_huffman() { fn test_encode_literal_with_name_ref_dynamic_huffman() {
for (index, result, _, _) in &NAME_REF_DYNAMIC_HUFFMAN { for (index, result, _, _) in NAME_REF_DYNAMIC_HUFFMAN {
let mut encoded_h = HeaderEncoder::new(66, true, 1000); let mut encoded_h = HeaderEncoder::new(66, true, 1000);
encoded_h.encode_literal_with_name_ref(false, *index, VALUE); encoded_h.encode_literal_with_name_ref(false, *index, VALUE);
encoded_h.fix_header_block_prefix(); encoded_h.fix_header_block_prefix();
assert_eq!(&encoded_h.deref(), result); assert_eq!(&&*encoded_h, result);
} }
} }
#[test] #[test]
@ -714,17 +680,17 @@ mod tests {
let mut encoded_h = HeaderEncoder::new(66, false, 1000); let mut encoded_h = HeaderEncoder::new(66, false, 1000);
encoded_h.encode_literal_with_name_literal(VALUE, VALUE); encoded_h.encode_literal_with_name_literal(VALUE, VALUE);
encoded_h.fix_header_block_prefix(); encoded_h.fix_header_block_prefix();
assert_eq!(&encoded_h.deref(), &LITERAL_LITERAL); assert_eq!(&*encoded_h, LITERAL_LITERAL);
let mut encoded_h = HeaderEncoder::new(66, true, 1000); let mut encoded_h = HeaderEncoder::new(66, true, 1000);
encoded_h.encode_literal_with_name_literal(VALUE, VALUE); encoded_h.encode_literal_with_name_literal(VALUE, VALUE);
encoded_h.fix_header_block_prefix(); encoded_h.fix_header_block_prefix();
assert_eq!(&encoded_h.deref(), &LITERAL_LITERAL_HUFFMAN); assert_eq!(&*encoded_h, LITERAL_LITERAL_HUFFMAN);
} }
#[test] #[test]
fn decode_indexed_static() { fn decode_indexed_static() {
for (_, encoded, decoded1, decoded2) in &INDEX_STATIC_TEST { for (_, encoded, decoded1, decoded2) in INDEX_STATIC_TEST {
let table = HeaderTable::new(false); let table = HeaderTable::new(false);
let mut decoder_h = HeaderDecoder::new(encoded); let mut decoder_h = HeaderDecoder::new(encoded);
if let HeaderDecoderResult::Headers(result) = if let HeaderDecoderResult::Headers(result) =
@ -751,7 +717,7 @@ mod tests {
#[test] #[test]
fn decode_indexed_dynamic() { fn decode_indexed_dynamic() {
for (_, encoded, decoded1, decoded2) in &INDEX_DYNAMIC_TEST { for (_, encoded, decoded1, decoded2) in INDEX_DYNAMIC_TEST {
let mut table = HeaderTable::new(false); let mut table = HeaderTable::new(false);
fill_table(&mut table); fill_table(&mut table);
let mut decoder_h = HeaderDecoder::new(encoded); let mut decoder_h = HeaderDecoder::new(encoded);
@ -769,7 +735,7 @@ mod tests {
#[test] #[test]
fn decode_indexed_dynamic_post() { fn decode_indexed_dynamic_post() {
for (_, encoded, decoded1, decoded2) in &INDEX_DYNAMIC_POST_TEST { for (_, encoded, decoded1, decoded2) in INDEX_DYNAMIC_POST_TEST {
let mut table = HeaderTable::new(false); let mut table = HeaderTable::new(false);
fill_table(&mut table); fill_table(&mut table);
let mut decoder_h = HeaderDecoder::new(encoded); let mut decoder_h = HeaderDecoder::new(encoded);
@ -787,7 +753,7 @@ mod tests {
#[test] #[test]
fn decode_literal_with_name_ref_static() { fn decode_literal_with_name_ref_static() {
for (_, encoded, decoded1, decoded2) in &NAME_REF_STATIC { for (_, encoded, decoded1, decoded2) in NAME_REF_STATIC {
let table = HeaderTable::new(false); let table = HeaderTable::new(false);
let mut decoder_h = HeaderDecoder::new(encoded); let mut decoder_h = HeaderDecoder::new(encoded);
if let HeaderDecoderResult::Headers(result) = if let HeaderDecoderResult::Headers(result) =
@ -804,7 +770,7 @@ mod tests {
#[test] #[test]
fn decode_literal_with_name_ref_dynamic() { fn decode_literal_with_name_ref_dynamic() {
for (_, encoded, decoded1, decoded2) in &NAME_REF_DYNAMIC { for (_, encoded, decoded1, decoded2) in NAME_REF_DYNAMIC {
let mut table = HeaderTable::new(false); let mut table = HeaderTable::new(false);
fill_table(&mut table); fill_table(&mut table);
let mut decoder_h = HeaderDecoder::new(encoded); let mut decoder_h = HeaderDecoder::new(encoded);
@ -822,7 +788,7 @@ mod tests {
#[test] #[test]
fn decode_literal_with_name_ref_dynamic_post() { fn decode_literal_with_name_ref_dynamic_post() {
for (_, encoded, decoded1, decoded2) in &NAME_REF_DYNAMIC_POST { for (_, encoded, decoded1, decoded2) in NAME_REF_DYNAMIC_POST {
let mut table = HeaderTable::new(false); let mut table = HeaderTable::new(false);
fill_table(&mut table); fill_table(&mut table);
let mut decoder_h = HeaderDecoder::new(encoded); let mut decoder_h = HeaderDecoder::new(encoded);
@ -840,7 +806,7 @@ mod tests {
#[test] #[test]
fn decode_literal_with_name_ref_dynamic_huffman() { fn decode_literal_with_name_ref_dynamic_huffman() {
for (_, encoded, decoded1, decoded2) in &NAME_REF_DYNAMIC_HUFFMAN { for (_, encoded, decoded1, decoded2) in NAME_REF_DYNAMIC_HUFFMAN {
let mut table = HeaderTable::new(false); let mut table = HeaderTable::new(false);
fill_table(&mut table); fill_table(&mut table);
let mut decoder_h = HeaderDecoder::new(encoded); let mut decoder_h = HeaderDecoder::new(encoded);
@ -886,7 +852,42 @@ mod tests {
// Test that we are ignoring N-bit. // Test that we are ignoring N-bit.
#[test] #[test]
fn decode_ignore_n_bit() { fn decode_ignore_n_bit() {
for (encoded, decoded1, decoded2) in &TEST_N_BIT { const TEST_N_BIT: &[(&[u8], &str, &str)] = &[
(
&[
0x02, 0x41, 0x6f, 0x32, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b,
0x65, 0x79,
],
"header0",
"custom-key",
),
(
&[
0x02, 0x80, 0x08, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65,
0x79,
],
"header0",
"custom-key",
),
(
&[
0x0, 0x42, 0x37, 0x03, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65,
0x79, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65, 0x79,
],
"custom-key",
"custom-key",
),
(
&[
0x0, 0x42, 0x3f, 0x01, 0x25, 0xa8, 0x49, 0xe9, 0x5b, 0xa9, 0x7d, 0x7f, 0x88,
0x25, 0xa8, 0x49, 0xe9, 0x5b, 0xa9, 0x7d, 0x7f,
],
"custom-key",
"custom-key",
),
];
for (encoded, decoded1, decoded2) in TEST_N_BIT {
let mut table = HeaderTable::new(false); let mut table = HeaderTable::new(false);
fill_table(&mut table); fill_table(&mut table);
let mut decoder_h = HeaderDecoder::new(encoded); let mut decoder_h = HeaderDecoder::new(encoded);

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

@ -24,6 +24,7 @@ mod qlog;
mod qpack_send_buf; mod qpack_send_buf;
pub mod reader; pub mod reader;
mod static_table; mod static_table;
pub mod stats;
mod table; mod table;
pub type Header = (String, String); pub type Header = (String, String);

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

@ -0,0 +1,15 @@
// 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.
// Tracking of some useful statistics.
#[derive(Default, Debug)]
/// `QPack` statistics
pub struct Stats {
pub dynamic_table_inserts: usize,
// This is the munber of header blockes that reference the dynamic table.
pub dynamic_table_references: usize,
}

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

@ -1 +1 @@
{"files":{"Cargo.toml":"c2297a343ba36ee4af8f8deb001359d144b67c06702104d006130c1d0bb29ca3","TODO":"d759cb804b32fa9d96ea8d3574a3c4073da9fe6a0b02b708a0e22cce5a5b4a0f","src/cc.rs":"60d6de4376ba77801490a400a90078f93b5300aa24b16838b38a1bad805b784e","src/cid.rs":"208b1c847d23892287be59869e48a699ef027a84c45832e89df525df0c165d00","src/connection.rs":"fa88549ee30411f718a878ac226c28d64a922904ccc04cfb0be7f3db0fbd6e09","src/crypto.rs":"cbbb8f2df05fe8773315b4f1eab2cf6b7f1e889db68ca68a68329c7c7021bea5","src/dump.rs":"d69ccb0e3b240823b886a791186afbac9f2e26d1f1f67a55dbf86f8cd3e6203e","src/events.rs":"deee6ef1112034582af770212bb70ed2cdcd2b1b8bb167c9118ef39bbf454451","src/flow_mgr.rs":"34cc274c147c89fecacefb0402cfaa708369ecfa993abbe71e90643960a6d062","src/frame.rs":"5fd50fe01b06b2266850fd45365826100c08812c43a85f0d6bc619097232cc70","src/lib.rs":"ae6a6464cfb9900fb09c5f658a4f605e5a266f65cb3dfe3dc637cc40c9ce8f99","src/pace.rs":"cee74faccfba9de2a827782b5a34015626b7748be27ffd4942a4caaaf14c6c18","src/packet/mod.rs":"b065cf5bf69eec5e81ca17169989054a48312013858ebdf6836133b47364cd28","src/packet/retry.rs":"842b1fa864e03e2bbe76dd2daeaa727cf20440fed2b654ca3b50f62bc4df26a8","src/path.rs":"3ef5d00c247cfe0eced6885cdd283e25766ee979d5bdc662abfdf4d4b962dbf1","src/qlog.rs":"387f142164c5d5a07bbba8cab56fe9f34ef5d2eb4d2d8d4b9460d34a94bd14c6","src/recovery.rs":"524f38eccb323a4e6ef4fec9eb336fd6f9441d40c11f63c819c4db6bdd6f21eb","src/recv_stream.rs":"d9d81275b2044812fd90d8bca26399fb56e9f4442640eae89d567de03e602b50","src/send_stream.rs":"cd834ebd4386a776d897b1a5e52cad839784e389da8e2543ba1fb57649225cbd","src/server.rs":"fcdb6ef12b0bf06eea872be50b4e20c1bcff3bb2e23eafc7043f5633e5ee9cc7","src/stats.rs":"8593be6985c4545371c3d1563ba9582118d6005b0f51b9c04b98a0dd01a55002","src/stream_id.rs":"a61e10002c171f05b0ebeda821b4e6c8265fe793d167e6b8698983418836f8d3","src/tparams.rs":"94d6bf73b551af1b103bc32b71be2b6e6e0766108cdd9142bda4d2f1f3404f0e","src/tracking.rs":"b93fd7bf6f0b4dba2ed48f6fc3f039a63c92626e58ae1a0d2c9fec3f101e8fa8","tests/conn_vectors.rs":"27770faa461bb6ca45bc05c5f323e74d943e299fd2ae330aab61967b49bb26f4","tests/connection.rs":"a93985c199a9ef987106f4a20b35ebf803cdbbb855c07b1362b403eed7101ef8","tests/server.rs":"472754a045391d848c0994719d9dfd61494097c525fa26efa404258c163d9324"},"package":null} {"files":{"Cargo.toml":"31dc4db15835d200da3c3e194b04cfe7f397249c0bffba83789e16577bdc284a","TODO":"d759cb804b32fa9d96ea8d3574a3c4073da9fe6a0b02b708a0e22cce5a5b4a0f","src/cc.rs":"60d6de4376ba77801490a400a90078f93b5300aa24b16838b38a1bad805b784e","src/cid.rs":"208b1c847d23892287be59869e48a699ef027a84c45832e89df525df0c165d00","src/connection.rs":"e2794da4439757aa25612c09daad4acde7adf5218e036e933efea09cf9091ad4","src/crypto.rs":"d9ed166f3d431a09525aa033c54a11fbb2a092b66b279e89062044fb55bcdc0a","src/dump.rs":"d69ccb0e3b240823b886a791186afbac9f2e26d1f1f67a55dbf86f8cd3e6203e","src/events.rs":"ada1fe0ff4d2ac268311428b0dd707c534fa97ee4b09ad4ffcee6be84825ef70","src/flow_mgr.rs":"ff820f4f45fb5dbed5e4b1e9433483a36fc624bd5fa1a22dd7abb779ba723caf","src/frame.rs":"5fd50fe01b06b2266850fd45365826100c08812c43a85f0d6bc619097232cc70","src/lib.rs":"697106a316f36ade2dfd4979fdefc1d6f3600693b86a3ffa3808fc6e22757474","src/pace.rs":"cee74faccfba9de2a827782b5a34015626b7748be27ffd4942a4caaaf14c6c18","src/packet/mod.rs":"39cccf0a6a8639ec1e14fd60d5d24c70dbf1518e80a927f4e9f93571ee9f6ed8","src/packet/retry.rs":"842b1fa864e03e2bbe76dd2daeaa727cf20440fed2b654ca3b50f62bc4df26a8","src/path.rs":"3ef5d00c247cfe0eced6885cdd283e25766ee979d5bdc662abfdf4d4b962dbf1","src/qlog.rs":"387f142164c5d5a07bbba8cab56fe9f34ef5d2eb4d2d8d4b9460d34a94bd14c6","src/recovery.rs":"75a7e14089e7f07fdde65262580db40c87202dca3de5a7b5d68898db610e8af0","src/recv_stream.rs":"2aec5de8ac27d2646e1f27cfd5b5c28d267167dc2b758583f2c5c2e49f02d4d7","src/send_stream.rs":"cd834ebd4386a776d897b1a5e52cad839784e389da8e2543ba1fb57649225cbd","src/server.rs":"fcdb6ef12b0bf06eea872be50b4e20c1bcff3bb2e23eafc7043f5633e5ee9cc7","src/stats.rs":"8593be6985c4545371c3d1563ba9582118d6005b0f51b9c04b98a0dd01a55002","src/stream_id.rs":"74c3523085bfdddfb009a33a747b329b27007b3f0ba728b18a5b6e8ab8ad1d26","src/tparams.rs":"94d6bf73b551af1b103bc32b71be2b6e6e0766108cdd9142bda4d2f1f3404f0e","src/tracking.rs":"b93fd7bf6f0b4dba2ed48f6fc3f039a63c92626e58ae1a0d2c9fec3f101e8fa8","tests/conn_vectors.rs":"27770faa461bb6ca45bc05c5f323e74d943e299fd2ae330aab61967b49bb26f4","tests/connection.rs":"a93985c199a9ef987106f4a20b35ebf803cdbbb855c07b1362b403eed7101ef8","tests/server.rs":"9e3940d4a317f3cb9c845e6c882db90d2b237cb9e1e687fa610787f91e29ae43"},"package":null}

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

@ -1,6 +1,6 @@
[package] [package]
name = "neqo-transport" name = "neqo-transport"
version = "0.4.3" version = "0.4.4"
authors = ["EKR <ekr@rtfm.com>", "Andy Grover <agrover@mozilla.com>"] authors = ["EKR <ekr@rtfm.com>", "Andy Grover <agrover@mozilla.com>"]
edition = "2018" edition = "2018"
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"

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

@ -433,6 +433,17 @@ pub struct Connection {
/// Checked against tparam value from peer /// Checked against tparam value from peer
remote_original_destination_cid: Option<ConnectionId>, remote_original_destination_cid: Option<ConnectionId>,
/// We sometimes save a datagram (just one) against the possibility that keys
/// will later become available.
/// One example of this is the case where a Handshake packet containing a
/// certificate is received coalesced with a 1-RTT packet. The certificate
/// might need to authenticated by the application before the 1-RTT packet can
/// be processed.
/// The boolean indicates whether processing should be deferred: after saving,
/// we usually immediately try to process this, but that won't work until after
/// returning to the application.
saved_datagram: Option<(Datagram, bool)>,
pub(crate) crypto: Crypto, pub(crate) crypto: Crypto,
pub(crate) acks: AckTracker, pub(crate) acks: AckTracker,
idle_timeout: IdleTimeout, idle_timeout: IdleTimeout,
@ -557,6 +568,7 @@ impl Connection {
local_initial_source_cid, local_initial_source_cid,
remote_initial_source_cid: None, remote_initial_source_cid: None,
remote_original_destination_cid: None, remote_original_destination_cid: None,
saved_datagram: None,
crypto, crypto,
acks: AckTracker::default(), acks: AckTracker::default(),
idle_timeout: IdleTimeout::default(), idle_timeout: IdleTimeout::default(),
@ -647,12 +659,12 @@ impl Connection {
} }
/// Enable a set of ciphers. /// Enable a set of ciphers.
pub fn enable_ciphers(&mut self, ciphers: &[Cipher]) -> Res<()> { pub fn set_ciphers(&mut self, ciphers: &[Cipher]) -> Res<()> {
if self.state != State::Init { if self.state != State::Init {
qerror!([self], "Cannot enable ciphers in state {:?}", self.state); qerror!([self], "Cannot enable ciphers in state {:?}", self.state);
return Err(Error::ConnectionState); return Err(Error::ConnectionState);
} }
self.crypto.tls.enable_ciphers(ciphers)?; self.crypto.tls.set_ciphers(ciphers)?;
Ok(()) Ok(())
} }
@ -760,9 +772,12 @@ impl Connection {
/// Call by application when the peer cert has been verified /// Call by application when the peer cert has been verified
pub fn authenticated(&mut self, status: AuthenticationStatus, now: Instant) { pub fn authenticated(&mut self, status: AuthenticationStatus, now: Instant) {
qinfo!([self], "Authenticated {:?}", status);
self.crypto.tls.authenticated(status); self.crypto.tls.authenticated(status);
let res = self.handshake(now, PNSpace::Handshake, None); let res = self.handshake(now, PNSpace::Handshake, None);
self.absorb_error(now, res); self.absorb_error(now, res);
// Try to handle packets that couldn't be processed before.
self.process_saved(now, true);
} }
/// Get the role of the connection. /// Get the role of the connection.
@ -848,6 +863,8 @@ impl Connection {
return; return;
} }
self.process_saved(now, false);
let res = self.crypto.states.check_key_update(now); let res = self.crypto.states.check_key_update(now);
self.absorb_error(now, res); self.absorb_error(now, res);
@ -943,7 +960,7 @@ impl Connection {
match self.output(now) { match self.output(now) {
SendOption::Yes(dgram) => Output::Datagram(dgram), SendOption::Yes(dgram) => Output::Datagram(dgram),
SendOption::No(paced) => match self.state { SendOption::No(paced) => match self.state {
State::Closed(_) => Output::None, State::Init | State::Closed(_) => Output::None,
State::Closing { timeout, .. } | State::Draining { timeout, .. } => { State::Closing { timeout, .. } | State::Draining { timeout, .. } => {
Output::Callback(timeout.duration_since(now)) Output::Callback(timeout.duration_since(now))
} }
@ -953,6 +970,7 @@ impl Connection {
} }
/// Process input and generate output. /// Process input and generate output.
#[must_use = "Output of the process function must be handled"]
pub fn process(&mut self, dgram: Option<Datagram>, now: Instant) -> Output { pub fn process(&mut self, dgram: Option<Datagram>, now: Instant) -> Output {
if let Some(d) = dgram { if let Some(d) = dgram {
self.process_input(d, now); self.process_input(d, now);
@ -1038,8 +1056,15 @@ impl Connection {
.map_or(false, |t| Self::token_equal(t, token)) .map_or(false, |t| Self::token_equal(t, token))
} }
fn check_stateless_reset(&mut self, d: &Datagram, now: Instant) -> Res<()> { fn check_stateless_reset<'a, 'b>(
if self.is_stateless_reset(d) { &'a mut self,
d: &'b Datagram,
slice: &'b [u8],
now: Instant,
) -> Res<()> {
// Only look for a stateless reset if we are dealing with the entire
// datagram. No point in running the check multiple times.
if d.len() == slice.len() && self.is_stateless_reset(d) {
// Failing to process a packet in a datagram might // Failing to process a packet in a datagram might
// indicate that there is a stateless reset present. // indicate that there is a stateless reset present.
qdebug!([self], "Stateless reset: {}", hex(&d[d.len() - 16..])); qdebug!([self], "Stateless reset: {}", hex(&d[d.len() - 16..]));
@ -1054,6 +1079,42 @@ impl Connection {
} }
} }
/// Process any saved packet.
/// When `always` is false, the packet is only processed if time has
/// passed since it was saved. Otherwise saved packets are saved and then
/// dropped instantly.
fn process_saved(&mut self, now: Instant, always: bool) {
if let Some((_, ref mut defer)) = self.saved_datagram {
if always || !*defer {
let d = self.saved_datagram.take().unwrap().0;
qdebug!([self], "process saved datagram: {:?}", d);
self.process_input(d, now);
} else {
*defer = false;
}
}
}
/// In case a datagram arrives that we can only partially process, save any
/// part that we don't have keys for.
fn maybe_save_datagram<'a, 'b>(
&'a mut self,
d: &'b Datagram,
slice: &'b [u8],
now: Instant,
) -> bool {
// Only save partial datagrams to avoid looping.
// It also means that we don't have to worry about it being a stateless reset.
if slice.len() < d.len() {
let save = Datagram::new(d.source(), d.destination(), slice);
qdebug!([self], "saving datagram@{:?} {:?}", now, save);
self.saved_datagram = Some((save, true));
true
} else {
false
}
}
fn input(&mut self, d: Datagram, now: Instant) -> Res<Vec<(Frame, PNSpace)>> { fn input(&mut self, d: Datagram, now: Instant) -> Res<Vec<(Frame, PNSpace)>> {
let mut slc = &d[..]; let mut slc = &d[..];
let mut frames = Vec::new(); let mut frames = Vec::new();
@ -1102,10 +1163,24 @@ impl Connection {
} }
} }
(PacketType::VersionNegotiation, State::WaitInitial, Role::Client) => { (PacketType::VersionNegotiation, State::WaitInitial, Role::Client) => {
self.set_state(State::Closed(ConnectionError::Transport( match packet.supported_versions() {
Error::VersionNegotiation, Ok(versions) => {
))); if versions.is_empty() || versions.contains(&self.quic_version.as_u32())
return Err(Error::VersionNegotiation); {
// Ignore VersionNegotiation packets that contain the current version.
self.stats.dropped_rx += 1;
return Ok(frames);
}
self.set_state(State::Closed(ConnectionError::Transport(
Error::VersionNegotiation,
)));
return Err(Error::VersionNegotiation);
}
Err(_) => {
self.stats.dropped_rx += 1;
return Ok(frames);
}
}
} }
(PacketType::Retry, State::WaitInitial, Role::Client) => { (PacketType::Retry, State::WaitInitial, Role::Client) => {
self.handle_retry(packet)?; self.handle_retry(packet)?;
@ -1154,47 +1229,49 @@ impl Connection {
qtrace!([self], "Received unverified packet {:?}", packet); qtrace!([self], "Received unverified packet {:?}", packet);
let pto = self.loss_recovery.pto(); let pto = self.loss_recovery.pto();
let payload = packet.decrypt(&mut self.crypto.states, now + pto); match packet.decrypt(&mut self.crypto.states, now + pto) {
if let Ok(payload) = payload { Ok(payload) => {
// TODO(ekr@rtfm.com): Have the server blow away the initial // TODO(ekr@rtfm.com): Have the server blow away the initial
// crypto state if this fails? Otherwise, we will get a panic // crypto state if this fails? Otherwise, we will get a panic
// on the assert for doesn't exist. // on the assert for doesn't exist.
// OK, we have a valid packet. // OK, we have a valid packet.
self.idle_timeout.on_packet_received(now); self.idle_timeout.on_packet_received(now);
dump_packet( dump_packet(
self, self,
"-> RX", "-> RX",
payload.packet_type(), payload.packet_type(),
payload.pn(), payload.pn(),
&payload[..], &payload[..],
); );
qlog::packet_received(&mut self.qlog, &payload)?; qlog::packet_received(&mut self.qlog, &payload)?;
let res = self.process_packet(&payload, now); let res = self.process_packet(&payload, now);
if res.is_err() && self.path.is_none() { if res.is_err() && self.path.is_none() {
// We need to make a path for sending an error message. // We need to make a path for sending an error message.
// But this connection is going to be closed. // But this connection is going to be closed.
self.remote_initial_source_cid = Some(ConnectionId::from(packet.scid())); self.remote_initial_source_cid = Some(ConnectionId::from(packet.scid()));
self.initialize_path(d.destination(), d.source()); self.initialize_path(d.destination(), d.source());
}
frames.extend(res?);
if self.state == State::WaitInitial {
self.start_handshake(&packet, &d)?;
}
self.process_migrations(&d)?;
} }
frames.extend(res?); Err(e) => {
if self.state == State::WaitInitial { // While connecting we might want to save the remainder of a packet.
self.start_handshake(&packet, &d)?; if matches!(e, Error::KeysNotFound) && self.maybe_save_datagram(&d, slc, now) {
} break;
self.process_migrations(&d)?; }
} else { // Decryption failure, or not having keys is not fatal.
// Decryption failure, or not having keys is not fatal. // If the state isn't available, or we can't decrypt the packet, drop
// If the state isn't available, or we can't decrypt the packet, drop // the rest of the datagram on the floor, but don't generate an error.
// the rest of the datagram on the floor, but don't generate an error. self.check_stateless_reset(&d, slc, now)?;
self.stats.pkt_dropped("Decryption failure"); self.stats.pkt_dropped("Decryption failure");
if slc.len() == d.len() {
self.check_stateless_reset(&d, now)?
} }
} }
slc = remainder; slc = remainder;
} }
if slc.len() == d.len() { self.check_stateless_reset(&d, slc, now)?;
self.check_stateless_reset(&d, now)?
}
Ok(frames) Ok(frames)
} }
@ -1416,7 +1493,6 @@ impl Connection {
/// Add frames to the provided builder and /// Add frames to the provided builder and
/// return whether any of them were ACK eliciting. /// return whether any of them were ACK eliciting.
#[allow(clippy::useless_let_if_seq)]
fn add_frames( fn add_frames(
&mut self, &mut self,
builder: &mut PacketBuilder, builder: &mut PacketBuilder,
@ -1426,13 +1502,14 @@ impl Connection {
now: Instant, now: Instant,
) -> (Vec<RecoveryToken>, bool) { ) -> (Vec<RecoveryToken>, bool) {
let mut tokens = Vec::new(); let mut tokens = Vec::new();
let mut ack_eliciting = false;
if profile.pto() { let mut ack_eliciting = if profile.pto() {
// Add a PING on a PTO. This might get a more expedient ACK. // Add a PING on a PTO. This might get a more expedient ACK.
builder.encode_varint(Frame::Ping.get_type()); builder.encode_varint(Frame::Ping.get_type());
ack_eliciting = true; true
} } else {
false
};
// All useful frames are at least 2 bytes. // All useful frames are at least 2 bytes.
while builder.len() + 2 < limit { while builder.len() + 2 < limit {
@ -1675,7 +1752,9 @@ impl Connection {
debug_assert!(!info.token.is_empty()); debug_assert!(!info.token.is_empty());
let tph = self.tps.borrow(); let tph = self.tps.borrow();
let tp = tph let tp = tph
.remote() .remote
.as_ref()
.unwrap()
.get_bytes(tparams::ORIGINAL_DESTINATION_CONNECTION_ID); .get_bytes(tparams::ORIGINAL_DESTINATION_CONNECTION_ID);
if self if self
.remote_original_destination_cid .remote_original_destination_cid
@ -1765,6 +1844,10 @@ impl Connection {
// There is a chance that this could be called less often, but getting the // There is a chance that this could be called less often, but getting the
// conditions right is a little tricky, so call it on every CRYPTO frame. // conditions right is a little tricky, so call it on every CRYPTO frame.
if try_update { if try_update {
// We have transport parameters, it's go time.
if self.tps.borrow().remote.is_some() {
self.set_initial_limits();
}
self.crypto.install_keys(self.role); self.crypto.install_keys(self.role);
} }
@ -1898,10 +1981,10 @@ impl Connection {
// But if it does, open it up all the way // But if it does, open it up all the way
self.flow_mgr.borrow_mut().max_data(LOCAL_MAX_DATA); self.flow_mgr.borrow_mut().max_data(LOCAL_MAX_DATA);
} }
Frame::StreamDataBlocked { stream_id, .. } => { Frame::StreamDataBlocked {
// TODO(agrover@mozilla.com): how should we be using stream_id,
// currently-unused stream_data_limit? stream_data_limit,
} => {
// Terminate connection with STREAM_STATE_ERROR if send-only // Terminate connection with STREAM_STATE_ERROR if send-only
// stream (-transport 19.13) // stream (-transport 19.13)
if stream_id.is_send_only(self.role()) { if stream_id.is_send_only(self.role()) {
@ -1909,7 +1992,18 @@ impl Connection {
} }
if let (_, Some(rs)) = self.obtain_stream(stream_id)? { if let (_, Some(rs)) = self.obtain_stream(stream_id)? {
rs.maybe_send_flowc_update(); if let Some(msd) = rs.max_stream_data() {
qinfo!(
[self],
"Got StreamDataBlocked(id {} MSD {}); curr MSD {}",
stream_id.as_u64(),
stream_data_limit,
msd
);
if stream_data_limit != msd {
self.flow_mgr.borrow_mut().max_stream_data(stream_id, msd)
}
}
} }
} }
Frame::StreamsBlocked { stream_type, .. } => { Frame::StreamsBlocked { stream_type, .. } => {
@ -2279,17 +2373,17 @@ impl Connection {
pub fn stream_create(&mut self, st: StreamType) -> Res<u64> { pub fn stream_create(&mut self, st: StreamType) -> Res<u64> {
// Can't make streams while closing, otherwise rely on the stream limits. // Can't make streams while closing, otherwise rely on the stream limits.
match self.state { match self.state {
State::Closing { .. } | State::Closed { .. } => return Err(Error::ConnectionState), State::Closing { .. } | State::Draining { .. } | State::Closed { .. } => {
return Err(Error::ConnectionState);
}
State::WaitInitial | State::Handshaking => { State::WaitInitial | State::Handshaking => {
if !matches!(self.zero_rtt_state, ZeroRttState::Sending) { if self.role == Role::Client && self.zero_rtt_state != ZeroRttState::Sending {
return Err(Error::ConnectionState); return Err(Error::ConnectionState);
} }
} }
// In all other states, trust that the stream limits are correct.
_ => (), _ => (),
} }
if self.tps.borrow().remote.is_none() && self.tps.borrow().remote_0rtt.is_none() {
return Err(Error::ConnectionState);
}
Ok(match st { Ok(match st {
StreamType::UniDi => { StreamType::UniDi => {
@ -2495,6 +2589,7 @@ mod tests {
use crate::cc::PACING_BURST_SIZE; use crate::cc::PACING_BURST_SIZE;
use crate::cc::{INITIAL_CWND_PKTS, MIN_CONG_WINDOW}; use crate::cc::{INITIAL_CWND_PKTS, MIN_CONG_WINDOW};
use crate::frame::{CloseError, StreamType}; use crate::frame::{CloseError, StreamType};
use crate::packet::PACKET_BIT_LONG;
use crate::path::PATH_MTU_V6; use crate::path::PATH_MTU_V6;
use crate::recovery::ACK_ONLY_SIZE_LIMIT; use crate::recovery::ACK_ONLY_SIZE_LIMIT;
use crate::recovery::PTO_PACKET_COUNT; use crate::recovery::PTO_PACKET_COUNT;
@ -2502,10 +2597,12 @@ mod tests {
use std::convert::TryInto; use std::convert::TryInto;
use neqo_common::matches; use neqo_common::matches;
use neqo_crypto::constants::TLS_CHACHA20_POLY1305_SHA256;
use std::mem; use std::mem;
use test_fixture::{self, assertions, fixture_init, loopback, now}; use test_fixture::{self, assertions, fixture_init, loopback, now};
const AT_LEAST_PTO: Duration = Duration::from_secs(1); const AT_LEAST_PTO: Duration = Duration::from_secs(1);
const DEFAULT_STREAM_DATA: &[u8] = b"message";
// This is fabulous: because test_fixture uses the public API for Connection, // This is fabulous: because test_fixture uses the public API for Connection,
// it gets a different type to the ones that are referenced via super::*. // it gets a different type to the ones that are referenced via super::*.
@ -2785,17 +2882,17 @@ mod tests {
_ => None, _ => None,
}); });
let stream_id = stream_ids.next().expect("should have a new stream event"); let stream_id = stream_ids.next().expect("should have a new stream event");
let (received, fin) = server.stream_recv(stream_id, &mut buf).unwrap(); let (received, fin) = server.stream_recv(stream_id.as_u64(), &mut buf).unwrap();
assert_eq!(received, 4000); assert_eq!(received, 4000);
assert_eq!(fin, false); assert_eq!(fin, false);
let (received, fin) = server.stream_recv(stream_id, &mut buf).unwrap(); let (received, fin) = server.stream_recv(stream_id.as_u64(), &mut buf).unwrap();
assert_eq!(received, 140); assert_eq!(received, 140);
assert_eq!(fin, false); assert_eq!(fin, false);
let stream_id = stream_ids let stream_id = stream_ids
.next() .next()
.expect("should have a second new stream event"); .expect("should have a second new stream event");
let (received, fin) = server.stream_recv(stream_id, &mut buf).unwrap(); let (received, fin) = server.stream_recv(stream_id.as_u64(), &mut buf).unwrap();
assert_eq!(received, 60); assert_eq!(received, 60);
assert_eq!(fin, true); assert_eq!(fin, true);
} }
@ -2811,7 +2908,7 @@ mod tests {
let mut b = server; let mut b = server;
let mut now = now; let mut now = now;
let mut datagram = None; let mut input = None;
let is_done = |c: &mut Connection| match c.state() { let is_done = |c: &mut Connection| match c.state() {
State::Confirmed | State::Closing { .. } | State::Closed(..) => true, State::Confirmed | State::Closing { .. } | State::Closed(..) => true,
_ => false, _ => false,
@ -2819,12 +2916,14 @@ mod tests {
while !is_done(a) { while !is_done(a) {
let _ = maybe_authenticate(a); let _ = maybe_authenticate(a);
let d = a.process(datagram, now); let had_input = input.is_some();
datagram = d.dgram(); let output = a.process(input, now).dgram();
assert!(had_input || output.is_some());
input = output;
now += rtt / 2; now += rtt / 2;
mem::swap(&mut a, &mut b); mem::swap(&mut a, &mut b);
} }
a.process(datagram, now); let _ = a.process(input, now);
now now
} }
@ -3058,7 +3157,7 @@ mod tests {
_ => None, _ => None,
}) })
.expect("should have received a new stream event"); .expect("should have received a new stream event");
assert_eq!(client_stream_id, server_stream_id); assert_eq!(client_stream_id, server_stream_id.as_u64());
} }
#[test] #[test]
@ -3089,11 +3188,11 @@ mod tests {
let server_stream_id = server let server_stream_id = server
.events() .events()
.find_map(|evt| match evt { .find_map(|evt| match evt {
ConnectionEvent::NewStream { stream_id, .. } => Some(stream_id), ConnectionEvent::NewStream { stream_id } => Some(stream_id),
_ => None, _ => None,
}) })
.expect("should have received a new stream event"); .expect("should have received a new stream event");
assert_eq!(client_stream_id, server_stream_id); assert_eq!(client_stream_id, server_stream_id.as_u64());
} }
#[test] #[test]
@ -3190,11 +3289,11 @@ mod tests {
let stream_id = client.stream_create(StreamType::BiDi).unwrap(); let stream_id = client.stream_create(StreamType::BiDi).unwrap();
client.stream_send(stream_id, &[0x00]).unwrap(); client.stream_send(stream_id, &[0x00]).unwrap();
let out = client.process(None, now()); let out = client.process(None, now());
server.process(out.dgram(), now()); let _ = server.process(out.dgram(), now());
assert_eq!(Ok(()), server.stream_close_send(stream_id)); assert_eq!(Ok(()), server.stream_close_send(stream_id));
let out = server.process(None, now()); let out = server.process(None, now());
client.process(out.dgram(), now()); let _ = client.process(out.dgram(), now());
let stream_readable = |e| matches!(e, ConnectionEvent::RecvStreamReadable {..}); let stream_readable = |e| matches!(e, ConnectionEvent::RecvStreamReadable {..});
assert!(client.events().any(stream_readable)); assert!(client.events().any(stream_readable));
} }
@ -3244,10 +3343,10 @@ mod tests {
assert_eq!(res, Output::Callback(LOCAL_IDLE_TIMEOUT)); assert_eq!(res, Output::Callback(LOCAL_IDLE_TIMEOUT));
// Still connected after 29 seconds. Idle timer not reset // Still connected after 29 seconds. Idle timer not reset
client.process(None, now + LOCAL_IDLE_TIMEOUT - Duration::from_secs(1)); let _ = client.process(None, now + LOCAL_IDLE_TIMEOUT - Duration::from_secs(1));
assert!(matches!(client.state(), State::Confirmed)); assert!(matches!(client.state(), State::Confirmed));
client.process(None, now + LOCAL_IDLE_TIMEOUT); let _ = client.process(None, now + LOCAL_IDLE_TIMEOUT);
// Not connected after LOCAL_IDLE_TIMEOUT seconds. // Not connected after LOCAL_IDLE_TIMEOUT seconds.
assert!(matches!(client.state(), State::Closed(_))); assert!(matches!(client.state(), State::Closed(_)));
@ -3347,14 +3446,14 @@ mod tests {
// Still connected after 39 seconds because idle timer reset by outgoing // Still connected after 39 seconds because idle timer reset by outgoing
// packet // packet
client.process( let _ = client.process(
out.dgram(), out.dgram(),
now + LOCAL_IDLE_TIMEOUT + Duration::from_secs(9), now + LOCAL_IDLE_TIMEOUT + Duration::from_secs(9),
); );
assert!(matches!(client.state(), State::Confirmed)); assert!(matches!(client.state(), State::Confirmed));
// Not connected after 40 seconds. // Not connected after 40 seconds.
client.process(None, now + LOCAL_IDLE_TIMEOUT + Duration::from_secs(10)); let _ = client.process(None, now + LOCAL_IDLE_TIMEOUT + Duration::from_secs(10));
assert!(matches!(client.state(), State::Closed(_))); assert!(matches!(client.state(), State::Closed(_)));
} }
@ -3379,12 +3478,12 @@ mod tests {
let _out = client.process(None, now + Duration::from_secs(20)); let _out = client.process(None, now + Duration::from_secs(20));
// Still connected after 39 seconds. // Still connected after 39 seconds.
client.process(None, now + LOCAL_IDLE_TIMEOUT + Duration::from_secs(9)); let _ = client.process(None, now + LOCAL_IDLE_TIMEOUT + Duration::from_secs(9));
assert!(matches!(client.state(), State::Confirmed)); assert!(matches!(client.state(), State::Confirmed));
// Not connected after 40 seconds because timer not reset by second // Not connected after 40 seconds because timer not reset by second
// outgoing packet // outgoing packet
client.process(None, now + LOCAL_IDLE_TIMEOUT + Duration::from_secs(10)); let _ = client.process(None, now + LOCAL_IDLE_TIMEOUT + Duration::from_secs(10));
assert!(matches!(client.state(), State::Closed(_))); assert!(matches!(client.state(), State::Closed(_)));
} }
@ -3409,16 +3508,16 @@ mod tests {
let out = server.process_output(now + Duration::from_secs(10)); let out = server.process_output(now + Duration::from_secs(10));
assert_ne!(out.as_dgram_ref(), None); assert_ne!(out.as_dgram_ref(), None);
client.process(out.dgram(), now + Duration::from_secs(20)); let _ = client.process(out.dgram(), now + Duration::from_secs(20));
assert!(matches!(client.state(), State::Confirmed)); assert!(matches!(client.state(), State::Confirmed));
// Still connected after 49 seconds because idle timer reset by received // Still connected after 49 seconds because idle timer reset by received
// packet // packet
client.process(None, now + LOCAL_IDLE_TIMEOUT + Duration::from_secs(19)); let _ = client.process(None, now + LOCAL_IDLE_TIMEOUT + Duration::from_secs(19));
assert!(matches!(client.state(), State::Confirmed)); assert!(matches!(client.state(), State::Confirmed));
// Not connected after 50 seconds. // Not connected after 50 seconds.
client.process(None, now + LOCAL_IDLE_TIMEOUT + Duration::from_secs(20)); let _ = client.process(None, now + LOCAL_IDLE_TIMEOUT + Duration::from_secs(20));
assert!(matches!(client.state(), State::Closed(_))); assert!(matches!(client.state(), State::Closed(_)));
} }
@ -3550,7 +3649,7 @@ mod tests {
let stream_id = client.stream_create(StreamType::BiDi).unwrap(); let stream_id = client.stream_create(StreamType::BiDi).unwrap();
client.stream_send(stream_id, &[0x00]).unwrap(); client.stream_send(stream_id, &[0x00]).unwrap();
let out = client.process(None, now()); let out = client.process(None, now());
server.process(out.dgram(), now()); let _ = server.process(out.dgram(), now());
let stream_readable = |e| matches!(e, ConnectionEvent::RecvStreamReadable {..}); let stream_readable = |e| matches!(e, ConnectionEvent::RecvStreamReadable {..});
assert!(server.events().any(stream_readable)); assert!(server.events().any(stream_readable));
@ -3570,7 +3669,7 @@ mod tests {
let out = server.process(out_second_data_frame.dgram(), now()); let out = server.process(out_second_data_frame.dgram(), now());
assert!(!server.events().any(stream_readable)); assert!(!server.events().any(stream_readable));
client.process(out.dgram(), now()); let _ = client.process(out.dgram(), now());
assert_eq!( assert_eq!(
Err(Error::FinalSizeError), Err(Error::FinalSizeError),
client.stream_send(stream_id, &[0x00]) client.stream_send(stream_id, &[0x00])
@ -3590,7 +3689,7 @@ mod tests {
let stream_id = client.stream_create(StreamType::BiDi).unwrap(); let stream_id = client.stream_create(StreamType::BiDi).unwrap();
client.stream_send(stream_id, &[0x00]).unwrap(); client.stream_send(stream_id, &[0x00]).unwrap();
let out = client.process(None, now()); let out = client.process(None, now());
server.process(out.dgram(), now()); let _ = server.process(out.dgram(), now());
let stream_readable = |e| matches!(e, ConnectionEvent::RecvStreamReadable {..}); let stream_readable = |e| matches!(e, ConnectionEvent::RecvStreamReadable {..});
assert!(server.events().any(stream_readable)); assert!(server.events().any(stream_readable));
@ -3613,7 +3712,7 @@ mod tests {
assert!(!server.events().any(stream_readable)); assert!(!server.events().any(stream_readable));
// The client gets the STOP_SENDING frame. // The client gets the STOP_SENDING frame.
client.process(out.dgram(), now()); let _ = client.process(out.dgram(), now());
assert_eq!( assert_eq!(
Err(Error::InvalidStreamId), Err(Error::InvalidStreamId),
client.stream_send(stream_id, &[0x00]) client.stream_send(stream_id, &[0x00])
@ -4559,6 +4658,9 @@ mod tests {
} }
fn check_discarded(peer: &mut Connection, pkt: Datagram, dropped: usize, dups: usize) { fn check_discarded(peer: &mut Connection, pkt: Datagram, dropped: usize, dups: usize) {
// Make sure to flush any saved datagrams before doing this.
let _ = peer.process_output(now());
let dropped_before = peer.stats.dropped_rx; let dropped_before = peer.stats.dropped_rx;
let dups_before = peer.stats.dups_rx; let dups_before = peer.stats.dups_rx;
let out = peer.process(Some(pkt), now()); let out = peer.process(Some(pkt), now());
@ -4619,7 +4721,7 @@ mod tests {
#[must_use] #[must_use]
fn send_something(sender: &mut Connection, now: Instant) -> Datagram { fn send_something(sender: &mut Connection, now: Instant) -> Datagram {
let stream_id = sender.stream_create(StreamType::UniDi).unwrap(); let stream_id = sender.stream_create(StreamType::UniDi).unwrap();
assert!(sender.stream_send(stream_id, b"data").is_ok()); assert!(sender.stream_send(stream_id, DEFAULT_STREAM_DATA).is_ok());
assert!(sender.stream_close_send(stream_id).is_ok()); assert!(sender.stream_close_send(stream_id).is_ok());
let dgram = sender.process(None, now).dgram(); let dgram = sender.process(None, now).dgram();
dgram.expect("should have something to send") dgram.expect("should have something to send")
@ -4683,7 +4785,7 @@ mod tests {
let dgram = client.process(None, now).dgram(); let dgram = client.process(None, now).dgram();
assert!(dgram.is_some()); // Drop this packet. assert!(dgram.is_some()); // Drop this packet.
assert_eq!(client.get_epochs(), (Some(4), Some(3))); assert_eq!(client.get_epochs(), (Some(4), Some(3)));
server.process(None, now); let _ = server.process(None, now);
assert_eq!(server.get_epochs(), (Some(4), Some(4))); assert_eq!(server.get_epochs(), (Some(4), Some(4)));
// Even though the server has updated, it hasn't received an ACK yet. // Even though the server has updated, it hasn't received an ACK yet.
@ -4708,7 +4810,7 @@ mod tests {
assert!(server.initiate_key_update().is_err()); assert!(server.initiate_key_update().is_err());
now += AT_LEAST_PTO; now += AT_LEAST_PTO;
client.process(None, now); let _ = client.process(None, now);
assert_eq!(client.get_epochs(), (Some(4), Some(4))); assert_eq!(client.get_epochs(), (Some(4), Some(4)));
} }
@ -4736,7 +4838,7 @@ mod tests {
assert_eq!(server.get_epochs(), (Some(4), Some(3))); assert_eq!(server.get_epochs(), (Some(4), Some(3)));
// Now move the server temporarily into the future so that it // Now move the server temporarily into the future so that it
// rotates the keys. The client stays in the present. // rotates the keys. The client stays in the present.
server.process(None, now + AT_LEAST_PTO); let _ = server.process(None, now + AT_LEAST_PTO);
assert_eq!(server.get_epochs(), (Some(4), Some(4))); assert_eq!(server.get_epochs(), (Some(4), Some(4)));
} else { } else {
panic!("server should have a timer set"); panic!("server should have a timer set");
@ -5315,7 +5417,7 @@ mod tests {
let mut unknown_version_packet = vec![0x80, 0x1a, 0x1a, 0x1a, 0x1a]; let mut unknown_version_packet = vec![0x80, 0x1a, 0x1a, 0x1a, 0x1a];
unknown_version_packet.resize(1200, 0x0); unknown_version_packet.resize(1200, 0x0);
client.process( let _ = client.process(
Some(Datagram::new( Some(Datagram::new(
loopback(), loopback(),
loopback(), loopback(),
@ -5326,6 +5428,23 @@ mod tests {
assert_eq!(1, client.stats().dropped_rx); assert_eq!(1, client.stats().dropped_rx);
} }
/// Run a single ChaCha20-Poly1305 test and get a PTO.
#[test]
fn chacha20poly1305() {
let mut server = default_server();
let mut client = Connection::new_client(
test_fixture::DEFAULT_SERVER_NAME,
test_fixture::DEFAULT_ALPN,
Rc::new(RefCell::new(FixedConnectionIdManager::new(0))),
loopback(),
loopback(),
QuicVersion::default(),
)
.expect("create a default client");
client.set_ciphers(&[TLS_CHACHA20_POLY1305_SHA256]).unwrap();
connect_force_idle(&mut client, &mut server);
}
/// Test that a client can handle a stateless reset correctly. /// Test that a client can handle a stateless reset correctly.
#[test] #[test]
fn stateless_reset_client() { fn stateless_reset_client() {
@ -5342,4 +5461,290 @@ mod tests {
client.process_input(Datagram::new(loopback(), loopback(), vec![77; 21]), now()); client.process_input(Datagram::new(loopback(), loopback(), vec![77; 21]), now());
assert!(matches!(client.state(), State::Draining { .. })); assert!(matches!(client.state(), State::Draining { .. }));
} }
/// Test that a server can send 0.5 RTT application data.
#[test]
fn send_05rtt() {
let mut client = default_client();
let mut server = default_server();
let c1 = client.process(None, now()).dgram();
assert!(c1.is_some());
let s1 = server.process(c1, now()).dgram();
assert!(s1.is_some());
// The server should accept writes at this point.
let s2 = send_something(&mut server, now());
// We can't use the standard facility to complete the handshake, so
// drive it as aggressively as possible.
let _ = client.process(s1, now()).dgram(); // Just an ACK out of this.
client.authenticated(AuthenticationStatus::Ok, now());
assert_eq!(*client.state(), State::Connected);
// The client should accept data now.
client.process_input(s2, now());
let mut buf = vec![0; DEFAULT_STREAM_DATA.len() + 1];
let stream_id = client
.events()
.find_map(|e| {
if let ConnectionEvent::RecvStreamReadable { stream_id } = e {
Some(stream_id)
} else {
None
}
})
.unwrap();
let (l, ended) = client.stream_recv(stream_id, &mut buf).unwrap();
assert_eq!(&buf[..l], DEFAULT_STREAM_DATA);
assert!(ended);
}
/// Test that a server that coalesces 0.5 RTT with handshake packets
/// doesn't cause the client to drop application data.
#[test]
fn coalesce_05rtt() {
const RTT: Duration = Duration::from_millis(100);
let mut client = default_client();
let mut server = default_server();
let mut now = now();
// The first exchange doesn't offer a chance for the server to send.
// So drop the server flight and wait for the PTO.
let c1 = client.process(None, now).dgram();
assert!(c1.is_some());
now += RTT / 2;
let s1 = server.process(c1, now).dgram();
assert!(s1.is_some());
// Drop the server flight. Then send some data.
let stream_id = server.stream_create(StreamType::UniDi).unwrap();
assert!(server.stream_send(stream_id, DEFAULT_STREAM_DATA).is_ok());
assert!(server.stream_close_send(stream_id).is_ok());
// Now after a PTO the client can send another packet.
// The server should then send its entire flight again,
// including the application data, which it sends in a 1-RTT packet.
now += AT_LEAST_PTO;
let c2 = client.process(None, now).dgram();
assert!(c2.is_some());
now += RTT / 2;
let s2 = server.process(c2, now).dgram();
assert!(s2.is_some());
// The client should process the datagram. It can't process the 1-RTT
// packet until authentication completes though. So it saves it.
now += RTT / 2;
assert_eq!(client.stats.dropped_rx, 0);
let _ = client.process(s2, now).dgram();
// This packet will contain an ACK, but we can ignore it.
assert_eq!(client.stats.dropped_rx, 0);
assert!(client.saved_datagram.is_some());
// After (successful) authentication, the packet is processed.
maybe_authenticate(&mut client);
let c3 = client.process(None, now).dgram();
assert!(c3.is_some());
assert_eq!(client.stats.dropped_rx, 0);
assert!(client.saved_datagram.is_none());
// Allow the handshake to complete.
now += RTT / 2;
let s3 = server.process(c3, now).dgram();
assert!(s3.is_some());
assert_eq!(*server.state(), State::Confirmed);
now += RTT / 2;
let c5 = client.process(s3, now).dgram();
assert!(c5.is_none());
assert_eq!(*client.state(), State::Confirmed);
assert_eq!(client.stats().dropped_rx, 0);
}
#[test]
fn server_receive_unknown_first_packet() {
let mut server = default_server();
let mut unknown_version_packet = vec![0x80, 0x1a, 0x1a, 0x1a, 0x1a];
unknown_version_packet.resize(1200, 0x0);
assert_eq!(
server.process(
Some(Datagram::new(
loopback(),
loopback(),
unknown_version_packet,
)),
now(),
),
Output::None
);
assert_eq!(1, server.stats().dropped_rx);
}
fn create_vn(initial_pkt: &[u8], versions: &[u32]) -> Vec<u8> {
let mut dec = Decoder::from(&initial_pkt[5..]); // Skip past version.
let dcid = dec.decode_vec(1).expect("client DCID");
let scid = dec.decode_vec(1).expect("client SCID");
let mut encoder = Encoder::default();
encoder.encode_byte(PACKET_BIT_LONG);
encoder.encode(&[0; 4]); // Zero version == VN.
encoder.encode_vec(1, dcid);
encoder.encode_vec(1, scid);
for v in versions {
encoder.encode_uint(4, *v);
}
encoder.into()
}
#[test]
fn version_negotiation_current_version() {
let mut client = default_client();
// Start the handshake.
let initial_pkt = client
.process(None, now())
.dgram()
.expect("a datagram")
.to_vec();
let vn = create_vn(
&initial_pkt,
&[0x1a1_a1a1a, QuicVersion::default().as_u32()],
);
assert_eq!(
client.process(Some(Datagram::new(loopback(), loopback(), vn,)), now(),),
Output::Callback(Duration::from_millis(120))
);
assert_eq!(*client.state(), State::WaitInitial);
assert_eq!(1, client.stats().dropped_rx);
}
#[test]
fn version_negotiation_only_reserved() {
let mut client = default_client();
// Start the handshake.
let initial_pkt = client
.process(None, now())
.dgram()
.expect("a datagram")
.to_vec();
let vn = create_vn(&initial_pkt, &[0x1a1a_1a1a, 0x2a2a_2a2a]);
assert_eq!(
client.process(Some(Datagram::new(loopback(), loopback(), vn,)), now(),),
Output::None
);
match client.state() {
State::Closed(err) => {
assert_eq!(*err, ConnectionError::Transport(Error::VersionNegotiation))
}
_ => panic!("Invalid client state"),
}
}
#[test]
fn version_negotiation_corrupted() {
let mut client = default_client();
// Start the handshake.
let initial_pkt = client
.process(None, now())
.dgram()
.expect("a datagram")
.to_vec();
let vn = create_vn(&initial_pkt, &[0x1a1a_1a1a, 0x2a2a_2a2a]);
assert_eq!(
client.process(
Some(Datagram::new(loopback(), loopback(), &vn[..vn.len() - 1])),
now(),
),
Output::Callback(Duration::from_millis(120))
);
assert_eq!(*client.state(), State::WaitInitial);
assert_eq!(1, client.stats().dropped_rx);
}
#[test]
fn version_negotiation_empty() {
let mut client = default_client();
// Start the handshake.
let initial_pkt = client
.process(None, now())
.dgram()
.expect("a datagram")
.to_vec();
let vn = create_vn(&initial_pkt, &[]);
assert_eq!(
client.process(Some(Datagram::new(loopback(), loopback(), vn)), now(),),
Output::Callback(Duration::from_millis(120))
);
assert_eq!(*client.state(), State::WaitInitial);
assert_eq!(1, client.stats().dropped_rx);
}
#[test]
fn version_negotiation_not_supported() {
let mut client = default_client();
// Start the handshake.
let initial_pkt = client
.process(None, now())
.dgram()
.expect("a datagram")
.to_vec();
let vn = create_vn(&initial_pkt, &[0x1a1a_1a1a, 0x2a2a_2a2a, 0xff00_0001]);
assert_eq!(
client.process(Some(Datagram::new(loopback(), loopback(), vn)), now(),),
Output::None
);
match client.state() {
State::Closed(err) => {
assert_eq!(*err, ConnectionError::Transport(Error::VersionNegotiation))
}
_ => panic!("Invalid client state"),
}
}
#[test]
fn stream_data_blocked_generates_max_stream_data() {
let mut client = default_client();
let mut server = default_server();
connect(&mut client, &mut server);
let now = now();
// Try to say we're blocked beyond the initial data window
server
.flow_mgr
.borrow_mut()
.stream_data_blocked(3.into(), RX_STREAM_DATA_WINDOW * 4);
let out = server.process(None, now);
assert!(out.as_dgram_ref().is_some());
let frames = client.test_process_input(out.dgram().unwrap(), now);
assert!(frames
.iter()
.any(|(f, _)| matches!(f, Frame::StreamDataBlocked { .. })));
let out = client.process_output(now);
assert!(out.as_dgram_ref().is_some());
let frames = server.test_process_input(out.dgram().unwrap(), now);
// Client should have sent a MaxStreamData frame with just the initial
// window value.
assert!(frames.iter().any(
|(f, _)| matches!(f, Frame::MaxStreamData { maximum_stream_data, .. }
if *maximum_stream_data == RX_STREAM_DATA_WINDOW)
));
}
} }

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

@ -16,8 +16,9 @@ use neqo_crypto::aead::Aead;
use neqo_crypto::hp::HpKey; use neqo_crypto::hp::HpKey;
use neqo_crypto::{ use neqo_crypto::{
hkdf, Agent, AntiReplay, Cipher, Epoch, HandshakeState, Record, RecordList, SymKey, hkdf, Agent, AntiReplay, Cipher, Epoch, HandshakeState, Record, RecordList, SymKey,
TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CT_HANDSHAKE, TLS_EPOCH_APPLICATION_DATA, TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_CT_HANDSHAKE,
TLS_EPOCH_HANDSHAKE, TLS_EPOCH_INITIAL, TLS_EPOCH_ZERO_RTT, TLS_VERSION_1_3, TLS_EPOCH_APPLICATION_DATA, TLS_EPOCH_HANDSHAKE, TLS_EPOCH_INITIAL, TLS_EPOCH_ZERO_RTT,
TLS_VERSION_1_3,
}; };
use crate::frame::Frame; use crate::frame::Frame;
@ -46,7 +47,11 @@ impl Crypto {
anti_replay: Option<&AntiReplay>, anti_replay: Option<&AntiReplay>,
) -> Res<Self> { ) -> Res<Self> {
agent.set_version_range(TLS_VERSION_1_3, TLS_VERSION_1_3)?; agent.set_version_range(TLS_VERSION_1_3, TLS_VERSION_1_3)?;
agent.enable_ciphers(&[TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384])?; agent.set_ciphers(&[
TLS_AES_128_GCM_SHA256,
TLS_AES_256_GCM_SHA384,
TLS_CHACHA20_POLY1305_SHA256,
])?;
agent.set_alpn(protocols)?; agent.set_alpn(protocols)?;
agent.disable_end_of_early_data()?; agent.disable_end_of_early_data()?;
match &mut agent { match &mut agent {
@ -532,7 +537,7 @@ impl CryptoDxAppData {
pub fn next(&self) -> Res<Self> { pub fn next(&self) -> Res<Self> {
if self.dx.epoch == usize::max_value() { if self.dx.epoch == usize::max_value() {
// Guard against too many key updates. // Guard against too many key updates.
return Err(Error::KeysNotFound); return Err(Error::KeysExhausted);
} }
let next_secret = Self::update_secret(self.cipher, &self.next_secret)?; let next_secret = Self::update_secret(self.cipher, &self.next_secret)?;
Ok(Self { Ok(Self {
@ -857,6 +862,51 @@ impl CryptoStates {
read_update_time: None, read_update_time: None,
} }
} }
#[cfg(test)]
pub(crate) fn test_chacha() -> Self {
const SECRET: &[u8] = &[
0x9a, 0xc3, 0x12, 0xa7, 0xf8, 0x77, 0x46, 0x8e, 0xbe, 0x69, 0x42, 0x27, 0x48, 0xad,
0x00, 0xa1, 0x54, 0x43, 0xf1, 0x82, 0x03, 0xa0, 0x7d, 0x60, 0x60, 0xf6, 0x88, 0xf3,
0x0f, 0x21, 0x63, 0x2b,
];
let secret =
hkdf::import_key(TLS_VERSION_1_3, TLS_CHACHA20_POLY1305_SHA256, SECRET).unwrap();
let app_read = || CryptoDxAppData {
dx: CryptoDxState {
direction: CryptoDxDirection::Read,
epoch: 0,
aead: Aead::new(
TLS_VERSION_1_3,
TLS_CHACHA20_POLY1305_SHA256,
&secret,
"quic ",
)
.unwrap(),
hpkey: HpKey::extract(
TLS_VERSION_1_3,
TLS_CHACHA20_POLY1305_SHA256,
&secret,
"quic hp",
)
.unwrap(),
used_pn: 0..645_971_972,
min_pn: 0,
},
cipher: TLS_CHACHA20_POLY1305_SHA256,
next_secret: secret.clone(),
};
Self {
initial: None,
handshake: None,
zero_rtt: None,
cipher: TLS_CHACHA20_POLY1305_SHA256,
app_write: None,
app_read: Some(app_read()),
app_read_next: Some(app_read()),
read_update_time: None,
}
}
} }
impl std::fmt::Display for CryptoStates { impl std::fmt::Display for CryptoStates {

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

@ -22,12 +22,9 @@ pub enum ConnectionEvent {
/// Cert authentication needed /// Cert authentication needed
AuthenticationNeeded, AuthenticationNeeded,
/// A new uni (read) or bidi stream has been opened by the peer. /// A new uni (read) or bidi stream has been opened by the peer.
NewStream { NewStream { stream_id: StreamId },
stream_id: u64,
stream_type: StreamType,
},
/// Space available in the buffer for an application write to succeed. /// Space available in the buffer for an application write to succeed.
SendStreamWritable { stream_id: u64 }, SendStreamWritable { stream_id: StreamId },
/// New bytes available for reading. /// New bytes available for reading.
RecvStreamReadable { stream_id: u64 }, RecvStreamReadable { stream_id: u64 },
/// Peer reset the stream. /// Peer reset the stream.
@ -58,10 +55,7 @@ impl ConnectionEvents {
} }
pub fn new_stream(&self, stream_id: StreamId) { pub fn new_stream(&self, stream_id: StreamId) {
self.insert(ConnectionEvent::NewStream { self.insert(ConnectionEvent::NewStream { stream_id });
stream_id: stream_id.as_u64(),
stream_type: stream_id.stream_type(),
});
} }
pub fn recv_stream_readable(&self, stream_id: StreamId) { pub fn recv_stream_readable(&self, stream_id: StreamId) {
@ -81,9 +75,7 @@ impl ConnectionEvents {
} }
pub fn send_stream_writable(&self, stream_id: StreamId) { pub fn send_stream_writable(&self, stream_id: StreamId) {
self.insert(ConnectionEvent::SendStreamWritable { self.insert(ConnectionEvent::SendStreamWritable { stream_id });
stream_id: stream_id.as_u64(),
});
} }
pub fn send_stream_stop_sending(&self, stream_id: StreamId, app_error: AppError) { pub fn send_stream_stop_sending(&self, stream_id: StreamId, app_error: AppError) {
@ -97,7 +89,7 @@ impl ConnectionEvents {
} }
pub fn send_stream_complete(&self, stream_id: StreamId) { pub fn send_stream_complete(&self, stream_id: StreamId) {
self.remove(|evt| matches!(evt, ConnectionEvent::SendStreamWritable { stream_id: x } if *x == stream_id.as_u64())); self.remove(|evt| matches!(evt, ConnectionEvent::SendStreamWritable { stream_id: x } if *x == stream_id));
self.remove(|evt| matches!(evt, ConnectionEvent::SendStreamStopSending { stream_id: x, .. } if *x == stream_id.as_u64())); self.remove(|evt| matches!(evt, ConnectionEvent::SendStreamStopSending { stream_id: x, .. } if *x == stream_id.as_u64()));

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

@ -265,7 +265,9 @@ impl FlowMgr {
} => self.stop_sending(stream_id, application_error_code), } => self.stop_sending(stream_id, application_error_code),
Frame::MaxStreamData { stream_id, .. } => { Frame::MaxStreamData { stream_id, .. } => {
if let Some(rs) = recv_streams.get_mut(&stream_id) { if let Some(rs) = recv_streams.get_mut(&stream_id) {
rs.flowc_lost() if let Some(msd) = rs.max_stream_data() {
self.max_stream_data(stream_id, msd)
}
} }
} }
Frame::PathResponse { .. } => qinfo!("Path Response lost, not re-sent"), Frame::PathResponse { .. } => qinfo!("Path Response lost, not re-sent"),

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

@ -76,10 +76,13 @@ pub enum Error {
InvalidResumptionToken, InvalidResumptionToken,
InvalidRetry, InvalidRetry,
InvalidStreamId, InvalidStreamId,
// Packet protection keys aren't available yet, or they have been discarded. /// Packet protection keys are exhausted.
/// Also used when too many key updates have happened.
KeysExhausted,
/// Packet protection keys aren't available yet, or they have been discarded.
KeysNotFound, KeysNotFound,
// An attempt to update keys can be blocked if /// An attempt to update keys can be blocked if
// a packet sent with the current keys hasn't been acknowledged. /// a packet sent with the current keys hasn't been acknowledged.
KeyUpdateBlocked, KeyUpdateBlocked,
NoMoreData, NoMoreData,
NotConnected, NotConnected,

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

@ -24,7 +24,7 @@ const PACKET_TYPE_0RTT: u8 = 0x01;
const PACKET_TYPE_HANDSHAKE: u8 = 0x2; const PACKET_TYPE_HANDSHAKE: u8 = 0x2;
const PACKET_TYPE_RETRY: u8 = 0x03; const PACKET_TYPE_RETRY: u8 = 0x03;
const PACKET_BIT_LONG: u8 = 0x80; pub const PACKET_BIT_LONG: u8 = 0x80;
const PACKET_BIT_SHORT: u8 = 0x00; const PACKET_BIT_SHORT: u8 = 0x00;
const PACKET_BIT_KEY_PHASE: u8 = 0x04; const PACKET_BIT_KEY_PHASE: u8 = 0x04;
const PACKET_BIT_FIXED_QUIC: u8 = 0x40; const PACKET_BIT_FIXED_QUIC: u8 = 0x40;
@ -634,12 +634,23 @@ impl<'a> PublicPacket<'a> {
data: d, data: d,
}) })
} else { } else {
Err(Error::DecryptError) Err(Error::KeysNotFound)
} }
} else { } else {
Err(Error::DecryptError) Err(Error::KeysNotFound)
} }
} }
pub fn supported_versions(&self) -> Res<Vec<Version>> {
assert_eq!(self.packet_type, PacketType::VersionNegotiation);
let mut decoder = Decoder::new(&self.data[self.header_len..]);
let mut res = Vec::new();
while decoder.remaining() > 0 {
let version = Version::try_from(Self::opt(decoder.decode_uint(4))?)?;
res.push(version);
}
Ok(res)
}
} }
impl fmt::Debug for PublicPacket<'_> { impl fmt::Debug for PublicPacket<'_> {
@ -1081,4 +1092,22 @@ mod tests {
0x4000_0000_0000_0002 0x4000_0000_0000_0002
); );
} }
#[test]
fn chacha20_sample() {
const PACKET: &[u8] = &[
0x4c, 0xfe, 0x41, 0x89, 0x65, 0x5e, 0x5c, 0xd5, 0x5c, 0x41, 0xf6, 0x90, 0x80, 0x57,
0x5d, 0x79, 0x99, 0xc2, 0x5a, 0x5b, 0xfb,
];
fixture_init();
let (packet, slice) =
PublicPacket::decode(PACKET, &FixedConnectionIdManager::new(0)).unwrap();
assert!(slice.is_empty());
let decrypted = packet
.decrypt(&mut CryptoStates::test_chacha(), now())
.unwrap();
assert_eq!(decrypted.packet_type(), PacketType::Short);
assert_eq!(decrypted.pn(), 654_360_564);
assert_eq!(&decrypted[..], &[0x01]);
}
} }

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

@ -607,6 +607,7 @@ impl LossRecovery {
/// When receiving a retry, get all the sent packets so that they can be flushed. /// When receiving a retry, get all the sent packets so that they can be flushed.
/// We also need to pretend that they never happened for the purposes of congestion control. /// We also need to pretend that they never happened for the purposes of congestion control.
pub fn retry(&mut self) -> Vec<SentPacket> { pub fn retry(&mut self) -> Vec<SentPacket> {
self.pto_state = None;
let cc = &mut self.cc; let cc = &mut self.cc;
self.spaces self.spaces
.iter_mut() .iter_mut()
@ -816,8 +817,7 @@ mod tests {
let est = |sp| { let est = |sp| {
lr.spaces lr.spaces
.get(sp) .get(sp)
.map(LossRecoverySpace::loss_recovery_timer_start) .and_then(LossRecoverySpace::loss_recovery_timer_start)
.flatten()
}; };
println!( println!(
"loss times: {:?} {:?} {:?}", "loss times: {:?} {:?} {:?}",

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

@ -330,6 +330,15 @@ impl RecvStreamState {
_ => None, _ => None,
} }
} }
fn max_stream_data(&self) -> Option<u64> {
match self {
Self::Recv {
max_stream_data, ..
} => Some(*max_stream_data),
_ => None,
}
}
} }
/// Implement a QUIC receive stream. /// Implement a QUIC receive stream.
@ -483,16 +492,8 @@ impl RecvStream {
} }
} }
/// MAX_STREAM_DATA was lost. Send it again if still blocked. pub fn max_stream_data(&self) -> Option<u64> {
pub fn flowc_lost(&self) { self.state.max_stream_data()
if let RecvStreamState::Recv {
max_stream_data, ..
} = &self.state
{
self.flow_mgr
.borrow_mut()
.max_stream_data(self.stream_id, *max_stream_data)
}
} }
pub fn is_terminal(&self) -> bool { pub fn is_terminal(&self) -> bool {
@ -836,7 +837,7 @@ mod tests {
s.maybe_send_flowc_update(); s.maybe_send_flowc_update();
assert!(matches!(s.flow_mgr.borrow().peek(), None)); assert!(matches!(s.flow_mgr.borrow().peek(), None));
// But if lost, another frame is generated // But if lost, another frame is generated
s.flowc_lost(); flow_mgr.borrow_mut().max_stream_data(67.into(), 100);
assert!(matches!(s.flow_mgr.borrow_mut().next().unwrap(), Frame::MaxStreamData{..})); assert!(matches!(s.flow_mgr.borrow_mut().next().unwrap(), Frame::MaxStreamData{..}));
} }
} }

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

@ -47,8 +47,12 @@ impl StreamId {
Self(id) Self(id)
} }
pub fn as_u64(self) -> u64 {
self.0
}
pub fn is_bidi(self) -> bool { pub fn is_bidi(self) -> bool {
self.0 & 0x02 == 0 self.as_u64() & 0x02 == 0
} }
pub fn is_uni(self) -> bool { pub fn is_uni(self) -> bool {
@ -64,7 +68,7 @@ impl StreamId {
} }
pub fn is_client_initiated(self) -> bool { pub fn is_client_initiated(self) -> bool {
self.0 & 0x01 == 0 self.as_u64() & 0x01 == 0
} }
pub fn is_server_initiated(self) -> bool { pub fn is_server_initiated(self) -> bool {
@ -98,10 +102,6 @@ impl StreamId {
pub fn is_recv_only(self, my_role: Role) -> bool { pub fn is_recv_only(self, my_role: Role) -> bool {
self.is_uni() && self.is_remote_initiated(my_role) self.is_uni() && self.is_remote_initiated(my_role)
} }
pub fn as_u64(self) -> u64 {
self.0
}
} }
impl From<u64> for StreamId { impl From<u64> for StreamId {
@ -110,6 +110,18 @@ impl From<u64> for StreamId {
} }
} }
impl PartialEq<u64> for StreamId {
fn eq(&self, other: &u64) -> bool {
self.as_u64() == *other
}
}
impl ::std::fmt::Display for StreamId {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "{}", self.as_u64())
}
}
#[derive(Debug, Eq, PartialEq, Clone, Copy, Ord, PartialOrd, Hash)] #[derive(Debug, Eq, PartialEq, Clone, Copy, Ord, PartialOrd, Hash)]
pub struct StreamIndex(u64); pub struct StreamIndex(u64);

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

@ -411,6 +411,37 @@ fn retry_bad_token() {
assert!(dgram.is_none()); assert!(dgram.is_none());
} }
// This is really a client test, but we need a server with Retry to test it.
// In this test, the client sends Initial on PTO. The Retry should cause
// all loss recovery timers to be reset, but we had a bug where the PTO timer
// was not properly reset. This tests that the client generates a new Initial
// in response to receiving a Retry, even after it sends the Initial on PTO.
#[test]
fn retry_after_pto() {
let mut client = default_client();
let mut server = default_server();
server.set_retry_required(true);
let mut now = now();
let ci = client.process(None, now).dgram();
assert!(ci.is_some()); // sit on this for a bit.RefCell
// Let PTO fire on the client and then let it exhaust its PTO packets.
now += Duration::from_secs(1);
let pto1 = client.process(None, now).dgram();
assert!(pto1.unwrap().len() >= 1200);
let pto2 = client.process(None, now).dgram();
assert!(pto2.unwrap().len() >= 1200);
let cb = client.process(None, now).callback();
assert_ne!(cb, Duration::new(0, 0));
let retry = server.process(ci, now).dgram();
assertions::assert_retry(&retry.as_ref().unwrap());
let ci2 = client.process(retry, now).dgram();
assert!(ci2.unwrap().len() >= 1200);
}
// Generate an AEAD and header protection object for a client Initial. // Generate an AEAD and header protection object for a client Initial.
fn client_initial_aead_and_hp(dcid: &[u8]) -> (Aead, HpKey) { fn client_initial_aead_and_hp(dcid: &[u8]) -> (Aead, HpKey) {
const INITIAL_SALT: &[u8] = &[ const INITIAL_SALT: &[u8] = &[
@ -717,14 +748,10 @@ fn version_negotiation() {
} }
assert!(found, "valid version not found"); assert!(found, "valid version not found");
// Client ignores VN packet that contain negotiated version.
let res = client.process(Some(vn), now()); let res = client.process(Some(vn), now());
assert_eq!(res, Output::None); assert!(res.callback() > Duration::new(0, 120));
match client.state() { assert_eq!(client.state(), &State::WaitInitial);
State::Closed(err) => {
assert_eq!(*err, ConnectionError::Transport(Error::VersionNegotiation))
}
_ => panic!("Invalid client state"),
}
} }
#[test] #[test]