зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1644532 - Update to Neqo 0.4.1 r=dragana,necko-reviewers
Default to using draft 27. Differential Revision: https://phabricator.services.mozilla.com/D78960
This commit is contained in:
Родитель
34738f5854
Коммит
2475b7008d
|
@ -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.0"
|
||||
tag = "v0.4.1"
|
||||
|
||||
[source."https://github.com/mozilla/mp4parse-rust"]
|
||||
git = "https://github.com/mozilla/mp4parse-rust"
|
||||
|
|
|
@ -3091,8 +3091,8 @@ checksum = "a2983372caf4480544083767bf2d27defafe32af49ab4df3a0b7fc90793a3664"
|
|||
|
||||
[[package]]
|
||||
name = "neqo-common"
|
||||
version = "0.4.0"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.4.0#f35a3b7800a7062c8b34cae1bdcbf64733935149"
|
||||
version = "0.4.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.4.1#0aeafc8cfd0b7a3554170419b38c97948b0fb108"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"env_logger",
|
||||
|
@ -3104,8 +3104,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "neqo-crypto"
|
||||
version = "0.4.0"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.4.0#f35a3b7800a7062c8b34cae1bdcbf64733935149"
|
||||
version = "0.4.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.4.1#0aeafc8cfd0b7a3554170419b38c97948b0fb108"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"log",
|
||||
|
@ -3117,8 +3117,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "neqo-http3"
|
||||
version = "0.4.0"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.4.0#f35a3b7800a7062c8b34cae1bdcbf64733935149"
|
||||
version = "0.4.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.4.1#0aeafc8cfd0b7a3554170419b38c97948b0fb108"
|
||||
dependencies = [
|
||||
"log",
|
||||
"neqo-common",
|
||||
|
@ -3131,8 +3131,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "neqo-qpack"
|
||||
version = "0.4.0"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.4.0#f35a3b7800a7062c8b34cae1bdcbf64733935149"
|
||||
version = "0.4.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.4.1#0aeafc8cfd0b7a3554170419b38c97948b0fb108"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"log",
|
||||
|
@ -3146,8 +3146,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "neqo-transport"
|
||||
version = "0.4.0"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.4.0#f35a3b7800a7062c8b34cae1bdcbf64733935149"
|
||||
version = "0.4.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.4.1#0aeafc8cfd0b7a3554170419b38c97948b0fb108"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"log",
|
||||
|
|
|
@ -8,17 +8,17 @@ edition = "2018"
|
|||
name = "neqo_glue"
|
||||
|
||||
[dependencies]
|
||||
neqo-http3 = { tag = "v0.4.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-transport = { tag = "v0.4.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-common = { tag = "v0.4.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-qpack = { tag = "v0.4.0", git = "https://github.com/mozilla/neqo" }
|
||||
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" }
|
||||
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.0"
|
||||
tag = "v0.4.1"
|
||||
git = "https://github.com/mozilla/neqo"
|
||||
default-features = false
|
||||
features = ["gecko"]
|
||||
|
|
|
@ -8,7 +8,7 @@ use neqo_http3::Error as Http3Error;
|
|||
use neqo_http3::{Http3Client, Http3ClientEvent, Http3State};
|
||||
use neqo_qpack::QpackSettings;
|
||||
use neqo_transport::Error as TransportError;
|
||||
use neqo_transport::{FixedConnectionIdManager, Output};
|
||||
use neqo_transport::{FixedConnectionIdManager, Output, QuicVersion};
|
||||
use nserror::*;
|
||||
use nsstring::*;
|
||||
use std::cell::RefCell;
|
||||
|
@ -76,6 +76,7 @@ impl NeqoHttp3Conn {
|
|||
local,
|
||||
remote,
|
||||
qpack_settings,
|
||||
QuicVersion::Draft27,
|
||||
) {
|
||||
Ok(c) => c,
|
||||
Err(_) => return Err(NS_ERROR_INVALID_ARG),
|
||||
|
|
|
@ -5,16 +5,16 @@ authors = ["Dragana Damjanovic <dragana.damjano@gmail.com>"]
|
|||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
neqo-transport = { tag = "v0.4.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-common = { tag = "v0.4.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-http3 = { tag = "v0.4.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-qpack = { tag = "v0.4.0", 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-http3 = { tag = "v0.4.1", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-qpack = { tag = "v0.4.1", 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.0"
|
||||
tag = "v0.4.1"
|
||||
git = "https://github.com/mozilla/neqo"
|
||||
default-features = false
|
||||
features = ["gecko"]
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"1ae9f454f1303aac9492c99376ce4dea910cb22a92b87a8e67184e4e336defd5","src/codec.rs":"c33b458cf1631073587edf6b6bd1baafecc7fe9e18d3eb5c3ddc6aaa00bd70c5","src/datagram.rs":"569f8d9e34d7ee17144bf63d34136ecd9778da0d337e513f338738c50284615e","src/incrdecoder.rs":"8d44c4437461cae023448312cab4045ad6e3f0c9eb8af2383f7132be40a9d917","src/lib.rs":"ae4fd37c38e71ffe5a2df59cc4c6db102724e16fab047ddefb213706c66bade1","src/log.rs":"b8da388073f72a21128d52b0d0c963e07a3d3cf3368438ae3a50be34b8add3a4","src/qlog.rs":"4f131c7e4c2bb5862b33a0d1746348a4f63f9b57cfa7a85dce1b59f80ecfaa7b","src/timer.rs":"706333bf1b07f65df9d18904b1cb269e4b80dee93a9b239dd8cb128b293955ae","tests/log.rs":"480b165b7907ec642c508b303d63005eee1427115d6973a349eaf6b2242ed18d"},"package":null}
|
||||
{"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}
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "neqo-common"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
authors = ["Bobby Holley <bobbyholley@gmail.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT/Apache-2.0"
|
||||
|
|
|
@ -41,9 +41,28 @@ pub fn hex(buf: &[u8]) -> String {
|
|||
ret
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn hex_snip_middle(buf: &[u8]) -> String {
|
||||
const SHOW_LEN: usize = 8;
|
||||
if buf.len() <= SHOW_LEN * 2 {
|
||||
hex_with_len(buf)
|
||||
} else {
|
||||
let mut ret = String::with_capacity(SHOW_LEN * 2 + 16);
|
||||
ret.push_str(&format!("[{}]: ", buf.len()));
|
||||
for b in &buf[..SHOW_LEN] {
|
||||
ret.push_str(&format!("{:02x}", b));
|
||||
}
|
||||
ret.push_str("..");
|
||||
for b in &buf[buf.len() - SHOW_LEN..] {
|
||||
ret.push_str(&format!("{:02x}", b));
|
||||
}
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn hex_with_len(buf: &[u8]) -> String {
|
||||
let mut ret = String::with_capacity(10 + buf.len() * 3);
|
||||
let mut ret = String::with_capacity(10 + buf.len() * 2);
|
||||
ret.push_str(&format!("[{}]: ", buf.len()));
|
||||
for b in buf {
|
||||
ret.push_str(&format!("{:02x}", b));
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"2123157cae77dac2ae0e3f40f08e5720a3662f7c1fdb5259cb1f8a9e72387020","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":"979eeb1d7da5342d3a5fd0836132a37f074711a6056d0dc64a91f86717bbd501","src/aead.rs":"b0ed05d399a32e4c923d4d385e4ae72d675d24c6cc86471f59a4edbe5cb2159a","src/agent.rs":"2841e3ae0b9a86990a44a0ecaa0da061b4eea15d782bd35232367b99482fa1f7","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":"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}
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "neqo-crypto"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
authors = ["Martin Thomson <mt@lowentropy.net>"]
|
||||
edition = "2018"
|
||||
build = "build.rs"
|
||||
|
|
|
@ -21,25 +21,31 @@ const BINDINGS_CONFIG: &str = "bindings.toml";
|
|||
// This is the format of a single section of the configuration file.
|
||||
#[derive(Deserialize)]
|
||||
struct Bindings {
|
||||
// types that are explicitly included
|
||||
types: Option<Vec<String>>,
|
||||
// functions that are explicitly included
|
||||
functions: Option<Vec<String>>,
|
||||
// variables (and `#define`s) that are explicitly included
|
||||
variables: Option<Vec<String>>,
|
||||
// types that should be explicitly marked as opaque
|
||||
opaque: Option<Vec<String>>,
|
||||
// enumerations that are turned into a module (without this, the enum is
|
||||
// mapped using the default, which means that the individual values are
|
||||
// formed with an underscore as <enum_type>_<enum_value_name>).
|
||||
enums: Option<Vec<String>>,
|
||||
/// types that are explicitly included
|
||||
#[serde(default)]
|
||||
types: Vec<String>,
|
||||
/// functions that are explicitly included
|
||||
#[serde(default)]
|
||||
functions: Vec<String>,
|
||||
/// variables (and `#define`s) that are explicitly included
|
||||
#[serde(default)]
|
||||
variables: Vec<String>,
|
||||
/// types that should be explicitly marked as opaque
|
||||
#[serde(default)]
|
||||
opaque: Vec<String>,
|
||||
/// enumerations that are turned into a module (without this, the enum is
|
||||
/// mapped using the default, which means that the individual values are
|
||||
/// formed with an underscore as <enum_type>_<enum_value_name>).
|
||||
#[serde(default)]
|
||||
enums: Vec<String>,
|
||||
|
||||
// Any item that is specifically excluded; if none of the types, functions,
|
||||
// or variables fields are specified, everything defined will be mapped,
|
||||
// so this can be used to limit that.
|
||||
exclude: Option<Vec<String>>,
|
||||
/// Any item that is specifically excluded; if none of the types, functions,
|
||||
/// or variables fields are specified, everything defined will be mapped,
|
||||
/// so this can be used to limit that.
|
||||
#[serde(default)]
|
||||
exclude: Vec<String>,
|
||||
|
||||
// Whether the file is to be interpreted as C++
|
||||
/// Whether the file is to be interpreted as C++
|
||||
#[serde(default)]
|
||||
cplusplus: bool,
|
||||
}
|
||||
|
@ -253,23 +259,22 @@ fn build_bindings(base: &str, bindings: &Bindings, flags: &[String], gecko: bool
|
|||
builder = builder.clang_args(flags);
|
||||
|
||||
// Apply the configuration.
|
||||
let empty: Vec<String> = vec![];
|
||||
for v in bindings.types.as_ref().unwrap_or_else(|| &empty).iter() {
|
||||
for v in &bindings.types {
|
||||
builder = builder.whitelist_type(v);
|
||||
}
|
||||
for v in bindings.functions.as_ref().unwrap_or_else(|| &empty).iter() {
|
||||
for v in &bindings.functions {
|
||||
builder = builder.whitelist_function(v);
|
||||
}
|
||||
for v in bindings.variables.as_ref().unwrap_or_else(|| &empty).iter() {
|
||||
for v in &bindings.variables {
|
||||
builder = builder.whitelist_var(v);
|
||||
}
|
||||
for v in bindings.exclude.as_ref().unwrap_or_else(|| &empty).iter() {
|
||||
for v in &bindings.exclude {
|
||||
builder = builder.blacklist_item(v);
|
||||
}
|
||||
for v in bindings.opaque.as_ref().unwrap_or_else(|| &empty).iter() {
|
||||
for v in &bindings.opaque {
|
||||
builder = builder.opaque_type(v);
|
||||
}
|
||||
for v in bindings.enums.as_ref().unwrap_or_else(|| &empty).iter() {
|
||||
for v in &bindings.enums {
|
||||
builder = builder.constified_enum_module(v);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ use crate::secrets::SecretHolder;
|
|||
use crate::ssl::{self, PRBool};
|
||||
use crate::time::TimeHolder;
|
||||
|
||||
use neqo_common::{hex, matches, qdebug, qinfo, qtrace, qwarn};
|
||||
use neqo_common::{hex_snip_middle, matches, qdebug, qinfo, qtrace, qwarn};
|
||||
use std::cell::RefCell;
|
||||
use std::convert::TryFrom;
|
||||
use std::ffi::CString;
|
||||
|
@ -720,7 +720,11 @@ impl Client {
|
|||
let resumption = resumption_ptr.as_mut().unwrap();
|
||||
let mut v = Vec::with_capacity(len as usize);
|
||||
v.extend_from_slice(std::slice::from_raw_parts(token, len as usize));
|
||||
qinfo!([format!("{:p}", fd)], "Got resumption token {}", hex(&v));
|
||||
qinfo!(
|
||||
[format!("{:p}", fd)],
|
||||
"Got resumption token {}",
|
||||
hex_snip_middle(&v)
|
||||
);
|
||||
*resumption = Some(v);
|
||||
ssl::SECSuccess
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"e155725388085fb02552cfd19ebc1a5f3391dbd31557f85ad50caa728ce68c19","src/client_events.rs":"8c19986b7372b36d1265d4a848b07b5c334511cbdfc02f313c54e551523c08f5","src/connection.rs":"cebdb535151ec5598161091c6b709c38852aa32f32855cee8f2c6129a2bcb5a0","src/connection_client.rs":"4ce2aec1b869ab4d683dc5599eeb266899768ed13e6fe277fa7bdb8b4df9682e","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":"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}
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "neqo-http3"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
authors = ["Dragana Damjanovic <dragana.damjano@gmail.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT/Apache-2.0"
|
||||
|
|
|
@ -19,8 +19,8 @@ use neqo_common::{
|
|||
use neqo_crypto::{agent::CertificateInfo, AuthenticationStatus, SecretAgentInfo};
|
||||
use neqo_qpack::QpackSettings;
|
||||
use neqo_transport::{
|
||||
AppError, Connection, ConnectionEvent, ConnectionIdManager, Output, StreamId, StreamType,
|
||||
ZeroRttState,
|
||||
AppError, Connection, ConnectionEvent, ConnectionIdManager, Output, QuicVersion, StreamId,
|
||||
StreamType, ZeroRttState,
|
||||
};
|
||||
use std::cell::RefCell;
|
||||
use std::fmt::Display;
|
||||
|
@ -69,9 +69,17 @@ impl Http3Client {
|
|||
local_addr: SocketAddr,
|
||||
remote_addr: SocketAddr,
|
||||
qpack_settings: QpackSettings,
|
||||
quic_version: QuicVersion,
|
||||
) -> Res<Self> {
|
||||
Ok(Self::new_with_conn(
|
||||
Connection::new_client(server_name, protocols, cid_manager, local_addr, remote_addr)?,
|
||||
Connection::new_client(
|
||||
server_name,
|
||||
protocols,
|
||||
cid_manager,
|
||||
local_addr,
|
||||
remote_addr,
|
||||
quic_version,
|
||||
)?,
|
||||
qpack_settings,
|
||||
))
|
||||
}
|
||||
|
@ -595,7 +603,10 @@ mod tests {
|
|||
use neqo_common::{matches, Encoder};
|
||||
use neqo_crypto::AntiReplay;
|
||||
use neqo_qpack::encoder::QPackEncoder;
|
||||
use neqo_transport::{CloseError, ConnectionEvent, FixedConnectionIdManager, State};
|
||||
use neqo_transport::{
|
||||
CloseError, ConnectionEvent, ConnectionIdManager, FixedConnectionIdManager, QuicVersion,
|
||||
State,
|
||||
};
|
||||
use test_fixture::{
|
||||
default_server, fixture_init, loopback, now, DEFAULT_ALPN, DEFAULT_SERVER_NAME,
|
||||
};
|
||||
|
@ -623,6 +634,7 @@ mod tests {
|
|||
max_table_size_decoder: 100,
|
||||
max_blocked_streams: 100,
|
||||
},
|
||||
QuicVersion::default(),
|
||||
)
|
||||
.expect("create a default client")
|
||||
}
|
||||
|
@ -2967,11 +2979,17 @@ 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 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(FixedConnectionIdManager::new(10))),
|
||||
Rc::new(RefCell::new(cid_mgr)),
|
||||
QuicVersion::default(),
|
||||
initial_source_cid,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"23a69b4d2c9d585cb41be938442a7003beb73dd75c4ede25151d7ecf9365fde9","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":"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}
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "neqo-qpack"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
authors = ["Dragana Damjanovic <dragana.damjano@gmail.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT/Apache-2.0"
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"0a1d4ce17ba9db0b2a0b55cded951ffb59a4e72298b1ac876adbfc799c07994a","TODO":"d759cb804b32fa9d96ea8d3574a3c4073da9fe6a0b02b708a0e22cce5a5b4a0f","src/cc.rs":"60d6de4376ba77801490a400a90078f93b5300aa24b16838b38a1bad805b784e","src/cid.rs":"54e0f9c330014d296450f80f51b7031eee674b250d4ce24193b6d785b1d27f4f","src/connection.rs":"410937048e364eccd993872950e80b3b65314a61c65e47cdcbbd03d7ffabcb73","src/crypto.rs":"d00318e169b9634ab241e1dad0ec83ecfb93f9944b44891c850108e73f81ccd2","src/dump.rs":"d69ccb0e3b240823b886a791186afbac9f2e26d1f1f67a55dbf86f8cd3e6203e","src/events.rs":"deee6ef1112034582af770212bb70ed2cdcd2b1b8bb167c9118ef39bbf454451","src/flow_mgr.rs":"0b1c6e7587e411635723207ecface6c62d1243599dd017745c61eb94805b9886","src/frame.rs":"5f08b061f8fb7c2cc809116c5638c64d72646d914c688648b39345b775bb0246","src/lib.rs":"70b1b384d538b0e14c1843077848d4a00619e1f8316c23cfb6ba7ec3cb02cee0","src/pace.rs":"2cbc141722d75c87e99eb4e35da1479c47d55d8945f6c252c221543720c283ae","src/packet.rs":"b621ff1521d223345ff54650d94184f54596089b5d34edcfa68b4aae64d6be52","src/path.rs":"140365a03b9e226c0b03a1c3dba6e5235829006168da055c78b69d26bd0c98c7","src/qlog.rs":"92fff8f49c817090a7dbe39060543c4c7a9e45863cf5a430abc2e124d9050d6f","src/recovery.rs":"93e58b57438803709a6468345124655fc3ccc96d13d6514c4fb3e702a15b6f56","src/recv_stream.rs":"0650949aa8baae9e20c57eb2283490b782c41e6c67e9c093fc358145149e386f","src/send_stream.rs":"cd834ebd4386a776d897b1a5e52cad839784e389da8e2543ba1fb57649225cbd","src/server.rs":"84340521f8d29d4e6f6de6af787ce0f4c640df871fad72364d18fb3721151dd9","src/stats.rs":"a276bd9902939091578d3bcc95aa7dd0b32f5d29e528c12e7b93a0ab88474478","src/stream_id.rs":"db11def2ed81ef7c456c7c47827121c0a9ff54ac85228e6db6c790db8944febe","src/tparams.rs":"3c419a9f0fb9cc7edf6ae5b63bab9ecb5abbca3663b4615b1df37447b425f610","src/tracking.rs":"965d0bffc4c6171833a1e3ccb3d7cc31242a0e9f3c5ff77f925aa3a6594b167f","tests/conn_vectors.rs":"3de474009e75e0d283792daae4cb0eac7a1be00a4a6cfab6132c775fbefb1363","tests/connection.rs":"a93985c199a9ef987106f4a20b35ebf803cdbbb855c07b1362b403eed7101ef8","tests/server.rs":"1daefe9fea17ab9f45c57b805d357538d115068e168dc4d6bfc46f71403a986f"},"package":null}
|
||||
{"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}
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "neqo-transport"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
authors = ["EKR <ekr@rtfm.com>", "Andy Grover <agrover@mozilla.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT/Apache-2.0"
|
||||
|
|
|
@ -11,6 +11,7 @@ use neqo_crypto::random;
|
|||
|
||||
use std::borrow::Borrow;
|
||||
use std::cmp::max;
|
||||
use std::convert::AsRef;
|
||||
|
||||
pub const MAX_CONNECTION_ID_LEN: usize = 20;
|
||||
|
||||
|
@ -33,11 +34,17 @@ impl ConnectionId {
|
|||
Self::generate(len)
|
||||
}
|
||||
|
||||
pub fn as_ref(&self) -> ConnectionIdRef {
|
||||
pub fn as_cid_ref(&self) -> ConnectionIdRef {
|
||||
ConnectionIdRef::from(&self.cid[..])
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for ConnectionId {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.borrow()
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<[u8]> for ConnectionId {
|
||||
fn borrow(&self) -> &[u8] {
|
||||
&self.cid
|
||||
|
|
|
@ -19,8 +19,8 @@ use std::time::{Duration, Instant};
|
|||
use smallvec::SmallVec;
|
||||
|
||||
use neqo_common::{
|
||||
hex, matches, qdebug, qerror, qinfo, qlog::NeqoQlog, qtrace, qwarn, Datagram, Decoder, Encoder,
|
||||
Role,
|
||||
hex, hex_snip_middle, matches, qdebug, qerror, qinfo, qlog::NeqoQlog, qtrace, qwarn, Datagram,
|
||||
Decoder, Encoder, Role,
|
||||
};
|
||||
use neqo_crypto::agent::CertificateInfo;
|
||||
use neqo_crypto::{
|
||||
|
@ -37,7 +37,9 @@ use crate::frame::{
|
|||
AckRange, CloseError, Frame, FrameType, StreamType, FRAME_TYPE_CONNECTION_CLOSE_APPLICATION,
|
||||
FRAME_TYPE_CONNECTION_CLOSE_TRANSPORT,
|
||||
};
|
||||
use crate::packet::{DecryptedPacket, PacketBuilder, PacketNumber, PacketType, PublicPacket};
|
||||
use crate::packet::{
|
||||
DecryptedPacket, PacketBuilder, PacketNumber, PacketType, PublicPacket, QuicVersion,
|
||||
};
|
||||
use crate::path::Path;
|
||||
use crate::qlog;
|
||||
use crate::recovery::{LossRecovery, RecoveryToken, SendProfile, GRANULARITY};
|
||||
|
@ -209,14 +211,14 @@ impl ConnectionIdManager for FixedConnectionIdManager {
|
|||
|
||||
struct RetryInfo {
|
||||
token: Vec<u8>,
|
||||
odcid: ConnectionId,
|
||||
retry_source_cid: ConnectionId,
|
||||
}
|
||||
|
||||
impl RetryInfo {
|
||||
fn new(odcid: ConnectionId) -> Self {
|
||||
fn new(retry_source_cid: ConnectionId, token: Vec<u8>) -> Self {
|
||||
Self {
|
||||
token: Vec::new(),
|
||||
odcid,
|
||||
token,
|
||||
retry_source_cid,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -285,13 +287,14 @@ impl IdleTimeout {
|
|||
}
|
||||
}
|
||||
|
||||
/// StateManagement manages whether we need to send HANDSHAKE_DONE and CONNECTION_CLOSE.
|
||||
/// `StateSignaling` manages whether we need to send HANDSHAKE_DONE and CONNECTION_CLOSE.
|
||||
/// Valid state transitions are:
|
||||
/// * Idle -> HandshakeDone: at the server when the handshake completes
|
||||
/// * HandshakeDone -> Idle: when a HANDSHAKE_DONE frame is sent
|
||||
/// * Idle/HandshakeDone -> Closing/Draining: when closing or draining
|
||||
/// * Closing/Draining -> CloseSent: after sending CONNECTION_CLOSE
|
||||
/// * CloseSent -> Closing: any time a new CONNECTION_CLOSE is needed
|
||||
/// * -> Reset: from any state in case of a stateless reset
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
enum StateSignaling {
|
||||
Idle,
|
||||
|
@ -302,6 +305,7 @@ enum StateSignaling {
|
|||
/// This state saves the frame that might need to be sent again.
|
||||
/// If it is `None`, then we are draining and don't send.
|
||||
CloseSent(Option<Frame>),
|
||||
Reset,
|
||||
}
|
||||
|
||||
impl StateSignaling {
|
||||
|
@ -341,7 +345,9 @@ impl StateSignaling {
|
|||
frame_type: FrameType,
|
||||
message: impl AsRef<str>,
|
||||
) {
|
||||
*self = Self::Closing(Self::make_close_frame(error, frame_type, message));
|
||||
if *self != Self::Reset {
|
||||
*self = Self::Closing(Self::make_close_frame(error, frame_type, message));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn drain(
|
||||
|
@ -350,7 +356,9 @@ impl StateSignaling {
|
|||
frame_type: FrameType,
|
||||
message: impl AsRef<str>,
|
||||
) {
|
||||
*self = Self::Draining(Self::make_close_frame(error, frame_type, message));
|
||||
if *self != Self::Reset {
|
||||
*self = Self::Draining(Self::make_close_frame(error, frame_type, message));
|
||||
}
|
||||
}
|
||||
|
||||
/// If a close is pending, take a frame.
|
||||
|
@ -379,6 +387,11 @@ impl StateSignaling {
|
|||
*self = Self::Closing(frame);
|
||||
}
|
||||
}
|
||||
|
||||
/// We just got a stateless reset. Terminate.
|
||||
pub fn reset(&mut self) {
|
||||
*self = Self::Reset;
|
||||
}
|
||||
}
|
||||
|
||||
/// A QUIC Connection
|
||||
|
@ -411,6 +424,15 @@ pub struct Connection {
|
|||
/// During the handshake at the server, it also includes the randomized DCID pick by the client.
|
||||
valid_cids: Vec<ConnectionId>,
|
||||
retry_info: Option<RetryInfo>,
|
||||
|
||||
/// Since we need to communicate this to our peer in tparams, setting this
|
||||
/// value is part of constructing the struct.
|
||||
local_initial_source_cid: ConnectionId,
|
||||
/// Checked against tparam value from peer
|
||||
remote_initial_source_cid: Option<ConnectionId>,
|
||||
/// Checked against tparam value from peer
|
||||
remote_original_destination_cid: Option<ConnectionId>,
|
||||
|
||||
pub(crate) crypto: Crypto,
|
||||
pub(crate) acks: AckTracker,
|
||||
idle_timeout: IdleTimeout,
|
||||
|
@ -425,6 +447,8 @@ pub struct Connection {
|
|||
token: Option<Vec<u8>>,
|
||||
stats: Stats,
|
||||
qlog: Option<NeqoQlog>,
|
||||
|
||||
quic_version: QuicVersion,
|
||||
}
|
||||
|
||||
impl Debug for Connection {
|
||||
|
@ -445,6 +469,7 @@ impl Connection {
|
|||
cid_manager: CidMgr,
|
||||
local_addr: SocketAddr,
|
||||
remote_addr: SocketAddr,
|
||||
quic_version: QuicVersion,
|
||||
) -> Res<Self> {
|
||||
let dcid = ConnectionId::generate_initial();
|
||||
let scid = cid_manager.borrow_mut().generate_cid();
|
||||
|
@ -454,10 +479,17 @@ impl Connection {
|
|||
cid_manager,
|
||||
None,
|
||||
protocols,
|
||||
Some(Path::new(local_addr, remote_addr, scid, dcid.clone())),
|
||||
);
|
||||
Some(Path::new(
|
||||
local_addr,
|
||||
remote_addr,
|
||||
scid.clone(),
|
||||
dcid.clone(),
|
||||
)),
|
||||
quic_version,
|
||||
scid,
|
||||
)?;
|
||||
c.crypto.states.init(Role::Client, &dcid);
|
||||
c.retry_info = Some(RetryInfo::new(dcid));
|
||||
c.remote_original_destination_cid = Some(dcid);
|
||||
Ok(c)
|
||||
}
|
||||
|
||||
|
@ -467,15 +499,19 @@ impl Connection {
|
|||
protocols: &[impl AsRef<str>],
|
||||
anti_replay: &AntiReplay,
|
||||
cid_manager: CidMgr,
|
||||
quic_version: QuicVersion,
|
||||
local_initial_source_cid: ConnectionId,
|
||||
) -> Res<Self> {
|
||||
Ok(Self::new(
|
||||
Self::new(
|
||||
Role::Server,
|
||||
Server::new(certs)?.into(),
|
||||
cid_manager,
|
||||
Some(anti_replay),
|
||||
protocols,
|
||||
None,
|
||||
))
|
||||
quic_version,
|
||||
local_initial_source_cid,
|
||||
)
|
||||
}
|
||||
|
||||
fn set_tp_defaults(tps: &mut TransportParameters) {
|
||||
|
@ -498,6 +534,7 @@ impl Connection {
|
|||
tps.set_empty(tparams::DISABLE_MIGRATION);
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn new(
|
||||
role: Role,
|
||||
agent: Agent,
|
||||
|
@ -505,13 +542,19 @@ impl Connection {
|
|||
anti_replay: Option<&AntiReplay>,
|
||||
protocols: &[impl AsRef<str>],
|
||||
path: Option<Path>,
|
||||
) -> Self {
|
||||
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 crypto = Crypto::new(agent, protocols, tphandler.clone(), anti_replay)
|
||||
.expect("TLS should be configured successfully");
|
||||
tphandler.borrow_mut().local.set_bytes(
|
||||
tparams::INITIAL_SOURCE_CONNECTION_ID,
|
||||
local_initial_source_cid.to_vec(),
|
||||
);
|
||||
|
||||
Self {
|
||||
let crypto = Crypto::new(agent, protocols, tphandler.clone(), anti_replay)?;
|
||||
|
||||
Ok(Self {
|
||||
role,
|
||||
state: State::Init,
|
||||
cid_manager,
|
||||
|
@ -520,6 +563,9 @@ impl Connection {
|
|||
tps: tphandler,
|
||||
zero_rtt_state: ZeroRttState::Init,
|
||||
retry_info: None,
|
||||
local_initial_source_cid,
|
||||
remote_initial_source_cid: None,
|
||||
remote_original_destination_cid: None,
|
||||
crypto,
|
||||
acks: AckTracker::default(),
|
||||
idle_timeout: IdleTimeout::default(),
|
||||
|
@ -534,7 +580,8 @@ impl Connection {
|
|||
token: None,
|
||||
stats: Stats::default(),
|
||||
qlog: None,
|
||||
}
|
||||
quic_version,
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the local path.
|
||||
|
@ -564,13 +611,25 @@ impl Connection {
|
|||
}
|
||||
}
|
||||
|
||||
/// Set the connection ID that was originally chosen by the client.
|
||||
pub(crate) fn original_connection_id(&mut self, odcid: &ConnectionId) {
|
||||
/// 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_CONNECTION_ID, odcid.to_vec());
|
||||
.set_bytes(tparams::ORIGINAL_DESTINATION_CONNECTION_ID, odcid.to_vec());
|
||||
self.remote_original_destination_cid = Some(odcid);
|
||||
}
|
||||
|
||||
/// 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(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Set ALPN preferences. Strings that appear earlier in the list are given
|
||||
|
@ -612,7 +671,7 @@ impl Connection {
|
|||
.encode(enc_inner);
|
||||
});
|
||||
enc.encode(&t[..]);
|
||||
qinfo!("resumption token {}", hex(&enc[..]));
|
||||
qinfo!("resumption token {}", hex_snip_middle(&enc[..]));
|
||||
Some(enc.into())
|
||||
}
|
||||
None => None,
|
||||
|
@ -630,7 +689,7 @@ impl Connection {
|
|||
qerror!([self], "set token in state {:?}", self.state);
|
||||
return Err(Error::ConnectionState);
|
||||
}
|
||||
qinfo!([self], "resumption token {}", hex(token));
|
||||
qinfo!([self], "resumption token {}", hex_snip_middle(token));
|
||||
let mut dec = Decoder::from(token);
|
||||
|
||||
let smoothed_rtt = match dec.decode_varint() {
|
||||
|
@ -791,8 +850,8 @@ impl Connection {
|
|||
|
||||
/// Call in to process activity on the connection. Either new packets have
|
||||
/// arrived or a timeout has expired (or both).
|
||||
pub fn process_input(&mut self, dgram: Datagram, now: Instant) {
|
||||
let res = self.input(dgram, now);
|
||||
pub fn process_input(&mut self, d: Datagram, now: Instant) {
|
||||
let res = self.input(d, now);
|
||||
self.absorb_error(now, res);
|
||||
self.cleanup_streams();
|
||||
}
|
||||
|
@ -899,9 +958,8 @@ impl Connection {
|
|||
}
|
||||
|
||||
fn handle_retry(&mut self, packet: PublicPacket) -> Res<()> {
|
||||
qdebug!([self], "received Retry");
|
||||
debug_assert!(self.retry_info.is_some());
|
||||
if !self.retry_info.as_ref().unwrap().token.is_empty() {
|
||||
qinfo!([self], "received Retry");
|
||||
if self.retry_info.is_some() {
|
||||
qinfo!([self], "Dropping extra Retry");
|
||||
self.stats.dropped_rx += 1;
|
||||
return Ok(());
|
||||
|
@ -911,7 +969,7 @@ impl Connection {
|
|||
self.stats.dropped_rx += 1;
|
||||
return Ok(());
|
||||
}
|
||||
if !packet.is_valid_retry(&self.retry_info.as_ref().unwrap().odcid) {
|
||||
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;
|
||||
return Ok(());
|
||||
|
@ -923,12 +981,19 @@ impl Connection {
|
|||
qinfo!([self], "No path, but we received a Retry");
|
||||
return Err(Error::InternalError);
|
||||
};
|
||||
self.retry_info.as_mut().unwrap().token = packet.token().to_vec();
|
||||
|
||||
qinfo!(
|
||||
[self],
|
||||
"Valid Retry received, token={}",
|
||||
hex(packet.token())
|
||||
"Valid Retry received, token={} scid={}",
|
||||
hex(packet.token()),
|
||||
packet.scid()
|
||||
);
|
||||
|
||||
self.retry_info = Some(RetryInfo::new(
|
||||
ConnectionId::from(packet.scid()),
|
||||
packet.token().to_vec(),
|
||||
));
|
||||
|
||||
let lost_packets = self.loss_recovery.retry();
|
||||
self.handle_lost_packets(&lost_packets);
|
||||
|
||||
|
@ -946,6 +1011,45 @@ impl Connection {
|
|||
}
|
||||
}
|
||||
|
||||
fn token_equal(a: &[u8; 16], b: &[u8; 16]) -> bool {
|
||||
// rustc might decide to optimize this and make this non-constant-time
|
||||
// with respect to `t`, but it doesn't appear to currently.
|
||||
let mut c = 0;
|
||||
for (&a, &b) in a.iter().zip(b) {
|
||||
c |= a ^ b;
|
||||
}
|
||||
c == 0
|
||||
}
|
||||
|
||||
fn is_stateless_reset(&self, d: &Datagram) -> bool {
|
||||
if d.len() < 16 {
|
||||
return false;
|
||||
}
|
||||
let token = <&[u8; 16]>::try_from(&d[d.len() - 16..]).unwrap();
|
||||
// TODO(mt) only check the path that matches the datagram.
|
||||
self.path
|
||||
.as_ref()
|
||||
.map(|p| p.reset_token())
|
||||
.flatten()
|
||||
.map_or(false, |t| Self::token_equal(t, token))
|
||||
}
|
||||
|
||||
fn check_stateless_reset(&mut self, d: &Datagram, now: Instant) -> Res<()> {
|
||||
if self.is_stateless_reset(d) {
|
||||
// Failing to process a packet in a datagram might
|
||||
// indicate that there is a stateless reset present.
|
||||
qdebug!([self], "Stateless reset: {}", hex(&d[d.len() - 16..]));
|
||||
self.state_signaling.reset();
|
||||
self.set_state(State::Draining {
|
||||
error: ConnectionError::Transport(Error::StatelessReset),
|
||||
timeout: self.get_closing_period_time(now),
|
||||
});
|
||||
Err(Error::StatelessReset)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn input(&mut self, d: Datagram, now: Instant) -> Res<Vec<(Frame, PNSpace)>> {
|
||||
let mut slc = &d[..];
|
||||
let mut frames = Vec::new();
|
||||
|
@ -958,22 +1062,33 @@ impl Connection {
|
|||
match PublicPacket::decode(slc, self.cid_manager.borrow().as_decoder()) {
|
||||
Ok((packet, remainder)) => (packet, remainder),
|
||||
Err(e) => {
|
||||
qdebug!([self], "Garbage packet: {} {}", e, hex(slc));
|
||||
qdebug!([self], "Garbage packet: {}", e);
|
||||
qtrace!([self], "Garbage packet contents: {}", hex(slc));
|
||||
self.stats.dropped_rx += 1;
|
||||
return Ok(frames);
|
||||
break;
|
||||
}
|
||||
}; // TODO(mt) use in place of res, and allow errors
|
||||
};
|
||||
self.stats.packets_rx += 1;
|
||||
match (packet.packet_type(), &self.state, &self.role) {
|
||||
(PacketType::Initial, State::Init, Role::Server) => {
|
||||
if !packet.is_valid_initial() {
|
||||
self.stats.dropped_rx += 1;
|
||||
return Ok(frames);
|
||||
break;
|
||||
}
|
||||
qinfo!([self], "Received valid Initial packet");
|
||||
qinfo!(
|
||||
[self],
|
||||
"Received valid Initial packet with scid {:?} dcid {:?}",
|
||||
packet.scid(),
|
||||
packet.dcid()
|
||||
);
|
||||
self.set_state(State::WaitInitial);
|
||||
self.loss_recovery.start_pacer(now);
|
||||
self.crypto.states.init(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()));
|
||||
}
|
||||
}
|
||||
(PacketType::VersionNegotiation, State::WaitInitial, Role::Client) => {
|
||||
self.set_state(State::Closed(ConnectionError::Transport(
|
||||
|
@ -983,14 +1098,14 @@ impl Connection {
|
|||
}
|
||||
(PacketType::Retry, State::WaitInitial, Role::Client) => {
|
||||
self.handle_retry(packet)?;
|
||||
return Ok(frames);
|
||||
break;
|
||||
}
|
||||
(PacketType::VersionNegotiation, ..)
|
||||
| (PacketType::Retry, ..)
|
||||
| (PacketType::OtherVersion, ..) => {
|
||||
qwarn!("dropping {:?}", packet.packet_type());
|
||||
self.stats.dropped_rx += 1;
|
||||
return Ok(frames);
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
@ -999,14 +1114,14 @@ impl Connection {
|
|||
State::Init => {
|
||||
qinfo!([self], "Received message while in Init state");
|
||||
self.stats.dropped_rx += 1;
|
||||
return Ok(frames);
|
||||
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;
|
||||
return Ok(frames);
|
||||
break;
|
||||
}
|
||||
if self.role == Role::Server && packet.packet_type() == PacketType::Handshake {
|
||||
// Server has received a Handshake packet -> discard Initial keys and states
|
||||
|
@ -1017,12 +1132,12 @@ impl Connection {
|
|||
// Don't bother processing the packet. Instead ask to get a
|
||||
// new close frame.
|
||||
self.state_signaling.send_close();
|
||||
return Ok(frames);
|
||||
break;
|
||||
}
|
||||
State::Draining { .. } | State::Closed(..) => {
|
||||
// Do nothing.
|
||||
self.stats.dropped_rx += 1;
|
||||
return Ok(frames);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1030,7 +1145,6 @@ impl Connection {
|
|||
|
||||
let pto = self.loss_recovery.pto();
|
||||
let payload = packet.decrypt(&mut self.crypto.states, now + pto);
|
||||
slc = remainder;
|
||||
if let Ok(payload) = payload {
|
||||
// TODO(ekr@rtfm.com): Have the server blow away the initial
|
||||
// crypto state if this fails? Otherwise, we will get a panic
|
||||
|
@ -1059,7 +1173,14 @@ impl Connection {
|
|||
// 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;
|
||||
if slc.len() == d.len() {
|
||||
self.check_stateless_reset(&d, now)?
|
||||
}
|
||||
}
|
||||
slc = remainder;
|
||||
}
|
||||
if slc.len() == d.len() {
|
||||
self.check_stateless_reset(&d, now)?
|
||||
}
|
||||
Ok(frames)
|
||||
}
|
||||
|
@ -1122,7 +1243,7 @@ impl Connection {
|
|||
fn initialize_path(&mut self, packet: &PublicPacket, d: &Datagram) {
|
||||
debug_assert!(self.path.is_none());
|
||||
let mut p = Path::from_datagram(&d, ConnectionId::from(packet.scid()));
|
||||
p.add_local_cid(self.cid_manager.borrow_mut().generate_cid());
|
||||
p.add_local_cid(self.local_initial_source_cid.clone());
|
||||
self.path = Some(p);
|
||||
}
|
||||
|
||||
|
@ -1131,6 +1252,7 @@ impl Connection {
|
|||
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);
|
||||
|
||||
|
@ -1149,6 +1271,7 @@ 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(())
|
||||
|
@ -1195,6 +1318,7 @@ impl Connection {
|
|||
encoder: Encoder,
|
||||
tx: &CryptoDxState,
|
||||
retry_info: &Option<RetryInfo>,
|
||||
quic_version: QuicVersion,
|
||||
) -> (PacketType, PacketNumber, PacketBuilder) {
|
||||
let pt = match space {
|
||||
PNSpace::Initial => PacketType::Initial,
|
||||
|
@ -1218,7 +1342,13 @@ impl Connection {
|
|||
path.local_cid(),
|
||||
);
|
||||
|
||||
PacketBuilder::long(encoder, pt, path.remote_cid(), path.local_cid())
|
||||
PacketBuilder::long(
|
||||
encoder,
|
||||
pt,
|
||||
quic_version,
|
||||
path.remote_cid(),
|
||||
path.local_cid(),
|
||||
)
|
||||
};
|
||||
if pt == PacketType::Initial {
|
||||
builder.initial_token(if let Some(info) = retry_info {
|
||||
|
@ -1247,7 +1377,8 @@ impl Connection {
|
|||
continue;
|
||||
}
|
||||
|
||||
let (_, _, mut builder) = Self::build_packet_header(path, *space, encoder, tx, &None);
|
||||
let (_, _, mut builder) =
|
||||
Self::build_packet_header(path, *space, encoder, tx, &None, self.quic_version);
|
||||
// ConnectionError::Application is only allowed at 1RTT.
|
||||
if *space == PNSpace::ApplicationData {
|
||||
frame.marshal(&mut builder);
|
||||
|
@ -1339,8 +1470,14 @@ impl Connection {
|
|||
};
|
||||
|
||||
let header_start = encoder.len();
|
||||
let (pt, pn, mut builder) =
|
||||
Self::build_packet_header(path, *space, encoder, tx, &self.retry_info);
|
||||
let (pt, pn, mut builder) = Self::build_packet_header(
|
||||
path,
|
||||
*space,
|
||||
encoder,
|
||||
tx,
|
||||
&self.retry_info,
|
||||
self.quic_version,
|
||||
);
|
||||
let payload_start = builder.len();
|
||||
|
||||
// Work out if we have space left.
|
||||
|
@ -1486,28 +1623,142 @@ impl Connection {
|
|||
}
|
||||
}
|
||||
|
||||
fn validate_odcid(&mut self) -> Res<()> {
|
||||
// Here we drop our Retry state then validate it.
|
||||
if let Some(info) = self.retry_info.take() {
|
||||
if info.token.is_empty() {
|
||||
Ok(())
|
||||
} else {
|
||||
let tph = self.tps.borrow();
|
||||
let tp = tph.remote().get_bytes(tparams::ORIGINAL_CONNECTION_ID);
|
||||
if let Some(odcid_tp) = tp {
|
||||
if odcid_tp[..] == info.odcid[..] {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::InvalidRetry)
|
||||
}
|
||||
} else {
|
||||
Err(Error::InvalidRetry)
|
||||
/// Process the final set of transport parameters.
|
||||
fn process_tps(&mut self) -> Res<()> {
|
||||
self.validate_cids()?;
|
||||
if let Some(token) = self
|
||||
.tps
|
||||
.borrow()
|
||||
.remote
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.get_bytes(tparams::STATELESS_RESET_TOKEN)
|
||||
{
|
||||
let reset_token = <[u8; 16]>::try_from(token).unwrap().to_owned();
|
||||
self.path.as_mut().unwrap().set_reset_token(reset_token);
|
||||
}
|
||||
self.set_initial_limits();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_cids(&mut self) -> Res<()> {
|
||||
match self.quic_version {
|
||||
QuicVersion::Draft27 => self.validate_cids_draft_27(),
|
||||
_ => self.validate_cids_draft_28_plus(),
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_cids_draft_27(&mut self) -> Res<()> {
|
||||
if let Some(info) = &self.retry_info {
|
||||
debug_assert!(!info.token.is_empty());
|
||||
let tph = self.tps.borrow();
|
||||
let tp = tph
|
||||
.remote()
|
||||
.get_bytes(tparams::ORIGINAL_DESTINATION_CONNECTION_ID);
|
||||
if self
|
||||
.remote_original_destination_cid
|
||||
.as_ref()
|
||||
.map(ConnectionId::as_cid_ref)
|
||||
!= tp.map(ConnectionIdRef::from)
|
||||
{
|
||||
return Err(Error::InvalidRetry);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_cids_draft_28_plus(&mut self) -> Res<()> {
|
||||
let tph = self.tps.borrow();
|
||||
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);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debug_assert_eq!(self.role, Role::Server);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handshake(&mut self, now: Instant, space: PNSpace, data: Option<&[u8]>) -> Res<()> {
|
||||
|
@ -1860,8 +2111,7 @@ impl Connection {
|
|||
// Setting application keys has to occur after 0-RTT rejection.
|
||||
let pto = self.loss_recovery.pto();
|
||||
self.crypto.install_application_keys(now + pto)?;
|
||||
self.validate_odcid()?;
|
||||
self.set_initial_limits();
|
||||
self.process_tps()?;
|
||||
self.set_state(State::Connected);
|
||||
if self.role == Role::Server {
|
||||
self.state_signaling.handshake_done();
|
||||
|
@ -2286,16 +2536,23 @@ mod tests {
|
|||
Rc::new(RefCell::new(FixedConnectionIdManager::new(3))),
|
||||
loopback(),
|
||||
loopback(),
|
||||
QuicVersion::default(),
|
||||
)
|
||||
.expect("create a default client")
|
||||
}
|
||||
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(FixedConnectionIdManager::new(5))),
|
||||
Rc::new(RefCell::new(cid_mgr)),
|
||||
QuicVersion::default(),
|
||||
local_initial_source_cid,
|
||||
)
|
||||
.expect("create a default server")
|
||||
}
|
||||
|
@ -2627,6 +2884,7 @@ mod tests {
|
|||
Rc::new(RefCell::new(FixedConnectionIdManager::new(9))),
|
||||
loopback(),
|
||||
loopback(),
|
||||
QuicVersion::default(),
|
||||
)
|
||||
.unwrap();
|
||||
let mut server = default_server();
|
||||
|
@ -2878,11 +3136,17 @@ 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(FixedConnectionIdManager::new(10))),
|
||||
Rc::new(RefCell::new(cid_mgr)),
|
||||
QuicVersion::default(),
|
||||
local_initial_source_cid,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
@ -3235,11 +3499,17 @@ mod tests {
|
|||
#[test]
|
||||
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(FixedConnectionIdManager::new(6))),
|
||||
Rc::new(RefCell::new(cid_mgr)),
|
||||
QuicVersion::default(),
|
||||
local_initial_source_cid,
|
||||
)
|
||||
.expect("create a server");
|
||||
|
||||
|
@ -5083,4 +5353,21 @@ mod tests {
|
|||
);
|
||||
assert_eq!(1, client.stats().dropped_rx);
|
||||
}
|
||||
|
||||
/// Test that a client can handle a stateless reset correctly.
|
||||
#[test]
|
||||
fn stateless_reset_client() {
|
||||
let mut client = default_client();
|
||||
let mut server = default_server();
|
||||
server
|
||||
.set_local_tparam(
|
||||
tparams::STATELESS_RESET_TOKEN,
|
||||
TransportParameter::Bytes(vec![77; 16]),
|
||||
)
|
||||
.unwrap();
|
||||
connect_force_idle(&mut client, &mut server);
|
||||
|
||||
client.process_input(Datagram::new(loopback(), loopback(), vec![77; 21]), now());
|
||||
assert!(matches!(client.state(), State::Draining { .. }));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,12 +35,9 @@ pub use self::connection::{Connection, FixedConnectionIdManager, Output, State,
|
|||
pub use self::events::{ConnectionEvent, ConnectionEvents};
|
||||
pub use self::frame::CloseError;
|
||||
pub use self::frame::StreamType;
|
||||
pub use self::packet::QuicVersion;
|
||||
pub use self::stream_id::StreamId;
|
||||
|
||||
/// The supported version of the QUIC protocol.
|
||||
pub type Version = u32;
|
||||
pub const QUIC_VERSION: Version = 0xff00_0000 + 27;
|
||||
|
||||
const LOCAL_IDLE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(30); // 30 second
|
||||
|
||||
type TransportError = u64;
|
||||
|
@ -89,12 +86,12 @@ pub enum Error {
|
|||
PacketNumberOverlap,
|
||||
PeerApplicationError(AppError),
|
||||
PeerError(TransportError),
|
||||
StatelessReset,
|
||||
TooMuchData,
|
||||
UnexpectedMessage,
|
||||
UnknownFrameType,
|
||||
VersionNegotiation,
|
||||
WrongRole,
|
||||
KeysDiscarded,
|
||||
}
|
||||
|
||||
impl Error {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
use crate::cid::{ConnectionId, ConnectionIdDecoder, ConnectionIdRef, MAX_CONNECTION_ID_LEN};
|
||||
use crate::crypto::{CryptoDxState, CryptoStates};
|
||||
use crate::tracking::PNSpace;
|
||||
use crate::{Error, Res, Version, QUIC_VERSION};
|
||||
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};
|
||||
|
@ -37,6 +37,7 @@ const SAMPLE_SIZE: usize = 16;
|
|||
const SAMPLE_OFFSET: usize = 4;
|
||||
|
||||
pub type PacketNumber = u64;
|
||||
type Version = u32;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum PacketType {
|
||||
|
@ -62,6 +63,41 @@ impl PacketType {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum QuicVersion {
|
||||
Draft27,
|
||||
Draft28,
|
||||
}
|
||||
|
||||
impl QuicVersion {
|
||||
pub fn as_u32(self) -> Version {
|
||||
match self {
|
||||
Self::Draft27 => 0xff00_0000 + 27,
|
||||
Self::Draft28 => 0xff00_0000 + 28,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for QuicVersion {
|
||||
fn default() -> Self {
|
||||
Self::Draft28
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Version> for QuicVersion {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(ver: Version) -> Res<Self> {
|
||||
if ver == 0xff00_0000 + 27 {
|
||||
Ok(Self::Draft27)
|
||||
} else if ver == 0xff00_0000 + 28 {
|
||||
Ok(Self::Draft28)
|
||||
} else {
|
||||
Err(Error::VersionNegotiation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The AEAD used for Retry is fixed, so use this.
|
||||
fn make_retry_aead() -> Aead {
|
||||
#[cfg(debug_assertions)]
|
||||
|
@ -131,12 +167,13 @@ impl PacketBuilder {
|
|||
pub fn long(
|
||||
mut encoder: Encoder,
|
||||
pt: PacketType,
|
||||
quic_version: QuicVersion,
|
||||
dcid: &ConnectionId,
|
||||
scid: &ConnectionId,
|
||||
) -> Self {
|
||||
let header_start = encoder.len();
|
||||
encoder.encode_byte(PACKET_BIT_LONG | PACKET_BIT_FIXED_QUIC | pt.code() << 4);
|
||||
encoder.encode_uint(4, QUIC_VERSION);
|
||||
encoder.encode_uint(4, quic_version.as_u32());
|
||||
encoder.encode_vec(1, dcid);
|
||||
encoder.encode_vec(1, scid);
|
||||
Self {
|
||||
|
@ -239,7 +276,13 @@ impl PacketBuilder {
|
|||
/// As this is a simple packet, this is just an associated function.
|
||||
/// As Retry is odd (it has to be constructed with leading bytes),
|
||||
/// this returns a Vec<u8> rather than building on an encoder.
|
||||
pub fn retry(dcid: &[u8], scid: &[u8], token: &[u8], odcid: &[u8]) -> Res<Vec<u8>> {
|
||||
pub fn retry(
|
||||
quic_version: QuicVersion,
|
||||
dcid: &[u8],
|
||||
scid: &[u8],
|
||||
token: &[u8],
|
||||
odcid: &[u8],
|
||||
) -> Res<Vec<u8>> {
|
||||
let mut encoder = Encoder::default();
|
||||
encoder.encode_vec(1, odcid);
|
||||
let start = encoder.len();
|
||||
|
@ -249,7 +292,7 @@ impl PacketBuilder {
|
|||
| (PACKET_TYPE_RETRY << 4)
|
||||
| (random(1)[0] & 0xf),
|
||||
);
|
||||
encoder.encode_uint(4, QUIC_VERSION);
|
||||
encoder.encode_uint(4, quic_version.as_u32());
|
||||
encoder.encode_vec(1, dcid);
|
||||
encoder.encode_vec(1, scid);
|
||||
debug_assert_ne!(token.len(), 0);
|
||||
|
@ -277,7 +320,8 @@ impl PacketBuilder {
|
|||
encoder.encode(&[0; 4]); // Zero version == VN.
|
||||
encoder.encode_vec(1, dcid);
|
||||
encoder.encode_vec(1, scid);
|
||||
encoder.encode_uint(4, QUIC_VERSION);
|
||||
encoder.encode_uint(4, QuicVersion::Draft27.as_u32());
|
||||
encoder.encode_uint(4, QuicVersion::Draft28.as_u32());
|
||||
// Add a greased version, using the randomness already generated.
|
||||
for g in &mut grease[..4] {
|
||||
*g = *g & 0xf0 | 0x0a;
|
||||
|
@ -321,6 +365,8 @@ pub struct PublicPacket<'a> {
|
|||
token: &'a [u8],
|
||||
/// The size of the header, not including the packet number.
|
||||
header_len: usize,
|
||||
/// Protocol version, if present in header.
|
||||
quic_version: Option<QuicVersion>,
|
||||
/// A reference to the entire packet, including the header.
|
||||
data: &'a [u8],
|
||||
}
|
||||
|
@ -382,6 +428,7 @@ impl<'a> PublicPacket<'a> {
|
|||
scid: None,
|
||||
token: &[],
|
||||
header_len,
|
||||
quic_version: None,
|
||||
data,
|
||||
},
|
||||
&[],
|
||||
|
@ -405,14 +452,17 @@ impl<'a> PublicPacket<'a> {
|
|||
scid: Some(scid),
|
||||
token: &[],
|
||||
header_len: decoder.offset(),
|
||||
quic_version: None,
|
||||
data,
|
||||
},
|
||||
&[],
|
||||
));
|
||||
}
|
||||
|
||||
// Check that this is a long header from this version.
|
||||
if version != QUIC_VERSION {
|
||||
// Check that this is a long header from a supported version.
|
||||
let quic_version = if let Ok(v) = QuicVersion::try_from(version) {
|
||||
v
|
||||
} else {
|
||||
return Ok((
|
||||
Self {
|
||||
packet_type: PacketType::OtherVersion,
|
||||
|
@ -420,11 +470,13 @@ impl<'a> PublicPacket<'a> {
|
|||
scid: Some(scid),
|
||||
token: &[],
|
||||
header_len: decoder.offset(),
|
||||
quic_version: None,
|
||||
data,
|
||||
},
|
||||
&[],
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
if (first & PACKET_BIT_FIXED_QUIC) != PACKET_BIT_FIXED_QUIC {
|
||||
return Err(Error::InvalidPacket);
|
||||
}
|
||||
|
@ -450,6 +502,7 @@ impl<'a> PublicPacket<'a> {
|
|||
scid: Some(scid),
|
||||
token,
|
||||
header_len,
|
||||
quic_version: Some(quic_version),
|
||||
data,
|
||||
},
|
||||
remainder,
|
||||
|
@ -509,6 +562,10 @@ impl<'a> PublicPacket<'a> {
|
|||
self.token
|
||||
}
|
||||
|
||||
pub fn version(&self) -> Option<QuicVersion> {
|
||||
self.quic_version
|
||||
}
|
||||
|
||||
fn decode_pn(expected: PacketNumber, pn: u64, w: usize) -> PacketNumber {
|
||||
let window = 1_u64 << (w * 8);
|
||||
let candidate = (expected & !(window - 1)) | pn;
|
||||
|
@ -656,7 +713,7 @@ impl Deref for DecryptedPacket {
|
|||
mod tests {
|
||||
use super::*;
|
||||
use crate::crypto::{CryptoDxState, CryptoStates};
|
||||
use crate::FixedConnectionIdManager;
|
||||
use crate::{FixedConnectionIdManager, QuicVersion};
|
||||
use neqo_common::Encoder;
|
||||
use test_fixture::{fixture_init, now};
|
||||
|
||||
|
@ -678,15 +735,15 @@ mod tests {
|
|||
0xda, 0x1a, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04,
|
||||
];
|
||||
const SAMPLE_INITIAL: &[u8] = &[
|
||||
0xc9, 0xff, 0x00, 0x00, 0x1b, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5,
|
||||
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, 0xd8, 0xc3,
|
||||
0xa9, 0x52, 0x8d, 0x2b, 0x6a, 0xca, 0x20, 0xf0, 0x80, 0x47, 0xd9, 0xf0, 0x17, 0xf0,
|
||||
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,
|
||||
];
|
||||
|
||||
#[test]
|
||||
|
@ -702,6 +759,7 @@ mod tests {
|
|||
let mut builder = PacketBuilder::long(
|
||||
Encoder::new(),
|
||||
PacketType::Initial,
|
||||
QuicVersion::default(),
|
||||
&ConnectionId::from(&[][..]),
|
||||
&ConnectionId::from(SERVER_CID),
|
||||
);
|
||||
|
@ -736,7 +794,7 @@ mod tests {
|
|||
fn disallow_long_dcid() {
|
||||
let mut enc = Encoder::new();
|
||||
enc.encode_byte(PACKET_BIT_LONG | PACKET_BIT_FIXED_QUIC);
|
||||
enc.encode_uint(4, QUIC_VERSION);
|
||||
enc.encode_uint(4, QuicVersion::default().as_u32());
|
||||
enc.encode_vec(1, &[0x00; MAX_CONNECTION_ID_LEN + 1]);
|
||||
enc.encode_vec(1, &[]);
|
||||
enc.encode(&[0xff; 40]); // junk
|
||||
|
@ -748,7 +806,7 @@ mod tests {
|
|||
fn disallow_long_scid() {
|
||||
let mut enc = Encoder::new();
|
||||
enc.encode_byte(PACKET_BIT_LONG | PACKET_BIT_FIXED_QUIC);
|
||||
enc.encode_uint(4, QUIC_VERSION);
|
||||
enc.encode_uint(4, QuicVersion::default().as_u32());
|
||||
enc.encode_vec(1, &[]);
|
||||
enc.encode_vec(1, &[0x00; MAX_CONNECTION_ID_LEN + 2]);
|
||||
enc.encode(&[0xff; 40]); // junk
|
||||
|
@ -819,6 +877,7 @@ mod tests {
|
|||
let mut builder = PacketBuilder::long(
|
||||
Encoder::new(),
|
||||
PacketType::Handshake,
|
||||
QuicVersion::default(),
|
||||
&ConnectionId::from(SERVER_CID),
|
||||
&ConnectionId::from(CLIENT_CID),
|
||||
);
|
||||
|
@ -845,6 +904,7 @@ mod tests {
|
|||
let mut builder = PacketBuilder::long(
|
||||
Encoder::new(),
|
||||
PacketType::Initial,
|
||||
QuicVersion::default(),
|
||||
&ConnectionId::from(&[][..]),
|
||||
&ConnectionId::from(SERVER_CID),
|
||||
);
|
||||
|
@ -854,17 +914,34 @@ mod tests {
|
|||
assert!(encoder.is_empty());
|
||||
}
|
||||
|
||||
const SAMPLE_RETRY: &[u8] = &[
|
||||
const SAMPLE_RETRY_27: &[u8] = &[
|
||||
0xff, 0xff, 0x00, 0x00, 0x1b, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5,
|
||||
0x74, 0x6f, 0x6b, 0x65, 0x6e, 0xa5, 0x23, 0xcb, 0x5b, 0xa5, 0x24, 0x69, 0x5f, 0x65, 0x69,
|
||||
0xf2, 0x93, 0xa1, 0x35, 0x9d, 0x8e,
|
||||
];
|
||||
|
||||
const SAMPLE_RETRY_28: &[u8] = &[
|
||||
0xff, 0xff, 0x00, 0x00, 0x1c, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5,
|
||||
0x74, 0x6f, 0x6b, 0x65, 0x6e, 0xf7, 0x1a, 0x5f, 0x12, 0xaf, 0xe3, 0xec, 0xf8, 0x00, 0x1a,
|
||||
0x92, 0x0e, 0x6f, 0xdf, 0x1d, 0x63,
|
||||
];
|
||||
|
||||
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() {
|
||||
fn build_retry_single() {
|
||||
fixture_init();
|
||||
let retry = PacketBuilder::retry(&[], SERVER_CID, RETRY_TOKEN, CLIENT_CID).unwrap();
|
||||
let (sample_retry, quic_version) = pick_retry_version();
|
||||
let retry =
|
||||
PacketBuilder::retry(quic_version, &[], SERVER_CID, RETRY_TOKEN, CLIENT_CID).unwrap();
|
||||
|
||||
let (packet, remainder) = PublicPacket::decode(&retry, &cid_mgr()).unwrap();
|
||||
assert!(packet.is_valid_retry(&ConnectionId::from(CLIENT_CID)));
|
||||
|
@ -872,21 +949,22 @@ mod tests {
|
|||
|
||||
// The builder adds randomness, which makes expectations hard.
|
||||
// So only do a full check when that randomness matches up.
|
||||
if retry[0] == SAMPLE_RETRY[0] {
|
||||
assert_eq!(&retry, &SAMPLE_RETRY);
|
||||
if retry[0] == sample_retry[0] {
|
||||
assert_eq!(&retry, &sample_retry);
|
||||
} else {
|
||||
// Otherwise, just check that the header is OK.
|
||||
assert_eq!(retry[0] & 0xf0, 0xf0);
|
||||
let header_range = 1..retry.len() - 16;
|
||||
assert_eq!(&retry[header_range.clone()], &SAMPLE_RETRY[header_range]);
|
||||
assert_eq!(&retry[header_range.clone()], &sample_retry[header_range]);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_retry() {
|
||||
fixture_init();
|
||||
let (sample_retry, _) = pick_retry_version();
|
||||
let (packet, remainder) =
|
||||
PublicPacket::decode(SAMPLE_RETRY, &FixedConnectionIdManager::new(5)).unwrap();
|
||||
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);
|
||||
|
@ -899,7 +977,7 @@ 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();
|
||||
build_retry_single();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -907,16 +985,17 @@ mod tests {
|
|||
#[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, &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.to_vec();
|
||||
let last = damaged_retry.len() - 1;
|
||||
damaged_retry[last] ^= 66;
|
||||
let (packet, remainder) = PublicPacket::decode(&damaged_retry, &cid_mgr).unwrap();
|
||||
|
@ -938,8 +1017,8 @@ 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, 0x0a, 0x0a, 0x0a,
|
||||
0x0a,
|
||||
0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08, 0xff, 0x00, 0x00, 0x1b, 0xff, 0x00, 0x00,
|
||||
0x1c, 0x0a, 0x0a, 0x0a, 0x0a,
|
||||
];
|
||||
|
||||
#[test]
|
||||
|
@ -975,7 +1054,7 @@ mod tests {
|
|||
enc.encode_vec(1, BIG_DCID);
|
||||
enc.encode_vec(1, BIG_SCID);
|
||||
enc.encode_uint(4, 0x1a2a_3a4a_u64);
|
||||
enc.encode_uint(4, QUIC_VERSION);
|
||||
enc.encode_uint(4, QuicVersion::default().as_u32());
|
||||
enc.encode_uint(4, 0x5a6a_7a8a_u64);
|
||||
|
||||
let (packet, remainder) =
|
||||
|
|
|
@ -25,6 +25,7 @@ pub struct Path {
|
|||
remote: SocketAddr,
|
||||
local_cids: Vec<ConnectionId>,
|
||||
remote_cid: ConnectionId,
|
||||
reset_token: Option<[u8; 16]>,
|
||||
}
|
||||
|
||||
impl Path {
|
||||
|
@ -40,6 +41,7 @@ impl Path {
|
|||
remote,
|
||||
local_cids: vec![local_cid],
|
||||
remote_cid,
|
||||
reset_token: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,6 +52,7 @@ impl Path {
|
|||
remote: d.source(),
|
||||
local_cids: Vec::new(),
|
||||
remote_cid,
|
||||
reset_token: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,7 +83,7 @@ impl Path {
|
|||
self.local_cids.first().as_ref().unwrap()
|
||||
}
|
||||
|
||||
/// Set the remote connection ID based on the peer's valid.
|
||||
/// Set the remote connection ID based on the peer's choice.
|
||||
pub fn set_remote_cid(&mut self, cid: &ConnectionIdRef) {
|
||||
self.remote_cid = ConnectionId::from(cid);
|
||||
}
|
||||
|
@ -90,6 +93,16 @@ impl Path {
|
|||
&self.remote_cid
|
||||
}
|
||||
|
||||
/// Set the stateless reset token for the connection ID that is currently in use.
|
||||
pub fn set_reset_token(&mut self, token: [u8; 16]) {
|
||||
self.reset_token = Some(token);
|
||||
}
|
||||
|
||||
/// Access the reset token.
|
||||
pub fn reset_token(&self) -> Option<&[u8; 16]> {
|
||||
self.reset_token.as_ref()
|
||||
}
|
||||
|
||||
/// Make a datagram.
|
||||
pub fn datagram<V: Into<Vec<u8>>>(&self, payload: V) -> Datagram {
|
||||
Datagram::new(self.local, self.remote, payload)
|
||||
|
|
|
@ -16,7 +16,7 @@ use crate::frame::{self, Frame};
|
|||
use crate::packet::{DecryptedPacket, PacketNumber, PacketType};
|
||||
use crate::path::Path;
|
||||
use crate::tparams::{self, TransportParametersHandler};
|
||||
use crate::{Res, QUIC_VERSION};
|
||||
use crate::{QuicVersion, Res};
|
||||
|
||||
pub fn connection_tparams_set(
|
||||
qlog: &mut Option<NeqoQlog>,
|
||||
|
@ -31,15 +31,15 @@ pub fn connection_tparams_set(
|
|||
None,
|
||||
None,
|
||||
None,
|
||||
if let Some(ocid) = remote.get_bytes(tparams::ORIGINAL_CONNECTION_ID) {
|
||||
if let Some(ocid) = remote.get_bytes(tparams::ORIGINAL_DESTINATION_CONNECTION_ID) {
|
||||
// Cannot use packet::ConnectionId's Display trait implementation
|
||||
// because it does not include the 0x prefix.
|
||||
Some(hex(&ocid))
|
||||
Some(hex(ocid))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
if let Some(srt) = remote.get_bytes(tparams::STATELESS_RESET_TOKEN) {
|
||||
Some(hex(&srt))
|
||||
Some(hex(srt))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
|
@ -49,7 +49,7 @@ pub fn connection_tparams_set(
|
|||
None
|
||||
},
|
||||
Some(remote.get_integer(tparams::IDLE_TIMEOUT)),
|
||||
Some(remote.get_integer(tparams::MAX_PACKET_SIZE)),
|
||||
Some(remote.get_integer(tparams::MAX_UDP_PAYLOAD_SIZE)),
|
||||
Some(remote.get_integer(tparams::ACK_DELAY_EXPONENT)),
|
||||
Some(remote.get_integer(tparams::MAX_ACK_DELAY)),
|
||||
// TODO(hawkinsw@obs.cr): We do not yet handle ACTIVE_CONNECTION_ID_LIMIT in tparams yet.
|
||||
|
@ -163,7 +163,7 @@ fn connection_started(qlog: &mut Option<NeqoQlog>, path: &Path) -> Res<()> {
|
|||
Some("QUIC".into()),
|
||||
path.local_address().port().into(),
|
||||
path.remote_address().port().into(),
|
||||
Some(format!("{:x}", QUIC_VERSION)),
|
||||
Some(format!("{:x}", QuicVersion::default().as_u32())),
|
||||
Some(format!("{}", path.local_cid())),
|
||||
Some(format!("{}", path.remote_cid())),
|
||||
))?;
|
||||
|
|
|
@ -19,7 +19,7 @@ use neqo_crypto::{
|
|||
use crate::cid::{ConnectionId, ConnectionIdDecoder, ConnectionIdManager, ConnectionIdRef};
|
||||
use crate::connection::{Connection, Output, State};
|
||||
use crate::packet::{PacketBuilder, PacketType, PublicPacket};
|
||||
use crate::Res;
|
||||
use crate::{QuicVersion, Res};
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{HashMap, HashSet, VecDeque};
|
||||
|
@ -324,13 +324,14 @@ impl Server {
|
|||
token: Vec<u8>,
|
||||
dgram: Datagram,
|
||||
now: Instant,
|
||||
quic_version: QuicVersion,
|
||||
) -> Option<Datagram> {
|
||||
qdebug!([self], "Handle initial packet");
|
||||
match self.retry.validate(&token, dgram.source(), now) {
|
||||
RetryTokenResult::Invalid => None,
|
||||
RetryTokenResult::Pass => self.connection_attempt(dcid, None, dgram, now),
|
||||
RetryTokenResult::Pass => self.connection_attempt(dcid, None, dgram, now, quic_version),
|
||||
RetryTokenResult::Valid(orig_dcid) => {
|
||||
self.connection_attempt(dcid, Some(orig_dcid), dgram, now)
|
||||
self.connection_attempt(dcid, Some(orig_dcid), dgram, now, quic_version)
|
||||
}
|
||||
RetryTokenResult::Validate => {
|
||||
qinfo!([self], "Send retry for {:?}", dcid);
|
||||
|
@ -343,7 +344,7 @@ impl Server {
|
|||
return None;
|
||||
};
|
||||
let new_dcid = self.cid_manager.borrow_mut().generate_cid();
|
||||
let packet = PacketBuilder::retry(&scid, &new_dcid, &token, &dcid);
|
||||
let packet = PacketBuilder::retry(quic_version, &scid, &new_dcid, &token, &dcid);
|
||||
if let Ok(p) = packet {
|
||||
let retry = Datagram::new(dgram.destination(), dgram.source(), p);
|
||||
Some(retry)
|
||||
|
@ -361,6 +362,7 @@ impl Server {
|
|||
orig_dcid: Option<ConnectionId>,
|
||||
dgram: Datagram,
|
||||
now: Instant,
|
||||
quic_version: QuicVersion,
|
||||
) -> Option<Datagram> {
|
||||
let attempt_key = AttemptKey {
|
||||
remote_address: dgram.source(),
|
||||
|
@ -375,7 +377,7 @@ impl Server {
|
|||
let c = Rc::clone(c);
|
||||
self.process_connection(c, Some(dgram), now)
|
||||
} else {
|
||||
self.accept_connection(attempt_key, orig_dcid, dgram, now)
|
||||
self.accept_connection(attempt_key, dcid, orig_dcid, dgram, now, quic_version)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -432,13 +434,18 @@ impl Server {
|
|||
fn accept_connection(
|
||||
&mut self,
|
||||
attempt_key: AttemptKey,
|
||||
dcid: ConnectionId,
|
||||
orig_dcid: Option<ConnectionId>,
|
||||
dgram: Datagram,
|
||||
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(),
|
||||
|
@ -449,12 +456,16 @@ impl Server {
|
|||
&self.certs,
|
||||
&self.protocols,
|
||||
&self.anti_replay,
|
||||
cid_mgr.clone(),
|
||||
self.cid_manager.clone(),
|
||||
quic_version,
|
||||
local_initial_source_cid.clone(),
|
||||
);
|
||||
|
||||
if let Ok(mut c) = sconn {
|
||||
if let Some(odcid) = orig_dcid {
|
||||
c.original_connection_id(&odcid);
|
||||
// There was a retry.
|
||||
c.set_original_destination_cid(odcid);
|
||||
c.set_retry_source_cid(dcid);
|
||||
}
|
||||
c.set_qlog(self.create_qlog_trace(&attempt_key));
|
||||
let c = Rc::new(RefCell::new(ServerConnectionState {
|
||||
|
@ -463,6 +474,7 @@ impl Server {
|
|||
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());
|
||||
debug_assert!(previous_attempt.is_none());
|
||||
self.process_connection(c, Some(dgram), now)
|
||||
|
@ -507,7 +519,8 @@ impl Server {
|
|||
let dcid = ConnectionId::from(packet.dcid());
|
||||
let scid = ConnectionId::from(packet.scid());
|
||||
let token = packet.token().to_vec();
|
||||
self.handle_initial(dcid, scid, token, dgram, now)
|
||||
let quic_version = packet.version().expect("Initial must have version field");
|
||||
self.handle_initial(dcid, scid, token, dgram, now, quic_version)
|
||||
}
|
||||
PacketType::OtherVersion => {
|
||||
let vn = PacketBuilder::version_negotiation(packet.scid(), packet.dcid());
|
||||
|
@ -622,24 +635,32 @@ struct ServerConnectionIdManager {
|
|||
cid_manager: CidMgr,
|
||||
}
|
||||
|
||||
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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ConnectionIdDecoder for ServerConnectionIdManager {
|
||||
fn decode_cid<'a>(&self, dec: &mut Decoder<'a>) -> Option<ConnectionIdRef<'a>> {
|
||||
self.cid_manager.borrow_mut().decode_cid(dec)
|
||||
}
|
||||
}
|
||||
|
||||
impl ConnectionIdManager for ServerConnectionIdManager {
|
||||
fn generate_cid(&mut self) -> ConnectionId {
|
||||
let cid = self.cid_manager.borrow_mut().generate_cid();
|
||||
assert!(!cid.is_empty());
|
||||
let v = self
|
||||
.connections
|
||||
.borrow_mut()
|
||||
.insert(cid.clone(), self.c.as_ref().unwrap().clone());
|
||||
if let Some(v) = v {
|
||||
debug_assert!(Rc::ptr_eq(&v, self.c.as_ref().unwrap()));
|
||||
}
|
||||
self.insert_cid(cid.clone());
|
||||
cid
|
||||
}
|
||||
|
||||
fn as_decoder(&self) -> &dyn ConnectionIdDecoder {
|
||||
self
|
||||
}
|
||||
|
|
|
@ -27,20 +27,23 @@ macro_rules! tpids {
|
|||
};
|
||||
}
|
||||
tpids! {
|
||||
ORIGINAL_CONNECTION_ID = 0,
|
||||
IDLE_TIMEOUT = 1,
|
||||
STATELESS_RESET_TOKEN = 2,
|
||||
MAX_PACKET_SIZE = 3,
|
||||
INITIAL_MAX_DATA = 4,
|
||||
INITIAL_MAX_STREAM_DATA_BIDI_LOCAL = 5,
|
||||
INITIAL_MAX_STREAM_DATA_BIDI_REMOTE = 6,
|
||||
INITIAL_MAX_STREAM_DATA_UNI = 7,
|
||||
INITIAL_MAX_STREAMS_BIDI = 8,
|
||||
INITIAL_MAX_STREAMS_UNI = 9,
|
||||
ACK_DELAY_EXPONENT = 10,
|
||||
MAX_ACK_DELAY = 11,
|
||||
DISABLE_MIGRATION = 12,
|
||||
PREFERRED_ADDRESS = 13,
|
||||
ORIGINAL_DESTINATION_CONNECTION_ID = 0x00,
|
||||
IDLE_TIMEOUT = 0x01,
|
||||
STATELESS_RESET_TOKEN = 0x02,
|
||||
MAX_UDP_PAYLOAD_SIZE = 0x03,
|
||||
INITIAL_MAX_DATA = 0x04,
|
||||
INITIAL_MAX_STREAM_DATA_BIDI_LOCAL = 0x05,
|
||||
INITIAL_MAX_STREAM_DATA_BIDI_REMOTE = 0x06,
|
||||
INITIAL_MAX_STREAM_DATA_UNI = 0x07,
|
||||
INITIAL_MAX_STREAMS_BIDI = 0x08,
|
||||
INITIAL_MAX_STREAMS_UNI = 0x09,
|
||||
ACK_DELAY_EXPONENT = 0x0a,
|
||||
MAX_ACK_DELAY = 0x0b,
|
||||
DISABLE_MIGRATION = 0x0c,
|
||||
PREFERRED_ADDRESS = 0x0d,
|
||||
ACTIVE_CONNECTION_ID_LIMIT = 0x0e,
|
||||
INITIAL_SOURCE_CONNECTION_ID = 0x0f,
|
||||
RETRY_SOURCE_CONNECTION_ID = 0x10,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
@ -52,6 +55,7 @@ pub enum TransportParameter {
|
|||
|
||||
impl TransportParameter {
|
||||
fn encode(&self, enc: &mut Encoder, tp: TransportParameterId) {
|
||||
qdebug!("TP encoded; type 0x{:02x} val {:?}", tp, self);
|
||||
enc.encode_varint(tp);
|
||||
match self {
|
||||
Self::Bytes(a) => {
|
||||
|
@ -80,7 +84,9 @@ impl TransportParameter {
|
|||
qtrace!("TP {:x} length {:x}", tp, content.len());
|
||||
let mut d = Decoder::from(content);
|
||||
let value = match tp {
|
||||
ORIGINAL_CONNECTION_ID => Self::Bytes(d.decode_remainder().to_vec()),
|
||||
ORIGINAL_DESTINATION_CONNECTION_ID
|
||||
| INITIAL_SOURCE_CONNECTION_ID
|
||||
| RETRY_SOURCE_CONNECTION_ID => Self::Bytes(d.decode_remainder().to_vec()),
|
||||
STATELESS_RESET_TOKEN => {
|
||||
if d.remaining() != 16 {
|
||||
return Err(Error::TransportParameterError);
|
||||
|
@ -102,7 +108,7 @@ impl TransportParameter {
|
|||
_ => return Err(Error::StreamLimitError),
|
||||
},
|
||||
|
||||
MAX_PACKET_SIZE => match d.decode_varint() {
|
||||
MAX_UDP_PAYLOAD_SIZE => match d.decode_varint() {
|
||||
Some(v) if v >= 1200 => Self::Integer(v),
|
||||
_ => return Err(Error::TransportParameterError),
|
||||
},
|
||||
|
@ -111,6 +117,10 @@ impl TransportParameter {
|
|||
Some(v) if v <= 20 => Self::Integer(v),
|
||||
_ => return Err(Error::TransportParameterError),
|
||||
},
|
||||
ACTIVE_CONNECTION_ID_LIMIT => match d.decode_varint() {
|
||||
Some(v) if v <= 2 => Self::Integer(v),
|
||||
_ => return Err(Error::TransportParameterError),
|
||||
},
|
||||
|
||||
DISABLE_MIGRATION => Self::Empty,
|
||||
// Skip.
|
||||
|
@ -119,7 +129,7 @@ impl TransportParameter {
|
|||
if d.remaining() > 0 {
|
||||
return Err(Error::TooMuchData);
|
||||
}
|
||||
qtrace!("TP decoded; type {:x} val {:?}", tp, value);
|
||||
qdebug!("TP decoded; type 0x{:02x} val {:?}", tp, value);
|
||||
Ok(Some((tp, value)))
|
||||
}
|
||||
}
|
||||
|
@ -174,9 +184,10 @@ impl TransportParameters {
|
|||
| INITIAL_MAX_STREAM_DATA_UNI
|
||||
| INITIAL_MAX_STREAMS_BIDI
|
||||
| INITIAL_MAX_STREAMS_UNI => 0,
|
||||
MAX_PACKET_SIZE => 65527,
|
||||
MAX_UDP_PAYLOAD_SIZE => 65527,
|
||||
ACK_DELAY_EXPONENT => 3,
|
||||
MAX_ACK_DELAY => 25,
|
||||
ACTIVE_CONNECTION_ID_LIMIT => 2,
|
||||
_ => panic!("Transport parameter not known or not an Integer"),
|
||||
};
|
||||
match self.params.get(&tp) {
|
||||
|
@ -186,7 +197,7 @@ impl TransportParameters {
|
|||
}
|
||||
}
|
||||
|
||||
// Get an integer type or a default.
|
||||
// Set an integer type or a default.
|
||||
pub fn set_integer(&mut self, tp: TransportParameterId, value: u64) {
|
||||
match tp {
|
||||
IDLE_TIMEOUT
|
||||
|
@ -196,31 +207,38 @@ impl TransportParameters {
|
|||
| INITIAL_MAX_STREAM_DATA_UNI
|
||||
| INITIAL_MAX_STREAMS_BIDI
|
||||
| INITIAL_MAX_STREAMS_UNI
|
||||
| MAX_PACKET_SIZE
|
||||
| MAX_UDP_PAYLOAD_SIZE
|
||||
| ACK_DELAY_EXPONENT
|
||||
| MAX_ACK_DELAY => {
|
||||
| MAX_ACK_DELAY
|
||||
| ACTIVE_CONNECTION_ID_LIMIT => {
|
||||
self.set(tp, TransportParameter::Integer(value));
|
||||
}
|
||||
_ => panic!("Transport parameter not known"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_bytes(&self, tp: TransportParameterId) -> Option<Vec<u8>> {
|
||||
pub fn get_bytes(&self, tp: TransportParameterId) -> Option<&[u8]> {
|
||||
match tp {
|
||||
ORIGINAL_CONNECTION_ID | STATELESS_RESET_TOKEN => {}
|
||||
ORIGINAL_DESTINATION_CONNECTION_ID
|
||||
| INITIAL_SOURCE_CONNECTION_ID
|
||||
| RETRY_SOURCE_CONNECTION_ID
|
||||
| STATELESS_RESET_TOKEN => {}
|
||||
_ => panic!("Transport parameter not known or not type bytes"),
|
||||
}
|
||||
|
||||
match self.params.get(&tp) {
|
||||
None => None,
|
||||
Some(TransportParameter::Bytes(x)) => Some(x.to_vec()),
|
||||
Some(TransportParameter::Bytes(x)) => Some(&x),
|
||||
_ => panic!("Internal error"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_bytes(&mut self, tp: TransportParameterId, value: Vec<u8>) {
|
||||
match tp {
|
||||
ORIGINAL_CONNECTION_ID | STATELESS_RESET_TOKEN => {
|
||||
ORIGINAL_DESTINATION_CONNECTION_ID
|
||||
| INITIAL_SOURCE_CONNECTION_ID
|
||||
| RETRY_SOURCE_CONNECTION_ID
|
||||
| STATELESS_RESET_TOKEN => {
|
||||
self.set(tp, TransportParameter::Bytes(value));
|
||||
}
|
||||
_ => panic!("Transport parameter not known or not type bytes"),
|
||||
|
@ -256,11 +274,14 @@ impl TransportParameters {
|
|||
// Skip checks for these, which don't affect 0-RTT.
|
||||
if matches!(
|
||||
*k,
|
||||
ORIGINAL_CONNECTION_ID
|
||||
ORIGINAL_DESTINATION_CONNECTION_ID
|
||||
| INITIAL_SOURCE_CONNECTION_ID
|
||||
| RETRY_SOURCE_CONNECTION_ID
|
||||
| STATELESS_RESET_TOKEN
|
||||
| IDLE_TIMEOUT
|
||||
| ACK_DELAY_EXPONENT
|
||||
| MAX_ACK_DELAY
|
||||
| ACTIVE_CONNECTION_ID_LIMIT
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
@ -388,11 +409,12 @@ mod tests {
|
|||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_basic_tps() {
|
||||
fn basic_tps() {
|
||||
const RESET_TOKEN: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8];
|
||||
let mut tps = TransportParameters::default();
|
||||
tps.set(
|
||||
STATELESS_RESET_TOKEN,
|
||||
TransportParameter::Bytes(vec![1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]),
|
||||
TransportParameter::Bytes(RESET_TOKEN.to_vec()),
|
||||
);
|
||||
tps.params
|
||||
.insert(INITIAL_MAX_STREAMS_BIDI, TransportParameter::Integer(10));
|
||||
|
@ -406,13 +428,15 @@ mod tests {
|
|||
println!("TPS = {:?}", tps);
|
||||
assert_eq!(tps2.get_integer(IDLE_TIMEOUT), 0); // Default
|
||||
assert_eq!(tps2.get_integer(MAX_ACK_DELAY), 25); // Default
|
||||
assert_eq!(tps2.get_integer(ACTIVE_CONNECTION_ID_LIMIT), 2); // Default
|
||||
assert_eq!(tps2.get_integer(INITIAL_MAX_STREAMS_BIDI), 10); // Sent
|
||||
assert_eq!(
|
||||
tps2.get_bytes(STATELESS_RESET_TOKEN),
|
||||
Some(vec![1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8])
|
||||
);
|
||||
assert_eq!(tps2.get_bytes(ORIGINAL_CONNECTION_ID), None);
|
||||
assert_eq!(tps2.was_sent(ORIGINAL_CONNECTION_ID), false);
|
||||
assert_eq!(tps2.get_bytes(STATELESS_RESET_TOKEN), Some(RESET_TOKEN));
|
||||
assert_eq!(tps2.get_bytes(ORIGINAL_DESTINATION_CONNECTION_ID), None);
|
||||
assert_eq!(tps2.get_bytes(INITIAL_SOURCE_CONNECTION_ID), None);
|
||||
assert_eq!(tps2.get_bytes(RETRY_SOURCE_CONNECTION_ID), None);
|
||||
assert_eq!(tps2.was_sent(ORIGINAL_DESTINATION_CONNECTION_ID), false);
|
||||
assert_eq!(tps2.was_sent(INITIAL_SOURCE_CONNECTION_ID), false);
|
||||
assert_eq!(tps2.was_sent(RETRY_SOURCE_CONNECTION_ID), false);
|
||||
assert_eq!(tps2.was_sent(STATELESS_RESET_TOKEN), true);
|
||||
|
||||
let mut enc = Encoder::default();
|
||||
|
@ -430,6 +454,7 @@ mod tests {
|
|||
);
|
||||
tps_a.set(IDLE_TIMEOUT, TransportParameter::Integer(10));
|
||||
tps_a.set(MAX_ACK_DELAY, TransportParameter::Integer(22));
|
||||
tps_a.set(ACTIVE_CONNECTION_ID_LIMIT, TransportParameter::Integer(33));
|
||||
|
||||
let mut tps_b = TransportParameters::default();
|
||||
assert!(tps_a.ok_for_0rtt(&tps_b));
|
||||
|
@ -441,6 +466,7 @@ mod tests {
|
|||
);
|
||||
tps_b.set(IDLE_TIMEOUT, TransportParameter::Integer(100));
|
||||
tps_b.set(MAX_ACK_DELAY, TransportParameter::Integer(2));
|
||||
tps_b.set(ACTIVE_CONNECTION_ID_LIMIT, TransportParameter::Integer(44));
|
||||
assert!(tps_a.ok_for_0rtt(&tps_b));
|
||||
assert!(tps_b.ok_for_0rtt(&tps_a));
|
||||
}
|
||||
|
@ -455,7 +481,7 @@ mod tests {
|
|||
INITIAL_MAX_STREAM_DATA_UNI,
|
||||
INITIAL_MAX_STREAMS_BIDI,
|
||||
INITIAL_MAX_STREAMS_UNI,
|
||||
MAX_PACKET_SIZE,
|
||||
MAX_UDP_PAYLOAD_SIZE,
|
||||
];
|
||||
for i in INTEGER_KEYS {
|
||||
tps_a.set(*i, TransportParameter::Integer(12));
|
||||
|
|
|
@ -17,8 +17,8 @@ use neqo_crypto::{
|
|||
};
|
||||
use neqo_transport::{
|
||||
server::{ActiveConnectionRef, Server},
|
||||
Connection, ConnectionError, Error, FixedConnectionIdManager, Output, State, StreamType,
|
||||
QUIC_VERSION,
|
||||
Connection, ConnectionError, Error, FixedConnectionIdManager, Output, QuicVersion, State,
|
||||
StreamType,
|
||||
};
|
||||
use test_fixture::{self, assertions, default_client, now};
|
||||
|
||||
|
@ -210,7 +210,7 @@ fn drop_non_initial() {
|
|||
let mut header = neqo_common::Encoder::with_capacity(1200);
|
||||
header
|
||||
.encode_byte(0xfa)
|
||||
.encode_uint(4, QUIC_VERSION)
|
||||
.encode_uint(4, QuicVersion::default().as_u32())
|
||||
.encode_vec(1, CID)
|
||||
.encode_vec(1, CID);
|
||||
let mut bogus_data: Vec<u8> = header.into();
|
||||
|
@ -225,7 +225,7 @@ fn drop_non_initial() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn retry() {
|
||||
fn retry_basic() {
|
||||
let mut server = default_server();
|
||||
server.set_retry_required(true);
|
||||
let mut client = default_client();
|
||||
|
@ -601,7 +601,7 @@ fn mitm_retry() {
|
|||
assert!(matches!(
|
||||
*client.state(),
|
||||
State::Closing{
|
||||
error: ConnectionError::Transport(Error::InvalidRetry),
|
||||
error: ConnectionError::Transport(Error::ProtocolViolation),
|
||||
..
|
||||
}
|
||||
));
|
||||
|
@ -630,7 +630,7 @@ fn bad_client_initial() {
|
|||
let mut header_enc = Encoder::new();
|
||||
header_enc
|
||||
.encode_byte(0xc0) // Initial with 1 byte packet number.
|
||||
.encode_uint(4, QUIC_VERSION)
|
||||
.encode_uint(4, QuicVersion::default().as_u32())
|
||||
.encode_vec(1, dcid)
|
||||
.encode_vec(1, scid)
|
||||
.encode_vvec(&[])
|
||||
|
@ -713,7 +713,7 @@ fn version_negotiation() {
|
|||
let mut found = false;
|
||||
while dec.remaining() > 0 {
|
||||
let v = dec.decode_uint(4).expect("supported version");
|
||||
found |= v == u64::from(QUIC_VERSION);
|
||||
found |= v == u64::from(QuicVersion::default().as_u32());
|
||||
}
|
||||
assert!(found, "valid version not found");
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче