Bug 1646106 - Update to Neqo 0.4.3 r=dragana,necko-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D79893
This commit is contained in:
Andy Grover 2020-06-17 07:09:52 +00:00
parent 758b23093d
commit caf191f33d
47 changed files with 832 additions and 506 deletions

View File

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

24
Cargo.lock generated
View File

@ -3046,8 +3046,8 @@ checksum = "a2983372caf4480544083767bf2d27defafe32af49ab4df3a0b7fc90793a3664"
[[package]]
name = "neqo-common"
version = "0.4.1"
source = "git+https://github.com/mozilla/neqo?tag=v0.4.1#0aeafc8cfd0b7a3554170419b38c97948b0fb108"
version = "0.4.3"
source = "git+https://github.com/mozilla/neqo?tag=v0.4.3#7406cc1798ed5274cd8540b93bb3443ff4cc26e5"
dependencies = [
"chrono",
"env_logger",
@ -3059,8 +3059,8 @@ dependencies = [
[[package]]
name = "neqo-crypto"
version = "0.4.1"
source = "git+https://github.com/mozilla/neqo?tag=v0.4.1#0aeafc8cfd0b7a3554170419b38c97948b0fb108"
version = "0.4.3"
source = "git+https://github.com/mozilla/neqo?tag=v0.4.3#7406cc1798ed5274cd8540b93bb3443ff4cc26e5"
dependencies = [
"bindgen",
"log",
@ -3072,8 +3072,8 @@ dependencies = [
[[package]]
name = "neqo-http3"
version = "0.4.1"
source = "git+https://github.com/mozilla/neqo?tag=v0.4.1#0aeafc8cfd0b7a3554170419b38c97948b0fb108"
version = "0.4.3"
source = "git+https://github.com/mozilla/neqo?tag=v0.4.3#7406cc1798ed5274cd8540b93bb3443ff4cc26e5"
dependencies = [
"log",
"neqo-common",
@ -3086,8 +3086,8 @@ dependencies = [
[[package]]
name = "neqo-qpack"
version = "0.4.1"
source = "git+https://github.com/mozilla/neqo?tag=v0.4.1#0aeafc8cfd0b7a3554170419b38c97948b0fb108"
version = "0.4.3"
source = "git+https://github.com/mozilla/neqo?tag=v0.4.3#7406cc1798ed5274cd8540b93bb3443ff4cc26e5"
dependencies = [
"lazy_static",
"log",
@ -3101,8 +3101,8 @@ dependencies = [
[[package]]
name = "neqo-transport"
version = "0.4.1"
source = "git+https://github.com/mozilla/neqo?tag=v0.4.1#0aeafc8cfd0b7a3554170419b38c97948b0fb108"
version = "0.4.3"
source = "git+https://github.com/mozilla/neqo?tag=v0.4.3#7406cc1798ed5274cd8540b93bb3443ff4cc26e5"
dependencies = [
"lazy_static",
"log",
@ -3742,9 +3742,9 @@ dependencies = [
[[package]]
name = "qlog"
version = "0.2.0"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a1fdb4ef259b1b970958af7fbdedc4f107c872a9f856e01f3427c0bea44095f"
checksum = "4767943b701b674b8d5e8535d3242b6cbd8249bf5d72eee0d45f376a2b680ad4"
dependencies = [
"serde",
"serde_derive",

View File

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

View File

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

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"f301a07481862634459c8c1c07c4ffa71d6c41835d045814d19343560ee28beb","src/codec.rs":"c33b458cf1631073587edf6b6bd1baafecc7fe9e18d3eb5c3ddc6aaa00bd70c5","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":"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}

View File

@ -1,6 +1,6 @@
[package]
name = "neqo-common"
version = "0.4.1"
version = "0.4.3"
authors = ["Bobby Holley <bobbyholley@gmail.com>"]
edition = "2018"
license = "MIT/Apache-2.0"
@ -10,7 +10,7 @@ num-traits = "0.2"
log = {version = "0.4.0", default-features = false}
env_logger = "0.6.1"
lazy_static = "1.3.0"
qlog = "0.2.0"
qlog = "0.3.0"
chrono = "0.4.10"
[features]

View File

@ -684,7 +684,7 @@ mod tests {
enc_inner.encode(&[0xa5; 65]);
});
let mut v: Vec<u8> = enc.into();
v.split_off(3);
let _ = v.split_off(3);
assert_eq!(v, vec![0x40, 0x41, 0xa5]);
}

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"14863c8f22576992eaaad97bc9ddbf842f6ba625e48622ce22d9ec22d43b21b4","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":"d3fba31bbdc6b58ec6a593be580d00021e95a7e132dba61d381ebc10635b0844","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":"2a7eb6bc2992679e5c04cf5561a4ce886ecbf549454ed927b32abeb09019632d","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":"13231bafe24e3c24b3ca582805929cc6dac017180cff7400e062894f22df5735","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":"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}

View File

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

View File

@ -73,7 +73,7 @@ fn get_alpn(fd: *mut ssl::PRFileDesc, pre: bool) -> Res<Option<String>> {
(true, ssl::SSLNextProtoState::SSL_NEXT_PROTO_EARLY_VALUE)
| (false, ssl::SSLNextProtoState::SSL_NEXT_PROTO_NEGOTIATED)
| (false, ssl::SSLNextProtoState::SSL_NEXT_PROTO_SELECTED) => {
chosen.truncate(chosen_len as usize);
chosen.truncate(usize::try_from(chosen_len)?);
Some(match String::from_utf8(chosen) {
Ok(a) => a,
_ => return Err(Error::InternalError),
@ -164,8 +164,8 @@ impl SecretAgentInfo {
})?;
let info = unsafe { info.assume_init() };
Ok(Self {
version: info.protocolVersion as Version,
cipher: info.cipherSuite as Cipher,
version: info.protocolVersion,
cipher: info.cipherSuite,
group: Group::try_from(info.keaGroup)?,
resumed: info.resumed != 0,
early_data: info.earlyDataAccepted != 0,
@ -326,7 +326,7 @@ impl SecretAgent {
self.now.bind(self.fd)?;
self.configure()?;
secstatus_to_res(unsafe { ssl::SSL_ResetHandshake(self.fd, is_server as ssl::PRBool) })
secstatus_to_res(unsafe { ssl::SSL_ResetHandshake(self.fd, ssl::PRBool::from(is_server)) })
}
/// Default configuration.
@ -718,8 +718,9 @@ impl Client {
) -> ssl::SECStatus {
let resumption_ptr = arg as *mut Option<Vec<u8>>;
let resumption = resumption_ptr.as_mut().unwrap();
let mut v = Vec::with_capacity(len as usize);
v.extend_from_slice(std::slice::from_raw_parts(token, len as usize));
let len = usize::try_from(len).unwrap();
let mut v = Vec::with_capacity(len);
v.extend_from_slice(std::slice::from_raw_parts(token, len));
qinfo!(
[format!("{:p}", fd)],
"Got resumption token {}",
@ -869,7 +870,7 @@ impl Server {
let token = if client_token.is_null() {
&[]
} else {
std::slice::from_raw_parts(client_token, client_token_len as usize)
std::slice::from_raw_parts(client_token, usize::try_from(client_token_len).unwrap())
};
match check_state.checker.check(token) {
ZeroRttCheckResult::Accept => ssl::SSLHelloRetryRequestAction::ssl_hello_retry_accept,
@ -882,7 +883,7 @@ impl Server {
assert!(tok.len() <= usize::try_from(retry_token_max).unwrap());
let slc = std::slice::from_raw_parts_mut(retry_token, tok.len());
slc.copy_from_slice(&tok);
*retry_token_len = c_uint::try_from(tok.len()).expect("token was way too big");
*retry_token_len = c_uint::try_from(tok.len()).unwrap();
ssl::SSLHelloRetryRequestAction::ssl_hello_retry_request
}
}
@ -967,8 +968,8 @@ impl Deref for Agent {
impl DerefMut for Agent {
fn deref_mut(&mut self) -> &mut SecretAgent {
match self {
Self::Client(c) => c.deref_mut(),
Self::Server(s) => s.deref_mut(),
Self::Client(c) => &mut *c,
Self::Server(s) => &mut *s,
}
}
}

View File

@ -16,7 +16,6 @@ use crate::ssl::{
use std::cell::RefCell;
use std::convert::TryFrom;
use std::ops::DerefMut;
use std::os::raw::{c_uint, c_void};
use std::pin::Pin;
use std::rc::Rc;
@ -72,7 +71,7 @@ impl ExtensionTracker {
{
let handler_ptr = arg as *mut BoxedExtensionHandler;
let rc = handler_ptr.as_mut().unwrap();
f(rc.borrow_mut().deref_mut())
f(&mut *rc.borrow_mut())
}
#[allow(clippy::cast_possible_truncation)]

View File

@ -244,10 +244,9 @@ mod test {
// We allow replace_consts here because
// std::u64::max_value() isn't available
// in all of our targets
#[allow(clippy::replace_consts)]
fn overflow_interval() {
init();
let interval = Interval::from(Duration::from_micros(std::u64::MAX));
let interval = Interval::from(Duration::from_micros(u64::max_value()));
let res: Res<PRTime> = interval.try_into();
assert!(res.is_err());
}

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"d89c7eef0ce63197af3c1a0cb1c0bba52b04b017358926ffcf9062106fc556f0","src/client_events.rs":"8c19986b7372b36d1265d4a848b07b5c334511cbdfc02f313c54e551523c08f5","src/connection.rs":"cebdb535151ec5598161091c6b709c38852aa32f32855cee8f2c6129a2bcb5a0","src/connection_client.rs":"017b4072ecb6604d223ef910f2dfbaa4caf84e439351bf4feed2a8a7a4869bf6","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":"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}

View File

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

View File

@ -604,8 +604,7 @@ mod tests {
use neqo_crypto::AntiReplay;
use neqo_qpack::encoder::QPackEncoder;
use neqo_transport::{
CloseError, ConnectionEvent, ConnectionIdManager, FixedConnectionIdManager, QuicVersion,
State,
CloseError, ConnectionEvent, FixedConnectionIdManager, QuicVersion, State,
};
use test_fixture::{
default_server, fixture_init, loopback, now, DEFAULT_ALPN, DEFAULT_SERVER_NAME,
@ -2980,16 +2979,12 @@ mod tests {
let ar = AntiReplay::new(now(), test_fixture::ANTI_REPLAY_WINDOW, 1, 3)
.expect("setup anti-replay");
let mut cid_mgr = FixedConnectionIdManager::new(10);
let initial_source_cid = cid_mgr.generate_cid();
let mut server = Connection::new_server(
test_fixture::DEFAULT_KEYS,
test_fixture::DEFAULT_ALPN,
&ar,
Rc::new(RefCell::new(cid_mgr)),
Rc::new(RefCell::new(FixedConnectionIdManager::new(10))),
QuicVersion::default(),
initial_source_cid,
)
.unwrap();

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"fd88d05a2e011d4b5ca1145921572ed459695fa9d999239c2bdd2a5f3675fcc2","src/decoder.rs":"468b51d03aee3363d7998bb9e8a70d998a8279eb0089702a9fe4423f8c577f1e","src/decoder_instructions.rs":"a8e04dff5fc4c658322a10daadab947dc2e41932c00c3f8d387671a86d0516af","src/encoder.rs":"03cc95df1c57972cd8a19ffb77920f8daac52b4e220eac6182d05671d04e9d58","src/encoder_instructions.rs":"4fab8d6a86482139275f81fd30f9f8c462d6312faf0cdb9143fed1a1a514623f","src/header_block.rs":"3be489222ba59d1c9022d9bf813330a5d68f994fd3fe92fe6934f796cbab42f2","src/huffman.rs":"68fa0bada0c35d20f793980596accdcc548970214841f71789290fc334e51fc1","src/huffman_decode_helper.rs":"089ab15eda49eae035c8ac95f780ec495713ce5918dd1e5a5e4a6206e3c65e66","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"4413c57c8707c5fe47cdc4f40b6e2e9baa4f18fae9cecd895c11e509973ccc2a","src/prefix.rs":"8807126dbf4e7aff9afe164072c523b8fbfa0be5d4c57bb8291b510c8f0e8ca5","src/qlog.rs":"ee4eb799cadcd31e2569690ab1f7cbfb22179033ee7aec7ed217749eb0210fc9","src/qpack_send_buf.rs":"8c1b97d17220038c8e040edb5d5bfc39eb72ab50dfa325016e799740acc47558","src/reader.rs":"4bcea0de1d7dc09ec0cdff364d8f62da54bbbe1f6db55a495f943f31369b4074","src/static_table.rs":"fda9d5c6f38f94b0bf92d3afdf8432dce6e27e189736596e16727090c77b78ec","src/table.rs":"fc927a57c02a7556b0ea7152c713cfd84825b14343f809c7ed0cc2a2a011482f"},"package":null}
{"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}

View File

@ -1,6 +1,6 @@
[package]
name = "neqo-qpack"
version = "0.4.1"
version = "0.4.3"
authors = ["Dragana Damjanovic <dragana.damjano@gmail.com>"]
edition = "2018"
license = "MIT/Apache-2.0"
@ -12,7 +12,7 @@ neqo-crypto = { path = "./../neqo-crypto" }
log = {version = "0.4.0", default-features = false}
static_assertions = "1.1.0"
num-traits = "0.2"
qlog = "0.2.0"
qlog = "0.3.0"
lazy_static = "1.3.0"
[dev-dependencies]

View File

@ -188,7 +188,7 @@ impl HeaderEncoder {
impl Deref for HeaderEncoder {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.buf.deref()
&*self.buf
}
}

View File

@ -14,7 +14,7 @@ pub struct HuffmanDecoderNode {
}
lazy_static! {
pub static ref HUFFMAN_DECODE_ROOT: HuffmanDecoderNode = { make_huffman_tree(0, 0) };
pub static ref HUFFMAN_DECODE_ROOT: HuffmanDecoderNode = make_huffman_tree(0, 0);
}
fn make_huffman_tree(prefix: u32, len: u8) -> HuffmanDecoderNode {

View File

@ -128,7 +128,7 @@ impl QPData {
impl Deref for QPData {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.buf.deref()
&*self.buf
}
}

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"0607e358f61d26baaca0fec7926a772ade4be70c19a63ac20d3a4c144b22ebb4","TODO":"d759cb804b32fa9d96ea8d3574a3c4073da9fe6a0b02b708a0e22cce5a5b4a0f","src/cc.rs":"60d6de4376ba77801490a400a90078f93b5300aa24b16838b38a1bad805b784e","src/cid.rs":"208b1c847d23892287be59869e48a699ef027a84c45832e89df525df0c165d00","src/connection.rs":"d8a7923002494a768f04371a47cdddcf86b434df5700ca6f288c46f351c4c704","src/crypto.rs":"d00318e169b9634ab241e1dad0ec83ecfb93f9944b44891c850108e73f81ccd2","src/dump.rs":"d69ccb0e3b240823b886a791186afbac9f2e26d1f1f67a55dbf86f8cd3e6203e","src/events.rs":"deee6ef1112034582af770212bb70ed2cdcd2b1b8bb167c9118ef39bbf454451","src/flow_mgr.rs":"0b1c6e7587e411635723207ecface6c62d1243599dd017745c61eb94805b9886","src/frame.rs":"5f08b061f8fb7c2cc809116c5638c64d72646d914c688648b39345b775bb0246","src/lib.rs":"57f1018f31dd26241a2048bf9475fd883cf5904c227264aa7ede3cfcf9ecde91","src/pace.rs":"2cbc141722d75c87e99eb4e35da1479c47d55d8945f6c252c221543720c283ae","src/packet.rs":"8cf2913a333f1a994476fb1b15911ea894ecaa93c64ea22eb9b05ee4fe97aaf0","src/path.rs":"2dffade2760f76141708c57765a8b9e53ac2eac02662a02e2cb0e6eef5e97922","src/qlog.rs":"29d7348914766153eaf8395806a51c1f7a2af6322e982ba49500d3982198caeb","src/recovery.rs":"93e58b57438803709a6468345124655fc3ccc96d13d6514c4fb3e702a15b6f56","src/recv_stream.rs":"0650949aa8baae9e20c57eb2283490b782c41e6c67e9c093fc358145149e386f","src/send_stream.rs":"cd834ebd4386a776d897b1a5e52cad839784e389da8e2543ba1fb57649225cbd","src/server.rs":"09656965611aefa5ef277b113126fe20f958e91f331403d327dbdf2651468101","src/stats.rs":"a276bd9902939091578d3bcc95aa7dd0b32f5d29e528c12e7b93a0ab88474478","src/stream_id.rs":"db11def2ed81ef7c456c7c47827121c0a9ff54ac85228e6db6c790db8944febe","src/tparams.rs":"dae3d882156bb0842a946f7f03fa908536ee531d03e6725c1d845446a5d2e393","src/tracking.rs":"965d0bffc4c6171833a1e3ccb3d7cc31242a0e9f3c5ff77f925aa3a6594b167f","tests/conn_vectors.rs":"3de474009e75e0d283792daae4cb0eac7a1be00a4a6cfab6132c775fbefb1363","tests/connection.rs":"a93985c199a9ef987106f4a20b35ebf803cdbbb855c07b1362b403eed7101ef8","tests/server.rs":"9a8ba031ee547327e1423fa1441af840dd7cc0b4705c42a735dc7e12aef2e137"},"package":null}
{"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}

View File

@ -1,6 +1,6 @@
[package]
name = "neqo-transport"
version = "0.4.1"
version = "0.4.3"
authors = ["EKR <ekr@rtfm.com>", "Andy Grover <agrover@mozilla.com>"]
edition = "2018"
license = "MIT/Apache-2.0"
@ -11,7 +11,7 @@ neqo-common = { path = "../neqo-common" }
lazy_static = "1.3.0"
log = {version = "0.4.0", default-features = false}
smallvec = "1.0.0"
qlog = "0.2.0"
qlog = "0.3.0"
[dev-dependencies]
test-fixture = { path = "../test-fixture" }

View File

@ -472,24 +472,18 @@ impl Connection {
quic_version: QuicVersion,
) -> Res<Self> {
let dcid = ConnectionId::generate_initial();
let scid = cid_manager.borrow_mut().generate_cid();
let mut c = Self::new(
Role::Client,
Client::new(server_name)?.into(),
cid_manager,
None,
protocols,
Some(Path::new(
local_addr,
remote_addr,
scid.clone(),
dcid.clone(),
)),
None,
quic_version,
scid,
)?;
c.crypto.states.init(Role::Client, &dcid);
c.crypto.states.init(quic_version, Role::Client, &dcid);
c.remote_original_destination_cid = Some(dcid);
c.initialize_path(local_addr, remote_addr);
Ok(c)
}
@ -500,7 +494,6 @@ impl Connection {
anti_replay: &AntiReplay,
cid_manager: CidMgr,
quic_version: QuicVersion,
local_initial_source_cid: ConnectionId,
) -> Res<Self> {
Self::new(
Role::Server,
@ -510,7 +503,6 @@ impl Connection {
protocols,
None,
quic_version,
local_initial_source_cid,
)
}
@ -534,7 +526,6 @@ impl Connection {
tps.set_empty(tparams::DISABLE_MIGRATION);
}
#[allow(clippy::too_many_arguments)]
fn new(
role: Role,
agent: Agent,
@ -543,10 +534,10 @@ impl Connection {
protocols: &[impl AsRef<str>],
path: Option<Path>,
quic_version: QuicVersion,
local_initial_source_cid: ConnectionId,
) -> Res<Self> {
let tphandler = Rc::new(RefCell::new(TransportParametersHandler::default()));
Self::set_tp_defaults(&mut tphandler.borrow_mut().local);
let local_initial_source_cid = cid_manager.borrow_mut().generate_cid();
tphandler.borrow_mut().local.set_bytes(
tparams::INITIAL_SOURCE_CONNECTION_ID,
local_initial_source_cid.to_vec(),
@ -554,7 +545,7 @@ impl Connection {
let crypto = Crypto::new(agent, protocols, tphandler.clone(), anti_replay)?;
Ok(Self {
let mut c = Self {
role,
state: State::Init,
cid_manager,
@ -581,7 +572,9 @@ impl Connection {
stats: Stats::default(),
qlog: None,
quic_version,
})
};
c.stats.init(format!("{}", c));
Ok(c)
}
/// Get the local path.
@ -611,25 +604,39 @@ impl Connection {
}
}
/// Set the dest connection ID that was originally chosen by the client.
pub(crate) fn set_original_destination_cid(&mut self, odcid: ConnectionId) {
assert_eq!(self.role, Role::Server);
qtrace!([self], "Called set_original_destination_cid {}", odcid);
self.tps
.borrow_mut()
.local
.set_bytes(tparams::ORIGINAL_DESTINATION_CONNECTION_ID, odcid.to_vec());
self.remote_original_destination_cid = Some(odcid);
/// `odcid` is their original choice for our CID, which we get from the Retry token.
/// `remote_cid` is the value from the Source Connection ID field of
/// an incoming packet: what the peer wants us to use now.
/// `retry_cid` is what we asked them to use when we sent the Retry.
pub(crate) fn set_retry_cids(
&mut self,
odcid: ConnectionId,
remote_cid: ConnectionId,
retry_cid: ConnectionId,
) {
debug_assert_eq!(self.role, Role::Server);
qtrace!(
[self],
"Retry CIDs: odcid={} remote={} retry={}",
odcid,
remote_cid,
retry_cid
);
// We advertise "our" choices in transport parameters.
let local_tps = &mut self.tps.borrow_mut().local;
local_tps.set_bytes(tparams::ORIGINAL_DESTINATION_CONNECTION_ID, odcid.to_vec());
local_tps.set_bytes(tparams::RETRY_SOURCE_CONNECTION_ID, retry_cid.to_vec());
// ...and save their choices for later validation.
self.remote_initial_source_cid = Some(remote_cid);
}
/// Set the connection ID that was sent in retry.
pub(crate) fn set_retry_source_cid(&mut self, retry_source_cid: ConnectionId) {
assert_eq!(self.role, Role::Server);
qtrace!([self], "Called set_retry_source_cid {}", retry_source_cid);
self.tps.borrow_mut().local.set_bytes(
tparams::RETRY_SOURCE_CONNECTION_ID,
retry_source_cid.to_vec(),
);
fn retry_sent(&self) -> bool {
self.tps
.borrow()
.local
.get_bytes(tparams::RETRY_SOURCE_CONNECTION_ID)
.is_some()
}
/// Set ALPN preferences. Strings that appear earlier in the list are given
@ -960,18 +967,15 @@ impl Connection {
fn handle_retry(&mut self, packet: PublicPacket) -> Res<()> {
qinfo!([self], "received Retry");
if self.retry_info.is_some() {
qinfo!([self], "Dropping extra Retry");
self.stats.dropped_rx += 1;
self.stats.pkt_dropped("Extra Retry");
return Ok(());
}
if packet.token().is_empty() {
qinfo!([self], "Dropping Retry without a token");
self.stats.dropped_rx += 1;
self.stats.pkt_dropped("Retry without a token");
return Ok(());
}
if !packet.is_valid_retry(&self.remote_original_destination_cid.as_ref().unwrap()) {
qinfo!([self], "Dropping Retry with bad integrity tag");
self.stats.dropped_rx += 1;
self.stats.pkt_dropped("Retry with bad integrity tag");
return Ok(());
}
if let Some(p) = &mut self.path {
@ -997,9 +1001,9 @@ impl Connection {
let lost_packets = self.loss_recovery.retry();
self.handle_lost_packets(&lost_packets);
// Switching crypto state here might not happen eventually.
// https://github.com/quicwg/base-drafts/issues/2823
self.crypto.states.init(self.role, packet.scid());
self.crypto
.states
.init(self.quic_version, self.role, packet.scid());
Ok(())
}
@ -1062,9 +1066,9 @@ impl Connection {
match PublicPacket::decode(slc, self.cid_manager.borrow().as_decoder()) {
Ok((packet, remainder)) => (packet, remainder),
Err(e) => {
qdebug!([self], "Garbage packet: {}", e);
qinfo!([self], "Garbage packet: {}", e);
qtrace!([self], "Garbage packet contents: {}", hex(slc));
self.stats.dropped_rx += 1;
self.stats.pkt_dropped("Garbage packet");
break;
}
};
@ -1072,7 +1076,7 @@ impl Connection {
match (packet.packet_type(), &self.state, &self.role) {
(PacketType::Initial, State::Init, Role::Server) => {
if !packet.is_valid_initial() {
self.stats.dropped_rx += 1;
self.stats.pkt_dropped("Invalid Initial");
break;
}
qinfo!(
@ -1083,11 +1087,18 @@ impl Connection {
);
self.set_state(State::WaitInitial);
self.loss_recovery.start_pacer(now);
self.crypto.states.init(self.role, &packet.dcid());
self.crypto
.states
.init(self.quic_version, self.role, &packet.dcid());
self.remote_initial_source_cid = Some(ConnectionId::from(packet.scid()));
if self.remote_original_destination_cid.is_none() {
self.set_original_destination_cid(ConnectionId::from(packet.dcid()));
// We need to make sure that we set this transport parameter.
// This has to happen prior to processing the packet so that
// the TLS handshake has all it needs.
if !self.retry_sent() {
self.tps.borrow_mut().local.set_bytes(
tparams::ORIGINAL_DESTINATION_CONNECTION_ID,
packet.dcid().to_vec(),
)
}
}
(PacketType::VersionNegotiation, State::WaitInitial, Role::Client) => {
@ -1103,8 +1114,8 @@ impl Connection {
(PacketType::VersionNegotiation, ..)
| (PacketType::Retry, ..)
| (PacketType::OtherVersion, ..) => {
qwarn!("dropping {:?}", packet.packet_type());
self.stats.dropped_rx += 1;
self.stats
.pkt_dropped(format!("{:?}", packet.packet_type()));
break;
}
_ => {}
@ -1112,15 +1123,14 @@ impl Connection {
match self.state {
State::Init => {
qinfo!([self], "Received message while in Init state");
self.stats.dropped_rx += 1;
self.stats.pkt_dropped("Received while in Init state");
break;
}
State::WaitInitial => {}
State::Handshaking | State::Connected | State::Confirmed => {
if !self.is_valid_cid(packet.dcid()) {
qinfo!([self], "Ignoring packet with CID {:?}", packet.dcid());
self.stats.dropped_rx += 1;
self.stats
.pkt_dropped(format!("Ignoring packet with CID {:?}", packet.dcid()));
break;
}
if self.role == Role::Server && packet.packet_type() == PacketType::Handshake {
@ -1136,7 +1146,7 @@ impl Connection {
}
State::Draining { .. } | State::Closed(..) => {
// Do nothing.
self.stats.dropped_rx += 1;
self.stats.pkt_dropped(format!("State {:?}", self.state));
break;
}
}
@ -1161,7 +1171,10 @@ impl Connection {
qlog::packet_received(&mut self.qlog, &payload)?;
let res = self.process_packet(&payload, now);
if res.is_err() && self.path.is_none() {
self.initialize_path(&packet, &d);
// We need to make a path for sending an error message.
// But this connection is going to be closed.
self.remote_initial_source_cid = Some(ConnectionId::from(packet.scid()));
self.initialize_path(d.destination(), d.source());
}
frames.extend(res?);
if self.state == State::WaitInitial {
@ -1172,7 +1185,7 @@ impl Connection {
// Decryption failure, or not having keys is not fatal.
// 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.
self.stats.dropped_rx += 1;
self.stats.pkt_dropped("Decryption failure");
if slc.len() == d.len() {
self.check_stateless_reset(&d, now)?
}
@ -1240,21 +1253,31 @@ impl Connection {
Ok(frames)
}
fn initialize_path(&mut self, packet: &PublicPacket, d: &Datagram) {
fn initialize_path(&mut self, local_addr: SocketAddr, remote_addr: SocketAddr) {
debug_assert!(self.path.is_none());
let mut p = Path::from_datagram(&d, ConnectionId::from(packet.scid()));
p.add_local_cid(self.local_initial_source_cid.clone());
self.path = Some(p);
self.path = Some(Path::new(
local_addr,
remote_addr,
self.local_initial_source_cid.clone(),
// Ideally we know what the peer wants us to use for the remote CID.
// But we will use our own guess if necessary.
self.remote_initial_source_cid
.as_ref()
.or_else(|| self.remote_original_destination_cid.as_ref())
.unwrap()
.clone(),
));
}
fn start_handshake(&mut self, packet: &PublicPacket, d: &Datagram) -> Res<()> {
self.remote_initial_source_cid = Some(ConnectionId::from(packet.scid()));
if self.role == Role::Server {
assert_eq!(packet.packet_type(), PacketType::Initial);
// A server needs to accept the client's selected CID during the handshake.
self.valid_cids.push(ConnectionId::from(packet.dcid()));
// Install a path.
self.initialize_path(packet, d);
self.initialize_path(d.destination(), d.source());
self.zero_rtt_state = match self.crypto.enable_0rtt(self.role) {
Ok(true) => {
@ -1271,7 +1294,6 @@ impl Connection {
.find(|p| p.received_on(&d))
.expect("should have a path for sending Initial");
p.set_remote_cid(packet.scid());
self.remote_initial_source_cid = Some(ConnectionId::from(packet.scid()));
}
self.set_state(State::Handshaking);
Ok(())
@ -1513,7 +1535,7 @@ impl Connection {
let sent = SentPacket::new(
now,
ack_eliciting,
tokens,
Rc::new(tokens),
encoder.len() - header_start,
in_flight,
);
@ -1672,89 +1694,51 @@ impl Connection {
let remote_tps = tph.remote.as_ref().unwrap();
let tp = remote_tps.get_bytes(tparams::INITIAL_SOURCE_CONNECTION_ID);
match tp {
None => {
qwarn!(
"{} ISCID test failed: ISCID not found in tparams",
self.role
);
return Err(Error::ProtocolViolation);
}
Some(tp) => {
if self
.remote_initial_source_cid
.as_ref()
.unwrap()
.as_cid_ref()
!= ConnectionIdRef::from(tp)
{
qwarn!(
"{} ISCID test failed: self cid {:?} != tp cid {}",
self.role,
self.remote_initial_source_cid,
hex(&tp)
);
return Err(Error::ProtocolViolation);
}
}
if self
.remote_initial_source_cid
.as_ref()
.map(ConnectionId::as_cid_ref)
!= tp.map(ConnectionIdRef::from)
{
qwarn!(
"{} ISCID test failed: self cid {:?} != tp cid {:?}",
self.role,
self.remote_initial_source_cid,
tp.map(hex),
);
return Err(Error::ProtocolViolation);
}
if self.role == Role::Client {
let tp = remote_tps.get_bytes(tparams::ORIGINAL_DESTINATION_CONNECTION_ID);
match tp {
None => {
qwarn!(
"{} ODCID test failed: ODCID not found in tparams",
self.role
);
return Err(Error::ProtocolViolation);
}
Some(tp) => {
if self
.remote_original_destination_cid
.as_ref()
.map(ConnectionId::as_cid_ref)
!= Some(ConnectionIdRef::from(tp))
{
qwarn!(
"{} ODCID test failed: self cid {:?} != tp cid {}",
self.role,
self.remote_original_destination_cid,
hex(&tp)
);
return Err(Error::ProtocolViolation);
}
}
if self
.remote_original_destination_cid
.as_ref()
.map(ConnectionId::as_cid_ref)
!= tp.map(ConnectionIdRef::from)
{
qwarn!(
"{} ODCID test failed: self cid {:?} != tp cid {:?}",
self.role,
self.remote_original_destination_cid,
tp.map(hex),
);
return Err(Error::ProtocolViolation);
}
let tp = remote_tps.get_bytes(tparams::RETRY_SOURCE_CONNECTION_ID);
match (&tp, &self.retry_info) {
(None, None) => {}
(None, Some(_ri)) => {
qwarn!(
"{} RSCID test failed: RSCID not found in tparams",
self.role
);
return Err(Error::ProtocolViolation);
}
(Some(_tp), None) => {
qwarn!(
"{} RSCID test failed: tparam found but no retry packet received",
self.role
);
return Err(Error::ProtocolViolation);
}
(Some(tp), Some(ri)) => {
if **tp != *ri.retry_source_cid {
qwarn!(
"{} RSCID test failed. self cid {:?} != tp cid {}",
self.role,
ri.retry_source_cid,
hex(&**tp),
);
return Err(Error::ProtocolViolation);
}
}
let expected = self
.retry_info
.as_ref()
.map(|ri| ri.retry_source_cid.as_cid_ref());
if expected != tp.map(ConnectionIdRef::from) {
qwarn!(
"{} RSCID test failed. self cid {:?} != tp cid {:?}",
self.role,
expected,
tp.map(hex),
);
return Err(Error::ProtocolViolation);
}
}
@ -2006,7 +1990,7 @@ impl Connection {
/// to retransmit the frame as needed.
fn handle_lost_packets(&mut self, lost_packets: &[SentPacket]) {
for lost in lost_packets {
for token in &lost.tokens {
for token in lost.tokens.as_ref() {
qdebug!([self], "Lost: {:?}", token);
match token {
RecoveryToken::Ack(_) => {}
@ -2043,7 +2027,7 @@ impl Connection {
);
let acked_ranges =
Frame::decode_ack_frame(largest_acknowledged, first_ack_range, ack_ranges)?;
Frame::decode_ack_frame(largest_acknowledged, first_ack_range, &ack_ranges)?;
let (acked_packets, lost_packets) = self.loss_recovery.on_ack_received(
space,
largest_acknowledged,
@ -2052,10 +2036,10 @@ impl Connection {
now,
);
for acked in acked_packets {
for token in acked.tokens {
for token in acked.tokens.as_ref() {
match token {
RecoveryToken::Ack(at) => self.acks.acked(&at),
RecoveryToken::Stream(st) => self.send_streams.acked(&st),
RecoveryToken::Ack(at) => self.acks.acked(at),
RecoveryToken::Stream(st) => self.send_streams.acked(st),
RecoveryToken::Crypto(ct) => self.crypto.acked(ct),
RecoveryToken::Flow(ft) => {
self.flow_mgr.borrow_mut().acked(ft, &mut self.send_streams)
@ -2095,7 +2079,7 @@ impl Connection {
}
if self.role == Role::Server {
// Remove the randomized client CID from the list of acceptable CIDs.
assert_eq!(1, self.valid_cids.len());
debug_assert_eq!(1, self.valid_cids.len());
self.valid_cids.clear();
// Generate a qlog event that the server connection started.
qlog::server_connection_started(&mut self.qlog, self.path.as_ref().unwrap())?;
@ -2113,6 +2097,7 @@ impl Connection {
self.crypto.install_application_keys(now + pto)?;
self.process_tps()?;
self.set_state(State::Connected);
self.stats.resumed = self.crypto.tls.info().unwrap().resumed();
if self.role == Role::Server {
self.state_signaling.handshake_done();
self.set_state(State::Confirmed);
@ -2543,16 +2528,12 @@ mod tests {
pub fn default_server() -> Connection {
fixture_init();
let mut cid_mgr = FixedConnectionIdManager::new(5);
let local_initial_source_cid = cid_mgr.generate_cid();
Connection::new_server(
test_fixture::DEFAULT_KEYS,
test_fixture::DEFAULT_ALPN,
&test_fixture::anti_replay(),
Rc::new(RefCell::new(cid_mgr)),
Rc::new(RefCell::new(FixedConnectionIdManager::new(5))),
QuicVersion::default(),
local_initial_source_cid,
)
.expect("create a default server")
}
@ -3136,17 +3117,12 @@ mod tests {
// should result in the server rejecting 0-RTT.
let ar = AntiReplay::new(now(), test_fixture::ANTI_REPLAY_WINDOW, 1, 3)
.expect("setup anti-replay");
let mut cid_mgr = FixedConnectionIdManager::new(10);
let local_initial_source_cid = cid_mgr.generate_cid();
let mut server = Connection::new_server(
test_fixture::DEFAULT_KEYS,
test_fixture::DEFAULT_ALPN,
&ar,
Rc::new(RefCell::new(cid_mgr)),
Rc::new(RefCell::new(FixedConnectionIdManager::new(10))),
QuicVersion::default(),
local_initial_source_cid,
)
.unwrap();
@ -3500,16 +3476,12 @@ mod tests {
fn test_crypto_frame_split() {
let mut client = default_client();
let mut cid_mgr = FixedConnectionIdManager::new(6);
let local_initial_source_cid = cid_mgr.generate_cid();
let mut server = Connection::new_server(
test_fixture::LONG_CERT_KEYS,
test_fixture::DEFAULT_ALPN,
&test_fixture::anti_replay(),
Rc::new(RefCell::new(cid_mgr)),
Rc::new(RefCell::new(FixedConnectionIdManager::new(6))),
QuicVersion::default(),
local_initial_source_cid,
)
.expect("create a server");

View File

@ -21,7 +21,7 @@ use neqo_crypto::{
};
use crate::frame::Frame;
use crate::packet::PacketNumber;
use crate::packet::{PacketNumber, QuicVersion};
use crate::recovery::RecoveryToken;
use crate::recv_stream::RxStreamOrderer;
use crate::send_stream::TxBuffer;
@ -201,7 +201,7 @@ impl Crypto {
Ok(())
}
pub fn acked(&mut self, token: CryptoRecoveryToken) {
pub fn acked(&mut self, token: &CryptoRecoveryToken) {
qinfo!(
"Acked crypto frame space={} offset={} length={}",
token.space,
@ -282,17 +282,31 @@ impl CryptoDxState {
}
}
pub fn new_initial(direction: CryptoDxDirection, label: &str, dcid: &[u8]) -> Self {
const INITIAL_SALT: &[u8] = &[
pub fn new_initial(
quic_version: QuicVersion,
direction: CryptoDxDirection,
label: &str,
dcid: &[u8],
) -> Self {
qtrace!("new_initial for {:?}", quic_version);
const INITIAL_SALT_27: &[u8] = &[
0xc3, 0xee, 0xf7, 0x12, 0xc7, 0x2e, 0xbb, 0x5a, 0x11, 0xa7, 0xd2, 0x43, 0x2b, 0xb4,
0x63, 0x65, 0xbe, 0xf9, 0xf5, 0x02,
];
const INITIAL_SALT_29: &[u8] = &[
0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2, 0x4c, 0x9e, 0x97, 0x86, 0xf1, 0x9c, 0x61,
0x11, 0xe0, 0x43, 0x90, 0xa8, 0x99,
];
let salt = match quic_version {
QuicVersion::Draft27 | QuicVersion::Draft28 => INITIAL_SALT_27,
QuicVersion::Draft29 => INITIAL_SALT_29,
};
let cipher = TLS_AES_128_GCM_SHA256;
let initial_secret = hkdf::extract(
TLS_VERSION_1_3,
cipher,
Some(
hkdf::import_key(TLS_VERSION_1_3, cipher, INITIAL_SALT)
hkdf::import_key(TLS_VERSION_1_3, cipher, salt)
.as_ref()
.unwrap(),
),
@ -450,7 +464,12 @@ impl CryptoDxState {
pub(crate) fn test_default() -> Self {
// This matches the value in packet.rs
const CLIENT_CID: &[u8] = &[0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08];
Self::new_initial(CryptoDxDirection::Write, "server in", CLIENT_CID)
Self::new_initial(
QuicVersion::default(),
CryptoDxDirection::Write,
"server in",
CLIENT_CID,
)
}
}
@ -593,7 +612,7 @@ impl CryptoStates {
}
/// Create the initial crypto state.
pub fn init(&mut self, role: Role, dcid: &[u8]) {
pub fn init(&mut self, quic_version: QuicVersion, role: Role, dcid: &[u8]) {
const CLIENT_INITIAL_LABEL: &str = "client in";
const SERVER_INITIAL_LABEL: &str = "server in";
@ -604,14 +623,14 @@ impl CryptoStates {
hex(dcid)
);
let (write_label, read_label) = match role {
let (write, read) = match role {
Role::Client => (CLIENT_INITIAL_LABEL, SERVER_INITIAL_LABEL),
Role::Server => (SERVER_INITIAL_LABEL, CLIENT_INITIAL_LABEL),
};
let mut initial = CryptoState {
tx: CryptoDxState::new_initial(CryptoDxDirection::Write, write_label, dcid),
rx: CryptoDxState::new_initial(CryptoDxDirection::Read, read_label, dcid),
tx: CryptoDxState::new_initial(quic_version, CryptoDxDirection::Write, write, dcid),
rx: CryptoDxState::new_initial(quic_version, CryptoDxDirection::Read, read, dcid),
};
if let Some(prev) = &self.initial {
qinfo!(
@ -914,7 +933,7 @@ impl CryptoStreams {
self.get_mut(space).unwrap().rx.read_to_end(buf)
}
pub fn acked(&mut self, token: CryptoRecoveryToken) {
pub fn acked(&mut self, token: &CryptoRecoveryToken) {
self.get_mut(token.space)
.unwrap()
.tx

View File

@ -176,41 +176,27 @@ impl FlowMgr {
pub(crate) fn acked(
&mut self,
token: FlowControlRecoveryToken,
token: &FlowControlRecoveryToken,
send_streams: &mut SendStreams,
) {
if let Frame::ResetStream {
stream_id,
application_error_code,
final_size,
} = token
{
qinfo!(
"Reset received stream={} err={} final_size={}",
stream_id.as_u64(),
application_error_code,
final_size
);
const RESET_STREAM: &Frame = &Frame::ResetStream {
stream_id: StreamId::new(0),
application_error_code: 0,
final_size: 0,
};
if let Frame::ResetStream { stream_id, .. } = token {
qinfo!("Reset received stream={}", stream_id.as_u64());
if self
.from_streams
.remove(&(
stream_id,
mem::discriminant(&Frame::ResetStream {
stream_id,
application_error_code,
final_size,
}),
))
.remove(&(*stream_id, mem::discriminant(RESET_STREAM)))
.is_some()
{
qinfo!(
"Queued ResetStream for {} removed because previous ResetStream was acked",
stream_id.as_u64()
);
qinfo!("Removed RESET_STREAM frame for {}", stream_id.as_u64());
}
send_streams.reset_acked(stream_id);
send_streams.reset_acked(*stream_id);
}
}
@ -277,11 +263,9 @@ impl FlowMgr {
stream_id,
application_error_code,
} => self.stop_sending(stream_id, application_error_code),
// Resend MaxStreamData if not SizeKnown
// (maybe_send_flowc_update() checks this.)
Frame::MaxStreamData { stream_id, .. } => {
if let Some(rs) = recv_streams.get_mut(&stream_id) {
rs.maybe_send_flowc_update()
rs.flowc_lost()
}
}
Frame::PathResponse { .. } => qinfo!("Path Response lost, not re-sent"),

View File

@ -477,7 +477,7 @@ impl Frame {
pub fn decode_ack_frame(
largest_acked: u64,
first_ack_range: u64,
ack_ranges: Vec<AckRange>,
ack_ranges: &[AckRange],
) -> Res<Vec<(u64, u64)>> {
let mut acked_ranges = Vec::new();
@ -1053,7 +1053,7 @@ mod tests {
#[test]
fn test_decode_ack_frame() {
let res = Frame::decode_ack_frame(7, 2, vec![AckRange { gap: 0, range: 3 }]);
let res = Frame::decode_ack_frame(7, 2, &[AckRange { gap: 0, range: 3 }]);
assert!(res.is_ok());
assert_eq!(res.unwrap(), vec![(7, 5), (3, 0)]);
}

View File

@ -48,7 +48,7 @@ const ERROR_APPLICATION_CLOSE: TransportError = 12;
pub enum Error {
NoError,
InternalError,
ServerBusy,
ConnectionRefused,
FlowControlError,
StreamLimitError,
StreamStateError,
@ -101,7 +101,7 @@ impl Error {
| Self::IdleTimeout
| Self::PeerError(_)
| Self::PeerApplicationError(_) => 0,
Self::ServerBusy => 2,
Self::ConnectionRefused => 2,
Self::FlowControlError => 3,
Self::StreamLimitError => 4,
Self::StreamStateError => 5,

View File

@ -93,8 +93,7 @@ impl Pacer {
.as_nanos()
.saturating_mul(u128::try_from(cwnd * PACER_SPEEDUP).unwrap())
.checked_div(rtt.as_nanos())
.map(|i| usize::try_from(i).ok())
.flatten()
.and_then(|i| usize::try_from(i).ok())
.unwrap_or(self.m);
// Add the capacity up to a limit of `self.m`, then subtract `count`.

View File

@ -10,10 +10,9 @@ use crate::crypto::{CryptoDxState, CryptoStates};
use crate::tracking::PNSpace;
use crate::{Error, Res};
use neqo_common::{hex, hex_with_len, qerror, qtrace, Decoder, Encoder};
use neqo_crypto::{aead::Aead, hkdf, random, TLS_AES_128_GCM_SHA256, TLS_VERSION_1_3};
use neqo_common::{hex, hex_with_len, qtrace, Decoder, Encoder};
use neqo_crypto::random;
use std::cell::RefCell;
use std::convert::TryFrom;
use std::fmt;
use std::iter::ExactSizeIterator;
@ -36,6 +35,8 @@ const PACKET_HP_MASK_SHORT: u8 = 0x1f;
const SAMPLE_SIZE: usize = 16;
const SAMPLE_OFFSET: usize = 4;
mod retry;
pub type PacketNumber = u64;
type Version = u32;
@ -67,6 +68,7 @@ impl PacketType {
pub enum QuicVersion {
Draft27,
Draft28,
Draft29,
}
impl QuicVersion {
@ -74,13 +76,14 @@ impl QuicVersion {
match self {
Self::Draft27 => 0xff00_0000 + 27,
Self::Draft28 => 0xff00_0000 + 28,
Self::Draft29 => 0xff00_0000 + 29,
}
}
}
impl Default for QuicVersion {
fn default() -> Self {
Self::Draft28
Self::Draft29
}
}
@ -92,39 +95,15 @@ impl TryFrom<Version> for QuicVersion {
Ok(Self::Draft27)
} else if ver == 0xff00_0000 + 28 {
Ok(Self::Draft28)
} else if ver == 0xff00_0000 + 29 {
Ok(Self::Draft29)
} else {
Err(Error::VersionNegotiation)
}
}
}
/// The AEAD used for Retry is fixed, so use this.
fn make_retry_aead() -> Aead {
#[cfg(debug_assertions)]
::neqo_crypto::assert_initialized();
let secret = hkdf::import_key(
TLS_VERSION_1_3,
TLS_AES_128_GCM_SHA256,
&[
0x65, 0x6e, 0x61, 0xe3, 0x36, 0xae, 0x94, 0x17, 0xf7, 0xf0, 0xed, 0xd8, 0xd7, 0x8d,
0x46, 0x1e, 0x2a, 0xa7, 0x08, 0x4a, 0xba, 0x7a, 0x14, 0xc1, 0xe9, 0xf7, 0x26, 0xd5,
0x57, 0x09, 0x16, 0x9a,
],
)
.unwrap();
Aead::new(TLS_VERSION_1_3, TLS_AES_128_GCM_SHA256, &secret, "quic ").unwrap()
}
thread_local!(static RETRY_AEAD: RefCell<Aead> = RefCell::new(make_retry_aead()));
fn retry_expansion() -> usize {
if let Ok(ex) = RETRY_AEAD.try_with(|aead| aead.borrow().expansion()) {
ex
} else {
panic!("Unable to access Retry AEAD")
}
}
struct PacketBuilderoffsets {
struct PacketBuilderOffsets {
/// The bits of the first octet that need masking.
first_byte_mask: u8,
/// The offset of the length field.
@ -139,7 +118,7 @@ pub struct PacketBuilder {
encoder: Encoder,
pn: PacketNumber,
header: Range<usize>,
offsets: PacketBuilderoffsets,
offsets: PacketBuilderOffsets,
}
impl PacketBuilder {
@ -153,7 +132,7 @@ impl PacketBuilder {
encoder,
pn: u64::max_value(),
header: header_start..header_start,
offsets: PacketBuilderoffsets {
offsets: PacketBuilderOffsets {
first_byte_mask: PACKET_HP_MASK_SHORT,
pn: 0..0,
len: 0,
@ -180,7 +159,7 @@ impl PacketBuilder {
encoder,
pn: u64::max_value(),
header: header_start..header_start,
offsets: PacketBuilderoffsets {
offsets: PacketBuilderOffsets {
first_byte_mask: PACKET_HP_MASK_LONG,
pn: 0..0,
len: 0,
@ -297,15 +276,10 @@ impl PacketBuilder {
encoder.encode_vec(1, scid);
debug_assert_ne!(token.len(), 0);
encoder.encode(token);
let tag = RETRY_AEAD
.try_with(|aead| -> Res<Vec<u8>> {
let mut buf = vec![0; aead.borrow().expansion()];
Ok(aead.borrow().encrypt(0, &encoder, &[], &mut buf)?.to_vec())
})
.map_err(|e| {
qerror!("Unable to access Retry AEAD: {:?}", e);
Error::InternalError
})??;
let tag = retry::use_aead(quic_version, |aead| {
let mut buf = vec![0; aead.expansion()];
Ok(aead.encrypt(0, &encoder, &[], &mut buf)?.to_vec())
})?;
encoder.encode(&tag);
let mut complete: Vec<u8> = encoder.into();
Ok(complete.split_off(start))
@ -322,6 +296,7 @@ impl PacketBuilder {
encoder.encode_vec(1, scid);
encoder.encode_uint(4, QuicVersion::Draft27.as_u32());
encoder.encode_uint(4, QuicVersion::Draft28.as_u32());
encoder.encode_uint(4, QuicVersion::Draft29.as_u32());
// Add a greased version, using the randomness already generated.
for g in &mut grease[..4] {
*g = *g & 0xf0 | 0x0a;
@ -383,13 +358,14 @@ impl<'a> PublicPacket<'a> {
/// Decode the type-specific portions of a long header.
/// This includes reading the length and the remainder of the packet.
/// Returns a tuple of any token and the length of the header.
fn decode_type_specific(
fn decode_long(
decoder: &mut Decoder<'a>,
packet_type: PacketType,
quic_version: QuicVersion,
) -> Res<(&'a [u8], usize)> {
if packet_type == PacketType::Retry {
let header_len = decoder.offset();
let expansion = retry_expansion();
let expansion = retry::expansion(quic_version);
let token = Self::opt(decoder.decode(decoder.remaining() - expansion))?;
if token.is_empty() {
return Err(Error::InvalidPacket);
@ -492,7 +468,7 @@ impl<'a> PublicPacket<'a> {
};
// The type-specific code includes a token. This consumes the remainder of the packet.
let (token, header_len) = Self::decode_type_specific(&mut decoder, packet_type)?;
let (token, header_len) = Self::decode_long(&mut decoder, packet_type, quic_version)?;
let end = data.len() - decoder.remaining();
let (data, remainder) = data.split_at(end);
Ok((
@ -514,7 +490,8 @@ impl<'a> PublicPacket<'a> {
if self.packet_type != PacketType::Retry {
return false;
}
let expansion = retry_expansion();
let version = self.quic_version.unwrap();
let expansion = retry::expansion(version);
if self.data.len() <= expansion {
return false;
}
@ -522,19 +499,11 @@ impl<'a> PublicPacket<'a> {
let mut encoder = Encoder::with_capacity(self.data.len());
encoder.encode_vec(1, odcid);
encoder.encode(header);
RETRY_AEAD
.try_with(|aead| -> bool {
let mut buf = vec![0; expansion];
if let Ok(v) = aead.borrow().decrypt(0, &encoder, tag, &mut buf) {
v.is_empty()
} else {
false
}
})
.unwrap_or_else(|e| {
qerror!("Unable to access Retry AEAD: {:?}", e);
false
})
retry::use_aead(version, |aead| {
let mut buf = vec![0; expansion];
Ok(aead.decrypt(0, &encoder, tag, &mut buf)?.is_empty())
})
.unwrap_or(false)
}
pub fn is_valid_initial(&self) -> bool {
@ -726,24 +695,24 @@ mod tests {
}
const SAMPLE_INITIAL_PAYLOAD: &[u8] = &[
0x0d, 0x00, 0x00, 0x00, 0x00, 0x18, 0x41, 0x0a, 0x02, 0x00, 0x00, 0x56, 0x03, 0x03, 0xee,
0xfc, 0xe7, 0xf7, 0xb3, 0x7b, 0xa1, 0xd1, 0x63, 0x2e, 0x96, 0x67, 0x78, 0x25, 0xdd, 0xf7,
0x39, 0x88, 0xcf, 0xc7, 0x98, 0x25, 0xdf, 0x56, 0x6d, 0xc5, 0x43, 0x0b, 0x9a, 0x04, 0x5a,
0x12, 0x00, 0x13, 0x01, 0x00, 0x00, 0x2e, 0x00, 0x33, 0x00, 0x24, 0x00, 0x1d, 0x00, 0x20,
0x9d, 0x3c, 0x94, 0x0d, 0x89, 0x69, 0x0b, 0x84, 0xd0, 0x8a, 0x60, 0x99, 0x3c, 0x14, 0x4e,
0xca, 0x68, 0x4d, 0x10, 0x81, 0x28, 0x7c, 0x83, 0x4d, 0x53, 0x11, 0xbc, 0xf3, 0x2b, 0xb9,
0xda, 0x1a, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04,
0x02, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x40, 0x5a, 0x02, 0x00, 0x00, 0x56, 0x03, 0x03,
0xee, 0xfc, 0xe7, 0xf7, 0xb3, 0x7b, 0xa1, 0xd1, 0x63, 0x2e, 0x96, 0x67, 0x78, 0x25, 0xdd,
0xf7, 0x39, 0x88, 0xcf, 0xc7, 0x98, 0x25, 0xdf, 0x56, 0x6d, 0xc5, 0x43, 0x0b, 0x9a, 0x04,
0x5a, 0x12, 0x00, 0x13, 0x01, 0x00, 0x00, 0x2e, 0x00, 0x33, 0x00, 0x24, 0x00, 0x1d, 0x00,
0x20, 0x9d, 0x3c, 0x94, 0x0d, 0x89, 0x69, 0x0b, 0x84, 0xd0, 0x8a, 0x60, 0x99, 0x3c, 0x14,
0x4e, 0xca, 0x68, 0x4d, 0x10, 0x81, 0x28, 0x7c, 0x83, 0x4d, 0x53, 0x11, 0xbc, 0xf3, 0x2b,
0xb9, 0xda, 0x1a, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04,
];
const SAMPLE_INITIAL: &[u8] = &[
0xc9, 0xff, 0x00, 0x00, 0x1c, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5,
0x00, 0x40, 0x74, 0x16, 0x8b, 0xf2, 0x2b, 0x70, 0x02, 0x59, 0x6f, 0x99, 0xae, 0x67, 0xab,
0xf6, 0x5a, 0x58, 0x52, 0xf5, 0x4f, 0x58, 0xc3, 0x7c, 0x80, 0x86, 0x82, 0xe2, 0xe4, 0x04,
0x92, 0xd8, 0xa3, 0x89, 0x9f, 0xb0, 0x4f, 0xc0, 0xaf, 0xe9, 0xaa, 0xbc, 0x87, 0x67, 0xb1,
0x8a, 0x0a, 0xa4, 0x93, 0x53, 0x74, 0x26, 0x37, 0x3b, 0x48, 0xd5, 0x02, 0x21, 0x4d, 0xd8,
0x56, 0xd6, 0x3b, 0x78, 0xce, 0xe3, 0x7b, 0xc6, 0x64, 0xb3, 0xfe, 0x86, 0xd4, 0x87, 0xac,
0x7a, 0x77, 0xc5, 0x30, 0x38, 0xa3, 0xcd, 0x32, 0xf0, 0xb5, 0x00, 0x4d, 0x9f, 0x57, 0x54,
0xc4, 0xf7, 0xf2, 0xd1, 0xf3, 0x5c, 0xf3, 0xf7, 0x11, 0x63, 0x51, 0xc9, 0x2b, 0xda, 0x5b,
0x23, 0xc8, 0x10, 0x34, 0xab, 0x74, 0xf5, 0x4c, 0xb1, 0xbd, 0x72, 0x95, 0x12, 0x56,
0xc7, 0xff, 0x00, 0x00, 0x1d, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5,
0x00, 0x40, 0x75, 0xfb, 0x12, 0xff, 0x07, 0x82, 0x3a, 0x5d, 0x24, 0x53, 0x4d, 0x90, 0x6c,
0xe4, 0xc7, 0x67, 0x82, 0xa2, 0x16, 0x7e, 0x34, 0x79, 0xc0, 0xf7, 0xf6, 0x39, 0x5d, 0xc2,
0xc9, 0x16, 0x76, 0x30, 0x2f, 0xe6, 0xd7, 0x0b, 0xb7, 0xcb, 0xeb, 0x11, 0x7b, 0x4d, 0xdb,
0x7d, 0x17, 0x34, 0x98, 0x44, 0xfd, 0x61, 0xda, 0xe2, 0x00, 0xb8, 0x33, 0x8e, 0x1b, 0x93,
0x29, 0x76, 0xb6, 0x1d, 0x91, 0xe6, 0x4a, 0x02, 0xe9, 0xe0, 0xee, 0x72, 0xe3, 0xa6, 0xf6,
0x3a, 0xba, 0x4c, 0xee, 0xee, 0xc5, 0xbe, 0x2f, 0x24, 0xf2, 0xd8, 0x60, 0x27, 0x57, 0x29,
0x43, 0x53, 0x38, 0x46, 0xca, 0xa1, 0x3e, 0x6f, 0x16, 0x3f, 0xb2, 0x57, 0x47, 0x3d, 0xcc,
0xa2, 0x53, 0x96, 0xe8, 0x87, 0x24, 0xf1, 0xe5, 0xd9, 0x64, 0xde, 0xde, 0xe9, 0xb6, 0x33,
];
#[test]
@ -815,8 +784,8 @@ mod tests {
}
const SAMPLE_SHORT: &[u8] = &[
0x4c, 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5, 0x55, 0x80, 0x33, 0xda, 0x1a, 0x01,
0x19, 0x47, 0x57, 0xe2, 0x23, 0xcf, 0xe8, 0xde, 0x58, 0xce, 0x8b, 0xab, 0xc5, 0x19,
0x55, 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5, 0x99, 0x9c, 0xbd, 0x77, 0xf5, 0xd7,
0x0a, 0x28, 0xe8, 0xfb, 0xc3, 0xed, 0xf5, 0x71, 0xb1, 0x04, 0x32, 0x2a, 0xae, 0xae,
];
const SAMPLE_SHORT_PAYLOAD: &[u8] = &[0; 3];
@ -835,6 +804,7 @@ mod tests {
#[test]
fn decode_short() {
fixture_init();
let (packet, remainder) = PublicPacket::decode(SAMPLE_SHORT, &cid_mgr()).unwrap();
assert_eq!(packet.packet_type(), PacketType::Short);
assert!(remainder.is_empty());
@ -926,20 +896,16 @@ mod tests {
0x92, 0x0e, 0x6f, 0xdf, 0x1d, 0x63,
];
const SAMPLE_RETRY_29: &[u8] = &[
0xff, 0xff, 0x00, 0x00, 0x1d, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5,
0x74, 0x6f, 0x6b, 0x65, 0x6e, 0xd1, 0x69, 0x26, 0xd8, 0x1f, 0x6f, 0x9c, 0xa2, 0x95, 0x3a,
0x8a, 0xa4, 0x57, 0x5e, 0x1e, 0x49,
];
const RETRY_TOKEN: &[u8] = b"token";
fn pick_retry_version() -> (&'static [u8], QuicVersion) {
if random(1)[0] % 2 == 0 {
(SAMPLE_RETRY_27, QuicVersion::Draft27)
} else {
(SAMPLE_RETRY_28, QuicVersion::Draft28)
}
}
#[test]
fn build_retry_single() {
fn build_retry_single(quic_version: QuicVersion, sample_retry: &[u8]) {
fixture_init();
let (sample_retry, quic_version) = pick_retry_version();
let retry =
PacketBuilder::retry(quic_version, &[], SERVER_CID, RETRY_TOKEN, CLIENT_CID).unwrap();
@ -960,16 +926,18 @@ mod tests {
}
#[test]
fn decode_retry() {
fixture_init();
let (sample_retry, _) = pick_retry_version();
let (packet, remainder) =
PublicPacket::decode(sample_retry, &FixedConnectionIdManager::new(5)).unwrap();
assert!(packet.is_valid_retry(&ConnectionId::from(CLIENT_CID)));
assert!(packet.dcid().is_empty());
assert_eq!(&packet.scid()[..], SERVER_CID);
assert_eq!(packet.token(), RETRY_TOKEN);
assert!(remainder.is_empty());
fn build_retry_27() {
build_retry_single(QuicVersion::Draft27, SAMPLE_RETRY_27);
}
#[test]
fn build_retry_28() {
build_retry_single(QuicVersion::Draft28, SAMPLE_RETRY_28);
}
#[test]
fn build_retry_29() {
build_retry_single(QuicVersion::Draft29, SAMPLE_RETRY_29);
}
#[test]
@ -977,25 +945,53 @@ mod tests {
// Run the build_retry test a few times.
// This increases the chance that the full comparison happens.
for _ in 0..32 {
build_retry_single();
build_retry_27();
build_retry_28();
build_retry_29();
}
}
fn decode_retry(quic_version: QuicVersion, sample_retry: &[u8]) {
fixture_init();
let (packet, remainder) =
PublicPacket::decode(sample_retry, &FixedConnectionIdManager::new(5)).unwrap();
assert!(packet.is_valid_retry(&ConnectionId::from(CLIENT_CID)));
assert_eq!(Some(quic_version), packet.quic_version);
assert!(packet.dcid().is_empty());
assert_eq!(&packet.scid()[..], SERVER_CID);
assert_eq!(packet.token(), RETRY_TOKEN);
assert!(remainder.is_empty());
}
#[test]
fn decode_retry_27() {
decode_retry(QuicVersion::Draft27, SAMPLE_RETRY_27);
}
#[test]
fn decode_retry_28() {
decode_retry(QuicVersion::Draft28, SAMPLE_RETRY_28);
}
#[test]
fn decode_retry_29() {
decode_retry(QuicVersion::Draft29, SAMPLE_RETRY_29);
}
/// Check some packets that are clearly not valid Retry packets.
#[test]
fn invalid_retry() {
fixture_init();
let (sample_retry, _) = pick_retry_version();
let cid_mgr = FixedConnectionIdManager::new(5);
let odcid = ConnectionId::from(CLIENT_CID);
assert!(PublicPacket::decode(&[], &cid_mgr).is_err());
let (packet, remainder) = PublicPacket::decode(sample_retry, &cid_mgr).unwrap();
let (packet, remainder) = PublicPacket::decode(SAMPLE_RETRY_28, &cid_mgr).unwrap();
assert!(remainder.is_empty());
assert!(packet.is_valid_retry(&odcid));
let mut damaged_retry = sample_retry.to_vec();
let mut damaged_retry = SAMPLE_RETRY_28.to_vec();
let last = damaged_retry.len() - 1;
damaged_retry[last] ^= 66;
let (packet, remainder) = PublicPacket::decode(&damaged_retry, &cid_mgr).unwrap();
@ -1018,7 +1014,7 @@ mod tests {
const SAMPLE_VN: &[u8] = &[
0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5, 0x08,
0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08, 0xff, 0x00, 0x00, 0x1b, 0xff, 0x00, 0x00,
0x1c, 0x0a, 0x0a, 0x0a, 0x0a,
0x1c, 0xff, 0x00, 0x00, 0x1d, 0x0a, 0x0a, 0x0a, 0x0a,
];
#[test]

View File

@ -0,0 +1,60 @@
// 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.
#![deny(clippy::pedantic)]
use crate::packet::QuicVersion;
use crate::{Error, Res};
use neqo_common::qerror;
use neqo_crypto::{aead::Aead, hkdf, TLS_AES_128_GCM_SHA256, TLS_VERSION_1_3};
use std::cell::RefCell;
const RETRY_SECRET_27: &[u8] = &[
0x65, 0x6e, 0x61, 0xe3, 0x36, 0xae, 0x94, 0x17, 0xf7, 0xf0, 0xed, 0xd8, 0xd7, 0x8d, 0x46, 0x1e,
0x2a, 0xa7, 0x08, 0x4a, 0xba, 0x7a, 0x14, 0xc1, 0xe9, 0xf7, 0x26, 0xd5, 0x57, 0x09, 0x16, 0x9a,
];
const RETRY_SECRET_29: &[u8] = &[
0x8b, 0x0d, 0x37, 0xeb, 0x85, 0x35, 0x02, 0x2e, 0xbc, 0x8d, 0x76, 0xa2, 0x07, 0xd8, 0x0d, 0xf2,
0x26, 0x46, 0xec, 0x06, 0xdc, 0x80, 0x96, 0x42, 0xc3, 0x0a, 0x8b, 0xaa, 0x2b, 0xaa, 0xff, 0x4c,
];
/// The AEAD used for Retry is fixed, so use thread local storage.
fn make_aead(secret: &[u8]) -> Aead {
#[cfg(debug_assertions)]
::neqo_crypto::assert_initialized();
let secret = hkdf::import_key(TLS_VERSION_1_3, TLS_AES_128_GCM_SHA256, secret).unwrap();
Aead::new(TLS_VERSION_1_3, TLS_AES_128_GCM_SHA256, &secret, "quic ").unwrap()
}
thread_local!(static RETRY_AEAD_27: RefCell<Aead> = RefCell::new(make_aead(RETRY_SECRET_27)));
thread_local!(static RETRY_AEAD_29: RefCell<Aead> = RefCell::new(make_aead(RETRY_SECRET_29)));
/// Run a function with the appropriate Retry AEAD.
pub fn use_aead<F, T>(quic_version: QuicVersion, f: F) -> Res<T>
where
F: FnOnce(&Aead) -> Res<T>,
{
match quic_version {
QuicVersion::Draft27 | QuicVersion::Draft28 => &RETRY_AEAD_27,
QuicVersion::Draft29 => &RETRY_AEAD_29,
}
.try_with(|aead| f(&aead.borrow()))
.map_err(|e| {
qerror!("Unable to access Retry AEAD: {:?}", e);
Error::InternalError
})?
}
/// Determine how large the expansion is for a given key.
pub fn expansion(quic_version: QuicVersion) -> usize {
if let Ok(ex) = use_aead(quic_version, |aead| Ok(aead.expansion())) {
ex
} else {
panic!("Unable to access Retry AEAD")
}
}

View File

@ -45,17 +45,6 @@ impl Path {
}
}
/// Create a path based on a received packet.
pub fn from_datagram(d: &Datagram, remote_cid: ConnectionId) -> Self {
Self {
local: d.destination(),
remote: d.source(),
local_cids: Vec::new(),
remote_cid,
reset_token: None,
}
}
pub fn received_on(&self, d: &Datagram) -> bool {
self.local == d.destination() && self.remote == d.source()
}

View File

@ -177,8 +177,16 @@ fn frame_to_qlogframe(frame: &Frame) -> QuicFrame {
match frame {
Frame::Padding => QuicFrame::padding(),
Frame::Ping => QuicFrame::ping(),
Frame::Ack { ack_delay, .. } => {
QuicFrame::ack(Some(ack_delay.to_string()), None, None, None, None)
Frame::Ack {
largest_acknowledged,
ack_delay,
first_ack_range,
ack_ranges,
} => {
let ack_ranges =
Frame::decode_ack_frame(*largest_acknowledged, *first_ack_range, ack_ranges).ok();
QuicFrame::ack(Some(ack_delay.to_string()), ack_ranges, None, None, None)
}
Frame::ResetStream {
stream_id,
@ -277,7 +285,7 @@ fn frame_to_qlogframe(frame: &Frame) -> QuicFrame {
String::from_utf8_lossy(&reason_phrase).to_string(),
Some(frame_type.to_string()),
),
Frame::HandshakeDone => QuicFrame::unknown(0x1e),
Frame::HandshakeDone => QuicFrame::handshake_done(),
}
}

View File

@ -496,10 +496,7 @@ impl LossRecovery {
}
pub fn largest_acknowledged_pn(&self, pn_space: PNSpace) -> Option<u64> {
self.spaces
.get(pn_space)
.map(|sp| sp.largest_acked)
.flatten()
self.spaces.get(pn_space).and_then(|sp| sp.largest_acked)
}
pub fn pto(&self) -> Duration {
@ -784,6 +781,7 @@ impl ::std::fmt::Display for LossRecovery {
mod tests {
use super::{LossRecovery, LossRecoverySpace, PNSpace, SentPacket};
use std::convert::TryInto;
use std::rc::Rc;
use std::time::{Duration, Instant};
use test_fixture::now;
@ -862,7 +860,7 @@ mod tests {
lr.on_packet_sent(
PNSpace::ApplicationData,
pn,
SentPacket::new(pn_time(pn), true, Vec::new(), ON_SENT_SIZE, true),
SentPacket::new(pn_time(pn), true, Rc::default(), ON_SENT_SIZE, true),
);
}
}
@ -983,7 +981,7 @@ mod tests {
lr.on_packet_sent(
PNSpace::ApplicationData,
0,
SentPacket::new(pn_time(0), true, Vec::new(), ON_SENT_SIZE, true),
SentPacket::new(pn_time(0), true, Rc::default(), ON_SENT_SIZE, true),
);
lr.on_packet_sent(
PNSpace::ApplicationData,
@ -991,7 +989,7 @@ mod tests {
SentPacket::new(
pn_time(0) + INITIAL_RTT / 4,
true,
Vec::new(),
Rc::default(),
ON_SENT_SIZE,
true,
),
@ -1093,21 +1091,21 @@ mod tests {
lr.on_packet_sent(
PNSpace::Initial,
0,
SentPacket::new(pn_time(0), true, Vec::new(), ON_SENT_SIZE, true),
SentPacket::new(pn_time(0), true, Rc::default(), ON_SENT_SIZE, true),
);
lr.on_packet_sent(
PNSpace::Handshake,
0,
SentPacket::new(pn_time(1), true, Vec::new(), ON_SENT_SIZE, true),
SentPacket::new(pn_time(1), true, Rc::default(), ON_SENT_SIZE, true),
);
lr.on_packet_sent(
PNSpace::ApplicationData,
0,
SentPacket::new(pn_time(2), true, Vec::new(), ON_SENT_SIZE, true),
SentPacket::new(pn_time(2), true, Rc::default(), ON_SENT_SIZE, true),
);
// Now put all spaces on the LR timer so we can see them.
let pkt = SentPacket::new(pn_time(3), true, vec![], ON_SENT_SIZE, true);
let pkt = SentPacket::new(pn_time(3), true, Rc::default(), ON_SENT_SIZE, true);
for sp in PNSpace::iter() {
lr.on_packet_sent(*sp, 1, pkt.clone());
lr.on_ack_received(*sp, 1, vec![(1, 1)], Duration::from_secs(0), pn_time(3));
@ -1130,7 +1128,7 @@ mod tests {
lr.on_packet_sent(
PNSpace::Initial,
0,
SentPacket::new(pn_time(3), true, Vec::new(), ON_SENT_SIZE, true),
SentPacket::new(pn_time(3), true, Rc::default(), ON_SENT_SIZE, true),
);
assert_sent_times(&lr, None, None, Some(pn_time(2)));
}

View File

@ -461,29 +461,40 @@ impl RecvStream {
/// If we should tell the sender they have more credit, return an offset
pub fn maybe_send_flowc_update(&mut self) {
// Only ever needed if actively receiving and not in SizeKnown state
if let RecvStreamState::Recv {
max_bytes,
max_stream_data,
recv_buf,
} = &mut self.state
{
{
// Algo: send an update if app has consumed more than half
// the data in the current window
// TODO(agrover@mozilla.com): This algo is not great but
// should prevent Silly Window Syndrome. Spec refers to using
// highest seen offset somehow? RTT maybe?
let maybe_new_max = recv_buf.retired() + *max_bytes;
if maybe_new_max > (*max_bytes / 2) + *max_stream_data {
*max_stream_data = maybe_new_max;
self.flow_mgr
.borrow_mut()
.max_stream_data(self.stream_id, maybe_new_max)
}
// Algo: send an update if app has consumed more than half
// the data in the current window
// TODO(agrover@mozilla.com): This algo is not great but
// should prevent Silly Window Syndrome. Spec refers to using
// highest seen offset somehow? RTT maybe?
let maybe_new_max = recv_buf.retired() + *max_bytes;
if maybe_new_max > (*max_bytes / 2) + *max_stream_data {
*max_stream_data = maybe_new_max;
self.flow_mgr
.borrow_mut()
.max_stream_data(self.stream_id, maybe_new_max)
}
}
}
/// MAX_STREAM_DATA was lost. Send it again if still blocked.
pub fn flowc_lost(&self) {
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 {
matches!(
self.state,
@ -796,4 +807,36 @@ mod tests {
.unwrap();
assert!(matches!(s.flow_mgr.borrow().peek(), None));
}
#[test]
fn resend_flowc_if_lost() {
let flow_mgr = Rc::new(RefCell::new(FlowMgr::default()));
let conn_events = ConnectionEvents::default();
let frame1 = vec![0; RX_STREAM_DATA_WINDOW as usize];
let mut s = RecvStream::new(
67.into(),
RX_STREAM_DATA_WINDOW,
Rc::clone(&flow_mgr),
conn_events,
);
// A flow control update is queued
s.inbound_stream_frame(false, 0, frame1).unwrap();
flow_mgr.borrow_mut().max_stream_data(67.into(), 100);
// Generates frame
assert!(matches!(
s.flow_mgr.borrow_mut().next().unwrap(),
Frame::MaxStreamData { .. }
));
// Nothing else queued
assert!(matches!(s.flow_mgr.borrow().peek(), None));
// Asking for another one won't get you one
s.maybe_send_flowc_update();
assert!(matches!(s.flow_mgr.borrow().peek(), None));
// But if lost, another frame is generated
s.flowc_lost();
assert!(matches!(s.flow_mgr.borrow_mut().next().unwrap(), Frame::MaxStreamData{..}));
}
}

View File

@ -29,7 +29,7 @@ use std::mem;
use std::net::{IpAddr, SocketAddr};
use std::ops::{Deref, DerefMut};
use std::path::PathBuf;
use std::rc::Rc;
use std::rc::{Rc, Weak};
use std::time::{Duration, Instant};
pub enum InitialResult {
@ -119,9 +119,10 @@ impl RetryToken {
peer_address: SocketAddr,
now: Instant,
) -> Res<Vec<u8>> {
const EXPIRATION: Duration = Duration::from_secs(5);
// TODO(mt) rotate keys on a fixed schedule.
let mut token = Encoder::default();
const EXPIRATION: Duration = Duration::from_secs(5);
let end = now + EXPIRATION;
let end_millis = u32::try_from(end.duration_since(self.start_time).as_millis())?;
token.encode_uint(4, end_millis);
@ -191,6 +192,25 @@ struct AttemptKey {
odcid: ConnectionId,
}
/// `InitialDetails` holds important information for processing `Initial` packets.
struct InitialDetails {
src_cid: ConnectionId,
dst_cid: ConnectionId,
token: Vec<u8>,
quic_version: QuicVersion,
}
impl InitialDetails {
fn new(packet: &PublicPacket) -> Self {
Self {
src_cid: ConnectionId::from(packet.scid()),
dst_cid: ConnectionId::from(packet.dcid()),
token: packet.token().to_vec(),
quic_version: packet.version().unwrap(),
}
}
}
pub struct Server {
/// The names of certificates.
certs: Vec<String>,
@ -273,7 +293,7 @@ impl Server {
match out {
Output::Datagram(_) => {
qtrace!([self], "Sending packet, added to waiting connections");
self.waiting.push_back(c.clone());
self.waiting.push_back(Rc::clone(&c));
}
Output::Callback(delay) => {
let next = now + delay;
@ -281,7 +301,7 @@ impl Server {
qtrace!([self], "Change timer to {:?}", next);
self.remove_timer(&c);
c.borrow_mut().last_timer = next;
self.timers.add(next, c.clone());
self.timers.add(next, Rc::clone(&c));
}
}
_ => {
@ -290,7 +310,7 @@ impl Server {
}
if c.borrow().has_events() {
qtrace!([self], "Connection active: {:?}", c);
self.active.insert(ActiveConnectionRef { c: c.clone() });
self.active.insert(ActiveConnectionRef { c: Rc::clone(&c) });
}
if *c.borrow().state() > State::Handshaking {
@ -319,24 +339,23 @@ impl Server {
fn handle_initial(
&mut self,
dcid: ConnectionId,
scid: ConnectionId,
token: Vec<u8>,
initial: InitialDetails,
dgram: Datagram,
now: Instant,
quic_version: QuicVersion,
) -> Option<Datagram> {
qdebug!([self], "Handle initial packet");
match self.retry.validate(&token, dgram.source(), now) {
qdebug!([self], "Handle initial");
match self.retry.validate(&initial.token, dgram.source(), now) {
RetryTokenResult::Invalid => None,
RetryTokenResult::Pass => self.connection_attempt(dcid, None, dgram, now, quic_version),
RetryTokenResult::Pass => self.connection_attempt(initial, dgram, None, now),
RetryTokenResult::Valid(orig_dcid) => {
self.connection_attempt(dcid, Some(orig_dcid), dgram, now, quic_version)
self.connection_attempt(initial, dgram, Some(orig_dcid), now)
}
RetryTokenResult::Validate => {
qinfo!([self], "Send retry for {:?}", dcid);
qinfo!([self], "Send retry for {:?}", initial.dst_cid);
let res = self.retry.generate_token(&dcid, dgram.source(), now);
let res = self
.retry
.generate_token(&initial.dst_cid, dgram.source(), now);
let token = if let Ok(t) = res {
t
} else {
@ -344,7 +363,13 @@ impl Server {
return None;
};
let new_dcid = self.cid_manager.borrow_mut().generate_cid();
let packet = PacketBuilder::retry(quic_version, &scid, &new_dcid, &token, &dcid);
let packet = PacketBuilder::retry(
initial.quic_version,
&initial.src_cid,
&new_dcid,
&token,
&initial.dst_cid,
);
if let Ok(p) = packet {
let retry = Datagram::new(dgram.destination(), dgram.source(), p);
Some(retry)
@ -358,15 +383,14 @@ impl Server {
fn connection_attempt(
&mut self,
dcid: ConnectionId,
orig_dcid: Option<ConnectionId>,
initial: InitialDetails,
dgram: Datagram,
orig_dcid: Option<ConnectionId>,
now: Instant,
quic_version: QuicVersion,
) -> Option<Datagram> {
let attempt_key = AttemptKey {
remote_address: dgram.source(),
odcid: orig_dcid.as_ref().unwrap_or(&dcid).clone(),
odcid: orig_dcid.as_ref().unwrap_or(&initial.dst_cid).clone(),
};
if let Some(c) = self.active_attempts.get(&attempt_key) {
qdebug!(
@ -377,7 +401,7 @@ impl Server {
let c = Rc::clone(c);
self.process_connection(c, Some(dgram), now)
} else {
self.accept_connection(attempt_key, dcid, orig_dcid, dgram, now, quic_version)
self.accept_connection(attempt_key, initial, dgram, orig_dcid, now)
}
}
@ -434,38 +458,34 @@ impl Server {
fn accept_connection(
&mut self,
attempt_key: AttemptKey,
dcid: ConnectionId,
orig_dcid: Option<ConnectionId>,
initial: InitialDetails,
dgram: Datagram,
orig_dcid: Option<ConnectionId>,
now: Instant,
quic_version: QuicVersion,
) -> Option<Datagram> {
qinfo!([self], "Accept connection {:?}", attempt_key);
// The internal connection ID manager that we use is not used directly.
// Instead, wrap it so that we can save connection IDs.
let local_initial_source_cid = self.cid_manager.borrow_mut().generate_cid();
let cid_mgr = Rc::new(RefCell::new(ServerConnectionIdManager {
c: None,
cid_manager: self.cid_manager.clone(),
connections: self.connections.clone(),
c: Weak::new(),
cid_manager: Rc::clone(&self.cid_manager),
connections: Rc::clone(&self.connections),
saved_cids: Vec::new(),
}));
let sconn = Connection::new_server(
&self.certs,
&self.protocols,
&self.anti_replay,
self.cid_manager.clone(),
quic_version,
local_initial_source_cid.clone(),
Rc::clone(&cid_mgr) as _,
initial.quic_version,
);
if let Ok(mut c) = sconn {
if let Some(odcid) = orig_dcid {
// There was a retry.
c.set_original_destination_cid(odcid);
c.set_retry_source_cid(dcid);
// There was a retry, so set the connection IDs for.
c.set_retry_cids(odcid, initial.src_cid, initial.dst_cid);
}
c.set_qlog(self.create_qlog_trace(&attempt_key));
let c = Rc::new(RefCell::new(ServerConnectionState {
@ -473,9 +493,8 @@ impl Server {
last_timer: now,
active_attempt: Some(attempt_key.clone()),
}));
cid_mgr.borrow_mut().c = Some(c.clone());
cid_mgr.borrow_mut().insert_cid(local_initial_source_cid);
let previous_attempt = self.active_attempts.insert(attempt_key, c.clone());
cid_mgr.borrow_mut().set_connection(Rc::clone(&c));
let previous_attempt = self.active_attempts.insert(attempt_key, Rc::clone(&c));
debug_assert!(previous_attempt.is_none());
self.process_connection(c, Some(dgram), now)
} else {
@ -516,11 +535,8 @@ impl Server {
match packet.packet_type() {
PacketType::Initial => {
// Copy values from `packet` because they are currently still borrowing from `dgram`.
let dcid = ConnectionId::from(packet.dcid());
let scid = ConnectionId::from(packet.scid());
let token = packet.token().to_vec();
let quic_version = packet.version().expect("Initial must have version field");
self.handle_initial(dcid, scid, token, dgram, now, quic_version)
let initial = InitialDetails::new(&packet);
self.handle_initial(initial, dgram, now)
}
PacketType::OtherVersion => {
let vn = PacketBuilder::version_negotiation(packet.scid(), packet.dcid());
@ -630,21 +646,24 @@ impl PartialEq for ActiveConnectionRef {
impl Eq for ActiveConnectionRef {}
struct ServerConnectionIdManager {
c: Option<StateRef>,
c: Weak<RefCell<ServerConnectionState>>,
connections: ConnectionTableRef,
cid_manager: CidMgr,
saved_cids: Vec<ConnectionId>,
}
impl ServerConnectionIdManager {
fn insert_cid(&mut self, cid: ConnectionId) {
assert!(!cid.is_empty());
let v = self
.connections
.borrow_mut()
.insert(cid, self.c.as_ref().unwrap().clone());
if let Some(v) = v {
debug_assert!(Rc::ptr_eq(&v, self.c.as_ref().unwrap()));
pub fn set_connection(&mut self, c: StateRef) {
let saved = std::mem::replace(&mut self.saved_cids, Vec::with_capacity(0));
for cid in saved {
self.insert_cid(cid, Rc::clone(&c));
}
self.c = Rc::downgrade(&c);
}
fn insert_cid(&mut self, cid: ConnectionId, rc: StateRef) {
debug_assert!(!cid.is_empty());
self.connections.borrow_mut().insert(cid, rc);
}
}
@ -657,7 +676,13 @@ impl ConnectionIdDecoder for ServerConnectionIdManager {
impl ConnectionIdManager for ServerConnectionIdManager {
fn generate_cid(&mut self) -> ConnectionId {
let cid = self.cid_manager.borrow_mut().generate_cid();
self.insert_cid(cid.clone());
if let Some(rc) = self.c.upgrade() {
self.insert_cid(cid.clone(), rc);
} else {
// This function can be called before the connection is set.
// So save any connection IDs until that hookup happens.
self.saved_cids.push(cid.clone());
}
cid
}

View File

@ -6,9 +6,13 @@
// Tracking of some useful statistics.
use neqo_common::qwarn;
#[derive(Default, Debug)]
/// Connection statistics
pub struct Stats {
conn_display_info: String,
/// Total packets received
pub packets_rx: usize,
/// Total packets sent
@ -17,4 +21,22 @@ pub struct Stats {
pub dups_rx: usize,
/// Dropped datagrams, or parts thereof
pub dropped_rx: usize,
/// resumption used
pub resumed: bool,
}
impl Stats {
pub fn init(&mut self, conn_info: String) {
self.conn_display_info = conn_info;
}
pub fn pkt_dropped(&mut self, reason: impl AsRef<str>) {
self.dropped_rx += 1;
qwarn!(
[self.conn_display_info],
"Dropped received packet: {}; Total: {}",
reason.as_ref(),
self.dropped_rx
)
}
}

View File

@ -43,6 +43,10 @@ impl StreamIndexes {
pub struct StreamId(u64);
impl StreamId {
pub const fn new(id: u64) -> Self {
Self(id)
}
pub fn is_bidi(self) -> bool {
self.0 & 0x02 == 0
}
@ -102,7 +106,7 @@ impl StreamId {
impl From<u64> for StreamId {
fn from(val: u64) -> Self {
Self(val)
Self::new(val)
}
}

View File

@ -118,7 +118,7 @@ impl TransportParameter {
_ => return Err(Error::TransportParameterError),
},
ACTIVE_CONNECTION_ID_LIMIT => match d.decode_varint() {
Some(v) if v <= 2 => Self::Integer(v),
Some(v) if v >= 2 => Self::Integer(v),
_ => return Err(Error::TransportParameterError),
},

View File

@ -10,6 +10,7 @@
use std::collections::VecDeque;
use std::convert::TryInto;
use std::rc::Rc;
use std::time::{Duration, Instant};
use neqo_common::{qdebug, qinfo, qtrace, qwarn};
@ -66,7 +67,7 @@ impl From<PacketType> for PNSpace {
pub struct SentPacket {
ack_eliciting: bool,
pub time_sent: Instant,
pub tokens: Vec<RecoveryToken>,
pub tokens: Rc<Vec<RecoveryToken>>,
time_declared_lost: Option<Instant>,
/// After a PTO, the packet has been released.
@ -80,7 +81,7 @@ impl SentPacket {
pub fn new(
time_sent: Instant,
ack_eliciting: bool,
tokens: Vec<RecoveryToken>,
tokens: Rc<Vec<RecoveryToken>>,
size: usize,
in_flight: bool,
) -> Self {
@ -530,8 +531,7 @@ impl AckTracker {
pn_space: PNSpace,
) -> Option<(Frame, Option<RecoveryToken>)> {
self.get_mut(pn_space)
.map(|space| space.get_frame(now))
.flatten()
.and_then(|space| space.get_frame(now))
}
}

View File

@ -5,14 +5,16 @@
// except according to those terms.
// Tests with the test vectors from the spec.
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(clippy::pedantic)]
#![deny(clippy::pedantic)]
use neqo_common::{Datagram, Encoder};
use neqo_transport::State;
use test_fixture::{default_server, loopback, now};
use neqo_transport::{Connection, FixedConnectionIdManager, QuicVersion, State};
use test_fixture::{self, loopback, now};
const INITIAL_PACKET: &str = "c0ff00001b088394c8f03e5157080000\
use std::cell::RefCell;
use std::rc::Rc;
const INITIAL_PACKET_27: &str = "c0ff00001b088394c8f03e5157080000\
449e3b343aa8535064a4268a0d9d7b1c\
9d250ae355162276e9b1e3011ef6bbc0\
ab48ad5bcc2681e953857ca62becd752\
@ -88,14 +90,111 @@ const INITIAL_PACKET: &str = "c0ff00001b088394c8f03e5157080000\
4709865bac824a94bb19058015e4e42d\
38d3b779d72edc00c5cd088eff802b05";
#[test]
fn process_client_initial() {
let mut server = default_server();
const INITIAL_PACKET_29: &str = "cdff00001d088394c8f03e5157080000\
449e9cdb990bfb66bc6a93032b50dd89\
73972d149421874d3849e3708d71354e\
a33bcdc356f3ea6e2a1a1bd7c3d14003\
8d3e784d04c30a2cdb40c32523aba2da\
fe1c1bf3d27a6be38fe38ae033fbb071\
3c1c73661bb6639795b42b97f77068ea\
d51f11fbf9489af2501d09481e6c64d4\
b8551cd3cea70d830ce2aeeec789ef55\
1a7fbe36b3f7e1549a9f8d8e153b3fac\
3fb7b7812c9ed7c20b4be190ebd89956\
26e7f0fc887925ec6f0606c5d36aa81b\
ebb7aacdc4a31bb5f23d55faef5c5190\
5783384f375a43235b5c742c78ab1bae\
0a188b75efbde6b3774ed61282f9670a\
9dea19e1566103ce675ab4e21081fb58\
60340a1e88e4f10e39eae25cd685b109\
29636d4f02e7fad2a5a458249f5c0298\
a6d53acbe41a7fc83fa7cc01973f7a74\
d1237a51974e097636b6203997f921d0\
7bc1940a6f2d0de9f5a11432946159ed\
6cc21df65c4ddd1115f86427259a196c\
7148b25b6478b0dc7766e1c4d1b1f515\
9f90eabc61636226244642ee148b464c\
9e619ee50a5e3ddc836227cad938987c\
4ea3c1fa7c75bbf88d89e9ada642b2b8\
8fe8107b7ea375b1b64889a4e9e5c38a\
1c896ce275a5658d250e2d76e1ed3a34\
ce7e3a3f383d0c996d0bed106c2899ca\
6fc263ef0455e74bb6ac1640ea7bfedc\
59f03fee0e1725ea150ff4d69a7660c5\
542119c71de270ae7c3ecfd1af2c4ce5\
51986949cc34a66b3e216bfe18b347e6\
c05fd050f85912db303a8f054ec23e38\
f44d1c725ab641ae929fecc8e3cefa56\
19df4231f5b4c009fa0c0bbc60bc75f7\
6d06ef154fc8577077d9d6a1d2bd9bf0\
81dc783ece60111bea7da9e5a9748069\
d078b2bef48de04cabe3755b197d52b3\
2046949ecaa310274b4aac0d008b1948\
c1082cdfe2083e386d4fd84c0ed0666d\
3ee26c4515c4fee73433ac703b690a9f\
7bf278a77486ace44c489a0c7ac8dfe4\
d1a58fb3a730b993ff0f0d61b4d89557\
831eb4c752ffd39c10f6b9f46d8db278\
da624fd800e4af85548a294c1518893a\
8778c4f6d6d73c93df200960104e062b\
388ea97dcf4016bced7f62b4f062cb6c\
04c20693d9a0e3b74ba8fe74cc012378\
84f40d765ae56a51688d985cf0ceaef4\
3045ed8c3f0c33bced08537f6882613a\
cd3b08d665fce9dd8aa73171e2d3771a\
61dba2790e491d413d93d987e2745af2\
9418e428be34941485c93447520ffe23\
1da2304d6a0fd5d07d08372202369661\
59bef3cf904d722324dd852513df39ae\
030d8173908da6364786d3c1bfcb19ea\
77a63b25f1e7fc661def480c5d00d444\
56269ebd84efd8e3a8b2c257eec76060\
682848cbf5194bc99e49ee75e4d0d254\
bad4bfd74970c30e44b65511d4ad0e6e\
c7398e08e01307eeeea14e46ccd87cf3\
6b285221254d8fc6a6765c524ded0085\
dca5bd688ddf722e2c0faf9d0fb2ce7a\
0c3f2cee19ca0ffba461ca8dc5d2c817\
8b0762cf67135558494d2a96f1a139f0\
edb42d2af89a9c9122b07acbc29e5e72\
2df8615c343702491098478a389c9872\
a10b0c9875125e257c7bfdf27eef4060\
bd3d00f4c14fd3e3496c38d3c5d1a566\
8c39350effbc2d16ca17be4ce29f02ed\
969504dda2a8c6b9ff919e693ee79e09\
089316e7d1d89ec099db3b2b268725d8\
88536a4b8bf9aee8fb43e82a4d919d48\
1802771a449b30f3fa2289852607b660";
let pkt: Vec<u8> = Encoder::from_hex(INITIAL_PACKET).into();
fn make_server(quic_version: QuicVersion) -> Connection {
test_fixture::fixture_init();
Connection::new_server(
test_fixture::DEFAULT_KEYS,
test_fixture::DEFAULT_ALPN,
&test_fixture::anti_replay(),
Rc::new(RefCell::new(FixedConnectionIdManager::new(5))),
quic_version,
)
.expect("create a default server")
}
fn process_client_initial(quic_version: QuicVersion, packet: &str) {
let mut server = make_server(quic_version);
let pkt: Vec<u8> = Encoder::from_hex(packet).into();
let dgram = Datagram::new(loopback(), loopback(), pkt);
assert_eq!(*server.state(), State::Init);
let out = server.process(Some(dgram), now());
assert_eq!(*server.state(), State::Handshaking);
assert!(out.dgram().is_some());
}
#[test]
fn process_client_initial_27() {
process_client_initial(QuicVersion::Draft27, &INITIAL_PACKET_27);
}
#[test]
fn process_client_initial_29() {
process_client_initial(QuicVersion::Draft29, &INITIAL_PACKET_29);
}

View File

@ -414,8 +414,8 @@ fn retry_bad_token() {
// Generate an AEAD and header protection object for a client Initial.
fn client_initial_aead_and_hp(dcid: &[u8]) -> (Aead, HpKey) {
const INITIAL_SALT: &[u8] = &[
0xc3, 0xee, 0xf7, 0x12, 0xc7, 0x2e, 0xbb, 0x5a, 0x11, 0xa7, 0xd2, 0x43, 0x2b, 0xb4, 0x63,
0x65, 0xbe, 0xf9, 0xf5, 0x02,
0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2, 0x4c, 0x9e, 0x97, 0x86, 0xf1, 0x9c, 0x61, 0x11,
0xe0, 0x43, 0x90, 0xa8, 0x99,
];
let initial_secret = hkdf::extract(
TLS_VERSION_1_3,

File diff suppressed because one or more lines are too long

101
third_party/rust/nom/.travis.yml vendored Normal file
View File

@ -0,0 +1,101 @@
language: rust
# sudo is required to enable kcov to use the personality syscall
sudo: required
dist: trusty
cache: cargo
rust:
- nightly
- beta
- stable
- 1.31.0
env:
matrix:
- FEATURES='--features "regexp regexp_macros"'
before_script:
- eval git pull --rebase https://github.com/Geal/nom master
- eval git log --pretty=oneline HEAD~5..HEAD
matrix:
include:
- rust: nightly
env: FEATURES='--no-default-features'
- rust: nightly
env: FEATURES='--no-default-features --features "alloc"'
- rust: stable
env: FEATURES=''
- rust: nightly
env: DOC_FEATURES='--features "std lexical regexp regexp_macros" --no-default-features'
before_script:
- export PATH=$HOME/.cargo/bin:$PATH
script:
- eval cargo doc --verbose $DOC_FEATURES
- rust: nightly
env: FEATURES=''
before_script:
- export PATH=$HOME/.cargo/bin:$PATH
- cargo install cargo-update || echo "cargo-update already installed"
- cargo install cargo-travis || echo "cargo-travis already installed"
- cargo install-update -a
- mkdir -p target/kcov-master
script:
cargo coveralls --verbose --all-features
allow_failures:
- rust: stable
env: FEATURES=''
before_script:
- export PATH=$HOME/.cargo/bin:$PATH
- rustup component add rustfmt-preview
script:
- eval cargo fmt -- --write-mode=diff
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/9c035a194ac4fd4cc061
on_success: change
on_failure: always
on_start: false
addons:
apt:
packages:
- libcurl4-openssl-dev
- libelf-dev
- libdw-dev
- binutils-dev
- cmake
sources:
- kalakris-cmake
cache:
directories:
- /home/travis/.cargo
before_cache:
- rm -rf /home/travis/.cargo/registry
script:
- eval cargo build --verbose $FEATURES
- eval cargo test --verbose $FEATURES
after_success: |
case "$TRAVIS_RUST_VERSION" in
nightly)
if [ "${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH}" != "master" ]; then
git fetch &&
git checkout master &&
cargo bench --verbose
fi
if [ "$FEATURES" == '--features "regexp regexp_macros"' ]; then
cargo bench --verbose
fi
;;
*)
;;
esac

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"313d2356fe74a99eeda858176ee65c3c4eb064ceba5e1665d494ba075ec358e1","README.md":"c74fdbabf7262695e42a9af0b8c0c2f089c188dde8b13bc71847551f126397b4","src/event.rs":"84a7cdb27d984e420ec5d9f63768c16db48bad5cf9bb4257fa52520b75655543","src/lib.rs":"5ce41ef6f0dae5112587fe1cc180eaa96455e1a172ec5f54a8bef0b86fabd20e"},"package":"3a1fdb4ef259b1b970958af7fbdedc4f107c872a9f856e01f3427c0bea44095f"}
{"files":{"Cargo.toml":"73d687d98f8be2b3f5435cad82703127f37bcb423cdc6da3f88a385f50960555","README.md":"c74fdbabf7262695e42a9af0b8c0c2f089c188dde8b13bc71847551f126397b4","src/event.rs":"9501c6f9a5d727f6c48e9992ca23538b2294e545e9bd7b7e06d0803f23bc417a","src/lib.rs":"c66b32efa9a306ff1ffdfaa802ad57d17f80d4d0ab64038e1e50f9319afb5476"},"package":"4767943b701b674b8d5e8535d3242b6cbd8249bf5d72eee0d45f376a2b680ad4"}

View File

@ -13,7 +13,7 @@
[package]
edition = "2018"
name = "qlog"
version = "0.2.0"
version = "0.3.0"
authors = ["Lucas Pardue <lucaspardue.24.7@gmail.com>"]
description = "qlog data model for QUIC and HTTP/3"
readme = "README.md"

View File

@ -704,8 +704,9 @@ impl Event {
/// * `EventType`=`Http3EventType::DataMoved`
/// * `EventData`=`H3DataMoved`.
pub fn h3_data_moved(
stream_id: String, offset: Option<String>, from: Option<H3DataRecipient>,
to: Option<H3DataRecipient>, raw: Option<String>,
stream_id: String, offset: Option<String>, length: Option<u64>,
from: Option<H3DataRecipient>, to: Option<H3DataRecipient>,
raw: Option<String>,
) -> Self {
Event {
category: EventCategory::Http,
@ -713,6 +714,7 @@ impl Event {
data: EventData::H3DataMoved {
stream_id,
offset,
length,
from,
to,
raw,
@ -721,7 +723,7 @@ impl Event {
}
pub fn h3_data_moved_min(stream_id: String) -> Self {
Event::h3_data_moved(stream_id, None, None, None, None)
Event::h3_data_moved(stream_id, None, None, None, None, None)
}
/// Returns:

View File

@ -73,9 +73,9 @@
//! ## Writing out logs
//! As events occur during the connection, the application appends them to the
//! trace. The qlog crate supports two modes of writing logs: the buffered mode
//! stores everything in memory and requires the application to serialize and write
//! the output, the streaming mode progressively writes serialized JSON output to a
//! writer designated by the application.
//! stores everything in memory and requires the application to serialize and
//! write the output, the streaming mode progressively writes serialized JSON
//! output to a writer designated by the application.
//!
//! ### Creating a Trace
//!
@ -378,7 +378,6 @@
//! );
//!
//! streamer.add_event(event).ok();
//!
//! ```
//!
//! In this example, the frames contained in the QUIC packet
@ -420,7 +419,6 @@
//! streamer.add_frame(padding, false).ok();
//!
//! streamer.finish_frames().ok();
//!
//! ```
//!
//! Once all events have have been written, the log
@ -479,10 +477,8 @@
//! [`add_frame()`]: struct.QlogStreamer.html#method.add_frame
//! [`finish_frames()`]: struct.QlogStreamer.html#method.finish_frames
//! [`finish_log()`]: struct.QlogStreamer.html#method.finish_log
use serde::{
Deserialize,
Serialize,
};
use serde::Serialize;
/// A quiche qlog error.
#[derive(Debug)]
@ -516,7 +512,7 @@ impl std::convert::From<std::io::Error> for Error {
}
}
pub const QLOG_VERSION: &str = "draft-01";
pub const QLOG_VERSION: &str = "draft-02-wip";
/// A specialized [`Result`] type for quiche qlog operations.
///
@ -574,7 +570,7 @@ pub enum StreamerState {
/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
pub struct QlogStreamer {
start_time: std::time::Instant,
writer: Box<dyn std::io::Write>,
writer: Box<dyn std::io::Write + Send>,
qlog: Qlog,
state: StreamerState,
first_event: bool,
@ -593,7 +589,7 @@ impl QlogStreamer {
pub fn new(
qlog_version: String, title: Option<String>, description: Option<String>,
summary: Option<String>, start_time: std::time::Instant, trace: Trace,
writer: Box<dyn std::io::Write>,
writer: Box<dyn std::io::Write + Send>,
) -> Self {
let qlog = Qlog {
qlog_version,
@ -790,7 +786,7 @@ impl QlogStreamer {
/// Returns the writer.
#[allow(clippy::borrowed_box)]
pub fn writer(&self) -> &Box<dyn std::io::Write> {
pub fn writer(&self) -> &Box<dyn std::io::Write + Send> {
&self.writer
}
}
@ -1458,6 +1454,7 @@ pub enum EventData {
H3DataMoved {
stream_id: String,
offset: Option<String>,
length: Option<u64>,
from: Option<H3DataRecipient>,
to: Option<H3DataRecipient>,
@ -1650,12 +1647,13 @@ pub enum QuicFrameTypeName {
PathResponse,
ConnectionClose,
ApplicationClose,
HandshakeDone,
Unknown,
}
// TODO: search for pub enum Error { to see how best to encode errors in qlog.
#[serde_with::skip_serializing_none]
#[derive(Clone, Serialize, Deserialize)]
#[derive(Clone, Serialize)]
pub struct PacketHeader {
pub packet_number: String,
pub packet_size: Option<u64>,
@ -1960,6 +1958,10 @@ pub enum QuicFrame {
trigger_frame_type: Option<String>,
},
HandshakeDone {
frame_type: QuicFrameTypeName,
},
Unknown {
frame_type: QuicFrameTypeName,
raw_frame_type: u64,
@ -2137,6 +2139,12 @@ impl QuicFrame {
}
}
pub fn handshake_done() -> Self {
QuicFrame::HandshakeDone {
frame_type: QuicFrameTypeName::HandshakeDone,
}
}
pub fn unknown(raw_frame_type: u64) -> Self {
QuicFrame::Unknown {
frame_type: QuicFrameTypeName::Unknown,
@ -2862,7 +2870,10 @@ mod tests {
});
// Some events hold frames, can't write any more events until frame
// writing is concluded.
// writing is concluded. Store event add time so that we can substitute
// it back into the qlog test output and avoid time-base flappiness.
let event_add_time =
format!("\"{}\"", s.start_time.elapsed().as_millis().to_string());
assert!(match s.add_event(event2.clone()) {
Ok(true) => true,
_ => false,
@ -2895,8 +2906,8 @@ mod tests {
let r = s.writer();
let w: &Box<std::io::Cursor<Vec<u8>>> = unsafe { std::mem::transmute(r) };
let log_string = r#"{"qlog_version":"version","title":"title","description":"description","traces":[{"vantage_point":{"type":"server"},"title":"Quiche qlog trace","description":"Quiche qlog trace description","configuration":{"time_units":"ms","time_offset":"0"},"event_fields":["relative_time","category","event","data"],"events":[["0","transport","packet_sent",{"packet_type":"handshake","header":{"packet_number":"0","packet_size":1251,"payload_length":1224,"version":"ff000018","scil":"8","dcil":"8","scid":"7e37e4dcc6682da8","dcid":"36ce104eee50101c"},"frames":[{"frame_type":"stream","stream_id":"40","offset":"40","length":"400","fin":true}]}],["0","transport","packet_sent",{"packet_type":"initial","header":{"packet_number":"0","packet_size":1251,"payload_length":1224,"version":"ff000018","scil":"8","dcil":"8","scid":"7e37e4dcc6682da8","dcid":"36ce104eee50101c"},"frames":[{"frame_type":"stream","stream_id":"0","offset":"0","length":"100","fin":true}]}]]}]}"#;
let log_string = r#"{"qlog_version":"version","title":"title","description":"description","traces":[{"vantage_point":{"type":"server"},"title":"Quiche qlog trace","description":"Quiche qlog trace description","configuration":{"time_units":"ms","time_offset":"0"},"event_fields":["relative_time","category","event","data"],"events":[["0","transport","packet_sent",{"packet_type":"handshake","header":{"packet_number":"0","packet_size":1251,"payload_length":1224,"version":"ff000018","scil":"8","dcil":"8","scid":"7e37e4dcc6682da8","dcid":"36ce104eee50101c"},"frames":[{"frame_type":"stream","stream_id":"40","offset":"40","length":"400","fin":true}]}],[event_add_time,"transport","packet_sent",{"packet_type":"initial","header":{"packet_number":"0","packet_size":1251,"payload_length":1224,"version":"ff000018","scil":"8","dcil":"8","scid":"7e37e4dcc6682da8","dcid":"36ce104eee50101c"},"frames":[{"frame_type":"stream","stream_id":"0","offset":"0","length":"100","fin":true}]}]]}]}"#;
let log_string = log_string.replace("event_add_time", &event_add_time);
let written_string = std::str::from_utf8(w.as_ref().get_ref()).unwrap();
assert_eq!(log_string, written_string);