forked from mirrors/gecko-dev
Bug 1805652 - neqo v0.6.3, r=necko-reviewers,jesup
Differential Revision: https://phabricator.services.mozilla.com/D164657
This commit is contained in:
parent
00ea9bd0f5
commit
1a5d5eb1c9
68 changed files with 2272 additions and 539 deletions
|
|
@ -97,7 +97,7 @@ replace-with = "vendored-sources"
|
|||
|
||||
[source."https://github.com/mozilla/neqo"]
|
||||
git = "https://github.com/mozilla/neqo"
|
||||
tag = "v0.6.1"
|
||||
tag = "v0.6.3"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."https://github.com/mozilla/uniffi-rs.git"]
|
||||
|
|
|
|||
22
Cargo.lock
generated
22
Cargo.lock
generated
|
|
@ -3594,8 +3594,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "neqo-common"
|
||||
version = "0.6.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.6.1#e71e860489447fed25b64bd8ec31a804dccb0dad"
|
||||
version = "0.6.3"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.6.3#4fe628bb911e4437169d974baa628c159e96f879"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"env_logger 0.9.0",
|
||||
|
|
@ -3607,10 +3607,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "neqo-crypto"
|
||||
version = "0.6.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.6.1#e71e860489447fed25b64bd8ec31a804dccb0dad"
|
||||
version = "0.6.3"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.6.3#4fe628bb911e4437169d974baa628c159e96f879"
|
||||
dependencies = [
|
||||
"bindgen 0.59.999",
|
||||
"bindgen 0.63.0",
|
||||
"log",
|
||||
"mozbuild",
|
||||
"neqo-common",
|
||||
|
|
@ -3621,8 +3621,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "neqo-http3"
|
||||
version = "0.6.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.6.1#e71e860489447fed25b64bd8ec31a804dccb0dad"
|
||||
version = "0.6.3"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.6.3#4fe628bb911e4437169d974baa628c159e96f879"
|
||||
dependencies = [
|
||||
"enumset",
|
||||
"lazy_static",
|
||||
|
|
@ -3639,8 +3639,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "neqo-qpack"
|
||||
version = "0.6.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.6.1#e71e860489447fed25b64bd8ec31a804dccb0dad"
|
||||
version = "0.6.3"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.6.3#4fe628bb911e4437169d974baa628c159e96f879"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"log",
|
||||
|
|
@ -3653,8 +3653,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "neqo-transport"
|
||||
version = "0.6.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.6.1#e71e860489447fed25b64bd8ec31a804dccb0dad"
|
||||
version = "0.6.3"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.6.3#4fe628bb911e4437169d974baa628c159e96f879"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
|
|
|
|||
|
|
@ -729,6 +729,12 @@ nsresult Http3Session::ProcessEvents() {
|
|||
mStreamIdHash.InsertOrUpdate(wtStream->StreamId(),
|
||||
std::move(wtStream));
|
||||
} break;
|
||||
case WebTransportEventExternal::Tag::Datagram:
|
||||
LOG(
|
||||
("Http3Session::ProcessEvents - "
|
||||
"WebTransportEventExternal::Tag::Datagram [this=%p]",
|
||||
this));
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@ license = "MPL-2.0"
|
|||
name = "neqo_glue"
|
||||
|
||||
[dependencies]
|
||||
neqo-http3 = { tag = "v0.6.1", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-transport = { tag = "v0.6.1", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-common = { tag = "v0.6.1", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-qpack = { tag = "v0.6.1", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-http3 = { tag = "v0.6.3", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-transport = { tag = "v0.6.3", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-common = { tag = "v0.6.3", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-qpack = { tag = "v0.6.3", git = "https://github.com/mozilla/neqo" }
|
||||
nserror = { path = "../../../xpcom/rust/nserror" }
|
||||
nsstring = { path = "../../../xpcom/rust/nsstring" }
|
||||
xpcom = { path = "../../../xpcom/rust/xpcom" }
|
||||
|
|
@ -26,7 +26,7 @@ static_prefs = { path = "../../../modules/libpref/init/static_prefs", optional =
|
|||
winapi = {version = "0.3", features = ["ws2def"] }
|
||||
|
||||
[dependencies.neqo-crypto]
|
||||
tag = "v0.6.1"
|
||||
tag = "v0.6.3"
|
||||
git = "https://github.com/mozilla/neqo"
|
||||
default-features = false
|
||||
features = ["gecko"]
|
||||
|
|
|
|||
|
|
@ -696,6 +696,9 @@ pub enum WebTransportEventExternal {
|
|||
stream_type: WebTransportStreamType,
|
||||
session_id: u64,
|
||||
},
|
||||
Datagram {
|
||||
session_id: u64,
|
||||
},
|
||||
}
|
||||
|
||||
impl WebTransportEventExternal {
|
||||
|
|
@ -728,6 +731,14 @@ impl WebTransportEventExternal {
|
|||
stream_type: stream_id.stream_type().into(),
|
||||
session_id: session_id.as_u64(),
|
||||
},
|
||||
WebTransportEvent::Datagram {
|
||||
session_id,
|
||||
datagram: _
|
||||
} => {
|
||||
WebTransportEventExternal::Datagram {
|
||||
session_id: session_id.as_u64(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,17 +6,17 @@ edition = "2018"
|
|||
license = "MPL-2.0"
|
||||
|
||||
[dependencies]
|
||||
neqo-transport = { tag = "v0.6.1", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-common = { tag = "v0.6.1", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-http3 = { tag = "v0.6.1", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-qpack = { tag = "v0.6.1", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-transport = { tag = "v0.6.3", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-common = { tag = "v0.6.3", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-http3 = { tag = "v0.6.3", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-qpack = { tag = "v0.6.3", git = "https://github.com/mozilla/neqo" }
|
||||
mio = "0.6.17"
|
||||
mio-extras = "2.0.5"
|
||||
log = "0.4.0"
|
||||
base64 = "0.13"
|
||||
|
||||
[dependencies.neqo-crypto]
|
||||
tag = "v0.6.1"
|
||||
tag = "v0.6.3"
|
||||
git = "https://github.com/mozilla/neqo"
|
||||
default-features = false
|
||||
features = ["gecko"]
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use neqo_crypto::{generate_ech_keys, init_db, AllowZeroRtt, AntiReplay};
|
|||
use neqo_http3::{
|
||||
Error, Http3OrWebTransportStream, Http3Parameters, Http3Server, Http3ServerEvent,
|
||||
WebTransportRequest, WebTransportServerEvent,
|
||||
WebTransportSessionAcceptAction,
|
||||
};
|
||||
use neqo_transport::server::Server;
|
||||
use neqo_transport::{
|
||||
|
|
@ -431,13 +432,13 @@ impl HttpServer for Http3TestServer {
|
|||
let path = ph.value();
|
||||
qtrace!("Serve request {}", path);
|
||||
if path == "/success" {
|
||||
session.response(true).unwrap();
|
||||
session.response(&WebTransportSessionAcceptAction::Accept).unwrap();
|
||||
} else if path == "/reject" {
|
||||
session.response(false).unwrap();
|
||||
session.response(&WebTransportSessionAcceptAction::Reject([Header::new(":status", "404")].to_vec())).unwrap();
|
||||
} else if path == "/closeafter0ms" {
|
||||
session.response(true).unwrap();
|
||||
session.response(&WebTransportSessionAcceptAction::Accept).unwrap();
|
||||
} else if path == "/closeafter100ms" {
|
||||
session.response(true).unwrap();
|
||||
session.response(&WebTransportSessionAcceptAction::Accept).unwrap();
|
||||
let expires = Instant::now() + Duration::from_millis(100);
|
||||
if !self.sessions_to_close.contains_key(&expires) {
|
||||
self.sessions_to_close.insert(expires, Vec::new());
|
||||
|
|
@ -447,17 +448,17 @@ impl HttpServer for Http3TestServer {
|
|||
.unwrap()
|
||||
.push(session);
|
||||
} else if path == "/create_unidi_stream" {
|
||||
session.response(true).unwrap();
|
||||
session.response(&WebTransportSessionAcceptAction::Accept).unwrap();
|
||||
self.sessions_to_create_stream.push((session, StreamType::UniDi));
|
||||
} else if path == "/create_bidi_stream" {
|
||||
session.response(true).unwrap();
|
||||
session.response(&WebTransportSessionAcceptAction::Accept).unwrap();
|
||||
self.sessions_to_create_stream.push((session, StreamType::BiDi));
|
||||
} else {
|
||||
session.response(true).unwrap();
|
||||
session.response(&WebTransportSessionAcceptAction::Accept).unwrap();
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
session.response(false).unwrap();
|
||||
session.response(&WebTransportSessionAcceptAction::Reject([Header::new(":status", "404")].to_vec())).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -476,6 +477,16 @@ impl HttpServer for Http3TestServer {
|
|||
self.webtransport_bidi_stream.insert(stream);
|
||||
}
|
||||
}
|
||||
Http3ServerEvent::WebTransport(WebTransportServerEvent::Datagram {
|
||||
session,
|
||||
datagram,
|
||||
}) => {
|
||||
qdebug!(
|
||||
"WebTransportServerEvent::Datagram {:?} {:?}",
|
||||
session,
|
||||
datagram
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"1e35362eb965155414173a29d9f0fbe1af3c6a66aa158af6701f235688dacd5c","build.rs":"a17b1bb1bd3de3fc958f72d4d1357f7bc4432faa26640c95b5fbfccf40579d67","src/codec.rs":"5aeb997fd0eca77241d1cc173f0d37aa8d2ec1725d5e3739c28f1999bf7c4bed","src/datagram.rs":"742aa0f39ac24d63431b58e23ebf925e27ec42340e5911020475de5f7f457a6d","src/event.rs":"f60fee9f4b09ef47ff5e4bfa21c07e45ffd5873c292f2605f24d834070127d62","src/header.rs":"b7d4eeb40952b36f71ae1f37ce82c9617af8b84c171576de4eca9d50a3071103","src/hrtime.rs":"c5f9f65a642b5782589a4caaf1e758845daa7ebf56c58dc9ef9f836e48026d29","src/incrdecoder.rs":"458f0228e41018d58f5a83c7895c9ea283f310fcb91c969e22026eb8ca3c84c9","src/lib.rs":"bf3e9922196f09554ef55d24c3331bb4c249d583fbbd9f5815670d9d23160838","src/log.rs":"f1ba46a9c2ef10b27211561f4851f933db941ec85ccd3425376d060034aea051","src/qlog.rs":"ca323c91d61810ebef2ebeb967836dda384a60a9fb492c2b8d1b235a98f2e4bf","src/timer.rs":"e63af7e7df968bf702583f263cfb63e6dca4e599bacffa2de0a6383d85333636","tests/log.rs":"480b165b7907ec642c508b303d63005eee1427115d6973a349eaf6b2242ed18d"},"package":null}
|
||||
{"files":{"Cargo.toml":"b27c96cc0da9ca1bc8731ee35100064dcf11df63613d08d02a2e07a66a6ffef0","build.rs":"a17b1bb1bd3de3fc958f72d4d1357f7bc4432faa26640c95b5fbfccf40579d67","src/codec.rs":"5aeb997fd0eca77241d1cc173f0d37aa8d2ec1725d5e3739c28f1999bf7c4bed","src/datagram.rs":"742aa0f39ac24d63431b58e23ebf925e27ec42340e5911020475de5f7f457a6d","src/event.rs":"f60fee9f4b09ef47ff5e4bfa21c07e45ffd5873c292f2605f24d834070127d62","src/header.rs":"b7d4eeb40952b36f71ae1f37ce82c9617af8b84c171576de4eca9d50a3071103","src/hrtime.rs":"c5f9f65a642b5782589a4caaf1e758845daa7ebf56c58dc9ef9f836e48026d29","src/incrdecoder.rs":"458f0228e41018d58f5a83c7895c9ea283f310fcb91c969e22026eb8ca3c84c9","src/lib.rs":"bf3e9922196f09554ef55d24c3331bb4c249d583fbbd9f5815670d9d23160838","src/log.rs":"f1ba46a9c2ef10b27211561f4851f933db941ec85ccd3425376d060034aea051","src/qlog.rs":"ca323c91d61810ebef2ebeb967836dda384a60a9fb492c2b8d1b235a98f2e4bf","src/timer.rs":"e63af7e7df968bf702583f263cfb63e6dca4e599bacffa2de0a6383d85333636","tests/log.rs":"480b165b7907ec642c508b303d63005eee1427115d6973a349eaf6b2242ed18d"},"package":null}
|
||||
4
third_party/rust/neqo-common/Cargo.toml
vendored
4
third_party/rust/neqo-common/Cargo.toml
vendored
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "neqo-common"
|
||||
version = "0.6.1"
|
||||
version = "0.6.3"
|
||||
authors = ["Bobby Holley <bobbyholley@gmail.com>"]
|
||||
edition = "2018"
|
||||
rust-version = "1.57.0"
|
||||
|
|
@ -12,7 +12,7 @@ log = {version = "0.4.0", default-features = false}
|
|||
env_logger = {version = "0.9", default-features = false}
|
||||
lazy_static = "1.3.0"
|
||||
qlog = "0.4.0"
|
||||
chrono = "0.4.10"
|
||||
chrono = {version = "0.4.10", default-features = false, features = ["std"]}
|
||||
|
||||
[features]
|
||||
default = ["deny-warnings"]
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"372b8108f43f8df1f6f26e72e434a2ae0ba00b8b4dba193451eb427738734069","TODO":"ac0f1c2ebcca03f5b3c0cc56c5aedbb030a4b511e438bc07a57361c789f91e9f","bindings/bindings.toml":"cb3e29ac6d1fd7083ffab81494afe1b9a2d9e41c60774438fd9681974c87c252","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":"99df86d0c11da5a8cbcc3be2560e6d764234a21b5d9b5f7ab1b70696e4f8670e","src/aead.rs":"140f77ffb5016836c970c39c6c3a42db9581a14b797b9cd05386d0dd0831fe63","src/aead_fuzzing.rs":"e11ea62b4605b84400edbd5fc394f008fc26d3b67467ba7fe1597b90db4c6a12","src/agent.rs":"1dfab420ca00789f745d440476b272e672ae756536f743d1faa9aa214bc0bcda","src/agentio.rs":"bce4c3dfcfa433209a409ac0c0752f8c95ab37bb6239a42f99b83858e8747bd1","src/auth.rs":"ced1a18f691894984244088020ea25dc1ee678603317f0c7dfc8b8842fa750b4","src/cert.rs":"628fc2384cdeb2a32bfbecb83c99af393df97fd6a76c6e8827e8240c0d47328b","src/constants.rs":"998e77bee88197a240032c1bfbddcff417a25ba82e576a0d2fe18ee9b63cefc7","src/ech.rs":"447f6297f50914249d0c92ec61d74df6c65ce4affceecb8cafe40927e855fe1d","src/err.rs":"f2cc71de2b40d7bba8119eeaee200337db9a0126176ba06e4902d7312facdb58","src/exp.rs":"61586662407359c1ecb8ed4987bc3c702f26ba2e203a091a51b6d6363cbd510f","src/ext.rs":"361277879194dc32f741b8d1894afe5fd3fcc8eb244f7dd5914eeb959b85717d","src/hkdf.rs":"3ff432cc9d40e1dc56e9f983b54b593647c4063a5ae0f16de0a64d033ac9bd94","src/hp.rs":"722a798a7d280b66bd0f8adc6f9135f7d8130f7f0ef45ea12b85d47a88adefda","src/lib.rs":"8d1bfe33999b20eeb5f7eef70d4c634de560de5376029f81b2412bca60176c39","src/once.rs":"b9850384899a1a016e839743d3489c0d4d916e1973746ef8c89872105d7d9736","src/p11.rs":"2ff35a2512bcf894684f24b94640e7fe9d4df6a20264aa3714f2f02fdb99e73d","src/prio.rs":"d9bd43a4d84db70fd552239d0852ea60b960957912f614b929d27dadccca803a","src/replay.rs":"c9bc0261fe1ae22e7212774c315a2669784e57762ca975a15250d4a33dbf3ea3","src/result.rs":"cef34dfcb907723e195b56501132e4560e250b327783cb5e41201da5b63e9b5c","src/secrets.rs":"d5d98e34b100568fecade932832379c52530c70a51ad2d37ee6b2dd008865f01","src/selfencrypt.rs":"f11ae7f6f1e6b602b6e729d71597116fb172190b57102af4f76b22fbe78c8b6a","src/ssl.rs":"ace1a162c3b189d52b5e5f9827c4300b7d47d3b2ae29a976d3bbc46c52328253","src/time.rs":"9bacbed11b0e40402731a9803fd1531272e00e199217c1560130ede50d7020f6","tests/aead.rs":"31b5b4374cc5ca2deee6267c4d5b4858defc74e694ec85af196339a76548a17c","tests/agent.rs":"94819f9eeba2afa0c25adc821755900f1488fd47af6d84d9507a112c29d1752a","tests/ext.rs":"eba9f03accdd598e38292ac88263a81b367d60d5a736a43117a3663de105ec48","tests/handshake.rs":"0fcfa8958686aacb42c56c51c6b234842fe990470d2069a67509869baaa18452","tests/hkdf.rs":"47830c1ea58a02d100522bdde6fabc02bb447ccb85affa0cdc44bc25da1be32a","tests/hp.rs":"316973740210fc1f8166920582795a41347a0aec9024fdc480e2ee83a7a5332d","tests/init.rs":"fc9e392b1efa0d8efb28952f73ffc05e5348e7b2b69207b60e375c3888a252a2","tests/selfencrypt.rs":"1125c858ec4e0a6994f34d162aa066cb003c61b324f268529ea04bcb641347cb"},"package":null}
|
||||
{"files":{"Cargo.toml":"fc03d4b7219e6615de21d3a5a2fa14e4ccd32014e081848b3fd917fcddf48d42","TODO":"ac0f1c2ebcca03f5b3c0cc56c5aedbb030a4b511e438bc07a57361c789f91e9f","bindings/bindings.toml":"cb3e29ac6d1fd7083ffab81494afe1b9a2d9e41c60774438fd9681974c87c252","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":"536e0436f19152aa5a23c340e93ebc24c3640153a8c885b723a9379432a9c6d4","src/aead.rs":"140f77ffb5016836c970c39c6c3a42db9581a14b797b9cd05386d0dd0831fe63","src/aead_fuzzing.rs":"e11ea62b4605b84400edbd5fc394f008fc26d3b67467ba7fe1597b90db4c6a12","src/agent.rs":"a0029413c37c71599971e08df8352fbfd7b7d1970a889ef85a1cabaff256ab11","src/agentio.rs":"bce4c3dfcfa433209a409ac0c0752f8c95ab37bb6239a42f99b83858e8747bd1","src/auth.rs":"ced1a18f691894984244088020ea25dc1ee678603317f0c7dfc8b8842fa750b4","src/cert.rs":"628fc2384cdeb2a32bfbecb83c99af393df97fd6a76c6e8827e8240c0d47328b","src/constants.rs":"998e77bee88197a240032c1bfbddcff417a25ba82e576a0d2fe18ee9b63cefc7","src/ech.rs":"447f6297f50914249d0c92ec61d74df6c65ce4affceecb8cafe40927e855fe1d","src/err.rs":"f2cc71de2b40d7bba8119eeaee200337db9a0126176ba06e4902d7312facdb58","src/exp.rs":"61586662407359c1ecb8ed4987bc3c702f26ba2e203a091a51b6d6363cbd510f","src/ext.rs":"361277879194dc32f741b8d1894afe5fd3fcc8eb244f7dd5914eeb959b85717d","src/hkdf.rs":"3ff432cc9d40e1dc56e9f983b54b593647c4063a5ae0f16de0a64d033ac9bd94","src/hp.rs":"606cae31d5cbbd5fd8f02e74e8e372ce6fabc7da3d0c625e905ff74e6cdde0e6","src/lib.rs":"8d1bfe33999b20eeb5f7eef70d4c634de560de5376029f81b2412bca60176c39","src/once.rs":"b9850384899a1a016e839743d3489c0d4d916e1973746ef8c89872105d7d9736","src/p11.rs":"d76a3d365fad3d7fbc8f7c0aacefc65ef737b9286672fa800d14711f50736a0e","src/prio.rs":"e5e169296c0ac69919c59fb6c1f8bd6bf079452eaa13d75da0edd41d435d3f6f","src/replay.rs":"c9bc0261fe1ae22e7212774c315a2669784e57762ca975a15250d4a33dbf3ea3","src/result.rs":"cef34dfcb907723e195b56501132e4560e250b327783cb5e41201da5b63e9b5c","src/secrets.rs":"d5d98e34b100568fecade932832379c52530c70a51ad2d37ee6b2dd008865f01","src/selfencrypt.rs":"f11ae7f6f1e6b602b6e729d71597116fb172190b57102af4f76b22fbe78c8b6a","src/ssl.rs":"90dfa84ebad961c5ecf3c2e85f9de7acf678dd3aed7e2b9f068036512f70a97d","src/time.rs":"9bacbed11b0e40402731a9803fd1531272e00e199217c1560130ede50d7020f6","tests/aead.rs":"31b5b4374cc5ca2deee6267c4d5b4858defc74e694ec85af196339a76548a17c","tests/agent.rs":"94819f9eeba2afa0c25adc821755900f1488fd47af6d84d9507a112c29d1752a","tests/ext.rs":"eba9f03accdd598e38292ac88263a81b367d60d5a736a43117a3663de105ec48","tests/handshake.rs":"0fcfa8958686aacb42c56c51c6b234842fe990470d2069a67509869baaa18452","tests/hkdf.rs":"47830c1ea58a02d100522bdde6fabc02bb447ccb85affa0cdc44bc25da1be32a","tests/hp.rs":"316973740210fc1f8166920582795a41347a0aec9024fdc480e2ee83a7a5332d","tests/init.rs":"fc9e392b1efa0d8efb28952f73ffc05e5348e7b2b69207b60e375c3888a252a2","tests/selfencrypt.rs":"1125c858ec4e0a6994f34d162aa066cb003c61b324f268529ea04bcb641347cb"},"package":null}
|
||||
4
third_party/rust/neqo-crypto/Cargo.toml
vendored
4
third_party/rust/neqo-crypto/Cargo.toml
vendored
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "neqo-crypto"
|
||||
version = "0.6.1"
|
||||
version = "0.6.3"
|
||||
authors = ["Martin Thomson <mt@lowentropy.net>"]
|
||||
edition = "2018"
|
||||
rust-version = "1.57.0"
|
||||
|
|
@ -12,7 +12,7 @@ neqo-common = { path = "../neqo-common" }
|
|||
log = {version = "0.4.0", default-features = false}
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = {version = "0.59", default-features = false, features= ["runtime"]}
|
||||
bindgen = {version = "0.63", default-features = false, features= ["runtime"]}
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
toml = "0.5"
|
||||
|
|
|
|||
4
third_party/rust/neqo-crypto/build.rs
vendored
4
third_party/rust/neqo-crypto/build.rs
vendored
|
|
@ -102,7 +102,7 @@ fn nss_dir() -> PathBuf {
|
|||
let dir = Path::new(&out_dir).join("nss");
|
||||
if !dir.exists() {
|
||||
Command::new("hg")
|
||||
.args(&[
|
||||
.args([
|
||||
"clone",
|
||||
"https://hg.mozilla.org/projects/nss",
|
||||
dir.to_str().unwrap(),
|
||||
|
|
@ -113,7 +113,7 @@ fn nss_dir() -> PathBuf {
|
|||
let nspr_dir = Path::new(&out_dir).join("nspr");
|
||||
if !nspr_dir.exists() {
|
||||
Command::new("hg")
|
||||
.args(&[
|
||||
.args([
|
||||
"clone",
|
||||
"https://hg.mozilla.org/projects/nspr",
|
||||
nspr_dir.to_str().unwrap(),
|
||||
|
|
|
|||
12
third_party/rust/neqo-crypto/src/agent.rs
vendored
12
third_party/rust/neqo-crypto/src/agent.rs
vendored
|
|
@ -596,7 +596,7 @@ impl SecretAgent {
|
|||
/// Return any fatal alert that the TLS stack might have sent.
|
||||
#[must_use]
|
||||
pub fn alert(&self) -> Option<&Alert> {
|
||||
(&*self.alert).as_ref()
|
||||
(*self.alert).as_ref()
|
||||
}
|
||||
|
||||
/// Call this function to mark the peer as authenticated.
|
||||
|
|
@ -930,7 +930,7 @@ impl Client {
|
|||
/// Error returned when the configuration is invalid.
|
||||
pub fn enable_ech(&mut self, ech_config_list: impl AsRef<[u8]>) -> Res<()> {
|
||||
let config = ech_config_list.as_ref();
|
||||
qdebug!([self], "Enable ECH for a server: {}", hex_with_len(&config));
|
||||
qdebug!([self], "Enable ECH for a server: {}", hex_with_len(config));
|
||||
self.ech_config = Vec::from(config);
|
||||
if config.is_empty() {
|
||||
unsafe { ech::SSL_EnableTls13GreaseEch(self.agent.fd, PRBool::from(true)) }
|
||||
|
|
@ -1189,8 +1189,8 @@ impl Deref for Agent {
|
|||
#[must_use]
|
||||
fn deref(&self) -> &SecretAgent {
|
||||
match self {
|
||||
Self::Client(c) => &**c,
|
||||
Self::Server(s) => &**s,
|
||||
Self::Client(c) => c,
|
||||
Self::Server(s) => s,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1198,8 +1198,8 @@ impl Deref for Agent {
|
|||
impl DerefMut for Agent {
|
||||
fn deref_mut(&mut self) -> &mut SecretAgent {
|
||||
match self {
|
||||
Self::Client(c) => &mut **c,
|
||||
Self::Server(s) => &mut **s,
|
||||
Self::Client(c) => c,
|
||||
Self::Server(s) => s,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
8
third_party/rust/neqo-crypto/src/hp.rs
vendored
8
third_party/rust/neqo-crypto/src/hp.rs
vendored
|
|
@ -150,7 +150,7 @@ impl HpKey {
|
|||
output.as_mut_ptr(),
|
||||
&mut output_len,
|
||||
c_int::try_from(output.len())?,
|
||||
(&sample[..Self::SAMPLE_SIZE]).as_ptr().cast(),
|
||||
sample[..Self::SAMPLE_SIZE].as_ptr().cast(),
|
||||
c_int::try_from(Self::SAMPLE_SIZE).unwrap(),
|
||||
)
|
||||
})?;
|
||||
|
|
@ -162,7 +162,7 @@ impl HpKey {
|
|||
let params: CK_CHACHA20_PARAMS = CK_CHACHA20_PARAMS {
|
||||
pBlockCounter: sample.as_ptr() as *mut u8,
|
||||
blockCounterBits: 32,
|
||||
pNonce: (&sample[4..Self::SAMPLE_SIZE]).as_ptr() as *mut _,
|
||||
pNonce: sample[4..Self::SAMPLE_SIZE].as_ptr() as *mut _,
|
||||
ulNonceBits: 96,
|
||||
};
|
||||
let mut output_len: c_uint = 0;
|
||||
|
|
@ -172,10 +172,10 @@ impl HpKey {
|
|||
**key,
|
||||
CK_MECHANISM_TYPE::from(CKM_CHACHA20),
|
||||
addr_of_mut!(param_item),
|
||||
(&mut output[..]).as_mut_ptr(),
|
||||
output[..].as_mut_ptr(),
|
||||
&mut output_len,
|
||||
c_uint::try_from(output.len())?,
|
||||
(&output[..]).as_ptr(),
|
||||
output[..].as_ptr(),
|
||||
c_uint::try_from(output.len())?,
|
||||
)
|
||||
})?;
|
||||
|
|
|
|||
1
third_party/rust/neqo-crypto/src/p11.rs
vendored
1
third_party/rust/neqo-crypto/src/p11.rs
vendored
|
|
@ -20,7 +20,6 @@ use std::os::raw::{c_int, c_uint};
|
|||
use std::ptr::null_mut;
|
||||
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
#[allow(unknown_lints, deref_nullptr)] // Until bindgen#1651 is fixed.
|
||||
#[allow(clippy::unreadable_literal)]
|
||||
#[allow(unknown_lints, clippy::borrow_as_ptr)]
|
||||
mod nss_p11 {
|
||||
|
|
|
|||
1
third_party/rust/neqo-crypto/src/prio.rs
vendored
1
third_party/rust/neqo-crypto/src/prio.rs
vendored
|
|
@ -5,7 +5,6 @@
|
|||
// except according to those terms.
|
||||
|
||||
#![allow(clippy::upper_case_acronyms)]
|
||||
#![allow(unknown_lints, deref_nullptr)] // Until bindgen#1651 is fixed.
|
||||
#![allow(
|
||||
dead_code,
|
||||
non_upper_case_globals,
|
||||
|
|
|
|||
1
third_party/rust/neqo-crypto/src/ssl.rs
vendored
1
third_party/rust/neqo-crypto/src/ssl.rs
vendored
|
|
@ -14,7 +14,6 @@
|
|||
unknown_lints,
|
||||
clippy::borrow_as_ptr
|
||||
)]
|
||||
#![allow(unknown_lints, deref_nullptr)] // Until bindgen#1651 is fixed.
|
||||
|
||||
use crate::constants::Epoch;
|
||||
use crate::err::{secstatus_to_res, Res};
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"7dd3f73b8b65f903607977de05ae02595340dd5e7afe6ac5010e400fc440c506","src/buffered_send_stream.rs":"4bc45ca03252dc34ab421a2af3499191b182a619143c61d5609a46377c9a0f3d","src/client_events.rs":"9d86145febad2f3fb05007eae3f5ad4834c78dd709fe388f05590405e34a614b","src/conn_params.rs":"7e33526de9c83c163049a2caf2bff0f997351cc61fad76fb6e8c6ec4b9f09938","src/connection.rs":"72c3c2a3c19481d519f4c1928c51dc7c1d4ab6e6cb2bd9ecfdfc5d5c09f485bb","src/connection_client.rs":"e4914a8e44eb6045615382eacf2499b0195574f19ce36e161ad3d3e186f69ebb","src/connection_server.rs":"de1e0359b902b1e98c923a8d5488302a68a3312b466590fdddaee6ec8327813b","src/control_stream_local.rs":"b86e1f869ad59bf2663501942a1a65d94c1dbc3e8770982459e0b620be4b6cf0","src/control_stream_remote.rs":"7a261ac7df77e90a428ab0f92457a934a92a8c581462fc1818efd3de0c0ebd69","src/features/extended_connect/mod.rs":"2bc2f0570b11318f3225173001dad1a5f05e4bf60dee49a2bf9d40e3a411e138","src/features/extended_connect/webtransport_session.rs":"abf84892c429c2ee79efd8e215bfd9da182163ba859cd24b6ee4ba6becceb6bd","src/features/extended_connect/webtransport_streams.rs":"784c5e317bb6af33f653ba82c1a5666b657c2a210263a415e913494f61613464","src/features/mod.rs":"a981ebbd03e7bb7ea2313e883452e44f052c48f28edb7fd53a0825911b490230","src/frames/hframe.rs":"8206e1a27ad805899f7e722c05dffa92649704bbaf98ff2a70a7ca1d6a55395e","src/frames/mod.rs":"258dd4bdf2daca19a62cd697d2c7f4709a35668b2b4dce3203675e814c9b40b8","src/frames/reader.rs":"0802cd8b41204bcec424fc6ed704a3bdbed0e5d38444f7a9b0550ad877b076a6","src/frames/tests/hframe.rs":"33a30bb98bb512606a06ae1752e1ed9e4588b7d3f5e9439ec83bb2e779d4ac80","src/frames/tests/mod.rs":"4933c519069ee4dac23587588f2b792c12d1363e92d0105e1eb169082e213559","src/frames/tests/reader.rs":"312a3deda7b3a4bbd7afed879c94d0644fce8e34435365ef9cae1fbaa62496af","src/frames/tests/wtframe.rs":"589ebe1e62ce4da63b37b7d22cde7ba572ddbf29336fdcdbbcd0a745f79dacd8","src/frames/wtframe.rs":"0eebdf9a275cd53ee6525f7387941601d119d933203d9b2425377adf8348d425","src/headers_checks.rs":"b80c1da2d9f336fa88f7b7f2a834d8e90e826260811771c7729785fdc92b20d4","src/lib.rs":"58d23d794cf5c68d6f2b68e93e3e7d1c5546d64d5d2357ca7cb7858aeb434124","src/priority.rs":"ae0fa461031893b4f7e0d12666072e7a4da80b1e8a1c0663ab9f9e27b3242754","src/push_controller.rs":"aa2a64180d8cb1b87682d0d8bbc42167188e8e1890261cb4cabb76de1fcc708b","src/qlog.rs":"44b6cdbb1d9d6ca47b793e9dbe531b8fdbd40147375f7e4c89aeab536c5d286b","src/qpack_decoder_receiver.rs":"75008d8ea5d538ee34aca4df72e58489417604ccafb61b064280782d6754dd0d","src/qpack_encoder_receiver.rs":"f95cc7d49e4d442b93d522f14ddfc581629664d84d6e13d03a520e855bbe442d","src/recv_message.rs":"5f70fb474e387653d7982374131b3b0c08417509469f273ccebf842bfcee836f","src/request_target.rs":"9182b641f7a7b55272e0e2e872d24a35b1207f35399221b08b899857c3e873ab","src/send_message.rs":"9e1b22ede2a105a79d7c02178801e1a46b06a80dc1c0d2a7d69b0eea7e89f319","src/server.rs":"ab00f395f7767d733091af3e3317527e5c302b2e5062b33943211ede75f10109","src/server_connection_events.rs":"3d89c2d9a30ee719acfbaae4b7720cb354eb73b11bc6ceb44571d68b05192b8b","src/server_events.rs":"3081fdd1e1950aeecae031452cd683335fb0a9dcec51722e614c5939f747b9d9","src/settings.rs":"e7babcce34c49d897c7d5ed93ef8e9ad02524cebff96a249c2ce84f1b968be21","src/stream_type_reader.rs":"f790b2aaa6758ad85487d98376895b5ee2c3098ffd4586825e1bb0b3c2375c75","tests/httpconn.rs":"f8d6e6a693d17cf2eb192a730e6fc929bd2814552356ce8d4423a0e3eac8c59d","tests/mod.rs":"fd6aee37243713e80fc526552f21f0222338cec9890409b6575a2a637b17ec1f","tests/priority.rs":"a606e5fa03451e09e28c7d5f1820ee85a4567e3969a1690c979761e62123bf54","tests/send_message.rs":"673ae1d0bf2dce46c21ee8353f45f189d2cb64a2f6e137ae38da6b2262ad066e","tests/webtransport/mod.rs":"635c0b0fe682a844f4366335a40b8b3a6539abe30843ee1bcfaf87a34b1d476c","tests/webtransport/negotiation.rs":"2da85dfd45e3dfdbab7608768d734e1f150e1b0ba14e982cbb6de16ba62789c2","tests/webtransport/sessions.rs":"5b4d8483ac018ad5a28adad5e778e2ed48db9c441d1354f6cf21d8e5c6f1a8b3","tests/webtransport/streams.rs":"fd5f075d93f0241290566f59f747d95530d2df579890fd0f6b9e79a557c89a67"},"package":null}
|
||||
{"files":{"Cargo.toml":"bf794c0aeb6200aafc695374c2218afd0cf6f7bab7e6b1c370eb0171fb785169","src/buffered_send_stream.rs":"4bc45ca03252dc34ab421a2af3499191b182a619143c61d5609a46377c9a0f3d","src/client_events.rs":"978ab01cf82c2390db442c6d8440209f9498f52a00ede7c8ea9813e649e15ae3","src/conn_params.rs":"7e33526de9c83c163049a2caf2bff0f997351cc61fad76fb6e8c6ec4b9f09938","src/connection.rs":"fe38c174b54b65c696e8fdc89da337cb19783fee78d6d6407223a8d13bb36c6a","src/connection_client.rs":"131b20981697002386ef2dff63345dfa4227547dd028293e16f91f72c1b9cd26","src/connection_server.rs":"365f246a0caa5d310da21587525b4793cd3046d973cce8f3aa62b8a1eac493a7","src/control_stream_local.rs":"b86e1f869ad59bf2663501942a1a65d94c1dbc3e8770982459e0b620be4b6cf0","src/control_stream_remote.rs":"7a261ac7df77e90a428ab0f92457a934a92a8c581462fc1818efd3de0c0ebd69","src/features/extended_connect/mod.rs":"94fc7b98ac335ffad4eb41d162b87f0ae9a86205cd3ef9c79d21081a99d6e610","src/features/extended_connect/tests/mod.rs":"fd6aee37243713e80fc526552f21f0222338cec9890409b6575a2a637b17ec1f","src/features/extended_connect/tests/webtransport/datagrams.rs":"0d8021b94491100d56f4c66ad852bea9d3f1286135e523e217db0e0487284172","src/features/extended_connect/tests/webtransport/mod.rs":"db7b31e6826e2fb6ab8051434d649d78a70d3b7e92e3760f79f7995c7b651558","src/features/extended_connect/tests/webtransport/negotiation.rs":"2d8b0bfa015eb7b57a844aea8abf4ae3c0ab478d1bf84bb53ef8b1837ca7b7ec","src/features/extended_connect/tests/webtransport/sessions.rs":"8471db54293452aa5ae2a0aab565b51e2907238679d5f4074ab3cc05f24036ff","src/features/extended_connect/tests/webtransport/streams.rs":"0ef81aef536f01413b13738cf59f69c7f819a75d655de3d6b905f2f3d84f8509","src/features/extended_connect/webtransport_session.rs":"3dea89800b4b364d140a443d12b25393fa3f50f9bc3f8d6f52e8f9b88cd74049","src/features/extended_connect/webtransport_streams.rs":"9562e5bf321f1338514a70ee89ccd88a15cd4ccf727ea3533b55bb1d5be27f04","src/features/mod.rs":"a981ebbd03e7bb7ea2313e883452e44f052c48f28edb7fd53a0825911b490230","src/frames/hframe.rs":"8206e1a27ad805899f7e722c05dffa92649704bbaf98ff2a70a7ca1d6a55395e","src/frames/mod.rs":"7d0a46ca147336d14781edb8dbee8b03c2e4bcd6646f5473a9d93d31fe73fecb","src/frames/reader.rs":"3d7af10a21833049aa0277caec4abe13d677d2d62526f1c83126f2defe19ee5e","src/frames/tests/hframe.rs":"33a30bb98bb512606a06ae1752e1ed9e4588b7d3f5e9439ec83bb2e779d4ac80","src/frames/tests/mod.rs":"81cac9702e9016dacd60085c2e3968093b356fe682ced33d7c9c1f3151b9201c","src/frames/tests/reader.rs":"312a3deda7b3a4bbd7afed879c94d0644fce8e34435365ef9cae1fbaa62496af","src/frames/tests/wtframe.rs":"589ebe1e62ce4da63b37b7d22cde7ba572ddbf29336fdcdbbcd0a745f79dacd8","src/frames/wtframe.rs":"0eebdf9a275cd53ee6525f7387941601d119d933203d9b2425377adf8348d425","src/headers_checks.rs":"b80c1da2d9f336fa88f7b7f2a834d8e90e826260811771c7729785fdc92b20d4","src/lib.rs":"50ac4975d3b5b5680a1f8d144da16b40f080bbe90e05679fe50d59ad5937d10b","src/priority.rs":"ae0fa461031893b4f7e0d12666072e7a4da80b1e8a1c0663ab9f9e27b3242754","src/push_controller.rs":"aa2a64180d8cb1b87682d0d8bbc42167188e8e1890261cb4cabb76de1fcc708b","src/qlog.rs":"44b6cdbb1d9d6ca47b793e9dbe531b8fdbd40147375f7e4c89aeab536c5d286b","src/qpack_decoder_receiver.rs":"50c5e7679304b227a5f86ab681396d59c5885a8d7a4b72985cce82f3f8eaa129","src/qpack_encoder_receiver.rs":"3deca0555826167bbaf8099eb1b394883e5e5c8c4ee68261f8c4816bdf686eda","src/recv_message.rs":"1f740c59676f5913108de68f41db1dfc1b8d6feeb0467c61ae652d6d26e75682","src/request_target.rs":"9182b641f7a7b55272e0e2e872d24a35b1207f35399221b08b899857c3e873ab","src/send_message.rs":"9e1b22ede2a105a79d7c02178801e1a46b06a80dc1c0d2a7d69b0eea7e89f319","src/server.rs":"cfcb1e9e44f3e4de220fe71cee9f4633bed911f49c1bc40a44b6ff95ec6f5a76","src/server_connection_events.rs":"df18dac1ca9048567a6aac4db34aa031cb80135b1ef6cd3ae67e3f621015e081","src/server_events.rs":"be39b5c07c6f1981b8d4c4afd8dfc704b0b2b440831f364079aeffeec4dedd8f","src/settings.rs":"e7babcce34c49d897c7d5ed93ef8e9ad02524cebff96a249c2ce84f1b968be21","src/stream_type_reader.rs":"983362180f19e47c938b3b81650e71c5bc5a55500ff425b1617d74e2ec9357f5","tests/httpconn.rs":"8b62aa9a24ccc45f436aa57ff7d5b37394d844eced6b204085fc5086b1a643c7","tests/priority.rs":"a606e5fa03451e09e28c7d5f1820ee85a4567e3969a1690c979761e62123bf54","tests/send_message.rs":"673ae1d0bf2dce46c21ee8353f45f189d2cb64a2f6e137ae38da6b2262ad066e","tests/webtransport.rs":"73b1b5a0297452e92c81793b986cbe666f6efe114b9ab5f719be5d3e92f1819c"},"package":null}
|
||||
2
third_party/rust/neqo-http3/Cargo.toml
vendored
2
third_party/rust/neqo-http3/Cargo.toml
vendored
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "neqo-http3"
|
||||
version = "0.6.1"
|
||||
version = "0.6.3"
|
||||
authors = ["Dragana Damjanovic <dragana.damjano@gmail.com>"]
|
||||
edition = "2018"
|
||||
rust-version = "1.57.0"
|
||||
|
|
|
|||
13
third_party/rust/neqo-http3/src/client_events.rs
vendored
13
third_party/rust/neqo-http3/src/client_events.rs
vendored
|
|
@ -35,6 +35,10 @@ pub enum WebTransportEvent {
|
|||
stream_id: StreamId,
|
||||
session_id: StreamId,
|
||||
},
|
||||
Datagram {
|
||||
session_id: StreamId,
|
||||
datagram: Vec<u8>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
|
|
@ -211,6 +215,15 @@ impl ExtendedConnectEvents for Http3ClientEvents {
|
|||
},
|
||||
));
|
||||
}
|
||||
|
||||
fn new_datagram(&self, session_id: StreamId, datagram: Vec<u8>) {
|
||||
self.insert(Http3ClientEvent::WebTransport(
|
||||
WebTransportEvent::Datagram {
|
||||
session_id,
|
||||
datagram,
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
impl Http3ClientEvents {
|
||||
|
|
|
|||
304
third_party/rust/neqo-http3/src/connection.rs
vendored
304
third_party/rust/neqo-http3/src/connection.rs
vendored
|
|
@ -27,11 +27,12 @@ use crate::{
|
|||
HttpRecvStreamEvents, NewStreamType, Priority, PriorityHandler, ReceiveOutput, RecvStream,
|
||||
RecvStreamEvents, SendStream, SendStreamEvents,
|
||||
};
|
||||
use neqo_common::{qdebug, qerror, qinfo, qtrace, qwarn, Header, MessageType, Role};
|
||||
use neqo_common::{qdebug, qerror, qinfo, qtrace, qwarn, Decoder, Header, MessageType, Role};
|
||||
use neqo_qpack::decoder::QPackDecoder;
|
||||
use neqo_qpack::encoder::QPackEncoder;
|
||||
use neqo_transport::{
|
||||
AppError, Connection, ConnectionError, State, StreamId, StreamType, ZeroRttState,
|
||||
AppError, Connection, ConnectionError, DatagramTracking, State, StreamId, StreamType,
|
||||
ZeroRttState,
|
||||
};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{BTreeSet, HashMap};
|
||||
|
|
@ -41,7 +42,7 @@ use std::rc::Rc;
|
|||
|
||||
use crate::{Error, Res};
|
||||
|
||||
pub struct RequestDescription<'b, 't, T>
|
||||
pub(crate) struct RequestDescription<'b, 't, T>
|
||||
where
|
||||
T: AsRequestTarget<'t> + ?Sized + Debug,
|
||||
{
|
||||
|
|
@ -52,6 +53,20 @@ where
|
|||
pub priority: Priority,
|
||||
}
|
||||
|
||||
pub enum WebTransportSessionAcceptAction {
|
||||
Accept,
|
||||
Reject(Vec<Header>),
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for WebTransportSessionAcceptAction {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
match self {
|
||||
WebTransportSessionAcceptAction::Accept => f.write_str("Accept"),
|
||||
WebTransportSessionAcceptAction::Reject(_) => f.write_str("Reject"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Http3RemoteSettingsState {
|
||||
NotReceived,
|
||||
|
|
@ -59,6 +74,19 @@ enum Http3RemoteSettingsState {
|
|||
ZeroRtt(HSettings),
|
||||
}
|
||||
|
||||
/// States:
|
||||
/// - `Initializing`: this is the state during the QUIC handshake,
|
||||
/// - `ZeroRtt`: 0-RTT has been enabled and is active
|
||||
/// - Connected
|
||||
/// - GoingAway(StreamId): The connection has received a `GOAWAY` frame
|
||||
/// - Closing(ConnectionError): The connection is closed. The closing has been initiated by this
|
||||
/// end of the connection, e.g., the `CONNECTION_CLOSE` frame has been sent. In this state, the
|
||||
/// connection waits a certain amount of time to retransmit the `CONNECTION_CLOSE` frame if
|
||||
/// needed.
|
||||
/// - Closed(ConnectionError): This is the final close state: closing has been initialized by the
|
||||
/// peer and an ack for the `CONNECTION_CLOSE` frame has been sent or the closing has been
|
||||
/// initiated by this end of the connection and the ack for the `CONNECTION_CLOSE` has been
|
||||
/// received or the waiting time has passed.
|
||||
#[derive(Debug, PartialEq, PartialOrd, Ord, Eq, Clone)]
|
||||
pub enum Http3State {
|
||||
Initializing,
|
||||
|
|
@ -79,6 +107,194 @@ impl Http3State {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
# HTTP/3 core implementation
|
||||
|
||||
This is the core implementation of HTTP/3 protocol. It implements most of the features of the
|
||||
protocol. `Http3Client` and `Http3ServerHandler` implement only client and server side behavior.
|
||||
|
||||
The API consists of:
|
||||
- functions that correspond to the `Http3Client` and `Http3ServerHandler` API:
|
||||
- `new`
|
||||
- `close`
|
||||
- `fetch` - only used by the client-side implementation
|
||||
- `read_data`
|
||||
- `stream_reset_send`
|
||||
- `stream_stop_sending`
|
||||
- `cancel_fetch`
|
||||
- `stream_close_send`
|
||||
- functions that correspond to [`WebTransport`](https://w3c.github.io/webtransport/) functions:
|
||||
- `webtransport_create_session` - only used by the client-side implementation
|
||||
- `webtransport_session_accept` - only used by the server-side implementation
|
||||
- `webtransport_close_session`
|
||||
- `webtransport_create_stream_local` - this function is called when an application wants to open
|
||||
a new `WebTransport` stream. For example `Http3Client::webtransport_create_stream` will call
|
||||
this function.
|
||||
- `webtransport_create_stream_remote` - this is called when a `WebTransport` stream has been
|
||||
opened by the peer and this function sets up the appropriate handler for the stream.
|
||||
- functions that are called by `process_http3`
|
||||
- `process_sending` - some send-streams are buffered streams(see the Streams section) and this
|
||||
function is called to trigger sending of the buffer data.
|
||||
- functions that are called to handle `ConnectionEvent`s:
|
||||
- `add_new_stream`
|
||||
- `handle_stream_readable`
|
||||
- `handle_stream_reset`
|
||||
- `handle_stream_stop_sending`
|
||||
- `handle_state_change`
|
||||
- `handle_zero_rtt_rejected`
|
||||
- Additional functions:
|
||||
- `set_features_listener`
|
||||
- `stream_has_pending_data`
|
||||
- `has_data_to_send`
|
||||
- `add_streams`
|
||||
- `add_recv_stream`
|
||||
- `queue_control_frame`
|
||||
- `queue_update_priority`
|
||||
- `set_0rtt_settings`
|
||||
- `get_settings`
|
||||
- `state`
|
||||
- `webtransport_enabled`
|
||||
|
||||
## Streams
|
||||
|
||||
Each `Http3Connection` holds a list of stream handlers. Each send and receive-handler is registered in
|
||||
`send_streams` and `recv_streams`. Unidirectional streams are registered only on one of the lists
|
||||
and bidirectional streams are registered in both lists and the 2 handlers are independent, e.g. one
|
||||
can be closed and removed ane second may still be active.
|
||||
|
||||
The only streams that are not registered are the local control stream, local QPACK decoder stream,
|
||||
and local QPACK encoder stream. These streams are send-streams and sending data on this stream is
|
||||
handled a bit differently. This is done in the `process_sending` function, i.e. the control data is
|
||||
sent first and QPACK data is sent after regular stream data is sent because this stream may have
|
||||
new data only after regular streams are handled (TODO we may improve this a bit to send QPACK
|
||||
commands before headers.)
|
||||
|
||||
There are the following types of streams:
|
||||
- `Control`: there is only a receiver stream of this type and the handler is `ControlStreamRemote`.
|
||||
- `Decoder`: there is only a receiver stream of this type and the handler is `DecoderRecvStream`.
|
||||
- `Encoder`: there is only a receiver stream of this type and the handler is `EncoderRecvStream`.
|
||||
- `NewStream`: there is only a receiver stream of this type and the handler is
|
||||
`NewStreamHeadReader`.
|
||||
- `Http`: `SendMessage` and `RecvMessage` handlers are responsible for this type of streams.
|
||||
- `Push`: `RecvMessage` is responsible for this type of streams.
|
||||
- `ExtendedConnect`: `WebTransportSession` is responsible sender and receiver handler.
|
||||
- `WebTransport(StreamId)`: `WebTransportSendStream` and `WebTransportRecvStream` are responsible
|
||||
sender and receiver handler.
|
||||
- `Unknown`: These are all other stream types that are not unknown to the current implementation
|
||||
and should be handled properly by the spec, e.g., in our implementation the streams are
|
||||
reset.
|
||||
|
||||
The streams are registered in `send_streams` and `recv_streams` in following ways depending if they
|
||||
are local or remote:
|
||||
- local streams:
|
||||
- all local stream will be registered with the appropriate handler.
|
||||
- remote streams:
|
||||
- all new incoming streams are registered with `NewStreamHeadReader`. This is triggered by
|
||||
`ConnectionEvent::NewStream` and `add_new_stream` is called.
|
||||
- reading from a `NewStreamHeadReader` stream, via the `receive` function, will decode a stream
|
||||
type. `NewStreamHeadReader::receive` will return `ReceiveOutput::NewStream(_)` when a stream
|
||||
type has been decoded. After this point the stream:
|
||||
- will be regegistered with the appropriate handler,
|
||||
- will be canceled if is an unknown stream type or
|
||||
- the connection will fail if it is unallowed stream type (receiveing HTTP request on the
|
||||
client-side).
|
||||
The output is handled in `handle_new_stream`, for control, qpack streams and partially
|
||||
`WebTransport` streams, otherwise the output is handled by `Http3Client` and `Http3ServerHandler`.
|
||||
|
||||
|
||||
### Receiving data
|
||||
|
||||
Reading from a stream is triggered by `ConnectionEvent::RecvStreamReadable` events for the stream.
|
||||
The receive handler is retrieved from `recv_streams` and its `RecvStream::receive` function is
|
||||
called.
|
||||
|
||||
Receiving data on `Http` streams is also triggered by the `read_data` function.
|
||||
`ConnectionEvent::RecvStreamReadable` events will trigger reading `HEADERS` frame and frame headers
|
||||
for `DATA` frames which will produce `Http3ClientEvent` or `Http3ServerEvent` events. The content of
|
||||
`DATA` frames is read by the application using the `read_data` function. The `read_data` function
|
||||
may read frame headers for consecutive `DATA` frames.
|
||||
|
||||
On a `WebTransport(_)` stream data will be read only by the `read_data` function. The
|
||||
`RecvStream::receive` function only produces an `Http3ClientEvent` or `Http3ServerEvent` event.
|
||||
|
||||
The `receive` and `read_data` functions may detect that the stream is done, e.g. FIN received. In
|
||||
this case, the stream will be removed from the `recv_stream` register, see `remove_recv_stream`.
|
||||
|
||||
### Sending data
|
||||
|
||||
All sender stream handlers have buffers. Data is first written into a buffer before being supplied
|
||||
to the QUIC layer. All data except the `DATA` frame and `WebTransport(_)`’s payload are written
|
||||
into the buffer. This includes stream type byte, e.g. `WEBTRANSPORT_STREAM` as well. In the case of
|
||||
`Http` and `WebTransport(_)` applications can write directly to the QUIC layer using the
|
||||
`send_data` function to avoid copying data. Sending data via the `send_data` function is only
|
||||
possible if there is no buffered data.
|
||||
|
||||
If a stream has buffered data it will be registered in the `streams_with_pending_data` queue and
|
||||
actual sending will be performed in the `process_sending` function call. (This is done in this way,
|
||||
i.e. data is buffered first and then sent, for 2 reasons: in this way, sending will happen in a
|
||||
single function, therefore error handling and clean up is easier and the QUIIC layer may not be
|
||||
able to accept all data and being able to buffer data is required in any case.)
|
||||
|
||||
The `send` and `send_data` functions may detect that the stream is closed and all outstanding data
|
||||
has been transferred to the QUIC layer. In this case, the stream will be removed from the
|
||||
`send_stream` register.
|
||||
|
||||
### `ControlStreamRemote`
|
||||
|
||||
The `ControlStreamRemote` handler uses `FrameReader` to read and decode frames received on the
|
||||
control frame. The `receive` returns `ReceiveOutput::ControlFrames(_)` with a list of control
|
||||
frames read (the list may be empty). The control frames are handled by `Http3Connection` and/or by
|
||||
`Http3Client` and `Http3ServerHandler`.
|
||||
|
||||
### `DecoderRecvStream` and `EncoderRecvStream`
|
||||
|
||||
The `receive` functions of these handlers call corresponding `receive` functions of `QPackDecoder`
|
||||
and `QPackDecoder`.
|
||||
|
||||
`DecoderRecvStream` returns `ReceiveOutput::UnblockedStreams(_)` that may contain a list of stream
|
||||
ids that are unblocked by receiving qpack decoder commands. `Http3Connection` will handle this
|
||||
output by calling `receive` for the listed stream ids.
|
||||
|
||||
`EncoderRecvStream` only returns `ReceiveOutput::NoOutput`.
|
||||
|
||||
Both handlers may return an error that will close the connection.
|
||||
|
||||
### `NewStreamHeadReader`
|
||||
|
||||
A new incoming receiver stream registers a `NewStreamHeadReader` handler. This handler reads the
|
||||
first bytes of a stream to detect a stream type. The `receive` function returns
|
||||
`ReceiveOutput::NoOutput` if a stream type is still not known by reading the available stream data
|
||||
or `ReceiveOutput::NewStream(_)`. The handling of the output is explained above.
|
||||
|
||||
### `SendMessage` and `RecvMessage`
|
||||
|
||||
`RecvMessage::receive` only returns `ReceiveOutput::NoOutput`. It also have an event listener of
|
||||
type `HttpRecvStreamEvents`. The listener is called when headers are ready, or data is ready, etc.
|
||||
|
||||
For example for `Http` stream the listener will produce `HeaderReady` and `DataReadable` events.
|
||||
|
||||
### `WebTransportSession`
|
||||
|
||||
A `WebTransport` session is connected to a control stream that is in essence an HTTP transaction.
|
||||
Therefore, `WebTransportSession` will internally use a `SendMessage` and `RecvMessage` handler to
|
||||
handle parsing and sending of HTTP part of the control stream. When HTTP headers are exchenged,
|
||||
`WebTransportSession` will take over handling of stream data. `WebTransportSession` sets
|
||||
`WebTransportSessionListener` as the `RecvMessage` event listener.
|
||||
|
||||
`WebTransportSendStream` and `WebTransportRecvStream` are associated with a `WebTransportSession`
|
||||
and they will be canceled if the session is closed. To be avle to do this `WebTransportSession`
|
||||
holds a list of its active streams and clean up is done in `remove_extended_connect`.
|
||||
|
||||
### `WebTransportSendStream` and `WebTransportRecvStream`
|
||||
|
||||
`WebTransport` streams are associated with a session. `WebTransportSendStream` and
|
||||
`WebTransportRecvStream` hold a reference to the session and are registered in the session upon
|
||||
creation by `Http3Connection`. The `WebTransportSendStream` and `WebTransportRecvStream`
|
||||
handlers will be unregistered from the session if they are closed, reset, or canceled.
|
||||
|
||||
The call to function `receive` may produce `Http3ClientEvent::DataReadable`. Actual reading of
|
||||
data is done in the `read_data` function.
|
||||
*/
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Http3Connection {
|
||||
role: Role,
|
||||
|
|
@ -126,10 +342,15 @@ impl Http3Connection {
|
|||
}
|
||||
}
|
||||
|
||||
/// This function is called when a not default feature needs to be negotiated. This is currently
|
||||
/// only used for the `WebTransport` feature. The negotiation is done via the `SETTINGS` frame
|
||||
/// and when the peer's `SETTINGS` frame has been received the listener will be called.
|
||||
pub fn set_features_listener(&mut self, feature_listener: Http3ClientEvents) {
|
||||
self.webtransport.set_listener(feature_listener);
|
||||
}
|
||||
|
||||
/// This function creates and initializes, i.e. send stream type, the control and qpack
|
||||
/// streams.
|
||||
fn initialize_http3_connection(&mut self, conn: &mut Connection) -> Res<()> {
|
||||
qinfo!([self], "Initialize the http3 connection.");
|
||||
self.control_stream_local.create(conn)?;
|
||||
|
|
@ -173,6 +394,10 @@ impl Http3Connection {
|
|||
!self.streams_with_pending_data.is_empty()
|
||||
}
|
||||
|
||||
/// This function calls the `send` function for all streams that have data to send. If a stream
|
||||
/// has data to send it will be added to the `streams_with_pending_data` list.
|
||||
///
|
||||
/// Control and QPACK streams are handled differently and are never added to the list.
|
||||
fn send_non_control_streams(&mut self, conn: &mut Connection) -> Res<()> {
|
||||
let to_send = mem::take(&mut self.streams_with_pending_data);
|
||||
for stream_id in to_send {
|
||||
|
|
@ -192,7 +417,8 @@ impl Http3Connection {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Call `send` for all streams that need to send data.
|
||||
/// Call `send` for all streams that need to send data. See explanation for the main structure
|
||||
/// for more details.
|
||||
pub fn process_sending(&mut self, conn: &mut Connection) -> Res<()> {
|
||||
// check if control stream has data to send.
|
||||
self.control_stream_local
|
||||
|
|
@ -228,6 +454,8 @@ impl Http3Connection {
|
|||
}
|
||||
}
|
||||
|
||||
/// This is called when a `ConnectionEvent::NewStream` event is received. This register the
|
||||
/// stream with a `NewStreamHeadReader` handler.
|
||||
pub fn add_new_stream(&mut self, stream_id: StreamId) {
|
||||
qtrace!([self], "A new stream: {}.", stream_id);
|
||||
self.recv_streams.insert(
|
||||
|
|
@ -236,6 +464,8 @@ impl Http3Connection {
|
|||
);
|
||||
}
|
||||
|
||||
/// The function calls `receive` for a stream. It also deals with the outcome of a read by
|
||||
/// calling `handle_stream_manipulation_output`.
|
||||
#[allow(clippy::option_if_let_else)] // False positive as borrow scope isn't lexical here.
|
||||
fn stream_receive(&mut self, conn: &mut Connection, stream_id: StreamId) -> Res<ReceiveOutput> {
|
||||
qtrace!([self], "Readable stream {}.", stream_id);
|
||||
|
|
@ -271,8 +501,9 @@ impl Http3Connection {
|
|||
/// This function handles reading from all streams, i.e. control, qpack, request/response
|
||||
/// stream and unidi stream that are still do not have a type.
|
||||
/// The function cannot handle:
|
||||
/// 1) a Push stream (if an unknown unidi stream is decoded to be a push stream)
|
||||
/// 2) frames `MaxPushId` or `Goaway` must be handled by `Http3Client`/`Server`.
|
||||
/// 1) a `Push(_)`, `Htttp` or `WebTransportStream(_)` stream
|
||||
/// 2) frames `MaxPushId`, `PriorityUpdateRequest`, `PriorityUpdateRequestPush` or `Goaway`
|
||||
/// must be handled by `Http3Client`/`Server`.
|
||||
/// The function returns `ReceiveOutput`.
|
||||
pub fn handle_stream_readable(
|
||||
&mut self,
|
||||
|
|
@ -306,7 +537,7 @@ impl Http3Connection {
|
|||
ReceiveOutput::NewStream(_) => {
|
||||
unreachable!("NewStream should have been handled already")
|
||||
}
|
||||
_ => Ok(output),
|
||||
ReceiveOutput::NoOutput => Ok(output),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -419,6 +650,17 @@ impl Http3Connection {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn handle_datagram(&mut self, datagram: &[u8]) {
|
||||
let mut decoder = Decoder::new(datagram);
|
||||
let session = decoder
|
||||
.decode_varint()
|
||||
.and_then(|id| self.recv_streams.get_mut(&StreamId::from(id)))
|
||||
.and_then(|stream| stream.webtransport());
|
||||
if let Some(s) = session {
|
||||
s.borrow_mut().datagram(decoder.decode_remainder().to_vec());
|
||||
}
|
||||
}
|
||||
|
||||
fn check_stream_exists(&self, stream_type: Http3StreamType) -> Res<()> {
|
||||
if self
|
||||
.recv_streams
|
||||
|
|
@ -431,10 +673,10 @@ impl Http3Connection {
|
|||
}
|
||||
}
|
||||
|
||||
/// If the new stream is a control stream, this function creates a proper handler
|
||||
/// If the new stream is a control or QPACK stream, this function creates a proper handler
|
||||
/// and perform a read.
|
||||
/// if the new stream is a push stream, the function returns `ReceiveOutput::PushStream`
|
||||
/// and the caller will handle it.
|
||||
/// if the new stream is a `Push(_)`, `Http` or `WebTransportStream(_)` stream, the function
|
||||
/// returns `ReceiveOutput::NewStream(_)` and the caller will handle it.
|
||||
/// If the stream is of a unknown type the stream will be closed.
|
||||
fn handle_new_stream(
|
||||
&mut self,
|
||||
|
|
@ -872,9 +1114,12 @@ impl Http3Connection {
|
|||
conn: &mut Connection,
|
||||
stream_id: StreamId,
|
||||
events: Box<dyn ExtendedConnectEvents>,
|
||||
accept: bool,
|
||||
accept_res: &WebTransportSessionAcceptAction,
|
||||
) -> Res<()> {
|
||||
qtrace!("Respond to WebTransport session with accept={}.", accept);
|
||||
qtrace!(
|
||||
"Respond to WebTransport session with accept={}.",
|
||||
accept_res
|
||||
);
|
||||
if !self.webtransport_enabled() {
|
||||
return Err(Error::Unavailable);
|
||||
}
|
||||
|
|
@ -891,17 +1136,17 @@ impl Http3Connection {
|
|||
|
||||
let send_stream = self.send_streams.get_mut(&stream_id);
|
||||
|
||||
match (send_stream, recv_stream, accept) {
|
||||
match (send_stream, recv_stream, accept_res) {
|
||||
(None, None, _) => Err(Error::InvalidStreamId),
|
||||
(None, Some(_), _) | (Some(_), None, _) => {
|
||||
// TODO this needs a better error
|
||||
self.cancel_fetch(stream_id, Error::HttpRequestRejected.code(), conn)?;
|
||||
Err(Error::InvalidStreamId)
|
||||
}
|
||||
(Some(s), Some(_r), false) => {
|
||||
(Some(s), Some(_r), WebTransportSessionAcceptAction::Reject(headers)) => {
|
||||
if s.http_stream()
|
||||
.ok_or(Error::InvalidStreamId)?
|
||||
.send_headers(&[Header::new(":status", "404")], conn)
|
||||
.send_headers(headers, conn)
|
||||
.is_ok()
|
||||
{
|
||||
mem::drop(self.stream_close_send(conn, stream_id));
|
||||
|
|
@ -912,7 +1157,7 @@ impl Http3Connection {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
(Some(s), Some(_r), true) => {
|
||||
(Some(s), Some(_r), WebTransportSessionAcceptAction::Accept) => {
|
||||
if s.http_stream()
|
||||
.ok_or(Error::InvalidStreamId)?
|
||||
.send_headers(&[Header::new(":status", "200")], conn)
|
||||
|
|
@ -1090,8 +1335,25 @@ impl Http3Connection {
|
|||
}
|
||||
}
|
||||
|
||||
// If the control stream has received frames MaxPushId or Goaway which handling is specific to
|
||||
// the client and server, we must give them to the specific client/server handler.
|
||||
pub fn webtransport_send_datagram(
|
||||
&mut self,
|
||||
session_id: StreamId,
|
||||
conn: &mut Connection,
|
||||
buf: &[u8],
|
||||
id: impl Into<DatagramTracking>,
|
||||
) -> Res<()> {
|
||||
self.recv_streams
|
||||
.get_mut(&session_id)
|
||||
.ok_or(Error::InvalidStreamId)?
|
||||
.webtransport()
|
||||
.ok_or(Error::InvalidStreamId)?
|
||||
.borrow_mut()
|
||||
.send_datagram(conn, buf, id)
|
||||
}
|
||||
|
||||
/// If the control stream has received frames `MaxPushId`, `Goaway`, `PriorityUpdateRequest` or
|
||||
/// `PriorityUpdateRequestPush` which handling is specific to the client and server, we must
|
||||
/// give them to the specific client/server handler.
|
||||
fn handle_control_frame(&mut self, f: HFrame) -> Res<Option<HFrame>> {
|
||||
qinfo!([self], "Handle a control frame {:?}", f);
|
||||
if !matches!(f, HFrame::Settings { .. })
|
||||
|
|
@ -1266,11 +1528,7 @@ impl Http3Connection {
|
|||
wt: &Rc<RefCell<WebTransportSession>>,
|
||||
conn: &mut Connection,
|
||||
) {
|
||||
let out = wt.borrow_mut().take_sub_streams();
|
||||
if out.is_none() {
|
||||
return;
|
||||
}
|
||||
let (recv, send) = out.unwrap();
|
||||
let (recv, send) = wt.borrow_mut().take_sub_streams();
|
||||
|
||||
for id in recv {
|
||||
qtrace!("Remove the extended connect sub receiver stream {}", id);
|
||||
|
|
|
|||
408
third_party/rust/neqo-http3/src/connection_client.rs
vendored
408
third_party/rust/neqo-http3/src/connection_client.rs
vendored
|
|
@ -21,10 +21,11 @@ use neqo_common::{
|
|||
use neqo_crypto::{agent::CertificateInfo, AuthenticationStatus, ResumptionToken, SecretAgentInfo};
|
||||
use neqo_qpack::Stats as QpackStats;
|
||||
use neqo_transport::{
|
||||
AppError, Connection, ConnectionEvent, ConnectionId, ConnectionIdGenerator, Output,
|
||||
Stats as TransportStats, StreamId, StreamType, Version, ZeroRttState,
|
||||
AppError, Connection, ConnectionEvent, ConnectionId, ConnectionIdGenerator, DatagramTracking,
|
||||
Output, Stats as TransportStats, StreamId, StreamType, Version, ZeroRttState,
|
||||
};
|
||||
use std::cell::RefCell;
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt::Debug;
|
||||
use std::fmt::Display;
|
||||
use std::mem;
|
||||
|
|
@ -59,6 +60,231 @@ fn alpn_from_quic_version(version: Version) -> &'static str {
|
|||
}
|
||||
}
|
||||
|
||||
/// # The HTTP/3 client API
|
||||
///
|
||||
/// This module implements the HTTP/3 client API. The main implementation of the protocol is in
|
||||
/// [connection.rs](https://github.com/mozilla/neqo/blob/main/neqo-http3/src/connection.rs) which
|
||||
/// implements common behavior for the client-side and the server-side. `Http3Client` structure
|
||||
/// implements the public API and set of functions that differ between the client and the server.
|
||||
|
||||
/// The API is used for:
|
||||
/// - create and close an endpoint:
|
||||
/// - [`new`](struct.Http3Client.html#method.new)
|
||||
/// - [`new_with_conn`](struct.Http3Client.html#method.new_with_conn)
|
||||
/// - [`close`](struct.Http3Client.html#method.close)
|
||||
/// - configuring an endpoint:
|
||||
/// - [`authenticated`](struct.Http3Client.html#method.authenticated)
|
||||
/// - [`enable_ech`](struct.Http3Client.html#method.enable_ech)
|
||||
/// - [`enable_resumption`](struct.Http3Client.html#method.enable_resumption)
|
||||
/// - [`initiate_key_update`](struct.Http3Client.html#method.initiate_key_update)
|
||||
/// - [`set_qlog`](struct.Http3Client.html#method.set_qlog)
|
||||
/// - retrieving information about a connection:
|
||||
/// - [`peer_certificate`](struct.Http3Client.html#method.peer_certificate)
|
||||
/// - [`qpack_decoder_stats`](struct.Http3Client.html#method.qpack_decoder_stats)
|
||||
/// - [`qpack_encoder_stats`](struct.Http3Client.html#method.qpack_encoder_stats)
|
||||
/// - [`transport_stats`](struct.Http3Client.html#method.transport_stats)
|
||||
/// - [`state`](struct.Http3Client.html#method.state)
|
||||
/// - [`take_resumption_token`](struct.Http3Client.html#method.take_resumption_token)
|
||||
/// - [`tls_inf`](struct.Http3Client.html#method.tls_info)
|
||||
/// - driving HTTP/3 session:
|
||||
/// - [`process_output`](struct.Http3Client.html#method.process_output)
|
||||
/// - [`process_input`](struct.Http3Client.html#method.process_input)
|
||||
/// - [`process`](struct.Http3Client.html#method.process)
|
||||
/// - create requests, send/receive data, and cancel requests:
|
||||
/// - [`fetch`](struct.Http3Client.html#method.fetch)
|
||||
/// - [`send_data`](struct.Http3Client.html#method.send_data)
|
||||
/// - [`read_dara`](struct.Http3Client.html#method.read_data)
|
||||
/// - [`stream_close_send`](struct.Http3Client.html#method.stream_close_send)
|
||||
/// - [`cancel_fetch`](struct.Http3Client.html#method.cancel_fetch)
|
||||
/// - [`stream_reset_send`](struct.Http3Client.html#method.stream_reset_send)
|
||||
/// - [`stream_stop_sending`](struct.Http3Client.html#method.stream_stop_sending)
|
||||
/// - [`set_stream_max_data`](struct.Http3Client.html#method.set_stream_max_data)
|
||||
/// - priority feature:
|
||||
/// - [`priority_update`](struct.Http3Client.html#method.priority_update)
|
||||
/// - `WebTransport` feature:
|
||||
/// - [`webtransport_create_session`](struct.Http3Client.html#method.webtransport_create_session)
|
||||
/// - [`webtransport_close_session`](struct.Http3Client.html#method.webtransport_close_session)
|
||||
/// - [`webtransport_create_stream`](struct.Http3Client.html#method.webtransport_create_sstream)
|
||||
/// - [`webtransport_enabled`](struct.Http3Client.html#method.webtransport_enabled)
|
||||
///
|
||||
/// ## Examples
|
||||
///
|
||||
/// ### Fetching a resource
|
||||
///
|
||||
/// ```ignore
|
||||
/// let mut client = Http3Client::new(...);
|
||||
///
|
||||
/// // Perform a handshake
|
||||
/// ...
|
||||
///
|
||||
/// let req = client
|
||||
/// .fetch(
|
||||
/// Instant::now(),
|
||||
/// "GET",
|
||||
/// &("https", "something.com", "/"),
|
||||
/// &[Header::new("example1", "value1"), Header::new("example1", "value2")],
|
||||
/// Priority::default(),
|
||||
/// )
|
||||
/// .unwrap();
|
||||
///
|
||||
/// client.stream_close_send(req).unwrap();
|
||||
///
|
||||
/// loop {
|
||||
/// // exchange packets
|
||||
/// ...
|
||||
///
|
||||
/// while let Some(event) = client.next_event() {
|
||||
/// match event {
|
||||
/// Http3ClientEvent::HeaderReady { stream_id, headers, interim, fin } => {
|
||||
/// println!("New response headers received for stream {:?} [fin={?}, interim={:?}]: {:?}",
|
||||
/// stream_id,
|
||||
/// fin,
|
||||
/// interim,
|
||||
/// headers,
|
||||
/// );
|
||||
/// }
|
||||
/// Http3ClientEvent::DataReadable { stream_id } => {
|
||||
/// println!("New data available on stream {}", stream_id);
|
||||
/// let mut buf = [0; 100];
|
||||
/// let (amount, fin) = client.read_data(now(), stream_id, &mut buf).unwrap();
|
||||
/// println!("Read {:?} bytes from stream {:?} [fin={?}]",
|
||||
/// amount,
|
||||
/// stream_id,
|
||||
/// fin,
|
||||
/// );
|
||||
/// }
|
||||
/// _ => {
|
||||
/// println!("Unhandled event {:?}", event);
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///```
|
||||
///
|
||||
/// ### Creating a `WebTransport` session
|
||||
///
|
||||
/// ```ignore
|
||||
/// let mut client = Http3Client::new(...);
|
||||
///
|
||||
/// // Perform a handshake
|
||||
/// ...
|
||||
///
|
||||
/// // Create a session
|
||||
/// let wt_session_id = client
|
||||
/// .webtransport_create_session(now(), &("https", "something.com", "/"), &[])
|
||||
/// .unwrap();
|
||||
///
|
||||
/// loop {
|
||||
/// // exchange packets
|
||||
/// ...
|
||||
///
|
||||
/// while let Some(event) = client.next_event() {
|
||||
/// match event {
|
||||
/// Http3ClientEvent::WebTransport(WebTransportEvent::Session{
|
||||
/// stream_id,
|
||||
/// status
|
||||
/// }) => {
|
||||
/// println!("The response from the server: WebTransport session ID {:?} status={:?}",
|
||||
/// stream_id,
|
||||
/// status,
|
||||
/// );
|
||||
/// }
|
||||
/// _ => {
|
||||
/// println!("Unhandled event {:?}", event);
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
///```
|
||||
///
|
||||
/// ### `WebTransport`: create a stream, send and receive data on the stream
|
||||
///
|
||||
/// ```ignore
|
||||
/// const BUF_CLIENT: &[u8] = &[0; 10];
|
||||
/// // wt_session_id is the session ID of a newly created WebTransport session, see the example above.
|
||||
///
|
||||
/// // create a stream
|
||||
/// let wt_stream_id = client
|
||||
/// .webtransport_create_stream(wt_session_id, StreamType::BiDi)
|
||||
/// .unwrap();
|
||||
///
|
||||
/// // send data
|
||||
/// let data_sent = client.send_data(wt_stream_id, BUF_CLIENT).unwrap();
|
||||
/// assert_eq!(data_sent, BUF_CLIENT.len());
|
||||
///
|
||||
/// // close stream for sending
|
||||
/// client.stream_close_send(wt_stream_id).unwrap();
|
||||
///
|
||||
/// // wait for data from the server
|
||||
/// loop {
|
||||
/// // exchange packets
|
||||
/// ...
|
||||
///
|
||||
/// while let Some(event) = client.next_event() {
|
||||
/// match event {
|
||||
/// Http3ClientEvent::DataReadable{ stream_id } => {
|
||||
/// println!("Data receivedd form the server on WebTransport stream ID {:?}",
|
||||
/// stream_id,
|
||||
/// );
|
||||
/// let mut buf = [0; 100];
|
||||
/// let (amount, fin) = client.read_data(now(), stream_id, &mut buf).unwrap();
|
||||
/// println!("Read {:?} bytes from stream {:?} [fin={?}]",
|
||||
/// amount,
|
||||
/// stream_id,
|
||||
/// fin,
|
||||
/// );
|
||||
/// }
|
||||
/// _ => {
|
||||
/// println!("Unhandled event {:?}", event);
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ### `WebTransport`: receive a new stream form the server
|
||||
///
|
||||
/// ```ignore
|
||||
/// // wt_session_id is the session ID of a newly created WebTransport session, see the example above.
|
||||
///
|
||||
/// // wait for a new stream from the server
|
||||
/// loop {
|
||||
/// // exchange packets
|
||||
/// ...
|
||||
///
|
||||
/// while let Some(event) = client.next_event() {
|
||||
/// match event {
|
||||
/// Http3ClientEvent::WebTransport(WebTransportEvent::NewStream {
|
||||
/// stream_id,
|
||||
/// session_id,
|
||||
/// }) => {
|
||||
/// println!("New stream received on session{:?}, stream id={:?} stream type={:?}",
|
||||
/// sesson_id.stream_id(),
|
||||
/// stream_id.stream_id(),
|
||||
/// stream_id.stream_type()
|
||||
/// );
|
||||
/// }
|
||||
/// Http3ClientEvent::DataReadable{ stream_id } => {
|
||||
/// println!("Data receivedd form the server on WebTransport stream ID {:?}",
|
||||
/// stream_id,
|
||||
/// );
|
||||
/// let mut buf = [0; 100];
|
||||
/// let (amount, fin) = client.read_data(now(), stream_id, &mut buf).unwrap();
|
||||
/// println!("Read {:?} bytes from stream {:?} [fin={:?}]",
|
||||
/// amount,
|
||||
/// stream_id,
|
||||
/// fin,
|
||||
/// );
|
||||
/// }
|
||||
/// _ => {
|
||||
/// println!("Unhandled event {:?}", event);
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
pub struct Http3Client {
|
||||
conn: Connection,
|
||||
base_handler: Http3Connection,
|
||||
|
|
@ -75,7 +301,7 @@ impl Display for Http3Client {
|
|||
impl Http3Client {
|
||||
/// # Errors
|
||||
/// Making a `neqo-transport::connection` may produce an error. This can only be a crypto error if
|
||||
/// the socket can't be created or configured.
|
||||
/// the crypto context can't be created or configured.
|
||||
pub fn new(
|
||||
server_name: impl Into<String>,
|
||||
cid_manager: Rc<RefCell<dyn ConnectionIdGenerator>>,
|
||||
|
|
@ -103,6 +329,10 @@ impl Http3Client {
|
|||
))
|
||||
}
|
||||
|
||||
/// This is a similar function to `new`. In this case, `neqo-transport::connection` has been
|
||||
/// already created.
|
||||
///
|
||||
/// It is recommended to use `new` instead.
|
||||
#[must_use]
|
||||
pub fn new_with_conn(c: Connection, http3_parameters: Http3Parameters) -> Self {
|
||||
let events = Http3ClientEvents::default();
|
||||
|
|
@ -125,6 +355,7 @@ impl Http3Client {
|
|||
self.conn.role()
|
||||
}
|
||||
|
||||
/// The function returns the current state of the connection.
|
||||
#[must_use]
|
||||
pub fn state(&self) -> Http3State {
|
||||
self.base_handler.state()
|
||||
|
|
@ -142,6 +373,10 @@ impl Http3Client {
|
|||
}
|
||||
|
||||
/// This called when peer certificates have been verified.
|
||||
///
|
||||
/// `Http3ClientEvent::AuthenticationNeeded` event is emitted when peer’s certificates are
|
||||
/// available and need to be verified. When the verification is completed this function is
|
||||
/// called. To inform HTTP/3 session of the verification results.
|
||||
pub fn authenticated(&mut self, status: AuthenticationStatus, now: Instant) {
|
||||
self.conn.authenticated(status, now);
|
||||
}
|
||||
|
|
@ -175,12 +410,18 @@ impl Http3Client {
|
|||
})
|
||||
}
|
||||
|
||||
/// Get a resumption token. The correct way to obtain a resumption token is
|
||||
/// waiting for the `Http3ClientEvent::ResumptionToken` event. However, some
|
||||
/// servers don't send `NEW_TOKEN` frames and so that event might be slow in
|
||||
/// arriving. This is especially a problem for short-lived connections, where
|
||||
/// the connection is closed before any events are released. This retrieves
|
||||
/// the token, without waiting for the `NEW_TOKEN` frame to arrive.
|
||||
/// The correct way to obtain a resumption token is to wait for the
|
||||
/// `Http3ClientEvent::ResumptionToken` event. To emit the event we are waiting for a
|
||||
/// resumtion token and a `NEW_TOKEN` frame to arrive. Some servers don't send `NEW_TOKEN`
|
||||
/// frames and in this case, we wait for 3xPTO before emitting an event. This is especially a
|
||||
/// problem for short-lived connections, where the connection is closed before any events are
|
||||
/// released. This function retrieves the token, without waiting for a `NEW_TOKEN` frame to
|
||||
/// arrive.
|
||||
///
|
||||
/// In addition to the token, HTTP/3 settings are encoded into the token before giving it to
|
||||
/// the application(`encode_resumption_token`). When the resumption token is supplied to a new
|
||||
/// connection the HTTP/3 setting will be decoded and used until the setting are received from
|
||||
/// the server.
|
||||
pub fn take_resumption_token(&mut self, now: Instant) -> Option<ResumptionToken> {
|
||||
self.conn
|
||||
.take_resumption_token(now)
|
||||
|
|
@ -188,6 +429,10 @@ impl Http3Client {
|
|||
}
|
||||
|
||||
/// This may be call if an application has a resumption token. This must be called before connection starts.
|
||||
///
|
||||
/// The resumption token also contains encoded HTTP/3 settings. The settings will be decoded
|
||||
/// and used until the setting are received from the server.
|
||||
///
|
||||
/// # Errors
|
||||
/// An error is return if token cannot be decoded or a connection is is a wrong state.
|
||||
/// # Panics
|
||||
|
|
@ -201,7 +446,7 @@ impl Http3Client {
|
|||
Some(v) => v,
|
||||
None => return Err(Error::InvalidResumptionToken),
|
||||
};
|
||||
qtrace!([self], " settings {}", hex_with_len(&settings_slice));
|
||||
qtrace!([self], " settings {}", hex_with_len(settings_slice));
|
||||
let mut dec_settings = Decoder::from(settings_slice);
|
||||
let mut settings = HSettings::default();
|
||||
Error::map_error(
|
||||
|
|
@ -209,7 +454,7 @@ impl Http3Client {
|
|||
Error::InvalidResumptionToken,
|
||||
)?;
|
||||
let tok = dec.decode_remainder();
|
||||
qtrace!([self], " Transport token {}", hex(&tok));
|
||||
qtrace!([self], " Transport token {}", hex(tok));
|
||||
self.conn.enable_resumption(now, tok)?;
|
||||
if self.conn.state().closed() {
|
||||
let state = self.conn.state().clone();
|
||||
|
|
@ -260,8 +505,9 @@ impl Http3Client {
|
|||
|
||||
// API: Request/response
|
||||
|
||||
/// This is call to make a new http request. Each request can have headers and they are added when request
|
||||
/// is created. A response body may be added by calling `send_data`.
|
||||
/// The function fetches a resource using `method`, `target` and `headers`. A response body
|
||||
/// may be added by calling `send_data`. `stream_close_send` must be sent to finish the request
|
||||
/// even if request data are not sent.
|
||||
/// # Errors
|
||||
/// If a new stream cannot be created an error will be return.
|
||||
/// # Panics
|
||||
|
|
@ -308,8 +554,8 @@ impl Http3Client {
|
|||
self.base_handler.queue_update_priority(stream_id, priority)
|
||||
}
|
||||
|
||||
/// An application may reset a stream(request).
|
||||
/// Both sides, sending and receiving side, will be closed.
|
||||
/// An application may cancel a stream(request).
|
||||
/// Both sides, the receiviing and sending side, sending and receiving side, will be closed.
|
||||
/// # Errors
|
||||
/// An error will be return if a stream does not exist.
|
||||
pub fn cancel_fetch(&mut self, stream_id: StreamId, error: AppError) -> Res<()> {
|
||||
|
|
@ -343,7 +589,10 @@ impl Http3Client {
|
|||
.stream_stop_sending(&mut self.conn, stream_id, error)
|
||||
}
|
||||
|
||||
/// To supply a request body this function is called (headers are supplied through the `fetch` function.)
|
||||
/// This function is used for regular HTTP requests and `WebTransport` streams.
|
||||
/// In the case of regular HTTP requests, the request body is supplied using this function, and
|
||||
/// headers are supplied through the `fetch` function.
|
||||
///
|
||||
/// # Errors
|
||||
/// `InvalidStreamId` if the stream does not exist,
|
||||
/// `AlreadyClosed` if the stream has already been closed.
|
||||
|
|
@ -478,6 +727,35 @@ impl Http3Client {
|
|||
)
|
||||
}
|
||||
|
||||
/// Send `WebTransport` datagram.
|
||||
/// # Errors
|
||||
/// It may return `InvalidStreamId` if a stream does not exist anymore.
|
||||
/// The function returns `TooMuchData` if the supply buffer is bigger than
|
||||
/// the allowed remote datagram size.
|
||||
pub fn webtransport_send_datagram(
|
||||
&mut self,
|
||||
session_id: StreamId,
|
||||
buf: &[u8],
|
||||
id: impl Into<DatagramTracking>,
|
||||
) -> Res<()> {
|
||||
qtrace!("webtransport_send_datagram session:{:?}", session_id);
|
||||
self.base_handler
|
||||
.webtransport_send_datagram(session_id, &mut self.conn, buf, id)
|
||||
}
|
||||
|
||||
/// Returns the current max size of a datagram that can fit into a packet.
|
||||
/// The value will change over time depending on the encoded size of the
|
||||
/// packet number, ack frames, etc.
|
||||
/// # Errors
|
||||
/// The function returns `NotAvailable` if datagrams are not enabled.
|
||||
/// # Panics
|
||||
/// This cannot panic. The max varint length is 8.
|
||||
pub fn webtransport_max_datagram_size(&self, session_id: StreamId) -> Res<u64> {
|
||||
Ok(self.conn.max_datagram_size()?
|
||||
- u64::try_from(Encoder::varint_len(session_id.as_u64())).unwrap())
|
||||
}
|
||||
|
||||
/// This function combines `process_input` and `process_output` function.
|
||||
pub fn process(&mut self, dgram: Option<Datagram>, now: Instant) -> Output {
|
||||
qtrace!([self], "Process.");
|
||||
if let Some(d) = dgram {
|
||||
|
|
@ -486,19 +764,34 @@ impl Http3Client {
|
|||
self.process_output(now)
|
||||
}
|
||||
|
||||
/// Supply an incoming QUIC packet.
|
||||
/// The function should be called when there is a new UDP packet available. The function will
|
||||
/// handle the packet payload.
|
||||
///
|
||||
/// First, the payload will be handled by the QUIC layer. Afterward, `process_http3` will be
|
||||
/// called to handle new [`ConnectionEvent`][1]s.
|
||||
///
|
||||
/// After this function is called `process_output` should be called to check whether new
|
||||
/// packets need to be sent or if a timer needs to be updated.
|
||||
///
|
||||
/// [1]: ../neqo_transport/enum.ConnectionEvent.html
|
||||
pub fn process_input(&mut self, dgram: Datagram, now: Instant) {
|
||||
qtrace!([self], "Process input.");
|
||||
self.conn.process_input(dgram, now);
|
||||
self.process_http3(now);
|
||||
}
|
||||
|
||||
// Only used by neqo-interop
|
||||
/// This should not be used because it gives access to functionalities that may disrupt the
|
||||
/// proper functioning of the HTTP/3 session.
|
||||
/// Only used by `neqo-interop`.
|
||||
pub fn conn(&mut self) -> &mut Connection {
|
||||
&mut self.conn
|
||||
}
|
||||
|
||||
/// Process HTTP3 layer.
|
||||
/// When `process_output`, `process_input`, or `process` is called we must call this function
|
||||
/// as well. The functions calls `Http3Client::check_connection_events` to handle events from
|
||||
/// the QUC layer and calls `Http3Connection::process_sending` to ensure that HTTP/3 layer
|
||||
/// data, e.g. control frames, are sent.
|
||||
fn process_http3(&mut self, now: Instant) {
|
||||
qtrace!([self], "Process http3 internal.");
|
||||
match self.base_handler.state() {
|
||||
|
|
@ -521,8 +814,32 @@ impl Http3Client {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get packet that need to be written into a UDP socket or a timer value if there is no data to send.
|
||||
/// This function should be called repeatedly until timer value is returned.
|
||||
/// The function should be called to check if there is a new UDP packet to be sent. It should
|
||||
/// be called after a new packet is received and processed and after a timer expires (QUIC
|
||||
/// needs timers to handle events like PTO detection and timers are not implemented by the neqo
|
||||
/// library, but instead must be driven by the application).
|
||||
///
|
||||
/// `process_output` can return:
|
||||
/// - a [`Output::Datagram(Datagram)`][1]: data that should be sent as a UDP payload,
|
||||
/// - a [`Output::Callback(Duration)`][1]: the duration of a timer. `process_output` should be called at least after the time expires,
|
||||
/// - [`Output::None`][1]: this is returned when `Nttp3Client` is done and can be destroyed.
|
||||
///
|
||||
/// The application should call this function repeatedly until a timer value or None is
|
||||
/// returned. After that, the application should call the function again if a new UDP packet is
|
||||
/// received and processed or the timer value expires.
|
||||
///
|
||||
/// The HTTP/3 neqo implementation drives the HTTP/3 and QUC layers, therefore this function
|
||||
/// will call both layers:
|
||||
/// - First it calls HTTP/3 layer processing (`process_http3`) to make sure the layer writes
|
||||
/// data to QUIC layer or cancels streams if needed.
|
||||
/// - Then QUIC layer processing is called - [`Connection::process_output`][3]. This produces a
|
||||
/// packet or a timer value. It may also produce ned [`ConnectionEvent`][2]s, e.g. connection
|
||||
/// state-change event.
|
||||
/// - Therefore the HTTP/3 layer processing (`process_http3`) is called again.
|
||||
///
|
||||
/// [1]: ../neqo_transport/enum.Output.html
|
||||
/// [2]: ../neqo_transport/struct.ConnectionEvents.html
|
||||
/// [3]: ../neqo_transport/struct.Connection.html#method.process_output
|
||||
pub fn process_output(&mut self, now: Instant) -> Output {
|
||||
qtrace!([self], "Process output.");
|
||||
|
||||
|
|
@ -537,8 +854,8 @@ impl Http3Client {
|
|||
out
|
||||
}
|
||||
|
||||
// This function takes the provided result and check for an error.
|
||||
// An error results in closing the connection.
|
||||
/// This function takes the provided result and check for an error.
|
||||
/// An error results in closing the connection.
|
||||
fn check_result<ERR>(&mut self, now: Instant, res: &Res<ERR>) -> bool {
|
||||
match &res {
|
||||
Err(Error::HttpGoaway) => {
|
||||
|
|
@ -559,13 +876,31 @@ impl Http3Client {
|
|||
}
|
||||
}
|
||||
|
||||
// If this return an error the connection must be closed.
|
||||
/// This function checks [`ConnectionEvent`][2]s emitted by the QUIC layer, e.g. connection change
|
||||
/// state events, new incoming stream data is available, a stream is was reset, etc. The HTTP/3
|
||||
/// layer needs to handle these events. Most of the events are handled by
|
||||
/// [`Http3Connection`][1] by calling appropriate functions, e.g. `handle_state_change`,
|
||||
/// `handle_stream_reset`, etc. [`Http3Connection`][1] handle functionalities that are common
|
||||
/// for the client and server side. Some of the functionalities are specific to the client and
|
||||
/// they are handled by `Http3Client`. For example, [`ConnectionEvent::RecvStreamReadable`][3] event
|
||||
/// is handled by `Http3Client::handle_stream_readable`. The function calls
|
||||
/// `Http3Connection::handle_stream_readable` and then hands the return value as appropriate
|
||||
/// for the client-side.
|
||||
///
|
||||
/// [1]: https://github.com/mozilla/neqo/blob/main/neqo-http3/src/connection.rs
|
||||
/// [2]: ../neqo_transport/enum.ConnectionEvent.html
|
||||
/// [3]: ../neqo_transport/enum.ConnectionEvent.html#variant.RecvStreamReadable
|
||||
fn check_connection_events(&mut self) -> Res<()> {
|
||||
qtrace!([self], "Check connection events.");
|
||||
while let Some(e) = self.conn.next_event() {
|
||||
qdebug!([self], "check_connection_events - event {:?}.", e);
|
||||
match e {
|
||||
ConnectionEvent::NewStream { stream_id } => {
|
||||
// During this event we only add a new stream to the Http3Connection stream list,
|
||||
// with NewStreamHeadReader stream handler.
|
||||
// This function will not read from the stream and try to decode the stream.
|
||||
// RecvStreamReadable will be emitted after this event and reading, i.e. decoding
|
||||
// of a stream will happen during that event.
|
||||
self.base_handler.add_new_stream(stream_id);
|
||||
}
|
||||
ConnectionEvent::SendStreamWritable { stream_id } => {
|
||||
|
|
@ -617,8 +952,10 @@ impl Http3Client {
|
|||
self.events.resumption_token(t);
|
||||
}
|
||||
}
|
||||
ConnectionEvent::Datagram(dgram) => {
|
||||
self.base_handler.handle_datagram(&dgram);
|
||||
}
|
||||
ConnectionEvent::SendStreamComplete { .. }
|
||||
| ConnectionEvent::Datagram { .. }
|
||||
| ConnectionEvent::OutgoingDatagramOutcome { .. }
|
||||
| ConnectionEvent::IncomingDatagramDropped => {}
|
||||
}
|
||||
|
|
@ -626,6 +963,25 @@ impl Http3Client {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// This function handled new data available on a stream. It calls
|
||||
/// `Http3Client::handle_stream_readable` and handles its response. Reading streams are mostly
|
||||
/// handled by [`Http3Connection`][1] because most part of it is common for the client and
|
||||
/// server. The following actions need to be handled by the client-specific code:
|
||||
/// - `ReceiveOutput::NewStream(NewStreamType::Push(_))` - the server cannot receive a push
|
||||
/// stream,
|
||||
/// - `ReceiveOutput::NewStream(NewStreamType::Http)` - client cannot receive a
|
||||
/// server-initiated HTTP request,
|
||||
/// - `ReceiveOutput::NewStream(NewStreamType::WebTransportStream(_))` - because
|
||||
/// `Http3ClientEvents`is needed and events handler is specific to the client.
|
||||
/// - `ReceiveOutput::ControlFrames(control_frames)` - some control frame handling differs
|
||||
/// between the client and the server:
|
||||
/// - `HFrame::CancelPush` - only the client-side may receive it,
|
||||
/// - `HFrame::MaxPushId { .. }`, `HFrame::PriorityUpdateRequest { .. } ` and
|
||||
/// `HFrame::PriorityUpdatePush` can only be receive on the server side,
|
||||
/// - `HFrame::Goaway { stream_id }` needs specific handling by the client by the protocol
|
||||
/// specification.
|
||||
///
|
||||
/// [1]: https://github.com/mozilla/neqo/blob/main/neqo-http3/src/connection.rs
|
||||
fn handle_stream_readable(&mut self, stream_id: StreamId) -> Res<()> {
|
||||
match self
|
||||
.base_handler
|
||||
|
|
@ -4326,7 +4682,7 @@ mod tests {
|
|||
&mut client,
|
||||
&mut server,
|
||||
request_stream_id,
|
||||
&[0x0, 0x3, 0x61, 0x62, 0x63], // a data frame
|
||||
[0x0, 0x3, 0x61, 0x62, 0x63], // a data frame
|
||||
false,
|
||||
);
|
||||
|
||||
|
|
@ -4351,7 +4707,7 @@ mod tests {
|
|||
&mut client,
|
||||
&mut server,
|
||||
request_stream_id,
|
||||
&[0x0, 0x0],
|
||||
[0x0, 0x0],
|
||||
true,
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use crate::connection::{Http3Connection, Http3State};
|
||||
use crate::connection::{Http3Connection, Http3State, WebTransportSessionAcceptAction};
|
||||
use crate::frames::HFrame;
|
||||
use crate::recv_message::{RecvMessage, RecvMessageInfo};
|
||||
use crate::send_message::SendMessage;
|
||||
|
|
@ -14,7 +14,9 @@ use crate::{
|
|||
ReceiveOutput, Res,
|
||||
};
|
||||
use neqo_common::{event::Provider, qdebug, qinfo, qtrace, Header, MessageType, Role};
|
||||
use neqo_transport::{AppError, Connection, ConnectionEvent, StreamId, StreamType};
|
||||
use neqo_transport::{
|
||||
AppError, Connection, ConnectionEvent, DatagramTracking, StreamId, StreamType,
|
||||
};
|
||||
use std::rc::Rc;
|
||||
use std::time::Instant;
|
||||
|
||||
|
|
@ -140,7 +142,7 @@ impl Http3ServerHandler {
|
|||
&mut self,
|
||||
conn: &mut Connection,
|
||||
stream_id: StreamId,
|
||||
accept: bool,
|
||||
accept: &WebTransportSessionAcceptAction,
|
||||
) -> Res<()> {
|
||||
self.needs_processing = true;
|
||||
self.base_handler.webtransport_session_accept(
|
||||
|
|
@ -185,6 +187,18 @@ impl Http3ServerHandler {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn webtransport_send_datagram(
|
||||
&mut self,
|
||||
conn: &mut Connection,
|
||||
session_id: StreamId,
|
||||
buf: &[u8],
|
||||
id: impl Into<DatagramTracking>,
|
||||
) -> Res<()> {
|
||||
self.needs_processing = true;
|
||||
self.base_handler
|
||||
.webtransport_send_datagram(session_id, conn, buf, id)
|
||||
}
|
||||
|
||||
/// Process HTTTP3 layer.
|
||||
pub fn process_http3(&mut self, conn: &mut Connection, now: Instant) {
|
||||
qtrace!([self], "Process http3 internal.");
|
||||
|
|
@ -273,13 +287,13 @@ impl Http3ServerHandler {
|
|||
s.stream_writable();
|
||||
}
|
||||
}
|
||||
ConnectionEvent::Datagram(dgram) => self.base_handler.handle_datagram(&dgram),
|
||||
ConnectionEvent::AuthenticationNeeded
|
||||
| ConnectionEvent::EchFallbackAuthenticationNeeded { .. }
|
||||
| ConnectionEvent::ZeroRttRejected
|
||||
| ConnectionEvent::ResumptionToken(..) => return Err(Error::HttpInternal(4)),
|
||||
ConnectionEvent::SendStreamComplete { .. }
|
||||
| ConnectionEvent::SendStreamCreatable { .. }
|
||||
| ConnectionEvent::Datagram { .. }
|
||||
| ConnectionEvent::OutgoingDatagramOutcome { .. }
|
||||
| ConnectionEvent::IncomingDatagramDropped => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
#![allow(clippy::module_name_repetitions)]
|
||||
|
||||
pub mod webtransport_session;
|
||||
pub mod webtransport_streams;
|
||||
pub(crate) mod webtransport_session;
|
||||
pub(crate) mod webtransport_streams;
|
||||
|
||||
use crate::client_events::Http3ClientEvents;
|
||||
use crate::features::NegotiationState;
|
||||
|
|
@ -15,7 +15,7 @@ use crate::settings::{HSettingType, HSettings};
|
|||
use crate::{CloseType, Http3StreamInfo, Http3StreamType};
|
||||
use neqo_transport::{AppError, StreamId};
|
||||
use std::fmt::Debug;
|
||||
pub use webtransport_session::WebTransportSession;
|
||||
pub(crate) use webtransport_session::WebTransportSession;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum SessionCloseReason {
|
||||
|
|
@ -32,13 +32,13 @@ impl From<CloseType> for SessionCloseReason {
|
|||
}
|
||||
CloseType::Done => SessionCloseReason::Clean {
|
||||
error: 0,
|
||||
message: "".to_string(),
|
||||
message: String::new(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ExtendedConnectEvents: Debug {
|
||||
pub(crate) trait ExtendedConnectEvents: Debug {
|
||||
fn session_start(&self, connect_type: ExtendedConnectType, stream_id: StreamId, status: u16);
|
||||
fn session_end(
|
||||
&self,
|
||||
|
|
@ -47,10 +47,11 @@ pub trait ExtendedConnectEvents: Debug {
|
|||
reason: SessionCloseReason,
|
||||
);
|
||||
fn extended_connect_new_stream(&self, stream_info: Http3StreamInfo);
|
||||
fn new_datagram(&self, session_id: StreamId, datagram: Vec<u8>);
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Copy, Clone, Eq)]
|
||||
pub enum ExtendedConnectType {
|
||||
pub(crate) enum ExtendedConnectType {
|
||||
WebTransport,
|
||||
}
|
||||
|
||||
|
|
@ -61,12 +62,6 @@ impl ExtendedConnectType {
|
|||
"webtransport"
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
#[allow(clippy::unused_self)] // this will change when there is more types of the extended CONNECT.
|
||||
pub fn setting_type(self) -> HSettingType {
|
||||
HSettingType::EnableWebTransport
|
||||
}
|
||||
|
||||
#[allow(clippy::unused_self)] // This will change when we have more features using ExtendedConnectType.
|
||||
#[must_use]
|
||||
pub fn get_stream_type(self, session_id: StreamId) -> Http3StreamType {
|
||||
|
|
@ -82,7 +77,7 @@ impl From<ExtendedConnectType> for HSettingType {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ExtendedConnectFeature {
|
||||
pub(crate) struct ExtendedConnectFeature {
|
||||
feature_negotiation: NegotiationState,
|
||||
}
|
||||
|
||||
|
|
@ -107,3 +102,5 @@ impl ExtendedConnectFeature {
|
|||
self.feature_negotiation.enabled()
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
|
|
|||
128
third_party/rust/neqo-http3/src/features/extended_connect/tests/webtransport/datagrams.rs
vendored
Normal file
128
third_party/rust/neqo-http3/src/features/extended_connect/tests/webtransport/datagrams.rs
vendored
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use crate::features::extended_connect::tests::webtransport::{
|
||||
wt_default_parameters, WtTest, DATAGRAM_SIZE,
|
||||
};
|
||||
use crate::{Error, Http3Parameters};
|
||||
use neqo_common::Encoder;
|
||||
use neqo_transport::Error as TransportError;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
const DGRAM: &[u8] = &[0, 100];
|
||||
|
||||
#[test]
|
||||
fn no_datagrams() {
|
||||
let mut wt = WtTest::new_with_params(
|
||||
Http3Parameters::default().webtransport(true),
|
||||
Http3Parameters::default().webtransport(true),
|
||||
);
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
||||
assert_eq!(
|
||||
wt_session.max_datagram_size(),
|
||||
Err(Error::TransportError(TransportError::NotAvailable))
|
||||
);
|
||||
assert_eq!(
|
||||
wt.max_datagram_size(wt_session.stream_id()),
|
||||
Err(Error::TransportError(TransportError::NotAvailable))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
wt_session.send_datagram(DGRAM, None),
|
||||
Err(Error::TransportError(TransportError::TooMuchData))
|
||||
);
|
||||
assert_eq!(
|
||||
wt.send_datagram(wt_session.stream_id(), DGRAM),
|
||||
Err(Error::TransportError(TransportError::TooMuchData))
|
||||
);
|
||||
|
||||
wt.exchange_packets();
|
||||
wt.check_no_datagram_received_client();
|
||||
wt.check_no_datagram_received_server();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn datagrams() {
|
||||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
||||
assert_eq!(
|
||||
wt_session.max_datagram_size(),
|
||||
Ok(DATAGRAM_SIZE
|
||||
- u64::try_from(Encoder::varint_len(wt_session.stream_id().as_u64())).unwrap())
|
||||
);
|
||||
assert_eq!(
|
||||
wt.max_datagram_size(wt_session.stream_id()),
|
||||
Ok(DATAGRAM_SIZE
|
||||
- u64::try_from(Encoder::varint_len(wt_session.stream_id().as_u64())).unwrap())
|
||||
);
|
||||
|
||||
assert_eq!(wt_session.send_datagram(DGRAM, None), Ok(()));
|
||||
assert_eq!(wt.send_datagram(wt_session.stream_id(), DGRAM), Ok(()));
|
||||
|
||||
wt.exchange_packets();
|
||||
wt.check_datagram_received_client(wt_session.stream_id(), DGRAM);
|
||||
wt.check_datagram_received_server(&wt_session, DGRAM);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn datagrams_server_only() {
|
||||
let mut wt = WtTest::new_with_params(
|
||||
Http3Parameters::default().webtransport(true),
|
||||
wt_default_parameters(),
|
||||
);
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
||||
assert_eq!(
|
||||
wt_session.max_datagram_size(),
|
||||
Err(Error::TransportError(TransportError::NotAvailable))
|
||||
);
|
||||
assert_eq!(
|
||||
wt.max_datagram_size(wt_session.stream_id()),
|
||||
Ok(DATAGRAM_SIZE
|
||||
- u64::try_from(Encoder::varint_len(wt_session.stream_id().as_u64())).unwrap())
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
wt_session.send_datagram(DGRAM, None),
|
||||
Err(Error::TransportError(TransportError::TooMuchData))
|
||||
);
|
||||
assert_eq!(wt.send_datagram(wt_session.stream_id(), DGRAM), Ok(()));
|
||||
|
||||
wt.exchange_packets();
|
||||
wt.check_datagram_received_server(&wt_session, DGRAM);
|
||||
wt.check_no_datagram_received_client();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn datagrams_client_only() {
|
||||
let mut wt = WtTest::new_with_params(
|
||||
wt_default_parameters(),
|
||||
Http3Parameters::default().webtransport(true),
|
||||
);
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
||||
assert_eq!(
|
||||
wt_session.max_datagram_size(),
|
||||
Ok(DATAGRAM_SIZE
|
||||
- u64::try_from(Encoder::varint_len(wt_session.stream_id().as_u64())).unwrap())
|
||||
);
|
||||
assert_eq!(
|
||||
wt.max_datagram_size(wt_session.stream_id()),
|
||||
Err(Error::TransportError(TransportError::NotAvailable))
|
||||
);
|
||||
|
||||
assert_eq!(wt_session.send_datagram(DGRAM, None), Ok(()));
|
||||
assert_eq!(
|
||||
wt.send_datagram(wt_session.stream_id(), DGRAM),
|
||||
Err(Error::TransportError(TransportError::TooMuchData))
|
||||
);
|
||||
|
||||
wt.exchange_packets();
|
||||
wt.check_datagram_received_client(wt_session.stream_id(), DGRAM);
|
||||
wt.check_no_datagram_received_server();
|
||||
}
|
||||
|
|
@ -4,46 +4,57 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
mod datagrams;
|
||||
mod negotiation;
|
||||
mod sessions;
|
||||
mod streams;
|
||||
use neqo_common::event::Provider;
|
||||
|
||||
use neqo_crypto::AuthenticationStatus;
|
||||
use neqo_http3::{
|
||||
use crate::{
|
||||
features::extended_connect::SessionCloseReason, Error, Http3Client, Http3ClientEvent,
|
||||
Http3OrWebTransportStream, Http3Parameters, Http3Server, Http3ServerEvent, Http3State,
|
||||
WebTransportEvent, WebTransportRequest, WebTransportServerEvent,
|
||||
WebTransportSessionAcceptAction,
|
||||
};
|
||||
use neqo_transport::{StreamId, StreamType};
|
||||
use neqo_crypto::AuthenticationStatus;
|
||||
use neqo_transport::{ConnectionParameters, StreamId, StreamType};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use test_fixture::{
|
||||
addr, anti_replay, fixture_init, now, CountingConnectionIdGenerator, DEFAULT_ALPN_H3,
|
||||
DEFAULT_KEYS, DEFAULT_SERVER_NAME,
|
||||
};
|
||||
|
||||
pub fn default_http3_client(webtransport: bool) -> Http3Client {
|
||||
const DATAGRAM_SIZE: u64 = 1200;
|
||||
|
||||
pub fn wt_default_parameters() -> Http3Parameters {
|
||||
Http3Parameters::default()
|
||||
.webtransport(true)
|
||||
.connection_parameters(ConnectionParameters::default().datagram_size(DATAGRAM_SIZE))
|
||||
}
|
||||
|
||||
pub fn default_http3_client(client_params: Http3Parameters) -> Http3Client {
|
||||
fixture_init();
|
||||
Http3Client::new(
|
||||
DEFAULT_SERVER_NAME,
|
||||
Rc::new(RefCell::new(CountingConnectionIdGenerator::default())),
|
||||
addr(),
|
||||
addr(),
|
||||
Http3Parameters::default().webtransport(webtransport),
|
||||
client_params,
|
||||
now(),
|
||||
)
|
||||
.expect("create a default client")
|
||||
}
|
||||
|
||||
pub fn default_http3_server(webtransport: bool) -> Http3Server {
|
||||
pub fn default_http3_server(server_params: Http3Parameters) -> Http3Server {
|
||||
Http3Server::new(
|
||||
now(),
|
||||
DEFAULT_KEYS,
|
||||
DEFAULT_ALPN_H3,
|
||||
anti_replay(),
|
||||
Rc::new(RefCell::new(CountingConnectionIdGenerator::default())),
|
||||
Http3Parameters::default().webtransport(webtransport),
|
||||
server_params,
|
||||
None,
|
||||
)
|
||||
.expect("create a server")
|
||||
|
|
@ -86,12 +97,15 @@ fn connect_with(client: &mut Http3Client, server: &mut Http3Server) {
|
|||
let out = client.process(out.dgram(), now());
|
||||
let out = server.process(out.dgram(), now());
|
||||
let out = client.process(out.dgram(), now());
|
||||
let _ = server.process(out.dgram(), now());
|
||||
std::mem::drop(server.process(out.dgram(), now()));
|
||||
}
|
||||
|
||||
fn connect(wt_enable_client: bool, wt_enable_server: bool) -> (Http3Client, Http3Server) {
|
||||
let mut client = default_http3_client(wt_enable_client);
|
||||
let mut server = default_http3_server(wt_enable_server);
|
||||
fn connect(
|
||||
client_params: Http3Parameters,
|
||||
server_params: Http3Parameters,
|
||||
) -> (Http3Client, Http3Server) {
|
||||
let mut client = default_http3_client(client_params);
|
||||
let mut server = default_http3_server(server_params);
|
||||
connect_with(&mut client, &mut server);
|
||||
(client, server)
|
||||
}
|
||||
|
|
@ -103,7 +117,12 @@ struct WtTest {
|
|||
|
||||
impl WtTest {
|
||||
pub fn new() -> Self {
|
||||
let (client, server) = connect(true, true);
|
||||
let (client, server) = connect(wt_default_parameters(), wt_default_parameters());
|
||||
Self { client, server }
|
||||
}
|
||||
|
||||
pub fn new_with_params(client_params: Http3Parameters, server_params: Http3Parameters) -> Self {
|
||||
let (client, server) = connect(client_params, server_params);
|
||||
Self { client, server }
|
||||
}
|
||||
|
||||
|
|
@ -111,7 +130,10 @@ impl WtTest {
|
|||
connect_with(&mut client, &mut server);
|
||||
Self { client, server }
|
||||
}
|
||||
fn negotiate_wt_session(&mut self, accept: bool) -> (StreamId, Option<WebTransportRequest>) {
|
||||
fn negotiate_wt_session(
|
||||
&mut self,
|
||||
accept: &WebTransportSessionAcceptAction,
|
||||
) -> (StreamId, Option<WebTransportRequest>) {
|
||||
let wt_session_id = self
|
||||
.client
|
||||
.webtransport_create_session(now(), &("https", "something.com", "/"), &[])
|
||||
|
|
@ -148,7 +170,8 @@ impl WtTest {
|
|||
}
|
||||
|
||||
fn create_wt_session(&mut self) -> WebTransportRequest {
|
||||
let (wt_session_id, wt_server_session) = self.negotiate_wt_session(true);
|
||||
let (wt_session_id, wt_server_session) =
|
||||
self.negotiate_wt_session(&WebTransportSessionAcceptAction::Accept);
|
||||
let wt_session_negotiated_event = |e| {
|
||||
matches!(
|
||||
e,
|
||||
|
|
@ -202,12 +225,12 @@ impl WtTest {
|
|||
pub fn check_session_closed_event_client(
|
||||
&mut self,
|
||||
wt_session_id: StreamId,
|
||||
expected_reason: SessionCloseReason,
|
||||
expected_reason: &SessionCloseReason,
|
||||
) {
|
||||
let mut event_found = false;
|
||||
|
||||
while let Some(event) = self.client.next_event() {
|
||||
event_found = WtTest::session_closed_client(&event, wt_session_id, &expected_reason);
|
||||
event_found = WtTest::session_closed_client(&event, wt_session_id, expected_reason);
|
||||
if event_found {
|
||||
break;
|
||||
}
|
||||
|
|
@ -239,13 +262,13 @@ impl WtTest {
|
|||
pub fn check_session_closed_event_server(
|
||||
&mut self,
|
||||
wt_session: &mut WebTransportRequest,
|
||||
expected_reeason: SessionCloseReason,
|
||||
expected_reeason: &SessionCloseReason,
|
||||
) {
|
||||
let event = self.server.next_event().unwrap();
|
||||
assert!(WtTest::session_closed_server(
|
||||
&event,
|
||||
wt_session.stream_id(),
|
||||
&expected_reeason
|
||||
expected_reeason
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -353,7 +376,7 @@ impl WtTest {
|
|||
expected_stop_sending_ids: &[StreamId],
|
||||
expected_error_stream_stop_sending: Option<u64>,
|
||||
expected_local: bool,
|
||||
expected_session_close: Option<(StreamId, SessionCloseReason)>,
|
||||
expected_session_close: &Option<(StreamId, SessionCloseReason)>,
|
||||
) {
|
||||
let mut reset_ids_count = 0;
|
||||
let mut stop_sending_ids_count = 0;
|
||||
|
|
@ -392,7 +415,6 @@ impl WtTest {
|
|||
}
|
||||
|
||||
fn create_wt_stream_server(
|
||||
&mut self,
|
||||
wt_server_session: &mut WebTransportRequest,
|
||||
stream_type: StreamType,
|
||||
) -> Http3OrWebTransportStream {
|
||||
|
|
@ -494,7 +516,7 @@ impl WtTest {
|
|||
expected_error_stream_reset: Option<u64>,
|
||||
expected_stop_sending_ids: &[StreamId],
|
||||
expected_error_stream_stop_sending: Option<u64>,
|
||||
expected_session_close: Option<(StreamId, SessionCloseReason)>,
|
||||
expected_session_close: &Option<(StreamId, SessionCloseReason)>,
|
||||
) {
|
||||
let mut reset_ids_count = 0;
|
||||
let mut stop_sending_ids_count = 0;
|
||||
|
|
@ -537,11 +559,72 @@ impl WtTest {
|
|||
}
|
||||
|
||||
pub fn session_close_frame_server(
|
||||
&mut self,
|
||||
wt_session: &mut WebTransportRequest,
|
||||
error: u32,
|
||||
message: &str,
|
||||
) {
|
||||
wt_session.close_session(error, message).unwrap();
|
||||
}
|
||||
|
||||
fn max_datagram_size(&self, stream_id: StreamId) -> Result<u64, Error> {
|
||||
self.client.webtransport_max_datagram_size(stream_id)
|
||||
}
|
||||
|
||||
fn send_datagram(&mut self, stream_id: StreamId, buf: &[u8]) -> Result<(), Error> {
|
||||
self.client.webtransport_send_datagram(stream_id, buf, None)
|
||||
}
|
||||
|
||||
fn check_datagram_received_client(
|
||||
&mut self,
|
||||
expected_stream_id: StreamId,
|
||||
expected_dgram: &[u8],
|
||||
) {
|
||||
let wt_datagram_event = |e| {
|
||||
matches!(
|
||||
e,
|
||||
Http3ClientEvent::WebTransport(WebTransportEvent::Datagram {
|
||||
session_id,
|
||||
datagram
|
||||
}) if session_id == expected_stream_id && datagram == expected_dgram
|
||||
)
|
||||
};
|
||||
assert!(self.client.events().any(wt_datagram_event));
|
||||
}
|
||||
|
||||
fn check_datagram_received_server(
|
||||
&mut self,
|
||||
expected_session: &WebTransportRequest,
|
||||
expected_dgram: &[u8],
|
||||
) {
|
||||
let wt_datagram_event = |e| {
|
||||
matches!(
|
||||
e,
|
||||
Http3ServerEvent::WebTransport(WebTransportServerEvent::Datagram {
|
||||
session,
|
||||
datagram
|
||||
}) if session.stream_id() == expected_session.stream_id() && datagram == expected_dgram
|
||||
)
|
||||
};
|
||||
assert!(self.server.events().any(wt_datagram_event));
|
||||
}
|
||||
|
||||
fn check_no_datagram_received_client(&mut self) {
|
||||
let wt_datagram_event = |e| {
|
||||
matches!(
|
||||
e,
|
||||
Http3ClientEvent::WebTransport(WebTransportEvent::Datagram { .. })
|
||||
)
|
||||
};
|
||||
assert!(!self.client.events().any(wt_datagram_event));
|
||||
}
|
||||
|
||||
fn check_no_datagram_received_server(&mut self) {
|
||||
let wt_datagram_event = |e| {
|
||||
matches!(
|
||||
e,
|
||||
Http3ServerEvent::WebTransport(WebTransportServerEvent::Datagram { .. })
|
||||
)
|
||||
};
|
||||
assert!(!self.server.events().any(wt_datagram_event));
|
||||
}
|
||||
}
|
||||
290
third_party/rust/neqo-http3/src/features/extended_connect/tests/webtransport/negotiation.rs
vendored
Normal file
290
third_party/rust/neqo-http3/src/features/extended_connect/tests/webtransport/negotiation.rs
vendored
Normal file
|
|
@ -0,0 +1,290 @@
|
|||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use super::{connect, default_http3_client, default_http3_server, exchange_packets};
|
||||
use crate::{
|
||||
settings::{HSetting, HSettingType, HSettings},
|
||||
Error, HFrame, Http3Client, Http3ClientEvent, Http3Parameters, Http3Server, Http3State,
|
||||
WebTransportEvent,
|
||||
};
|
||||
use neqo_common::{event::Provider, Encoder};
|
||||
use neqo_crypto::AuthenticationStatus;
|
||||
use neqo_transport::{Connection, ConnectionError, StreamType};
|
||||
use std::time::Duration;
|
||||
use test_fixture::{default_server_h3, now};
|
||||
|
||||
fn check_wt_event(client: &mut Http3Client, wt_enable_client: bool, wt_enable_server: bool) {
|
||||
let wt_event = client.events().find_map(|e| {
|
||||
if let Http3ClientEvent::WebTransport(WebTransportEvent::Negotiated(neg)) = e {
|
||||
Some(neg)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
assert_eq!(wt_event.is_some(), wt_enable_client);
|
||||
if let Some(wt) = wt_event {
|
||||
assert_eq!(wt, wt_enable_client && wt_enable_server);
|
||||
}
|
||||
}
|
||||
|
||||
fn connect_wt(wt_enabled_client: bool, wt_enabled_server: bool) -> (Http3Client, Http3Server) {
|
||||
connect(
|
||||
Http3Parameters::default().webtransport(wt_enabled_client),
|
||||
Http3Parameters::default().webtransport(wt_enabled_server),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn negotiate_wt() {
|
||||
let (mut client, _server) = connect_wt(true, true);
|
||||
assert!(client.webtransport_enabled());
|
||||
check_wt_event(&mut client, true, true);
|
||||
|
||||
let (mut client, _server) = connect_wt(true, false);
|
||||
assert!(!client.webtransport_enabled());
|
||||
check_wt_event(&mut client, true, false);
|
||||
|
||||
let (mut client, _server) = connect_wt(false, true);
|
||||
assert!(!client.webtransport_enabled());
|
||||
check_wt_event(&mut client, false, true);
|
||||
|
||||
let (mut client, _server) = connect_wt(false, false);
|
||||
assert!(!client.webtransport_enabled());
|
||||
check_wt_event(&mut client, false, false);
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum ClientState {
|
||||
ClientEnabled,
|
||||
ClientDisabled,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum ClientResumedState {
|
||||
ClientResumed,
|
||||
ClientSuspended,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum ServerState {
|
||||
ServerEnabled,
|
||||
ServerDisabled,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum ServerResumedState {
|
||||
ServerResumed,
|
||||
ServerSuspended,
|
||||
}
|
||||
|
||||
fn zero_rtt(
|
||||
client_state: &ClientState,
|
||||
server_state: &ServerState,
|
||||
client_resumed: &ClientResumedState,
|
||||
server_resumed: &ServerResumedState,
|
||||
) {
|
||||
let (mut client, mut server) = connect_wt(
|
||||
ClientState::ClientEnabled.eq(client_state),
|
||||
ServerState::ServerEnabled.eq(server_state),
|
||||
);
|
||||
assert_eq!(
|
||||
client.webtransport_enabled(),
|
||||
ClientState::ClientEnabled.eq(client_state) && ServerState::ServerEnabled.eq(server_state)
|
||||
);
|
||||
|
||||
// exchane token
|
||||
let out = server.process(None, now());
|
||||
// We do not have a token so we need to wait for a resumption token timer to trigger.
|
||||
std::mem::drop(client.process(out.dgram(), now() + Duration::from_millis(250)));
|
||||
assert_eq!(client.state(), Http3State::Connected);
|
||||
let token = client
|
||||
.events()
|
||||
.find_map(|e| {
|
||||
if let Http3ClientEvent::ResumptionToken(token) = e {
|
||||
Some(token)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let mut client = default_http3_client(
|
||||
Http3Parameters::default()
|
||||
.webtransport(ClientResumedState::ClientResumed.eq(client_resumed)),
|
||||
);
|
||||
let mut server = default_http3_server(
|
||||
Http3Parameters::default()
|
||||
.webtransport(ServerResumedState::ServerResumed.eq(server_resumed)),
|
||||
);
|
||||
client
|
||||
.enable_resumption(now(), &token)
|
||||
.expect("Set resumption token.");
|
||||
assert_eq!(client.state(), Http3State::ZeroRtt);
|
||||
|
||||
exchange_packets(&mut client, &mut server);
|
||||
|
||||
assert_eq!(&client.state(), &Http3State::Connected);
|
||||
assert_eq!(
|
||||
client.webtransport_enabled(),
|
||||
ClientResumedState::ClientResumed.eq(client_resumed)
|
||||
&& ServerResumedState::ServerResumed.eq(server_resumed)
|
||||
);
|
||||
check_wt_event(
|
||||
&mut client,
|
||||
ClientResumedState::ClientResumed.eq(client_resumed),
|
||||
ServerResumedState::ServerResumed.eq(server_resumed),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zero_rtt_wt_settings() {
|
||||
zero_rtt(
|
||||
&ClientState::ClientEnabled,
|
||||
&ServerState::ServerEnabled,
|
||||
&ClientResumedState::ClientResumed,
|
||||
&ServerResumedState::ServerResumed,
|
||||
);
|
||||
zero_rtt(
|
||||
&ClientState::ClientEnabled,
|
||||
&ServerState::ServerEnabled,
|
||||
&ClientResumedState::ClientResumed,
|
||||
&ServerResumedState::ServerSuspended,
|
||||
);
|
||||
zero_rtt(
|
||||
&ClientState::ClientEnabled,
|
||||
&ServerState::ServerEnabled,
|
||||
&ClientResumedState::ClientSuspended,
|
||||
&ServerResumedState::ServerResumed,
|
||||
);
|
||||
zero_rtt(
|
||||
&ClientState::ClientEnabled,
|
||||
&ServerState::ServerEnabled,
|
||||
&ClientResumedState::ClientSuspended,
|
||||
&ServerResumedState::ServerSuspended,
|
||||
);
|
||||
|
||||
zero_rtt(
|
||||
&ClientState::ClientEnabled,
|
||||
&ServerState::ServerDisabled,
|
||||
&ClientResumedState::ClientResumed,
|
||||
&ServerResumedState::ServerSuspended,
|
||||
);
|
||||
zero_rtt(
|
||||
&ClientState::ClientEnabled,
|
||||
&ServerState::ServerDisabled,
|
||||
&ClientResumedState::ClientResumed,
|
||||
&ServerResumedState::ServerResumed,
|
||||
);
|
||||
zero_rtt(
|
||||
&ClientState::ClientEnabled,
|
||||
&ServerState::ServerDisabled,
|
||||
&ClientResumedState::ClientSuspended,
|
||||
&ServerResumedState::ServerSuspended,
|
||||
);
|
||||
zero_rtt(
|
||||
&ClientState::ClientEnabled,
|
||||
&ServerState::ServerDisabled,
|
||||
&ClientResumedState::ClientSuspended,
|
||||
&ServerResumedState::ServerResumed,
|
||||
);
|
||||
|
||||
zero_rtt(
|
||||
&ClientState::ClientDisabled,
|
||||
&ServerState::ServerDisabled,
|
||||
&ClientResumedState::ClientSuspended,
|
||||
&ServerResumedState::ServerSuspended,
|
||||
);
|
||||
zero_rtt(
|
||||
&ClientState::ClientDisabled,
|
||||
&ServerState::ServerDisabled,
|
||||
&ClientResumedState::ClientSuspended,
|
||||
&ServerResumedState::ServerResumed,
|
||||
);
|
||||
zero_rtt(
|
||||
&ClientState::ClientDisabled,
|
||||
&ServerState::ServerDisabled,
|
||||
&ClientResumedState::ClientResumed,
|
||||
&ServerResumedState::ServerSuspended,
|
||||
);
|
||||
zero_rtt(
|
||||
&ClientState::ClientDisabled,
|
||||
&ServerState::ServerDisabled,
|
||||
&ClientResumedState::ClientResumed,
|
||||
&ServerResumedState::ServerResumed,
|
||||
);
|
||||
|
||||
zero_rtt(
|
||||
&ClientState::ClientDisabled,
|
||||
&ServerState::ServerEnabled,
|
||||
&ClientResumedState::ClientSuspended,
|
||||
&ServerResumedState::ServerResumed,
|
||||
);
|
||||
zero_rtt(
|
||||
&ClientState::ClientDisabled,
|
||||
&ServerState::ServerEnabled,
|
||||
&ClientResumedState::ClientSuspended,
|
||||
&ServerResumedState::ServerSuspended,
|
||||
);
|
||||
zero_rtt(
|
||||
&ClientState::ClientDisabled,
|
||||
&ServerState::ServerEnabled,
|
||||
&ClientResumedState::ClientResumed,
|
||||
&ServerResumedState::ServerSuspended,
|
||||
);
|
||||
zero_rtt(
|
||||
&ClientState::ClientDisabled,
|
||||
&ServerState::ServerEnabled,
|
||||
&ClientResumedState::ClientResumed,
|
||||
&ServerResumedState::ServerResumed,
|
||||
);
|
||||
}
|
||||
|
||||
fn exchange_packets2(client: &mut Http3Client, server: &mut Connection) {
|
||||
let mut out = None;
|
||||
loop {
|
||||
out = client.process(out, now()).dgram();
|
||||
out = server.process(out, now()).dgram();
|
||||
if out.is_none() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wrong_setting_value() {
|
||||
const CONTROL_STREAM_TYPE: &[u8] = &[0x0];
|
||||
let mut client = default_http3_client(Http3Parameters::default());
|
||||
let mut server = default_server_h3();
|
||||
|
||||
exchange_packets2(&mut client, &mut server);
|
||||
client.authenticated(AuthenticationStatus::Ok, now());
|
||||
exchange_packets2(&mut client, &mut server);
|
||||
|
||||
let control = server.stream_create(StreamType::UniDi).unwrap();
|
||||
server.stream_send(control, CONTROL_STREAM_TYPE).unwrap();
|
||||
// Encode a settings frame and send it.
|
||||
let mut enc = Encoder::default();
|
||||
let settings = HFrame::Settings {
|
||||
settings: HSettings::new(&[HSetting::new(HSettingType::EnableWebTransport, 2)]),
|
||||
};
|
||||
settings.encode(&mut enc);
|
||||
assert_eq!(
|
||||
server.stream_send(control, enc.as_ref()).unwrap(),
|
||||
enc.as_ref().len()
|
||||
);
|
||||
|
||||
exchange_packets2(&mut client, &mut server);
|
||||
match client.state() {
|
||||
Http3State::Closing(err) | Http3State::Closed(err) => {
|
||||
assert_eq!(
|
||||
err,
|
||||
ConnectionError::Application(Error::HttpSettings.code())
|
||||
);
|
||||
}
|
||||
_ => panic!("Wrong state {:?}", client.state()),
|
||||
};
|
||||
}
|
||||
|
|
@ -4,16 +4,18 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use crate::webtransport::{default_http3_server, WtTest};
|
||||
use neqo_common::{event::Provider, Encoder};
|
||||
use neqo_http3::{
|
||||
features::extended_connect::SessionCloseReason, frames::WebTransportFrame, Error, Header,
|
||||
Http3ClientEvent, Http3OrWebTransportStream, Http3Parameters, Http3Server, Http3ServerEvent,
|
||||
Http3State, Priority, WebTransportEvent, WebTransportServerEvent,
|
||||
use crate::features::extended_connect::tests::webtransport::{
|
||||
default_http3_client, default_http3_server, wt_default_parameters, WtTest,
|
||||
};
|
||||
use neqo_transport::{ConnectionParameters, StreamType};
|
||||
use crate::{
|
||||
features::extended_connect::SessionCloseReason, frames::WebTransportFrame, Error, Header,
|
||||
Http3ClientEvent, Http3OrWebTransportStream, Http3Server, Http3ServerEvent, Http3State,
|
||||
Priority, WebTransportEvent, WebTransportServerEvent, WebTransportSessionAcceptAction,
|
||||
};
|
||||
use neqo_common::{event::Provider, Encoder};
|
||||
use neqo_transport::StreamType;
|
||||
use std::mem;
|
||||
use test_fixture::{http3_client_with_params, now};
|
||||
use test_fixture::now;
|
||||
|
||||
#[test]
|
||||
fn wt_session() {
|
||||
|
|
@ -24,9 +26,11 @@ fn wt_session() {
|
|||
#[test]
|
||||
fn wt_session_reject() {
|
||||
let mut wt = WtTest::new();
|
||||
let (wt_session_id, _wt_session) = wt.negotiate_wt_session(false);
|
||||
let accept_res =
|
||||
WebTransportSessionAcceptAction::Reject([Header::new(":status", "404")].to_vec());
|
||||
let (wt_session_id, _wt_session) = wt.negotiate_wt_session(&accept_res);
|
||||
|
||||
wt.check_session_closed_event_client(wt_session_id, SessionCloseReason::Status(404));
|
||||
wt.check_session_closed_event_client(wt_session_id, &SessionCloseReason::Status(404));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -37,7 +41,7 @@ fn wt_session_close_client() {
|
|||
wt.cancel_session_client(wt_session.stream_id());
|
||||
wt.check_session_closed_event_server(
|
||||
&mut wt_session,
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
&SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -49,7 +53,7 @@ fn wt_session_close_server() {
|
|||
wt.cancel_session_server(&mut wt_session);
|
||||
wt.check_session_closed_event_client(
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
&SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -62,9 +66,9 @@ fn wt_session_close_server_close_send() {
|
|||
wt.exchange_packets();
|
||||
wt.check_session_closed_event_client(
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Clean {
|
||||
&SessionCloseReason::Clean {
|
||||
error: 0,
|
||||
message: "".to_string(),
|
||||
message: String::new(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -80,7 +84,7 @@ fn wt_session_close_server_stop_sending() {
|
|||
wt.exchange_packets();
|
||||
wt.check_session_closed_event_client(
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
&SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -95,12 +99,12 @@ fn wt_session_close_server_reset() {
|
|||
wt.exchange_packets();
|
||||
wt.check_session_closed_event_client(
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
&SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wt_session_respone_with_1xx() {
|
||||
fn wt_session_response_with_1xx() {
|
||||
let mut wt = WtTest::new();
|
||||
|
||||
let wt_session_id = wt
|
||||
|
|
@ -134,7 +138,9 @@ fn wt_session_respone_with_1xx() {
|
|||
wt_server_session
|
||||
.send_headers(&[Header::new(":status", "111")])
|
||||
.unwrap();
|
||||
wt_server_session.response(true).unwrap();
|
||||
wt_server_session
|
||||
.response(&WebTransportSessionAcceptAction::Accept)
|
||||
.unwrap();
|
||||
|
||||
wt.exchange_packets();
|
||||
|
||||
|
|
@ -152,6 +158,19 @@ fn wt_session_respone_with_1xx() {
|
|||
assert_eq!(wt_session_id, wt_server_session.stream_id());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wt_session_response_with_redirect() {
|
||||
let mut wt = WtTest::new();
|
||||
|
||||
let accept_res = WebTransportSessionAcceptAction::Reject(
|
||||
[Header::new(":status", "302"), Header::new("location", "/")].to_vec(),
|
||||
);
|
||||
|
||||
let (wt_session_id, _wt_session) = wt.negotiate_wt_session(&accept_res);
|
||||
|
||||
wt.check_session_closed_event_client(wt_session_id, &SessionCloseReason::Status(302));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wt_session_respone_200_with_fin() {
|
||||
let mut wt = WtTest::new();
|
||||
|
|
@ -181,7 +200,9 @@ fn wt_session_respone_200_with_fin() {
|
|||
}
|
||||
|
||||
let mut wt_server_session = wt_server_session.unwrap();
|
||||
wt_server_session.response(true).unwrap();
|
||||
wt_server_session
|
||||
.response(&WebTransportSessionAcceptAction::Accept)
|
||||
.unwrap();
|
||||
wt_server_session.stream_close_send().unwrap();
|
||||
|
||||
wt.exchange_packets();
|
||||
|
|
@ -192,7 +213,7 @@ fn wt_session_respone_200_with_fin() {
|
|||
Http3ClientEvent::WebTransport(WebTransportEvent::SessionClosed{
|
||||
stream_id,
|
||||
reason
|
||||
}) if stream_id == wt_session_id && reason == SessionCloseReason::Clean{ error: 0, message: "".to_string()}
|
||||
}) if stream_id == wt_session_id && reason == SessionCloseReason::Clean{ error: 0, message: String::new()}
|
||||
)
|
||||
};
|
||||
assert!(wt.client.events().any(wt_session_close_event));
|
||||
|
|
@ -212,7 +233,7 @@ fn wt_session_close_frame_client() {
|
|||
|
||||
wt.check_session_closed_event_server(
|
||||
&mut wt_session,
|
||||
SessionCloseReason::Clean {
|
||||
&SessionCloseReason::Clean {
|
||||
error: ERROR_NUM,
|
||||
message: ERROR_MESSAGE.to_string(),
|
||||
},
|
||||
|
|
@ -226,12 +247,12 @@ fn wt_session_close_frame_server() {
|
|||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
||||
wt.session_close_frame_server(&mut wt_session, ERROR_NUM, ERROR_MESSAGE);
|
||||
WtTest::session_close_frame_server(&mut wt_session, ERROR_NUM, ERROR_MESSAGE);
|
||||
wt.exchange_packets();
|
||||
|
||||
wt.check_session_closed_event_client(
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Clean {
|
||||
&SessionCloseReason::Clean {
|
||||
error: ERROR_NUM,
|
||||
message: ERROR_MESSAGE.to_string(),
|
||||
},
|
||||
|
|
@ -257,7 +278,7 @@ fn wt_unknown_session_frame_client() {
|
|||
wt.exchange_packets();
|
||||
|
||||
// The session is still active
|
||||
let mut unidi_server = wt.create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
let mut unidi_server = WtTest::create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
wt.send_data_server(&mut unidi_server, BUF);
|
||||
wt.receive_data_client(unidi_server.stream_id(), true, BUF, false);
|
||||
|
||||
|
|
@ -271,14 +292,14 @@ fn wt_unknown_session_frame_client() {
|
|||
&[],
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
&None,
|
||||
);
|
||||
wt.check_events_after_closing_session_server(
|
||||
&[],
|
||||
None,
|
||||
&[unidi_server.stream_id()],
|
||||
Some(Error::HttpRequestCancelled.code()),
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Clean {
|
||||
error: ERROR_NUM,
|
||||
|
|
@ -309,11 +330,11 @@ fn wt_close_session_frame_broken_client() {
|
|||
// check that the webtransport session is closed.
|
||||
wt.check_session_closed_event_client(
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpGeneralProtocolStream.code()),
|
||||
&SessionCloseReason::Error(Error::HttpGeneralProtocolStream.code()),
|
||||
);
|
||||
wt.check_session_closed_event_server(
|
||||
&mut wt_session,
|
||||
SessionCloseReason::Error(Error::HttpGeneralProtocolStream.code()),
|
||||
&SessionCloseReason::Error(Error::HttpGeneralProtocolStream.code()),
|
||||
);
|
||||
|
||||
// The Http3 session is still working.
|
||||
|
|
@ -331,18 +352,16 @@ fn receive_request(server: &mut Http3Server) -> Option<Http3OrWebTransportStream
|
|||
}
|
||||
|
||||
#[test]
|
||||
// Ignoring this test as it is panicking at wt.create_wt_stream_client
|
||||
// Issue # 1386 is created to track this
|
||||
#[ignore]
|
||||
fn wt_close_session_cannot_be_sent_at_once() {
|
||||
const LIMIT: u64 = 500;
|
||||
const BUF: &[u8] = &[0; 443];
|
||||
const ERROR_NUM: u32 = 23;
|
||||
const ERROR_MESSAGE: &str = "Something went wrong";
|
||||
|
||||
let client = http3_client_with_params(
|
||||
Http3Parameters::default()
|
||||
.webtransport(true)
|
||||
.connection_parameters(ConnectionParameters::default().max_data(LIMIT)),
|
||||
);
|
||||
let server = default_http3_server(true);
|
||||
let client = default_http3_client(wt_default_parameters());
|
||||
let server = default_http3_server(wt_default_parameters());
|
||||
let mut wt = WtTest::new_with(client, server);
|
||||
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
|
@ -369,7 +388,7 @@ fn wt_close_session_cannot_be_sent_at_once() {
|
|||
req.send_data(BUF).unwrap();
|
||||
|
||||
// Now close the session.
|
||||
wt.session_close_frame_server(&mut wt_session, ERROR_NUM, ERROR_MESSAGE);
|
||||
WtTest::session_close_frame_server(&mut wt_session, ERROR_NUM, ERROR_MESSAGE);
|
||||
// server cannot create new streams.
|
||||
assert_eq!(
|
||||
wt_session.create_stream(StreamType::UniDi),
|
||||
|
|
@ -395,7 +414,7 @@ fn wt_close_session_cannot_be_sent_at_once() {
|
|||
&[unidi_client],
|
||||
Some(Error::HttpRequestCancelled.code()),
|
||||
false,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Clean {
|
||||
error: ERROR_NUM,
|
||||
|
|
@ -403,5 +422,5 @@ fn wt_close_session_cannot_be_sent_at_once() {
|
|||
},
|
||||
)),
|
||||
);
|
||||
wt.check_events_after_closing_session_server(&[], None, &[], None, None);
|
||||
wt.check_events_after_closing_session_server(&[], None, &[], None, &None);
|
||||
}
|
||||
|
|
@ -4,8 +4,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use crate::webtransport::WtTest;
|
||||
use neqo_http3::{features::extended_connect::SessionCloseReason, Error};
|
||||
use crate::features::extended_connect::tests::webtransport::WtTest;
|
||||
use crate::{features::extended_connect::SessionCloseReason, Error};
|
||||
use neqo_transport::StreamType;
|
||||
use std::mem;
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ fn wt_server_stream_uni() {
|
|||
|
||||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
let mut wt_server_stream = wt.create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
let mut wt_server_stream = WtTest::create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
wt.send_data_server(&mut wt_server_stream, BUF_SERVER);
|
||||
wt.receive_data_client(wt_server_stream.stream_id(), true, BUF_SERVER, false);
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ fn wt_server_stream_bidi() {
|
|||
|
||||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
let mut wt_server_stream = wt.create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
let mut wt_server_stream = WtTest::create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
wt.send_data_server(&mut wt_server_stream, BUF_SERVER);
|
||||
wt.receive_data_client(wt_server_stream.stream_id(), true, BUF_SERVER, false);
|
||||
wt.send_data_client(wt_server_stream.stream_id(), BUF_CLIENT);
|
||||
|
|
@ -96,7 +96,7 @@ fn wt_server_stream_uni_closed() {
|
|||
|
||||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
let mut wt_server_stream = wt.create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
let mut wt_server_stream = WtTest::create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
wt.send_data_server(&mut wt_server_stream, BUF_SERVER);
|
||||
wt.close_stream_sending_server(&mut wt_server_stream);
|
||||
wt.receive_data_client(wt_server_stream.stream_id(), true, BUF_SERVER, true);
|
||||
|
|
@ -109,7 +109,7 @@ fn wt_server_stream_bidi_close() {
|
|||
|
||||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
let mut wt_server_stream = wt.create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
let mut wt_server_stream = WtTest::create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
wt.send_data_server(&mut wt_server_stream, BUF_SERVER);
|
||||
wt.close_stream_sending_server(&mut wt_server_stream);
|
||||
wt.receive_data_client(wt_server_stream.stream_id(), true, BUF_SERVER, true);
|
||||
|
|
@ -137,7 +137,7 @@ fn wt_server_stream_uni_reset() {
|
|||
|
||||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
let mut wt_server_stream = wt.create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
let mut wt_server_stream = WtTest::create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
wt.send_data_server(&mut wt_server_stream, BUF_SERVER);
|
||||
wt.receive_data_client(wt_server_stream.stream_id(), true, BUF_SERVER, false);
|
||||
wt.reset_stream_server(&mut wt_server_stream);
|
||||
|
|
@ -168,7 +168,7 @@ fn wt_server_stream_bidi_reset() {
|
|||
|
||||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
let mut wt_server_stream = wt.create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
let mut wt_server_stream = WtTest::create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
wt.send_data_server(&mut wt_server_stream, BUF_SERVER);
|
||||
wt.receive_data_client(wt_server_stream.stream_id(), true, BUF_SERVER, false);
|
||||
|
||||
|
|
@ -198,7 +198,7 @@ fn wt_server_stream_uni_stop_sending() {
|
|||
|
||||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
let mut wt_server_stream = wt.create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
let mut wt_server_stream = WtTest::create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
wt.send_data_server(&mut wt_server_stream, BUF_SERVER);
|
||||
wt.receive_data_client(wt_server_stream.stream_id(), true, BUF_SERVER, false);
|
||||
wt.stream_stop_sending_client(wt_server_stream.stream_id());
|
||||
|
|
@ -231,7 +231,7 @@ fn wt_server_stream_bidi_stop_sending() {
|
|||
|
||||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
let mut wt_server_stream = wt.create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
let mut wt_server_stream = WtTest::create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
|
||||
wt.send_data_server(&mut wt_server_stream, BUF_SERVER);
|
||||
wt.receive_data_client(wt_server_stream.stream_id(), true, BUF_SERVER, false);
|
||||
|
|
@ -265,7 +265,7 @@ fn wt_client_session_close_1() {
|
|||
|
||||
let bidi_from_client = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::BiDi);
|
||||
wt.send_data_client(bidi_from_client, BUF);
|
||||
let _ = wt.receive_data_server(bidi_from_client, true, BUF, false);
|
||||
std::mem::drop(wt.receive_data_server(bidi_from_client, true, BUF, false));
|
||||
|
||||
wt.cancel_session_client(wt_session.stream_id());
|
||||
|
||||
|
|
@ -274,7 +274,7 @@ fn wt_client_session_close_1() {
|
|||
Some(Error::HttpRequestCancelled.code()),
|
||||
&[bidi_from_client],
|
||||
Some(Error::HttpRequestCancelled.code()),
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
|
|
@ -286,7 +286,7 @@ fn wt_client_session_close_1() {
|
|||
&[bidi_from_client],
|
||||
Some(Error::HttpRequestCancelled.code()),
|
||||
false,
|
||||
None,
|
||||
&None,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -300,7 +300,7 @@ fn wt_client_session_close_2() {
|
|||
let unidi_from_client = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::UniDi);
|
||||
|
||||
wt.send_data_client(unidi_from_client, BUF);
|
||||
let _ = wt.receive_data_server(unidi_from_client, true, BUF, false);
|
||||
std::mem::drop(wt.receive_data_server(unidi_from_client, true, BUF, false));
|
||||
|
||||
wt.cancel_session_client(wt_session.stream_id());
|
||||
|
||||
|
|
@ -309,7 +309,7 @@ fn wt_client_session_close_2() {
|
|||
Some(Error::HttpRequestCancelled.code()),
|
||||
&[],
|
||||
None,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
|
|
@ -321,7 +321,7 @@ fn wt_client_session_close_2() {
|
|||
&[unidi_from_client],
|
||||
Some(Error::HttpRequestCancelled.code()),
|
||||
false,
|
||||
None,
|
||||
&None,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -335,7 +335,7 @@ fn wt_client_session_close_3() {
|
|||
let unidi_from_client = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::UniDi);
|
||||
|
||||
wt.send_data_client(unidi_from_client, BUF);
|
||||
let _ = wt.receive_data_server(unidi_from_client, true, BUF, false);
|
||||
std::mem::drop(wt.receive_data_server(unidi_from_client, true, BUF, false));
|
||||
wt.close_stream_sending_client(unidi_from_client);
|
||||
|
||||
wt.cancel_session_client(wt_session.stream_id());
|
||||
|
|
@ -345,13 +345,13 @@ fn wt_client_session_close_3() {
|
|||
None,
|
||||
&[],
|
||||
None,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
);
|
||||
|
||||
wt.check_events_after_closing_session_client(&[], None, &[], None, false, None);
|
||||
wt.check_events_after_closing_session_client(&[], None, &[], None, false, &None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -374,7 +374,7 @@ fn wt_client_session_close_4() {
|
|||
None,
|
||||
&[],
|
||||
None,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
|
|
@ -386,7 +386,7 @@ fn wt_client_session_close_4() {
|
|||
&[unidi_from_client],
|
||||
Some(Error::HttpNoError.code()),
|
||||
false,
|
||||
None,
|
||||
&None,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -410,13 +410,13 @@ fn wt_client_session_close_5() {
|
|||
Some(Error::HttpNoError.code()),
|
||||
&[],
|
||||
None,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
);
|
||||
|
||||
wt.check_events_after_closing_session_client(&[], None, &[], None, false, None);
|
||||
wt.check_events_after_closing_session_client(&[], None, &[], None, false, &None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -426,7 +426,7 @@ fn wt_client_session_close_6() {
|
|||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
||||
let mut bidi_from_server = wt.create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
let mut bidi_from_server = WtTest::create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
wt.send_data_server(&mut bidi_from_server, BUF);
|
||||
wt.receive_data_client(bidi_from_server.stream_id(), true, BUF, false);
|
||||
|
||||
|
|
@ -437,7 +437,7 @@ fn wt_client_session_close_6() {
|
|||
Some(Error::HttpRequestCancelled.code()),
|
||||
&[bidi_from_server.stream_id()],
|
||||
Some(Error::HttpRequestCancelled.code()),
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
|
|
@ -449,7 +449,7 @@ fn wt_client_session_close_6() {
|
|||
&[bidi_from_server.stream_id()],
|
||||
Some(Error::HttpRequestCancelled.code()),
|
||||
false,
|
||||
None,
|
||||
&None,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -460,7 +460,7 @@ fn wt_client_session_close_7() {
|
|||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
||||
let mut unidi_from_server = wt.create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
let mut unidi_from_server = WtTest::create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
wt.send_data_server(&mut unidi_from_server, BUF);
|
||||
wt.receive_data_client(unidi_from_server.stream_id(), true, BUF, false);
|
||||
|
||||
|
|
@ -471,7 +471,7 @@ fn wt_client_session_close_7() {
|
|||
None,
|
||||
&[unidi_from_server.stream_id()],
|
||||
Some(Error::HttpRequestCancelled.code()),
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
|
|
@ -483,7 +483,7 @@ fn wt_client_session_close_7() {
|
|||
&[],
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
&None,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -494,7 +494,7 @@ fn wt_client_session_close_8() {
|
|||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
||||
let mut unidi_server = wt.create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
let mut unidi_server = WtTest::create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
wt.send_data_server(&mut unidi_server, BUF);
|
||||
wt.close_stream_sending_server(&mut unidi_server);
|
||||
wt.receive_data_client(unidi_server.stream_id(), true, BUF, true);
|
||||
|
|
@ -506,13 +506,13 @@ fn wt_client_session_close_8() {
|
|||
None,
|
||||
&[],
|
||||
None,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
);
|
||||
|
||||
wt.check_events_after_closing_session_client(&[], None, &[], None, false, None);
|
||||
wt.check_events_after_closing_session_client(&[], None, &[], None, false, &None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -522,7 +522,7 @@ fn wt_client_session_close_9() {
|
|||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
||||
let mut unidi_server = wt.create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
let mut unidi_server = WtTest::create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
wt.send_data_server(&mut unidi_server, BUF);
|
||||
wt.stream_stop_sending_client(unidi_server.stream_id());
|
||||
|
||||
|
|
@ -533,13 +533,13 @@ fn wt_client_session_close_9() {
|
|||
None,
|
||||
&[unidi_server.stream_id()],
|
||||
Some(Error::HttpNoError.code()),
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
);
|
||||
|
||||
wt.check_events_after_closing_session_client(&[], None, &[], None, false, None);
|
||||
wt.check_events_after_closing_session_client(&[], None, &[], None, false, &None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -549,7 +549,7 @@ fn wt_client_session_close_10() {
|
|||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
||||
let mut unidi_server = wt.create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
let mut unidi_server = WtTest::create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
wt.send_data_server(&mut unidi_server, BUF);
|
||||
wt.close_stream_sending_server(&mut unidi_server);
|
||||
|
||||
|
|
@ -560,7 +560,7 @@ fn wt_client_session_close_10() {
|
|||
None,
|
||||
&[],
|
||||
None,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
|
|
@ -572,7 +572,7 @@ fn wt_client_session_close_10() {
|
|||
&[],
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
&None,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -583,7 +583,7 @@ fn wt_client_session_close_11() {
|
|||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
||||
let mut bidi_server = wt.create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
let mut bidi_server = WtTest::create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
wt.send_data_server(&mut bidi_server, BUF);
|
||||
wt.close_stream_sending_server(&mut bidi_server);
|
||||
wt.receive_data_client(bidi_server.stream_id(), true, BUF, true);
|
||||
|
|
@ -597,13 +597,13 @@ fn wt_client_session_close_11() {
|
|||
None,
|
||||
&[],
|
||||
None,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
);
|
||||
|
||||
wt.check_events_after_closing_session_client(&[], None, &[], None, false, None);
|
||||
wt.check_events_after_closing_session_client(&[], None, &[], None, false, &None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -613,7 +613,7 @@ fn wt_client_session_close_12() {
|
|||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
||||
let mut bidi_server = wt.create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
let mut bidi_server = WtTest::create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
wt.send_data_server(&mut bidi_server, BUF);
|
||||
wt.close_stream_sending_server(&mut bidi_server);
|
||||
wt.stream_stop_sending_server(&mut bidi_server);
|
||||
|
|
@ -625,7 +625,7 @@ fn wt_client_session_close_12() {
|
|||
None,
|
||||
&[],
|
||||
None,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
|
|
@ -637,7 +637,7 @@ fn wt_client_session_close_12() {
|
|||
&[bidi_server.stream_id()],
|
||||
Some(Error::HttpNoError.code()),
|
||||
false,
|
||||
None,
|
||||
&None,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -650,10 +650,10 @@ fn wt_client_session_close_13() {
|
|||
|
||||
let bidi_client_1 = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::BiDi);
|
||||
wt.send_data_client(bidi_client_1, BUF);
|
||||
let _ = wt.receive_data_server(bidi_client_1, true, BUF, false);
|
||||
std::mem::drop(wt.receive_data_server(bidi_client_1, true, BUF, false));
|
||||
let bidi_client_2 = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::BiDi);
|
||||
wt.send_data_client(bidi_client_2, BUF);
|
||||
let _ = wt.receive_data_server(bidi_client_2, true, BUF, false);
|
||||
std::mem::drop(wt.receive_data_server(bidi_client_2, true, BUF, false));
|
||||
|
||||
wt.cancel_session_client(wt_session.stream_id());
|
||||
|
||||
|
|
@ -662,7 +662,7 @@ fn wt_client_session_close_13() {
|
|||
Some(Error::HttpRequestCancelled.code()),
|
||||
&[bidi_client_1, bidi_client_2],
|
||||
Some(Error::HttpRequestCancelled.code()),
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
|
|
@ -674,7 +674,7 @@ fn wt_client_session_close_13() {
|
|||
&[bidi_client_1, bidi_client_2],
|
||||
Some(Error::HttpRequestCancelled.code()),
|
||||
false,
|
||||
None,
|
||||
&None,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -700,7 +700,7 @@ fn wt_client_session_server_close_1() {
|
|||
|
||||
let bidi_client = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::BiDi);
|
||||
wt.send_data_client(bidi_client, BUF);
|
||||
let _ = wt.receive_data_server(bidi_client, true, BUF, false);
|
||||
std::mem::drop(wt.receive_data_server(bidi_client, true, BUF, false));
|
||||
|
||||
wt.cancel_session_server(&mut wt_session);
|
||||
|
||||
|
|
@ -710,7 +710,7 @@ fn wt_client_session_server_close_1() {
|
|||
&[bidi_client],
|
||||
Some(Error::HttpRequestCancelled.code()),
|
||||
false,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
|
|
@ -721,7 +721,7 @@ fn wt_client_session_server_close_1() {
|
|||
Some(Error::HttpRequestCancelled.code()),
|
||||
&[bidi_client],
|
||||
Some(Error::HttpRequestCancelled.code()),
|
||||
None,
|
||||
&None,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -734,7 +734,7 @@ fn wt_client_session_server_close_2() {
|
|||
|
||||
let unidi_client = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::UniDi);
|
||||
wt.send_data_client(unidi_client, BUF);
|
||||
let _ = wt.receive_data_server(unidi_client, true, BUF, false);
|
||||
std::mem::drop(wt.receive_data_server(unidi_client, true, BUF, false));
|
||||
|
||||
wt.cancel_session_server(&mut wt_session);
|
||||
|
||||
|
|
@ -744,7 +744,7 @@ fn wt_client_session_server_close_2() {
|
|||
&[unidi_client],
|
||||
Some(Error::HttpRequestCancelled.code()),
|
||||
false,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
|
|
@ -755,7 +755,7 @@ fn wt_client_session_server_close_2() {
|
|||
Some(Error::HttpRequestCancelled.code()),
|
||||
&[],
|
||||
None,
|
||||
None,
|
||||
&None,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -780,13 +780,13 @@ fn wt_client_session_server_close_3() {
|
|||
&[],
|
||||
None,
|
||||
false,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
);
|
||||
|
||||
wt.check_events_after_closing_session_server(&[], None, &[], None, None);
|
||||
wt.check_events_after_closing_session_server(&[], None, &[], None, &None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -809,13 +809,13 @@ fn wt_client_session_server_close_4() {
|
|||
&[unidi_client],
|
||||
Some(Error::HttpNoError.code()),
|
||||
false,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
);
|
||||
|
||||
wt.check_events_after_closing_session_server(&[], None, &[], None, None);
|
||||
wt.check_events_after_closing_session_server(&[], None, &[], None, &None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -825,7 +825,7 @@ fn wt_client_session_server_close_5() {
|
|||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
||||
let mut bidi_server = wt.create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
let mut bidi_server = WtTest::create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
wt.send_data_server(&mut bidi_server, BUF);
|
||||
wt.receive_data_client(bidi_server.stream_id(), true, BUF, false);
|
||||
|
||||
|
|
@ -837,7 +837,7 @@ fn wt_client_session_server_close_5() {
|
|||
&[bidi_server.stream_id()],
|
||||
Some(Error::HttpRequestCancelled.code()),
|
||||
false,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
|
|
@ -848,7 +848,7 @@ fn wt_client_session_server_close_5() {
|
|||
Some(Error::HttpRequestCancelled.code()),
|
||||
&[bidi_server.stream_id()],
|
||||
Some(Error::HttpRequestCancelled.code()),
|
||||
None,
|
||||
&None,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -859,7 +859,7 @@ fn wt_client_session_server_close_6() {
|
|||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
||||
let mut unidi_server = wt.create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
let mut unidi_server = WtTest::create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
wt.send_data_server(&mut unidi_server, BUF);
|
||||
wt.receive_data_client(unidi_server.stream_id(), true, BUF, false);
|
||||
|
||||
|
|
@ -871,7 +871,7 @@ fn wt_client_session_server_close_6() {
|
|||
&[],
|
||||
None,
|
||||
false,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
|
|
@ -881,7 +881,7 @@ fn wt_client_session_server_close_6() {
|
|||
None,
|
||||
&[unidi_server.stream_id()],
|
||||
Some(Error::HttpRequestCancelled.code()),
|
||||
None,
|
||||
&None,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -892,7 +892,7 @@ fn wt_client_session_server_close_7() {
|
|||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
||||
let mut unidi_server = wt.create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
let mut unidi_server = WtTest::create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
wt.send_data_server(&mut unidi_server, BUF);
|
||||
wt.close_stream_sending_server(&mut unidi_server);
|
||||
wt.receive_data_client(unidi_server.stream_id(), true, BUF, true);
|
||||
|
|
@ -906,13 +906,13 @@ fn wt_client_session_server_close_7() {
|
|||
&[],
|
||||
None,
|
||||
false,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
);
|
||||
|
||||
wt.check_events_after_closing_session_server(&[], None, &[], None, None);
|
||||
wt.check_events_after_closing_session_server(&[], None, &[], None, &None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -922,7 +922,7 @@ fn wt_client_session_server_close_8() {
|
|||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
||||
let mut unidi_server = wt.create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
let mut unidi_server = WtTest::create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
wt.send_data_server(&mut unidi_server, BUF);
|
||||
wt.close_stream_sending_server(&mut unidi_server);
|
||||
|
||||
|
|
@ -935,13 +935,13 @@ fn wt_client_session_server_close_8() {
|
|||
&[],
|
||||
None,
|
||||
false,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
);
|
||||
|
||||
wt.check_events_after_closing_session_server(&[], None, &[], None, None);
|
||||
wt.check_events_after_closing_session_server(&[], None, &[], None, &None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -951,7 +951,7 @@ fn wt_client_session_server_close_9() {
|
|||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
||||
let mut bidi_server = wt.create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
let mut bidi_server = WtTest::create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
wt.send_data_server(&mut bidi_server, BUF);
|
||||
wt.close_stream_sending_server(&mut bidi_server);
|
||||
wt.receive_data_client(bidi_server.stream_id(), true, BUF, true);
|
||||
|
|
@ -967,13 +967,13 @@ fn wt_client_session_server_close_9() {
|
|||
&[],
|
||||
None,
|
||||
false,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
);
|
||||
|
||||
wt.check_events_after_closing_session_server(&[], None, &[], None, None);
|
||||
wt.check_events_after_closing_session_server(&[], None, &[], None, &None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -983,7 +983,7 @@ fn wt_client_session_server_close_10() {
|
|||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
||||
let mut bidi_server = wt.create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
let mut bidi_server = WtTest::create_wt_stream_server(&mut wt_session, StreamType::BiDi);
|
||||
wt.send_data_server(&mut bidi_server, BUF);
|
||||
wt.close_stream_sending_server(&mut bidi_server);
|
||||
wt.stream_stop_sending_server(&mut bidi_server);
|
||||
|
|
@ -996,13 +996,13 @@ fn wt_client_session_server_close_10() {
|
|||
&[bidi_server.stream_id()],
|
||||
Some(Error::HttpNoError.code()),
|
||||
false,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
);
|
||||
|
||||
wt.check_events_after_closing_session_server(&[], None, &[], None, None);
|
||||
wt.check_events_after_closing_session_server(&[], None, &[], None, &None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1014,10 +1014,10 @@ fn wt_client_session_server_close_11() {
|
|||
|
||||
let bidi_client_1 = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::BiDi);
|
||||
wt.send_data_client(bidi_client_1, BUF);
|
||||
let _ = wt.receive_data_server(bidi_client_1, true, BUF, false);
|
||||
std::mem::drop(wt.receive_data_server(bidi_client_1, true, BUF, false));
|
||||
let bidi_client_2 = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::BiDi);
|
||||
wt.send_data_client(bidi_client_2, BUF);
|
||||
let _ = wt.receive_data_server(bidi_client_2, true, BUF, false);
|
||||
std::mem::drop(wt.receive_data_server(bidi_client_2, true, BUF, false));
|
||||
|
||||
wt.cancel_session_server(&mut wt_session);
|
||||
|
||||
|
|
@ -1027,7 +1027,7 @@ fn wt_client_session_server_close_11() {
|
|||
&[bidi_client_1, bidi_client_2],
|
||||
Some(Error::HttpRequestCancelled.code()),
|
||||
false,
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Error(Error::HttpNoError.code()),
|
||||
)),
|
||||
|
|
@ -1038,7 +1038,7 @@ fn wt_client_session_server_close_11() {
|
|||
Some(Error::HttpRequestCancelled.code()),
|
||||
&[bidi_client_1, bidi_client_2],
|
||||
Some(Error::HttpRequestCancelled.code()),
|
||||
None,
|
||||
&None,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1050,7 +1050,7 @@ fn wt_session_close_frame_and_streams_client() {
|
|||
let mut wt = WtTest::new();
|
||||
let mut wt_session = wt.create_wt_session();
|
||||
|
||||
let mut unidi_server = wt.create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
let mut unidi_server = WtTest::create_wt_stream_server(&mut wt_session, StreamType::UniDi);
|
||||
wt.send_data_server(&mut unidi_server, BUF);
|
||||
wt.exchange_packets();
|
||||
|
||||
|
|
@ -1061,7 +1061,7 @@ fn wt_session_close_frame_and_streams_client() {
|
|||
&[],
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
&None,
|
||||
);
|
||||
wt.exchange_packets();
|
||||
|
||||
|
|
@ -1070,7 +1070,7 @@ fn wt_session_close_frame_and_streams_client() {
|
|||
None,
|
||||
&[unidi_server.stream_id()],
|
||||
Some(Error::HttpRequestCancelled.code()),
|
||||
Some((
|
||||
&Some((
|
||||
wt_session.stream_id(),
|
||||
SessionCloseReason::Clean {
|
||||
error: ERROR_NUM,
|
||||
|
|
@ -17,7 +17,7 @@ use crate::{
|
|||
};
|
||||
use neqo_common::{qtrace, Encoder, Header, MessageType, Role};
|
||||
use neqo_qpack::{QPackDecoder, QPackEncoder};
|
||||
use neqo_transport::{Connection, StreamId};
|
||||
use neqo_transport::{Connection, DatagramTracking, StreamId};
|
||||
use std::any::Any;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::BTreeSet;
|
||||
|
|
@ -39,7 +39,7 @@ impl SessionState {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WebTransportSession {
|
||||
pub(crate) struct WebTransportSession {
|
||||
control_stream_recv: Box<dyn RecvStream>,
|
||||
control_stream_send: Box<dyn SendStream>,
|
||||
stream_event_listener: Rc<RefCell<WebTransportSessionListener>>,
|
||||
|
|
@ -209,14 +209,13 @@ impl WebTransportSession {
|
|||
}
|
||||
qtrace!("ExtendedConnect close the session");
|
||||
self.state = SessionState::Done;
|
||||
if let CloseType::ResetApp(_) = close_type {
|
||||
return;
|
||||
if !close_type.locally_initiated() {
|
||||
self.events.session_end(
|
||||
ExtendedConnectType::WebTransport,
|
||||
self.session_id,
|
||||
SessionCloseReason::from(close_type),
|
||||
);
|
||||
}
|
||||
self.events.session_end(
|
||||
ExtendedConnectType::WebTransport,
|
||||
self.session_id,
|
||||
SessionCloseReason::from(close_type),
|
||||
);
|
||||
}
|
||||
|
||||
/// # Panics
|
||||
|
|
@ -241,7 +240,7 @@ impl WebTransportSession {
|
|||
self.session_id,
|
||||
SessionCloseReason::Clean {
|
||||
error: 0,
|
||||
message: "".to_string(),
|
||||
message: String::new(),
|
||||
},
|
||||
);
|
||||
self.state = SessionState::Done;
|
||||
|
|
@ -265,7 +264,7 @@ impl WebTransportSession {
|
|||
self.session_id,
|
||||
SessionCloseReason::Clean {
|
||||
error: 0,
|
||||
message: "".to_string(),
|
||||
message: String::new(),
|
||||
},
|
||||
);
|
||||
SessionState::Done
|
||||
|
|
@ -323,11 +322,11 @@ impl WebTransportSession {
|
|||
matches!(self.state, SessionState::Active)
|
||||
}
|
||||
|
||||
pub fn take_sub_streams(&mut self) -> Option<(BTreeSet<StreamId>, BTreeSet<StreamId>)> {
|
||||
Some((
|
||||
pub fn take_sub_streams(&mut self) -> (BTreeSet<StreamId>, BTreeSet<StreamId>) {
|
||||
(
|
||||
mem::take(&mut self.recv_streams),
|
||||
mem::take(&mut self.send_streams),
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
/// # Errors
|
||||
|
|
@ -358,7 +357,7 @@ impl WebTransportSession {
|
|||
self.session_id,
|
||||
SessionCloseReason::Clean {
|
||||
error: 0,
|
||||
message: "".to_string(),
|
||||
message: String::new(),
|
||||
},
|
||||
);
|
||||
self.state = SessionState::Done;
|
||||
|
|
@ -391,6 +390,33 @@ impl WebTransportSession {
|
|||
fn send_data(&mut self, conn: &mut Connection, buf: &[u8]) -> Res<usize> {
|
||||
self.control_stream_send.send_data(conn, buf)
|
||||
}
|
||||
|
||||
/// # Errors
|
||||
/// Returns an error if the datagram exceeds the remote datagram size limit.
|
||||
pub fn send_datagram(
|
||||
&self,
|
||||
conn: &mut Connection,
|
||||
buf: &[u8],
|
||||
id: impl Into<DatagramTracking>,
|
||||
) -> Res<()> {
|
||||
qtrace!([self], "send_datagram state={:?}", self.state);
|
||||
if let SessionState::Active = self.state {
|
||||
let mut dgram_data = Encoder::default();
|
||||
dgram_data.encode_varint(self.session_id.as_u64() / 4);
|
||||
dgram_data.encode(buf);
|
||||
conn.send_datagram(dgram_data.as_ref(), id)?;
|
||||
} else {
|
||||
debug_assert!(false);
|
||||
return Err(Error::Unavailable);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn datagram(&mut self, datagram: Vec<u8>) {
|
||||
if let SessionState::Active = self.state {
|
||||
self.events.new_datagram(self.session_id, datagram);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Stream for Rc<RefCell<WebTransportSession>> {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ pub const WEBTRANSPORT_UNI_STREAM: u64 = 0x54;
|
|||
pub const WEBTRANSPORT_STREAM: u64 = 0x41;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WebTransportRecvStream {
|
||||
pub(crate) struct WebTransportRecvStream {
|
||||
stream_id: StreamId,
|
||||
events: Box<dyn RecvStreamEvents>,
|
||||
session: Rc<RefCell<WebTransportSession>>,
|
||||
|
|
@ -85,7 +85,7 @@ enum WebTransportSenderStreamState {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WebTransportSendStream {
|
||||
pub(crate) struct WebTransportSendStream {
|
||||
stream_id: StreamId,
|
||||
state: WebTransportSenderStreamState,
|
||||
events: Box<dyn SendStreamEvents>,
|
||||
|
|
|
|||
17
third_party/rust/neqo-http3/src/frames/mod.rs
vendored
17
third_party/rust/neqo-http3/src/frames/mod.rs
vendored
|
|
@ -4,13 +4,18 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
pub mod hframe;
|
||||
pub mod reader;
|
||||
pub mod wtframe;
|
||||
pub(crate) mod hframe;
|
||||
pub(crate) mod reader;
|
||||
pub(crate) mod wtframe;
|
||||
|
||||
pub use hframe::{HFrame, H3_FRAME_TYPE_HEADERS, H3_FRAME_TYPE_SETTINGS, H3_RESERVED_FRAME_TYPES};
|
||||
pub use reader::{FrameReader, StreamReaderConnectionWrapper, StreamReaderRecvStreamWrapper};
|
||||
pub use wtframe::WebTransportFrame;
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use hframe::{
|
||||
HFrame, H3_FRAME_TYPE_HEADERS, H3_FRAME_TYPE_SETTINGS, H3_RESERVED_FRAME_TYPES,
|
||||
};
|
||||
pub(crate) use reader::{
|
||||
FrameReader, StreamReaderConnectionWrapper, StreamReaderRecvStreamWrapper,
|
||||
};
|
||||
pub(crate) use wtframe::WebTransportFrame;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
|
|
|||
10
third_party/rust/neqo-http3/src/frames/reader.rs
vendored
10
third_party/rust/neqo-http3/src/frames/reader.rs
vendored
|
|
@ -17,7 +17,7 @@ use std::fmt::Debug;
|
|||
|
||||
const MAX_READ_SIZE: usize = 4096;
|
||||
|
||||
pub trait FrameDecoder<T> {
|
||||
pub(crate) trait FrameDecoder<T> {
|
||||
fn is_known_type(frame_type: u64) -> bool;
|
||||
/// # Errors
|
||||
/// Returns `HttpFrameUnexpected` if frames is not alowed, i.e. is a `H3_RESERVED_FRAME_TYPES`.
|
||||
|
|
@ -29,7 +29,7 @@ pub trait FrameDecoder<T> {
|
|||
fn decode(frame_type: u64, frame_len: u64, data: Option<&[u8]>) -> Res<Option<T>>;
|
||||
}
|
||||
|
||||
pub trait StreamReader {
|
||||
pub(crate) trait StreamReader {
|
||||
/// # Errors
|
||||
/// An error may happen while reading a stream, e.g. early close, protocol error, etc.
|
||||
/// Return an error if the stream was closed on the transport layer, but that information is not yet
|
||||
|
|
@ -37,7 +37,7 @@ pub trait StreamReader {
|
|||
fn read_data(&mut self, buf: &mut [u8]) -> Res<(usize, bool)>;
|
||||
}
|
||||
|
||||
pub struct StreamReaderConnectionWrapper<'a> {
|
||||
pub(crate) struct StreamReaderConnectionWrapper<'a> {
|
||||
conn: &'a mut Connection,
|
||||
stream_id: StreamId,
|
||||
}
|
||||
|
|
@ -57,7 +57,7 @@ impl<'a> StreamReader for StreamReaderConnectionWrapper<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct StreamReaderRecvStreamWrapper<'a> {
|
||||
pub(crate) struct StreamReaderRecvStreamWrapper<'a> {
|
||||
recv_stream: &'a mut Box<dyn RecvStream>,
|
||||
conn: &'a mut Connection,
|
||||
}
|
||||
|
|
@ -86,7 +86,7 @@ enum FrameReaderState {
|
|||
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
#[derive(Debug)]
|
||||
pub struct FrameReader {
|
||||
pub(crate) struct FrameReader {
|
||||
state: FrameReaderState,
|
||||
frame_type: u64,
|
||||
frame_len: u64,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use std::mem;
|
|||
use test_fixture::{default_client, default_server, now};
|
||||
|
||||
#[allow(clippy::many_single_char_names)]
|
||||
pub fn enc_dec<T: FrameDecoder<T>>(d: &Encoder, st: &str, remaining: usize) -> T {
|
||||
pub(crate) fn enc_dec<T: FrameDecoder<T>>(d: &Encoder, st: &str, remaining: usize) -> T {
|
||||
// For data, headers and push_promise we do not read all bytes from the buffer
|
||||
let d2 = Encoder::from_hex(st);
|
||||
assert_eq!(d.as_ref(), &d2.as_ref()[..d.as_ref().len()]);
|
||||
|
|
|
|||
176
third_party/rust/neqo-http3/src/lib.rs
vendored
176
third_party/rust/neqo-http3/src/lib.rs
vendored
|
|
@ -7,16 +7,144 @@
|
|||
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
|
||||
#![warn(clippy::pedantic)]
|
||||
|
||||
/*!
|
||||
|
||||
# The HTTP/3 protocol
|
||||
|
||||
This crate implements [RFC9114](https://datatracker.ietf.org/doc/html/rfc9114).
|
||||
|
||||
The implementation depends on:
|
||||
- [neqo-transport](../neqo_transport/index.html) --- implements the QUIC protocol
|
||||
([RFC9000](https://www.rfc-editor.org/info/rfc9000)) and
|
||||
- [neqo-qpack](../neqo_qpack/index.html) --- implements QPACK
|
||||
([RFC9204](https://www.rfc-editor.org/info/rfc9204));
|
||||
|
||||
## Features
|
||||
|
||||
Both client and server-side HTTP/3 protocols are implemented, although the server-side
|
||||
implementation is not meant to be used in production and its only purpose is to facilitate testing
|
||||
of the client-side code.
|
||||
|
||||
__`WebTransport`__
|
||||
([draft version 2](https://datatracker.ietf.org/doc/html/draft-vvv-webtransport-http3-02)) is
|
||||
supported and can be enabled using [`Http3Parameters`](struct.Http3Parameters.html).
|
||||
|
||||
## Interaction with an application
|
||||
|
||||
### Driving HTTP/3 session
|
||||
|
||||
The crate does not create an OS level UDP socket, it produces, i.e. encodes, data that should be
|
||||
sent as a payload in a UDP packet and consumes data received on the UDP socket. For example,
|
||||
[`std::net::UdpSocket`](std::net::UdpSocket) or [`mio::net::UdpSocket`](https://crates.io/crates/mio)
|
||||
could be used for creating UDP sockets.
|
||||
|
||||
The application is responsible for creating a socket, polling the socket, and sending and receiving
|
||||
data from the socket.
|
||||
|
||||
In addition to receiving data HTTP/3 session’s actions may be triggered when a certain amount of
|
||||
time passes, e.g. after a certain amount of time data may be considered lost and should be
|
||||
retransmitted, packet pacing requires a timer, etc. The implementation does not use timers, but
|
||||
instead informs the application when processing needs to be triggered.
|
||||
|
||||
|
||||
The core functions for driving HTTP/3 sessions are:
|
||||
- __On the client-side__ :
|
||||
- [`process_output`](struct.Http3Client.html#method.process_output) used for producing UDP
|
||||
payload. If a payload is not produced this function returns a callback time, e.g. the time when
|
||||
[`process_output`](struct.Http3Client.html#method.process_output) should be called again.
|
||||
- [`process_input`](struct.Http3Client.html#method.process_input) used consuming UDP payload.
|
||||
- [`process`](struct.Http3Client.html#method.process) combines the 2 functions into one, i.e. it
|
||||
consumes UDP payload if available and produces some UDP payload to be sent or returns a
|
||||
callback time.
|
||||
- __On the server-side__ only [`process`](struct.Http3Server.html#method.process) is
|
||||
available.
|
||||
|
||||
An example interaction with a socket:
|
||||
|
||||
```ignore
|
||||
let socket = match UdpSocket::bind(local_addr) {
|
||||
Err(e) => {
|
||||
eprintln!("Unable to bind UDP socket: {}", e);
|
||||
}
|
||||
Ok(s) => s,
|
||||
};
|
||||
let mut client = Http3Client::new(...);
|
||||
|
||||
...
|
||||
|
||||
// process_output can return 3 values, data to be sent, time duration when process_output should
|
||||
// be called, and None when Http3Client is done.
|
||||
match client.process_output(Instant::now()) {
|
||||
Output::Datagram(dgram) => {
|
||||
// Send dgram on a socket.
|
||||
socket.send_to(&dgram[..], dgram.destination())
|
||||
|
||||
}
|
||||
Output::Callback(duration) => {
|
||||
// the client is idle for “duration”, set read timeout on the socket to this value and
|
||||
// poll the socket for reading in the meantime.
|
||||
socket.set_read_timeout(Some(duration)).unwrap();
|
||||
}
|
||||
Output::None => {
|
||||
// client is done.
|
||||
}
|
||||
};
|
||||
|
||||
...
|
||||
|
||||
// Reading new data coming for the network.
|
||||
match socket.recv_from(&mut buf[..]) {
|
||||
Ok((sz, remote)) => {
|
||||
let d = Datagram::new(remote, *local_addr, &buf[..sz]);
|
||||
client.process_input(d, Instant::now());
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("UDP error: {}", err);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### HTTP/3 session events
|
||||
|
||||
[`Http3Client`](struct.Http3Client.html) and [`Http3Server`](struct.Http3Server.html) produce
|
||||
events that can be obtain by calling
|
||||
[`next_event`](neqo_common/event/trait.Provider.html#tymethod.next_event). The events are of type
|
||||
[`Http3ClientEvent`](enum.Http3ClientEvent.html) and
|
||||
[`Http3ServerEvent`](enum.Http3ServerEvent.html) respectively. They are informing the application
|
||||
when the connection changes state, when new data is received on a stream, etc.
|
||||
|
||||
```ignore
|
||||
...
|
||||
|
||||
while let Some(event) = client.next_event() {
|
||||
match event {
|
||||
Http3ClientEvent::DataReadable { stream_id } => {
|
||||
println!("New data available on stream {}", stream_id);
|
||||
}
|
||||
Http3ClientEvent::StateChange(Http3State::Connected) => {
|
||||
println!("Http3 session is in state Connected now");
|
||||
}
|
||||
_ => {
|
||||
println!("Unhandled event {:?}", event);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
mod buffered_send_stream;
|
||||
mod client_events;
|
||||
mod conn_params;
|
||||
mod connection;
|
||||
pub mod connection_client;
|
||||
mod connection_client;
|
||||
mod connection_server;
|
||||
mod control_stream_local;
|
||||
mod control_stream_remote;
|
||||
pub mod features;
|
||||
pub mod frames;
|
||||
mod frames;
|
||||
mod headers_checks;
|
||||
mod priority;
|
||||
mod push_controller;
|
||||
|
|
@ -24,12 +152,12 @@ mod qlog;
|
|||
mod qpack_decoder_receiver;
|
||||
mod qpack_encoder_receiver;
|
||||
mod recv_message;
|
||||
pub mod request_target;
|
||||
mod request_target;
|
||||
mod send_message;
|
||||
pub mod server;
|
||||
mod server;
|
||||
mod server_connection_events;
|
||||
mod server_events;
|
||||
pub mod settings;
|
||||
mod settings;
|
||||
mod stream_type_reader;
|
||||
|
||||
use neqo_qpack::Error as QpackError;
|
||||
|
|
@ -38,24 +166,24 @@ pub use neqo_transport::{Output, StreamId};
|
|||
use std::fmt::Debug;
|
||||
|
||||
use crate::priority::PriorityHandler;
|
||||
pub use buffered_send_stream::BufferedStream;
|
||||
use buffered_send_stream::BufferedStream;
|
||||
pub use client_events::{Http3ClientEvent, WebTransportEvent};
|
||||
pub use conn_params::Http3Parameters;
|
||||
pub use connection::Http3State;
|
||||
pub use connection::{Http3State, WebTransportSessionAcceptAction};
|
||||
pub use connection_client::Http3Client;
|
||||
use features::extended_connect::WebTransportSession;
|
||||
pub use frames::HFrame;
|
||||
pub use neqo_common::{Header, MessageType};
|
||||
use frames::HFrame;
|
||||
pub use neqo_common::Header;
|
||||
use neqo_common::MessageType;
|
||||
pub use priority::Priority;
|
||||
pub use server::Http3Server;
|
||||
pub use server_events::{
|
||||
Http3OrWebTransportStream, Http3ServerEvent, WebTransportRequest, WebTransportServerEvent,
|
||||
};
|
||||
pub use settings::HttpZeroRttChecker;
|
||||
use std::any::Any;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
pub use stream_type_reader::NewStreamType;
|
||||
use stream_type_reader::NewStreamType;
|
||||
|
||||
type Res<T> = Result<T, Error>;
|
||||
|
||||
|
|
@ -299,9 +427,8 @@ pub enum Http3StreamType {
|
|||
|
||||
#[must_use]
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
pub enum ReceiveOutput {
|
||||
enum ReceiveOutput {
|
||||
NoOutput,
|
||||
PushStream,
|
||||
ControlFrames(Vec<HFrame>),
|
||||
UnblockedStreams(Vec<StreamId>),
|
||||
NewStream(NewStreamType),
|
||||
|
|
@ -313,11 +440,11 @@ impl Default for ReceiveOutput {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait Stream: Debug {
|
||||
trait Stream: Debug {
|
||||
fn stream_type(&self) -> Http3StreamType;
|
||||
}
|
||||
|
||||
pub trait RecvStream: Stream {
|
||||
trait RecvStream: Stream {
|
||||
/// The stream reads data from the corresponding quic stream and returns `ReceiveOutput`.
|
||||
/// The function also returns true as the second parameter if the stream is done and
|
||||
/// could be forgotten, i.e. removed from all records.
|
||||
|
|
@ -345,7 +472,7 @@ pub trait RecvStream: Stream {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait HttpRecvStream: RecvStream {
|
||||
trait HttpRecvStream: RecvStream {
|
||||
/// This function is similar to the receive function and has the same output, i.e.
|
||||
/// a `ReceiveOutput` enum and bool. The bool is true if the stream is completely done
|
||||
/// and can be forgotten, i.e. removed from all records.
|
||||
|
|
@ -400,12 +527,12 @@ impl Http3StreamInfo {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait RecvStreamEvents: Debug {
|
||||
trait RecvStreamEvents: Debug {
|
||||
fn data_readable(&self, _stream_info: Http3StreamInfo) {}
|
||||
fn recv_closed(&self, _stream_info: Http3StreamInfo, _close_type: CloseType) {}
|
||||
}
|
||||
|
||||
pub trait HttpRecvStreamEvents: RecvStreamEvents {
|
||||
trait HttpRecvStreamEvents: RecvStreamEvents {
|
||||
fn header_ready(
|
||||
&self,
|
||||
stream_info: Http3StreamInfo,
|
||||
|
|
@ -416,7 +543,7 @@ pub trait HttpRecvStreamEvents: RecvStreamEvents {
|
|||
fn extended_connect_new_session(&self, _stream_id: StreamId, _headers: Vec<Header>) {}
|
||||
}
|
||||
|
||||
pub trait SendStream: Stream {
|
||||
trait SendStream: Stream {
|
||||
/// # Errors
|
||||
/// Error my occure during sending data, e.g. protocol error, etc.
|
||||
fn send(&mut self, conn: &mut Connection) -> Res<()>;
|
||||
|
|
@ -454,7 +581,7 @@ pub trait SendStream: Stream {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait HttpSendStream: SendStream {
|
||||
trait HttpSendStream: SendStream {
|
||||
/// This function is used to supply headers to a http message. The
|
||||
/// function is used for request headers, response headers, 1xx response and
|
||||
/// trailers.
|
||||
|
|
@ -465,7 +592,7 @@ pub trait HttpSendStream: SendStream {
|
|||
fn any(&self) -> &dyn Any;
|
||||
}
|
||||
|
||||
pub trait SendStreamEvents: Debug {
|
||||
trait SendStreamEvents: Debug {
|
||||
fn send_closed(&self, _stream_info: Http3StreamInfo, _close_type: CloseType) {}
|
||||
fn data_writable(&self, _stream_info: Http3StreamInfo) {}
|
||||
}
|
||||
|
|
@ -477,7 +604,7 @@ pub trait SendStreamEvents: Debug {
|
|||
/// that do not close the complete connection, e.g. unallowed headers.
|
||||
/// `Done` - the stream was closed without an error.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum CloseType {
|
||||
enum CloseType {
|
||||
ResetApp(AppError),
|
||||
ResetRemote(AppError),
|
||||
LocalError(AppError),
|
||||
|
|
@ -494,4 +621,9 @@ impl CloseType {
|
|||
Self::Done => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn locally_initiated(&self) -> bool {
|
||||
matches!(self, CloseType::ResetApp(_))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use std::cell::RefCell;
|
|||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DecoderRecvStream {
|
||||
pub(crate) struct DecoderRecvStream {
|
||||
stream_id: StreamId,
|
||||
decoder: Rc<RefCell<QPackDecoder>>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use std::cell::RefCell;
|
|||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct EncoderRecvStream {
|
||||
pub(crate) struct EncoderRecvStream {
|
||||
stream_id: StreamId,
|
||||
encoder: Rc<RefCell<QPackEncoder>>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ use std::fmt::Debug;
|
|||
use std::rc::Rc;
|
||||
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
pub struct RecvMessageInfo {
|
||||
pub(crate) struct RecvMessageInfo {
|
||||
pub message_type: MessageType,
|
||||
pub stream_type: Http3StreamType,
|
||||
pub stream_id: StreamId,
|
||||
|
|
|
|||
7
third_party/rust/neqo-http3/src/server.rs
vendored
7
third_party/rust/neqo-http3/src/server.rs
vendored
|
|
@ -229,6 +229,13 @@ impl Http3Server {
|
|||
handler.clone(),
|
||||
stream_info,
|
||||
)),
|
||||
Http3ServerConnEvent::ExtendedConnectDatagram {
|
||||
session_id,
|
||||
datagram,
|
||||
} => self.events.webtransport_datagram(
|
||||
WebTransportRequest::new(conn.clone(), handler.clone(), session_id),
|
||||
datagram,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,10 @@ pub(crate) enum Http3ServerConnEvent {
|
|||
reason: SessionCloseReason,
|
||||
},
|
||||
ExtendedConnectNewStream(Http3StreamInfo),
|
||||
ExtendedConnectDatagram {
|
||||
session_id: StreamId,
|
||||
datagram: Vec<u8>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
|
|
@ -140,6 +144,13 @@ impl ExtendedConnectEvents for Http3ServerConnEvents {
|
|||
fn extended_connect_new_stream(&self, stream_info: Http3StreamInfo) {
|
||||
self.insert(Http3ServerConnEvent::ExtendedConnectNewStream(stream_info));
|
||||
}
|
||||
|
||||
fn new_datagram(&self, session_id: StreamId, datagram: Vec<u8>) {
|
||||
self.insert(Http3ServerConnEvent::ExtendedConnectDatagram {
|
||||
session_id,
|
||||
datagram,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl Http3ServerConnEvents {
|
||||
|
|
|
|||
58
third_party/rust/neqo-http3/src/server_events.rs
vendored
58
third_party/rust/neqo-http3/src/server_events.rs
vendored
|
|
@ -6,17 +6,18 @@
|
|||
|
||||
#![allow(clippy::module_name_repetitions)]
|
||||
|
||||
use crate::connection::Http3State;
|
||||
use crate::connection::{Http3State, WebTransportSessionAcceptAction};
|
||||
use crate::connection_server::Http3ServerHandler;
|
||||
use crate::{
|
||||
features::extended_connect::SessionCloseReason, Http3StreamInfo, Http3StreamType, Priority, Res,
|
||||
};
|
||||
use neqo_common::{qdebug, qinfo, Header};
|
||||
use neqo_common::{qdebug, qinfo, Encoder, Header};
|
||||
use neqo_transport::server::ActiveConnectionRef;
|
||||
use neqo_transport::{AppError, Connection, StreamId, StreamType};
|
||||
use neqo_transport::{AppError, Connection, DatagramTracking, StreamId, StreamType};
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::VecDeque;
|
||||
use std::convert::TryFrom;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::rc::Rc;
|
||||
|
||||
|
|
@ -244,7 +245,7 @@ impl WebTransportRequest {
|
|||
/// Respond to a `WebTransport` session request.
|
||||
/// # Errors
|
||||
/// It may return `InvalidStreamId` if a stream does not exist anymore.
|
||||
pub fn response(&mut self, accept: bool) -> Res<()> {
|
||||
pub fn response(&mut self, accept: &WebTransportSessionAcceptAction) -> Res<()> {
|
||||
qinfo!([self], "Set a response for a WebTransport session.");
|
||||
self.stream_handler
|
||||
.handler
|
||||
|
|
@ -298,6 +299,45 @@ impl WebTransportRequest {
|
|||
Http3StreamInfo::new(id, Http3StreamType::WebTransport(session_id)),
|
||||
))
|
||||
}
|
||||
|
||||
/// Send `WebTransport` datagram.
|
||||
/// # Errors
|
||||
/// It may return `InvalidStreamId` if a stream does not exist anymore.
|
||||
/// The function returns `TooMuchData` if the supply buffer is bigger than
|
||||
/// the allowed remote datagram size.
|
||||
pub fn send_datagram(&mut self, buf: &[u8], id: impl Into<DatagramTracking>) -> Res<()> {
|
||||
let session_id = self.stream_handler.stream_id();
|
||||
self.stream_handler
|
||||
.handler
|
||||
.borrow_mut()
|
||||
.webtransport_send_datagram(
|
||||
&mut self.stream_handler.conn.borrow_mut(),
|
||||
session_id,
|
||||
buf,
|
||||
id,
|
||||
)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn remote_datagram_size(&self) -> u64 {
|
||||
self.stream_handler.conn.borrow().remote_datagram_size()
|
||||
}
|
||||
|
||||
/// Returns the current max size of a datagram that can fit into a packet.
|
||||
/// The value will change over time depending on the encoded size of the
|
||||
/// packet number, ack frames, etc.
|
||||
/// # Errors
|
||||
/// The function returns `NotAvailable` if datagrams are not enabled.
|
||||
/// # Panics
|
||||
/// This cannot panic. The max varint length is 8.
|
||||
pub fn max_datagram_size(&self) -> Res<u64> {
|
||||
let max_size = self.stream_handler.conn.borrow().max_datagram_size()?;
|
||||
Ok(max_size
|
||||
- u64::try_from(Encoder::varint_len(
|
||||
self.stream_handler.stream_id().as_u64(),
|
||||
))
|
||||
.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for WebTransportRequest {
|
||||
|
|
@ -340,6 +380,10 @@ pub enum WebTransportServerEvent {
|
|||
reason: SessionCloseReason,
|
||||
},
|
||||
NewStream(Http3OrWebTransportStream),
|
||||
Datagram {
|
||||
session: WebTransportRequest,
|
||||
datagram: Vec<u8>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
@ -508,4 +552,10 @@ impl Http3ServerEvents {
|
|||
WebTransportServerEvent::NewStream(stream),
|
||||
));
|
||||
}
|
||||
|
||||
pub(crate) fn webtransport_datagram(&self, session: WebTransportRequest, datagram: Vec<u8>) {
|
||||
self.insert(Http3ServerEvent::WebTransport(
|
||||
WebTransportServerEvent::Datagram { session, datagram },
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@ use neqo_qpack::decoder::QPACK_UNI_STREAM_TYPE_DECODER;
|
|||
use neqo_qpack::encoder::QPACK_UNI_STREAM_TYPE_ENCODER;
|
||||
use neqo_transport::{Connection, StreamId, StreamType};
|
||||
|
||||
pub const HTTP3_UNI_STREAM_TYPE_PUSH: u64 = 0x1;
|
||||
pub const WEBTRANSPORT_UNI_STREAM: u64 = 0x54;
|
||||
pub const WEBTRANSPORT_STREAM: u64 = 0x41;
|
||||
pub(crate) const HTTP3_UNI_STREAM_TYPE_PUSH: u64 = 0x1;
|
||||
pub(crate) const WEBTRANSPORT_UNI_STREAM: u64 = 0x54;
|
||||
pub(crate) const WEBTRANSPORT_STREAM: u64 = 0x41;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum NewStreamType {
|
||||
pub(crate) enum NewStreamType {
|
||||
Control,
|
||||
Decoder,
|
||||
Encoder,
|
||||
|
|
@ -74,7 +74,7 @@ impl NewStreamType {
|
|||
/// the `ReadType` state, `NewStreamHeadReader` changes to `ReadId` state and from there
|
||||
/// to `Done` state
|
||||
#[derive(Debug)]
|
||||
pub enum NewStreamHeadReader {
|
||||
pub(crate) enum NewStreamHeadReader {
|
||||
ReadType {
|
||||
role: Role,
|
||||
reader: IncrementalDecoderUint,
|
||||
|
|
|
|||
89
third_party/rust/neqo-http3/tests/httpconn.rs
vendored
89
third_party/rust/neqo-http3/tests/httpconn.rs
vendored
|
|
@ -6,14 +6,15 @@
|
|||
|
||||
#![allow(unused_assignments)]
|
||||
|
||||
use neqo_common::{event::Provider, Datagram};
|
||||
use neqo_common::{event::Provider, qtrace, Datagram};
|
||||
use neqo_crypto::{AuthenticationStatus, ResumptionToken};
|
||||
use neqo_http3::{
|
||||
Header, Http3Client, Http3ClientEvent, Http3OrWebTransportStream, Http3Parameters, Http3Server,
|
||||
Http3ServerEvent, Http3State, Priority,
|
||||
};
|
||||
use neqo_transport::{ConnectionParameters, StreamType};
|
||||
use neqo_transport::{ConnectionError, ConnectionParameters, Error, Output, StreamType};
|
||||
use std::mem;
|
||||
use std::time::{Duration, Instant};
|
||||
use test_fixture::*;
|
||||
|
||||
const RESPONSE_DATA: &[u8] = &[0x61, 0x62, 0x63];
|
||||
|
|
@ -111,6 +112,39 @@ fn connect_peers(hconn_c: &mut Http3Client, hconn_s: &mut Http3Server) -> Option
|
|||
out.dgram()
|
||||
}
|
||||
|
||||
fn connect_peers_with_network_propagation_delay(
|
||||
hconn_c: &mut Http3Client,
|
||||
hconn_s: &mut Http3Server,
|
||||
net_delay: u64,
|
||||
) -> (Option<Datagram>, Instant) {
|
||||
let net_delay = Duration::from_millis(net_delay);
|
||||
assert_eq!(hconn_c.state(), Http3State::Initializing);
|
||||
let mut now = now();
|
||||
let out = hconn_c.process(None, now); // Initial
|
||||
now += net_delay;
|
||||
let out = hconn_s.process(out.dgram(), now); // Initial + Handshake
|
||||
now += net_delay;
|
||||
let out = hconn_c.process(out.dgram(), now); // ACK
|
||||
now += net_delay;
|
||||
let out = hconn_s.process(out.dgram(), now); //consume ACK
|
||||
assert!(out.dgram().is_none());
|
||||
let authentication_needed = |e| matches!(e, Http3ClientEvent::AuthenticationNeeded);
|
||||
assert!(hconn_c.events().any(authentication_needed));
|
||||
now += net_delay;
|
||||
hconn_c.authenticated(AuthenticationStatus::Ok, now);
|
||||
let out = hconn_c.process(None, now); // Handshake
|
||||
assert_eq!(hconn_c.state(), Http3State::Connected);
|
||||
now += net_delay;
|
||||
let out = hconn_s.process(out.dgram(), now); // HANDSHAKE_DONE
|
||||
now += net_delay;
|
||||
let out = hconn_c.process(out.dgram(), now); // Consume HANDSHAKE_DONE, send control streams.
|
||||
now += net_delay;
|
||||
let out = hconn_s.process(out.dgram(), now); // consume and send control streams.
|
||||
now += net_delay;
|
||||
let out = hconn_c.process(out.dgram(), now); // consume control streams.
|
||||
(out.dgram(), now)
|
||||
}
|
||||
|
||||
fn connect() -> (Http3Client, Http3Server, Option<Datagram>) {
|
||||
let mut hconn_c = default_http3_client();
|
||||
let mut hconn_s = default_http3_server();
|
||||
|
|
@ -139,7 +173,7 @@ fn test_connect() {
|
|||
fn test_fetch() {
|
||||
let (mut hconn_c, mut hconn_s, dgram) = connect();
|
||||
|
||||
eprintln!("-----client");
|
||||
qtrace!("-----client");
|
||||
let req = hconn_c
|
||||
.fetch(
|
||||
now(),
|
||||
|
|
@ -152,13 +186,13 @@ fn test_fetch() {
|
|||
assert_eq!(req, 0);
|
||||
hconn_c.stream_close_send(req).unwrap();
|
||||
let out = hconn_c.process(dgram, now());
|
||||
eprintln!("-----server");
|
||||
qtrace!("-----server");
|
||||
let out = hconn_s.process(out.dgram(), now());
|
||||
mem::drop(hconn_c.process(out.dgram(), now()));
|
||||
process_server_events(&mut hconn_s);
|
||||
let out = hconn_s.process(None, now());
|
||||
|
||||
eprintln!("-----client");
|
||||
qtrace!("-----client");
|
||||
mem::drop(hconn_c.process(out.dgram(), now()));
|
||||
let out = hconn_s.process(None, now());
|
||||
mem::drop(hconn_c.process(out.dgram(), now()));
|
||||
|
|
@ -379,3 +413,48 @@ fn zerortt() {
|
|||
exchange_packets(&mut hconn_c, &mut hconn_s, out.dgram());
|
||||
process_client_events(&mut hconn_c);
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// When a client has an outstanding fetch, it will send keepalives.
|
||||
/// Test that it will successfully run until the connection times out.
|
||||
fn fetch_noresponse_will_idletimeout() {
|
||||
let mut hconn_c = default_http3_client();
|
||||
let mut hconn_s = default_http3_server();
|
||||
|
||||
let (dgram, mut now) =
|
||||
connect_peers_with_network_propagation_delay(&mut hconn_c, &mut hconn_s, 10);
|
||||
|
||||
qtrace!("-----client");
|
||||
let req = hconn_c
|
||||
.fetch(
|
||||
now,
|
||||
"GET",
|
||||
&("https", "something.com", "/"),
|
||||
&[],
|
||||
Priority::default(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(req, 0);
|
||||
hconn_c.stream_close_send(req).unwrap();
|
||||
let _out = hconn_c.process(dgram, now);
|
||||
qtrace!("-----server");
|
||||
|
||||
let mut done = false;
|
||||
while !done {
|
||||
while let Some(event) = hconn_c.next_event() {
|
||||
if let Http3ClientEvent::StateChange(state) = event {
|
||||
match state {
|
||||
Http3State::Closing(error_code) | Http3State::Closed(error_code) => {
|
||||
assert_eq!(error_code, ConnectionError::Transport(Error::IdleTimeout));
|
||||
done = true;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Output::Callback(t) = hconn_c.process_output(now) {
|
||||
now += t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
315
third_party/rust/neqo-http3/tests/webtransport.rs
vendored
Normal file
315
third_party/rust/neqo-http3/tests/webtransport.rs
vendored
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use neqo_common::event::Provider;
|
||||
use neqo_crypto::AuthenticationStatus;
|
||||
use neqo_http3::{
|
||||
Http3Client, Http3ClientEvent, Http3OrWebTransportStream, Http3Parameters, Http3Server,
|
||||
Http3ServerEvent, Http3State, WebTransportEvent, WebTransportRequest, WebTransportServerEvent,
|
||||
WebTransportSessionAcceptAction,
|
||||
};
|
||||
use neqo_transport::{StreamId, StreamType};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use test_fixture::{
|
||||
addr, anti_replay, fixture_init, now, CountingConnectionIdGenerator, DEFAULT_ALPN_H3,
|
||||
DEFAULT_KEYS, DEFAULT_SERVER_NAME,
|
||||
};
|
||||
|
||||
fn connect() -> (Http3Client, Http3Server) {
|
||||
fixture_init();
|
||||
let mut client = Http3Client::new(
|
||||
DEFAULT_SERVER_NAME,
|
||||
Rc::new(RefCell::new(CountingConnectionIdGenerator::default())),
|
||||
addr(),
|
||||
addr(),
|
||||
Http3Parameters::default().webtransport(true),
|
||||
now(),
|
||||
)
|
||||
.expect("create a default client");
|
||||
let mut server = Http3Server::new(
|
||||
now(),
|
||||
DEFAULT_KEYS,
|
||||
DEFAULT_ALPN_H3,
|
||||
anti_replay(),
|
||||
Rc::new(RefCell::new(CountingConnectionIdGenerator::default())),
|
||||
Http3Parameters::default().webtransport(true),
|
||||
None,
|
||||
)
|
||||
.expect("create a server");
|
||||
assert_eq!(client.state(), Http3State::Initializing);
|
||||
let out = client.process(None, now());
|
||||
assert_eq!(client.state(), Http3State::Initializing);
|
||||
|
||||
let out = server.process(out.dgram(), now());
|
||||
let out = client.process(out.dgram(), now());
|
||||
let out = server.process(out.dgram(), now());
|
||||
assert!(out.as_dgram_ref().is_none());
|
||||
|
||||
let authentication_needed = |e| matches!(e, Http3ClientEvent::AuthenticationNeeded);
|
||||
assert!(client.events().any(authentication_needed));
|
||||
client.authenticated(AuthenticationStatus::Ok, now());
|
||||
|
||||
let mut out = client.process(out.dgram(), now()).dgram();
|
||||
let connected = |e| matches!(e, Http3ClientEvent::StateChange(Http3State::Connected));
|
||||
assert!(client.events().any(connected));
|
||||
|
||||
assert_eq!(client.state(), Http3State::Connected);
|
||||
|
||||
// Exchange H3 setttings
|
||||
loop {
|
||||
out = server.process(out, now()).dgram();
|
||||
let dgram_present = out.is_some();
|
||||
out = client.process(out, now()).dgram();
|
||||
if out.is_none() && !dgram_present {
|
||||
break;
|
||||
}
|
||||
}
|
||||
(client, server)
|
||||
}
|
||||
|
||||
fn exchange_packets(client: &mut Http3Client, server: &mut Http3Server) {
|
||||
let mut out = None;
|
||||
loop {
|
||||
out = client.process(out, now()).dgram();
|
||||
out = server.process(out, now()).dgram();
|
||||
if out.is_none() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_wt_session(client: &mut Http3Client, server: &mut Http3Server) -> WebTransportRequest {
|
||||
let wt_session_id = client
|
||||
.webtransport_create_session(now(), &("https", "something.com", "/"), &[])
|
||||
.unwrap();
|
||||
exchange_packets(client, server);
|
||||
|
||||
let mut wt_server_session = None;
|
||||
while let Some(event) = server.next_event() {
|
||||
match event {
|
||||
Http3ServerEvent::WebTransport(WebTransportServerEvent::NewSession {
|
||||
mut session,
|
||||
headers,
|
||||
}) => {
|
||||
assert!(
|
||||
headers
|
||||
.iter()
|
||||
.any(|h| h.name() == ":method" && h.value() == "CONNECT")
|
||||
&& headers
|
||||
.iter()
|
||||
.any(|h| h.name() == ":protocol" && h.value() == "webtransport")
|
||||
);
|
||||
session
|
||||
.response(&WebTransportSessionAcceptAction::Accept)
|
||||
.unwrap();
|
||||
wt_server_session = Some(session);
|
||||
}
|
||||
Http3ServerEvent::Data { .. } => {
|
||||
panic!("There should not be any data events!");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
exchange_packets(client, server);
|
||||
|
||||
let wt_session_negotiated_event = |e| {
|
||||
matches!(
|
||||
e,
|
||||
Http3ClientEvent::WebTransport(WebTransportEvent::Session{
|
||||
stream_id,
|
||||
status
|
||||
}) if stream_id == wt_session_id && status == 200
|
||||
)
|
||||
};
|
||||
assert!(client.events().any(wt_session_negotiated_event));
|
||||
|
||||
let wt_server_session = wt_server_session.unwrap();
|
||||
assert_eq!(wt_session_id, wt_server_session.stream_id());
|
||||
wt_server_session
|
||||
}
|
||||
|
||||
fn send_data_client(
|
||||
client: &mut Http3Client,
|
||||
server: &mut Http3Server,
|
||||
wt_stream_id: StreamId,
|
||||
data: &[u8],
|
||||
) {
|
||||
assert_eq!(client.send_data(wt_stream_id, data).unwrap(), data.len());
|
||||
exchange_packets(client, server);
|
||||
}
|
||||
|
||||
fn send_data_server(
|
||||
client: &mut Http3Client,
|
||||
server: &mut Http3Server,
|
||||
wt_stream: &mut Http3OrWebTransportStream,
|
||||
data: &[u8],
|
||||
) {
|
||||
assert_eq!(wt_stream.send_data(data).unwrap(), data.len());
|
||||
exchange_packets(client, server);
|
||||
}
|
||||
|
||||
fn receive_data_client(
|
||||
client: &mut Http3Client,
|
||||
expected_stream_id: StreamId,
|
||||
new_stream: bool,
|
||||
expected_data: &[u8],
|
||||
expected_fin: bool,
|
||||
) {
|
||||
let mut new_stream_received = false;
|
||||
let mut data_received = false;
|
||||
while let Some(event) = client.next_event() {
|
||||
match event {
|
||||
Http3ClientEvent::WebTransport(WebTransportEvent::NewStream { stream_id, .. }) => {
|
||||
assert_eq!(stream_id, expected_stream_id);
|
||||
new_stream_received = true;
|
||||
}
|
||||
Http3ClientEvent::DataReadable { stream_id } => {
|
||||
assert_eq!(stream_id, expected_stream_id);
|
||||
let mut buf = [0; 100];
|
||||
let (amount, fin) = client.read_data(now(), stream_id, &mut buf).unwrap();
|
||||
assert_eq!(fin, expected_fin);
|
||||
assert_eq!(amount, expected_data.len());
|
||||
assert_eq!(&buf[..amount], expected_data);
|
||||
data_received = true;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
assert!(data_received);
|
||||
assert_eq!(new_stream, new_stream_received);
|
||||
}
|
||||
|
||||
fn receive_data_server(
|
||||
client: &mut Http3Client,
|
||||
server: &mut Http3Server,
|
||||
stream_id: StreamId,
|
||||
new_stream: bool,
|
||||
expected_data: &[u8],
|
||||
expected_fin: bool,
|
||||
) -> Http3OrWebTransportStream {
|
||||
exchange_packets(client, server);
|
||||
let mut new_stream_received = false;
|
||||
let mut data_received = false;
|
||||
let mut wt_stream = None;
|
||||
let mut stream_closed = false;
|
||||
let mut recv_data = Vec::new();
|
||||
while let Some(event) = server.next_event() {
|
||||
match event {
|
||||
Http3ServerEvent::WebTransport(WebTransportServerEvent::NewStream(request)) => {
|
||||
assert_eq!(stream_id, request.stream_id());
|
||||
new_stream_received = true;
|
||||
}
|
||||
Http3ServerEvent::Data {
|
||||
mut data,
|
||||
fin,
|
||||
stream,
|
||||
} => {
|
||||
recv_data.append(&mut data);
|
||||
stream_closed = fin;
|
||||
data_received = true;
|
||||
wt_stream = Some(stream);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
assert_eq!(&recv_data[..], expected_data);
|
||||
assert!(data_received);
|
||||
assert_eq!(new_stream, new_stream_received);
|
||||
assert_eq!(stream_closed, expected_fin);
|
||||
wt_stream.unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wt_client_stream_uni() {
|
||||
const BUF_CLIENT: &[u8] = &[0; 10];
|
||||
|
||||
let (mut client, mut server) = connect();
|
||||
let wt_session = create_wt_session(&mut client, &mut server);
|
||||
let wt_stream = client
|
||||
.webtransport_create_stream(wt_session.stream_id(), StreamType::UniDi)
|
||||
.unwrap();
|
||||
send_data_client(&mut client, &mut server, wt_stream, BUF_CLIENT);
|
||||
exchange_packets(&mut client, &mut server);
|
||||
receive_data_server(&mut client, &mut server, wt_stream, true, BUF_CLIENT, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wt_client_stream_bidi() {
|
||||
const BUF_CLIENT: &[u8] = &[0; 10];
|
||||
const BUF_SERVER: &[u8] = &[1; 20];
|
||||
|
||||
let (mut client, mut server) = connect();
|
||||
let wt_session = create_wt_session(&mut client, &mut server);
|
||||
let wt_client_stream = client
|
||||
.webtransport_create_stream(wt_session.stream_id(), StreamType::BiDi)
|
||||
.unwrap();
|
||||
send_data_client(&mut client, &mut server, wt_client_stream, BUF_CLIENT);
|
||||
let mut wt_server_stream = receive_data_server(
|
||||
&mut client,
|
||||
&mut server,
|
||||
wt_client_stream,
|
||||
true,
|
||||
BUF_CLIENT,
|
||||
false,
|
||||
);
|
||||
send_data_server(&mut client, &mut server, &mut wt_server_stream, BUF_SERVER);
|
||||
receive_data_client(&mut client, wt_client_stream, false, BUF_SERVER, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wt_server_stream_uni() {
|
||||
const BUF_SERVER: &[u8] = &[2; 30];
|
||||
|
||||
let (mut client, mut server) = connect();
|
||||
let mut wt_session = create_wt_session(&mut client, &mut server);
|
||||
let mut wt_server_stream = wt_session.create_stream(StreamType::UniDi).unwrap();
|
||||
send_data_server(&mut client, &mut server, &mut wt_server_stream, BUF_SERVER);
|
||||
receive_data_client(
|
||||
&mut client,
|
||||
wt_server_stream.stream_id(),
|
||||
true,
|
||||
BUF_SERVER,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wt_server_stream_bidi() {
|
||||
const BUF_CLIENT: &[u8] = &[0; 10];
|
||||
const BUF_SERVER: &[u8] = &[1; 20];
|
||||
|
||||
let (mut client, mut server) = connect();
|
||||
let mut wt_session = create_wt_session(&mut client, &mut server);
|
||||
let mut wt_server_stream = wt_session.create_stream(StreamType::BiDi).unwrap();
|
||||
send_data_server(&mut client, &mut server, &mut wt_server_stream, BUF_SERVER);
|
||||
receive_data_client(
|
||||
&mut client,
|
||||
wt_server_stream.stream_id(),
|
||||
true,
|
||||
BUF_SERVER,
|
||||
false,
|
||||
);
|
||||
send_data_client(
|
||||
&mut client,
|
||||
&mut server,
|
||||
wt_server_stream.stream_id(),
|
||||
BUF_CLIENT,
|
||||
);
|
||||
assert_eq!(
|
||||
receive_data_server(
|
||||
&mut client,
|
||||
&mut server,
|
||||
wt_server_stream.stream_id(),
|
||||
false,
|
||||
BUF_CLIENT,
|
||||
false
|
||||
)
|
||||
.stream_id(),
|
||||
wt_server_stream.stream_id()
|
||||
);
|
||||
}
|
||||
|
|
@ -1,156 +0,0 @@
|
|||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use super::{connect, default_http3_client, default_http3_server, exchange_packets};
|
||||
use neqo_common::{event::Provider, Encoder};
|
||||
use neqo_crypto::AuthenticationStatus;
|
||||
use neqo_http3::{
|
||||
settings::{HSetting, HSettingType, HSettings},
|
||||
Error, HFrame, Http3Client, Http3ClientEvent, Http3State, WebTransportEvent,
|
||||
};
|
||||
use neqo_transport::{Connection, ConnectionError, StreamType};
|
||||
use std::time::Duration;
|
||||
use test_fixture::*;
|
||||
|
||||
fn check_wt_event(client: &mut Http3Client, wt_enable_client: bool, wt_enable_server: bool) {
|
||||
let wt_event = client.events().find_map(|e| {
|
||||
if let Http3ClientEvent::WebTransport(WebTransportEvent::Negotiated(neg)) = e {
|
||||
Some(neg)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
assert_eq!(wt_event.is_some(), wt_enable_client);
|
||||
if let Some(wt) = wt_event {
|
||||
assert_eq!(wt, wt_enable_client && wt_enable_server);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn negotiate_wt() {
|
||||
let (mut client, _server) = connect(true, true);
|
||||
assert!(client.webtransport_enabled());
|
||||
check_wt_event(&mut client, true, true);
|
||||
|
||||
let (mut client, _server) = connect(true, false);
|
||||
assert!(!client.webtransport_enabled());
|
||||
check_wt_event(&mut client, true, false);
|
||||
|
||||
let (mut client, _server) = connect(false, true);
|
||||
assert!(!client.webtransport_enabled());
|
||||
check_wt_event(&mut client, false, true);
|
||||
|
||||
let (mut client, _server) = connect(false, false);
|
||||
assert!(!client.webtransport_enabled());
|
||||
check_wt_event(&mut client, false, false);
|
||||
}
|
||||
|
||||
fn zero_rtt(client_org: bool, server_org: bool, client_resumed: bool, server_resumed: bool) {
|
||||
let (mut client, mut server) = connect(client_org, server_org);
|
||||
assert_eq!(client.webtransport_enabled(), client_org && server_org);
|
||||
|
||||
// exchane token
|
||||
let out = server.process(None, now());
|
||||
// We do not have a token so we need to wait for a resumption token timer to trigger.
|
||||
let _ = client.process(out.dgram(), now() + Duration::from_millis(250));
|
||||
assert_eq!(client.state(), Http3State::Connected);
|
||||
let token = client
|
||||
.events()
|
||||
.find_map(|e| {
|
||||
if let Http3ClientEvent::ResumptionToken(token) = e {
|
||||
Some(token)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let mut client = default_http3_client(client_resumed);
|
||||
let mut server = default_http3_server(server_resumed);
|
||||
client
|
||||
.enable_resumption(now(), &token)
|
||||
.expect("Set resumption token.");
|
||||
assert_eq!(client.state(), Http3State::ZeroRtt);
|
||||
|
||||
exchange_packets(&mut client, &mut server);
|
||||
|
||||
assert_eq!(&client.state(), &Http3State::Connected);
|
||||
assert_eq!(
|
||||
client.webtransport_enabled(),
|
||||
client_resumed && server_resumed
|
||||
);
|
||||
check_wt_event(&mut client, client_resumed, server_resumed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zero_rtt_wt_settings() {
|
||||
zero_rtt(true, true, true, true);
|
||||
zero_rtt(true, true, true, false);
|
||||
zero_rtt(true, true, false, true);
|
||||
zero_rtt(true, true, false, false);
|
||||
|
||||
zero_rtt(true, false, true, false);
|
||||
zero_rtt(true, false, true, true);
|
||||
zero_rtt(true, false, false, false);
|
||||
zero_rtt(true, false, false, true);
|
||||
|
||||
zero_rtt(false, false, false, false);
|
||||
zero_rtt(false, false, false, true);
|
||||
zero_rtt(false, false, true, false);
|
||||
zero_rtt(false, false, true, true);
|
||||
|
||||
zero_rtt(false, true, false, true);
|
||||
zero_rtt(false, true, false, false);
|
||||
zero_rtt(false, true, true, false);
|
||||
zero_rtt(false, true, true, true);
|
||||
}
|
||||
|
||||
fn exchange_packets2(client: &mut Http3Client, server: &mut Connection) {
|
||||
let mut out = None;
|
||||
loop {
|
||||
out = client.process(out, now()).dgram();
|
||||
out = server.process(out, now()).dgram();
|
||||
if out.is_none() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wrong_setting_value() {
|
||||
const CONTROL_STREAM_TYPE: &[u8] = &[0x0];
|
||||
let mut client = default_http3_client(false);
|
||||
let mut server = default_server_h3();
|
||||
|
||||
exchange_packets2(&mut client, &mut server);
|
||||
client.authenticated(AuthenticationStatus::Ok, now());
|
||||
exchange_packets2(&mut client, &mut server);
|
||||
|
||||
let control = server.stream_create(StreamType::UniDi).unwrap();
|
||||
server.stream_send(control, CONTROL_STREAM_TYPE).unwrap();
|
||||
// Encode a settings frame and send it.
|
||||
let mut enc = Encoder::default();
|
||||
let settings = HFrame::Settings {
|
||||
settings: HSettings::new(&[HSetting::new(HSettingType::EnableWebTransport, 2)]),
|
||||
};
|
||||
settings.encode(&mut enc);
|
||||
assert_eq!(
|
||||
server.stream_send(control, enc.as_ref()).unwrap(),
|
||||
enc.as_ref().len()
|
||||
);
|
||||
|
||||
exchange_packets2(&mut client, &mut server);
|
||||
match client.state() {
|
||||
Http3State::Closing(err) | Http3State::Closed(err) => {
|
||||
assert_eq!(
|
||||
err,
|
||||
ConnectionError::Application(Error::HttpSettings.code())
|
||||
);
|
||||
}
|
||||
_ => panic!("Wrong state {:?}", client.state()),
|
||||
};
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"9c7bc0f5de79c42f0957ab114f8a4ca38c276cc9f90e3823dc3b5e3a85226b66","src/decoder.rs":"8bd336c91cca989883106a9d0bf26b117d224e0e7643960c3e97d0168d1853c4","src/decoder_instructions.rs":"2205c7635b8f0c568f6fe9a63c17028eaf8d29a9b5ac7136b6554cc7fbf35038","src/encoder.rs":"b888a819595fec47037d508b943f5ff04ed52ea376bef1f90e08edc6576e773c","src/encoder_instructions.rs":"1eb4f6eee2d9ff16f96dc5bf80dae9bc04316126f6eca933fb51dbd9218a439c","src/header_block.rs":"76f4c8fad6a13d4d24530cf067d20622cdbd345f7d9779b0be9691a77fa8fb63","src/huffman.rs":"3a9edaf827343ec6e43cfd50fcc0d0077287947160ae630da5c3ddaaefedd010","src/huffman_decode_helper.rs":"2970c57f052878b727c2f764490c54184f5c2608e1d6aa961c3b01509e290122","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"6e25612bb30f0e4361566662da1e5353131ae12f97938c6ac3b2dafbf6a8bc86","src/prefix.rs":"72c587c40aef4ed38cf13b2de91091d671611679be2a9da6f0b24abafaf50dc5","src/qlog.rs":"7618085e27bb3fb1f4d1c73ba501b9a293723293c4020b7cc4129676eb278131","src/qpack_send_buf.rs":"49ded6607ec0859cb3edc5a38ff48f4d2d292f0721673d4e20700d07ac324557","src/reader.rs":"be265cc8c317512f266fafdcc835d0e413caf5280a7cc945bfe6e7e849529d67","src/static_table.rs":"fda9d5c6f38f94b0bf92d3afdf8432dce6e27e189736596e16727090c77b78ec","src/stats.rs":"624dfa3b40858c304097bb0ce5b1be1bb4d7916b1abfc222f1aa705907009730","src/table.rs":"f7091bdd9ad1f8fe3b2298a7dbfd3d285c212d69569cda54f9bcf251cb758a21"},"package":null}
|
||||
{"files":{"Cargo.toml":"880cdcddc73dceafa69773ae482a1eaaced927504856130b0cc15ec91ac31e59","src/decoder.rs":"8bd336c91cca989883106a9d0bf26b117d224e0e7643960c3e97d0168d1853c4","src/decoder_instructions.rs":"2205c7635b8f0c568f6fe9a63c17028eaf8d29a9b5ac7136b6554cc7fbf35038","src/encoder.rs":"b888a819595fec47037d508b943f5ff04ed52ea376bef1f90e08edc6576e773c","src/encoder_instructions.rs":"1eb4f6eee2d9ff16f96dc5bf80dae9bc04316126f6eca933fb51dbd9218a439c","src/header_block.rs":"9ee3bc4189ae36ae0a926295f6f8b3a1169463a19ccbc65e6d588c8b317020ad","src/huffman.rs":"3a9edaf827343ec6e43cfd50fcc0d0077287947160ae630da5c3ddaaefedd010","src/huffman_decode_helper.rs":"2970c57f052878b727c2f764490c54184f5c2608e1d6aa961c3b01509e290122","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"6e25612bb30f0e4361566662da1e5353131ae12f97938c6ac3b2dafbf6a8bc86","src/prefix.rs":"72c587c40aef4ed38cf13b2de91091d671611679be2a9da6f0b24abafaf50dc5","src/qlog.rs":"7618085e27bb3fb1f4d1c73ba501b9a293723293c4020b7cc4129676eb278131","src/qpack_send_buf.rs":"bc86cce786b6c8a468aed8d436ec4a8a86b3d4a917495fff7931ba4026c36c47","src/reader.rs":"be265cc8c317512f266fafdcc835d0e413caf5280a7cc945bfe6e7e849529d67","src/static_table.rs":"fda9d5c6f38f94b0bf92d3afdf8432dce6e27e189736596e16727090c77b78ec","src/stats.rs":"624dfa3b40858c304097bb0ce5b1be1bb4d7916b1abfc222f1aa705907009730","src/table.rs":"f7091bdd9ad1f8fe3b2298a7dbfd3d285c212d69569cda54f9bcf251cb758a21"},"package":null}
|
||||
2
third_party/rust/neqo-qpack/Cargo.toml
vendored
2
third_party/rust/neqo-qpack/Cargo.toml
vendored
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "neqo-qpack"
|
||||
version = "0.6.1"
|
||||
version = "0.6.3"
|
||||
authors = ["Dragana Damjanovic <dragana.damjano@gmail.com>"]
|
||||
edition = "2018"
|
||||
rust-version = "1.57.0"
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ impl HeaderEncoder {
|
|||
impl Deref for HeaderEncoder {
|
||||
type Target = [u8];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&*self.buf
|
||||
&self.buf
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ impl QpackData {
|
|||
impl Deref for QpackData {
|
||||
type Target = [u8];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&*self.buf
|
||||
&self.buf
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
2
third_party/rust/neqo-transport/Cargo.toml
vendored
2
third_party/rust/neqo-transport/Cargo.toml
vendored
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "neqo-transport"
|
||||
version = "0.6.1"
|
||||
version = "0.6.3"
|
||||
authors = ["EKR <ekr@rtfm.com>", "Andy Grover <agrover@mozilla.com>"]
|
||||
edition = "2018"
|
||||
rust-version = "1.57.0"
|
||||
|
|
|
|||
4
third_party/rust/neqo-transport/src/cid.rs
vendored
4
third_party/rust/neqo-transport/src/cid.rs
vendored
|
|
@ -127,13 +127,13 @@ pub struct ConnectionIdRef<'a> {
|
|||
|
||||
impl<'a> ::std::fmt::Debug for ConnectionIdRef<'a> {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
write!(f, "CID {}", hex_with_len(&self.cid))
|
||||
write!(f, "CID {}", hex_with_len(self.cid))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ::std::fmt::Display for ConnectionIdRef<'a> {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
write!(f, "{}", hex(&self.cid))
|
||||
write!(f, "{}", hex(self.cid))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ impl IdleTimeout {
|
|||
IdleTimeoutState::Init => now,
|
||||
IdleTimeoutState::PacketReceived(t) | IdleTimeoutState::AckElicitingPacketSent(t) => t,
|
||||
};
|
||||
let delay = if keep_alive {
|
||||
let delay = if keep_alive && !self.keep_alive_outstanding {
|
||||
// For a keep-alive timer, wait for half the timeout interval, but be sure
|
||||
// not to wait too little or we will send many unnecessary probes.
|
||||
max(self.timeout / 2, pto)
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ pub struct Connection {
|
|||
received_untracked: bool,
|
||||
|
||||
/// This is responsible for the QuicDatagrams' handling:
|
||||
/// https://datatracker.ietf.org/doc/html/draft-ietf-quic-datagram
|
||||
/// <https://datatracker.ietf.org/doc/html/draft-ietf-quic-datagram>
|
||||
quic_datagrams: QuicDatagrams,
|
||||
|
||||
pub(crate) crypto: Crypto,
|
||||
|
|
@ -607,13 +607,13 @@ impl Connection {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get a resumption token. The correct way to obtain a resumption token is
|
||||
/// waiting for the `ConnectionEvent::ResumptionToken` event. However, some
|
||||
/// servers don't send `NEW_TOKEN` frames and so that event might be slow in
|
||||
/// arriving. This is especially a problem for short-lived connections, where
|
||||
/// the connection is closed before any events are released. This retrieves
|
||||
/// the token, without waiting for the `NEW_TOKEN` frame to arrive.
|
||||
///
|
||||
/// The correct way to obtain a resumption token is to wait for the
|
||||
/// `ConnectionEvent::ResumptionToken` event. To emit the event we are waiting for a
|
||||
/// resumption token and a `NEW_TOKEN` frame to arrive. Some servers don't send `NEW_TOKEN`
|
||||
/// frames and in this case, we wait for 3xPTO before emitting an event. This is especially a
|
||||
/// problem for short-lived connections, where the connection is closed before any events are
|
||||
/// released. This function retrieves the token, without waiting for a `NEW_TOKEN` frame to
|
||||
/// arrive.
|
||||
/// # Panics
|
||||
/// If this is called on a server.
|
||||
pub fn take_resumption_token(&mut self, now: Instant) -> Option<ResumptionToken> {
|
||||
|
|
@ -661,20 +661,20 @@ impl Connection {
|
|||
qtrace!([self], " RTT {:?}", rtt);
|
||||
|
||||
let tp_slice = dec.decode_vvec().ok_or(Error::InvalidResumptionToken)?;
|
||||
qtrace!([self], " transport parameters {}", hex(&tp_slice));
|
||||
qtrace!([self], " transport parameters {}", hex(tp_slice));
|
||||
let mut dec_tp = Decoder::from(tp_slice);
|
||||
let tp =
|
||||
TransportParameters::decode(&mut dec_tp).map_err(|_| Error::InvalidResumptionToken)?;
|
||||
|
||||
let init_token = dec.decode_vvec().ok_or(Error::InvalidResumptionToken)?;
|
||||
qtrace!([self], " Initial token {}", hex(&init_token));
|
||||
qtrace!([self], " Initial token {}", hex(init_token));
|
||||
|
||||
let tok = dec.decode_remainder();
|
||||
qtrace!([self], " TLS token {}", hex(&tok));
|
||||
qtrace!([self], " TLS token {}", hex(tok));
|
||||
|
||||
match self.crypto.tls {
|
||||
Agent::Client(ref mut c) => {
|
||||
let res = c.enable_resumption(&tok);
|
||||
let res = c.enable_resumption(tok);
|
||||
if let Err(e) = res {
|
||||
self.absorb_error::<Error>(now, Err(Error::from(e)));
|
||||
return Ok(());
|
||||
|
|
@ -2101,7 +2101,7 @@ impl Connection {
|
|||
|
||||
// Determine how we are sending packets (PTO, etc..).
|
||||
let mtu = path.borrow().mtu();
|
||||
let profile = self.loss_recovery.send_profile(&*path.borrow(), now);
|
||||
let profile = self.loss_recovery.send_profile(&path.borrow(), now);
|
||||
qdebug!([self], "output_path send_profile {:?}", profile);
|
||||
|
||||
// Frames for different epochs must go in different packets, but then these
|
||||
|
|
@ -2222,7 +2222,12 @@ impl Connection {
|
|||
let mut packets: Vec<u8> = encoder.into();
|
||||
if let Some(mut initial) = initial_sent.take() {
|
||||
if needs_padding {
|
||||
qdebug!([self], "pad Initial to path MTU {}", mtu);
|
||||
qdebug!(
|
||||
[self],
|
||||
"pad Initial from {} to path MTU {}",
|
||||
packets.len(),
|
||||
mtu
|
||||
);
|
||||
initial.size += mtu - packets.len();
|
||||
packets.resize(mtu, 0);
|
||||
}
|
||||
|
|
@ -2357,7 +2362,7 @@ impl Connection {
|
|||
self.cid_manager.set_limit(max_active_cids);
|
||||
}
|
||||
self.set_initial_limits();
|
||||
qlog::connection_tparams_set(&mut self.qlog, &*self.tps.borrow());
|
||||
qlog::connection_tparams_set(&mut self.qlog, &self.tps.borrow());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ fn early_application_close() {
|
|||
let dgram = server.process(dgram, now()).dgram();
|
||||
assert!(dgram.is_some());
|
||||
|
||||
server.close(now(), 77, String::from(""));
|
||||
server.close(now(), 77, String::new());
|
||||
assert!(server.state().closed());
|
||||
let dgram = server.process(None, now()).dgram();
|
||||
assert!(dgram.is_some());
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
use super::super::{Connection, ConnectionParameters, IdleTimeout, Output, State};
|
||||
use super::{
|
||||
connect, connect_force_idle, connect_with_rtt, default_client, default_server,
|
||||
maybe_authenticate, new_client, new_server, send_and_receive, send_something, AT_LEAST_PTO,
|
||||
DEFAULT_STREAM_DATA,
|
||||
connect, connect_force_idle, connect_rtt_idle, connect_with_rtt, default_client,
|
||||
default_server, maybe_authenticate, new_client, new_server, send_and_receive, send_something,
|
||||
AT_LEAST_PTO, DEFAULT_STREAM_DATA,
|
||||
};
|
||||
use crate::packet::PacketBuilder;
|
||||
use crate::stats::FrameStats;
|
||||
|
|
@ -272,7 +272,7 @@ fn idle_caching() {
|
|||
let mut client = default_client();
|
||||
let mut server = default_server();
|
||||
let start = now();
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, &[]);
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, []);
|
||||
|
||||
// Perform the first round trip, but drop the Initial from the server.
|
||||
// The client then caches the Handshake packet.
|
||||
|
|
@ -657,3 +657,78 @@ fn keep_alive_uni() {
|
|||
server.process_input(dgram.unwrap(), now());
|
||||
server.stream_keep_alive(stream, true).unwrap();
|
||||
}
|
||||
|
||||
/// Test a keep-alive ping is send if there are outstading ack-eliciting packets and that
|
||||
/// the connection is closed after the idle timeout passes.
|
||||
#[test]
|
||||
fn keep_alive_with_ack_eliciting_packet_lost() {
|
||||
const RTT: Duration = Duration::from_millis(500); // PTO will be ~1.1125s
|
||||
|
||||
// The idle time out will be set to ~ 5 * PTO. (IDLE_TIMEOUT/2 > pto and IDLE_TIMEOUT/2 < pto + 2pto)
|
||||
// After handshake all packets will be lost. The following steps will happen after the handshake:
|
||||
// - data will be sent on a stream that is marked for keep-alive, (at start time)
|
||||
// - PTO timer will trigger first, and the data will be retransmited toghether with a PING, (at the start time + pto)
|
||||
// - keep-alive timer will trigger and a keep-alive PING will be sent, (at the start time + IDLE_TIMEOUT / 2)
|
||||
// - PTO timer will trigger again. (at the start time + pto + 2*pto)
|
||||
// - Idle time out will trigger (at the timeout + IDLE_TIMEOUT)
|
||||
const IDLE_TIMEOUT: Duration = Duration::from_millis(6000);
|
||||
|
||||
let mut client = new_client(ConnectionParameters::default().idle_timeout(IDLE_TIMEOUT));
|
||||
let mut server = default_server();
|
||||
let mut now = connect_rtt_idle(&mut client, &mut server, RTT);
|
||||
// connect_rtt_idle increase now by RTT / 2;
|
||||
now -= RTT / 2;
|
||||
assert_idle(&mut client, now, IDLE_TIMEOUT);
|
||||
|
||||
// Create a stream.
|
||||
let stream = client.stream_create(StreamType::BiDi).unwrap();
|
||||
// Marking the stream for keep-alive changes the idle timeout.
|
||||
client.stream_keep_alive(stream, true).unwrap();
|
||||
assert_idle(&mut client, now, IDLE_TIMEOUT / 2);
|
||||
|
||||
// Send data on the stream that will be lost.
|
||||
let _ = client.stream_send(stream, DEFAULT_STREAM_DATA).unwrap();
|
||||
let _lost_packet = client.process_output(now).dgram();
|
||||
|
||||
let pto = client.process_output(now).callback();
|
||||
// Wait for packet to be marked lost.
|
||||
assert!(pto < IDLE_TIMEOUT / 2);
|
||||
now += pto;
|
||||
let retransmit = client.process_output(now).dgram();
|
||||
assert!(retransmit.is_some());
|
||||
let retransmit = client.process_output(now).dgram();
|
||||
assert!(retransmit.is_some());
|
||||
|
||||
// The next callback should be for an idle PING.
|
||||
assert_eq!(
|
||||
client.process_output(now).callback(),
|
||||
IDLE_TIMEOUT / 2 - pto
|
||||
);
|
||||
|
||||
// Wait that long and the client should send a PING frame.
|
||||
now += IDLE_TIMEOUT / 2 - pto;
|
||||
let pings_before = client.stats().frame_tx.ping;
|
||||
let ping = client.process_output(now).dgram();
|
||||
assert!(ping.is_some());
|
||||
assert_eq!(client.stats().frame_tx.ping, pings_before + 1);
|
||||
|
||||
// The next callback is for a PTO, the PTO timer is 2 * pto now.
|
||||
assert_eq!(client.process_output(now).callback(), pto * 2);
|
||||
now += pto * 2;
|
||||
// Now we will retransmit stream data.
|
||||
let retransmit = client.process_output(now).dgram();
|
||||
assert!(retransmit.is_some());
|
||||
let retransmit = client.process_output(now).dgram();
|
||||
assert!(retransmit.is_some());
|
||||
|
||||
// The next callback will be an idle timeout.
|
||||
assert_eq!(
|
||||
client.process_output(now).callback(),
|
||||
IDLE_TIMEOUT / 2 - 2 * pto
|
||||
);
|
||||
|
||||
now += IDLE_TIMEOUT / 2 - 2 * pto;
|
||||
let out = client.process_output(now);
|
||||
assert!(matches!(out, Output::None));
|
||||
assert!(matches!(client.state(), State::Closed(_)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -674,7 +674,7 @@ fn change_flow_control(stream_type: StreamType, new_fc: u64) {
|
|||
// server should receive a MAX_SREAM_DATA frame if the flow control window is updated.
|
||||
let out2 = client.process(None, now());
|
||||
let out3 = server.process(out2.dgram(), now());
|
||||
let expected = if RECV_BUFFER_START < new_fc { 1 } else { 0 };
|
||||
let expected = usize::from(RECV_BUFFER_START < new_fc);
|
||||
assert_eq!(server.stats().frame_rx.max_stream_data, expected);
|
||||
|
||||
// If the flow control window has been increased, server can write more data.
|
||||
|
|
|
|||
2
third_party/rust/neqo-transport/src/fc.rs
vendored
2
third_party/rust/neqo-transport/src/fc.rs
vendored
|
|
@ -803,7 +803,7 @@ mod test {
|
|||
fc[StreamType::BiDi].add_retired(1);
|
||||
fc[StreamType::BiDi].send_flowc_update();
|
||||
// consume the frame
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, &[]);
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, []);
|
||||
let mut tokens = Vec::new();
|
||||
fc[StreamType::BiDi].write_frames(&mut builder, &mut tokens, &mut FrameStats::default());
|
||||
assert_eq!(tokens.len(), 1);
|
||||
|
|
|
|||
1
third_party/rust/neqo-transport/src/lib.rs
vendored
1
third_party/rust/neqo-transport/src/lib.rs
vendored
|
|
@ -48,6 +48,7 @@ pub use self::connection::{
|
|||
};
|
||||
pub use self::events::{ConnectionEvent, ConnectionEvents};
|
||||
pub use self::frame::CloseError;
|
||||
pub use self::quic_datagrams::DatagramTracking;
|
||||
pub use self::stats::Stats;
|
||||
pub use self::stream_id::{StreamId, StreamType};
|
||||
pub use self::version::Version;
|
||||
|
|
|
|||
2
third_party/rust/neqo-transport/src/path.rs
vendored
2
third_party/rust/neqo-transport/src/path.rs
vendored
|
|
@ -767,7 +767,7 @@ impl Path {
|
|||
|
||||
// Send PATH_RESPONSE.
|
||||
let resp_sent = if let Some(challenge) = self.challenge.take() {
|
||||
qtrace!([self], "Responding to path challenge {}", hex(&challenge));
|
||||
qtrace!([self], "Responding to path challenge {}", hex(challenge));
|
||||
builder.encode_varint(FRAME_TYPE_PATH_RESPONSE);
|
||||
builder.encode(&challenge[..]);
|
||||
if builder.len() > builder.limit() {
|
||||
|
|
|
|||
4
third_party/rust/neqo-transport/src/qlog.rs
vendored
4
third_party/rust/neqo-transport/src/qlog.rs
vendored
|
|
@ -338,7 +338,7 @@ fn frame_to_qlogframe(frame: &Frame) -> QuicFrame {
|
|||
Frame::Crypto { offset, data } => {
|
||||
QuicFrame::crypto(offset.to_string(), data.len().to_string())
|
||||
}
|
||||
Frame::NewToken { token } => QuicFrame::new_token(token.len().to_string(), hex(&token)),
|
||||
Frame::NewToken { token } => QuicFrame::new_token(token.len().to_string(), hex(token)),
|
||||
Frame::Stream {
|
||||
fin,
|
||||
stream_id,
|
||||
|
|
@ -397,7 +397,7 @@ fn frame_to_qlogframe(frame: &Frame) -> QuicFrame {
|
|||
sequence_number.to_string(),
|
||||
retire_prior.to_string(),
|
||||
connection_id.len() as u64,
|
||||
hex(&connection_id),
|
||||
hex(connection_id),
|
||||
hex(stateless_reset_token),
|
||||
),
|
||||
Frame::RetireConnectionId { sequence_number } => {
|
||||
|
|
|
|||
|
|
@ -679,7 +679,7 @@ impl LossRecovery {
|
|||
};
|
||||
|
||||
let (acked_packets, any_ack_eliciting) =
|
||||
space.remove_acked(acked_ranges, &mut *self.stats.borrow_mut());
|
||||
space.remove_acked(acked_ranges, &mut self.stats.borrow_mut());
|
||||
if acked_packets.is_empty() {
|
||||
// No new information.
|
||||
return (Vec::new(), Vec::new());
|
||||
|
|
@ -887,7 +887,7 @@ impl LossRecovery {
|
|||
self.pto_state
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.count_pto(&mut *self.stats.borrow_mut());
|
||||
.count_pto(&mut self.stats.borrow_mut());
|
||||
|
||||
qlog::metrics_updated(
|
||||
&mut self.qlog,
|
||||
|
|
|
|||
|
|
@ -1248,7 +1248,7 @@ mod tests {
|
|||
assert!(s.has_frames_to_write());
|
||||
|
||||
// consume it
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, &[]);
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, []);
|
||||
let mut token = Vec::new();
|
||||
s.write_frame(&mut builder, &mut token, &mut FrameStats::default());
|
||||
|
||||
|
|
@ -1361,7 +1361,7 @@ mod tests {
|
|||
s.read(&mut buf).unwrap();
|
||||
assert!(session_fc.borrow().frame_needed());
|
||||
// consume it
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, &[]);
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, []);
|
||||
let mut token = Vec::new();
|
||||
session_fc
|
||||
.borrow_mut()
|
||||
|
|
@ -1382,7 +1382,7 @@ mod tests {
|
|||
s.read(&mut buf).unwrap();
|
||||
assert!(session_fc.borrow().frame_needed());
|
||||
// consume it
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, &[]);
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, []);
|
||||
let mut token = Vec::new();
|
||||
session_fc
|
||||
.borrow_mut()
|
||||
|
|
@ -1630,7 +1630,7 @@ mod tests {
|
|||
assert!(s.fc().unwrap().frame_needed());
|
||||
|
||||
// Write the fc update frame
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, &[]);
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, []);
|
||||
let mut token = Vec::new();
|
||||
let mut stats = FrameStats::default();
|
||||
fc.borrow_mut()
|
||||
|
|
|
|||
|
|
@ -1586,7 +1586,7 @@ mod tests {
|
|||
ss.insert(StreamId::from(0), s);
|
||||
|
||||
let mut tokens = Vec::new();
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, &[]);
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, []);
|
||||
|
||||
// Write a small frame: no fin.
|
||||
let written = builder.len();
|
||||
|
|
@ -1675,7 +1675,7 @@ mod tests {
|
|||
ss.insert(StreamId::from(0), s);
|
||||
|
||||
let mut tokens = Vec::new();
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, &[]);
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, []);
|
||||
ss.write_frames(
|
||||
TransmissionPriority::default(),
|
||||
&mut builder,
|
||||
|
|
@ -1753,7 +1753,7 @@ mod tests {
|
|||
assert_eq!(s.next_bytes(false), Some((0, &b"ab"[..])));
|
||||
|
||||
// This doesn't report blocking yet.
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, &[]);
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, []);
|
||||
let mut tokens = Vec::new();
|
||||
let mut stats = FrameStats::default();
|
||||
s.write_blocked_frame(
|
||||
|
|
@ -1806,7 +1806,7 @@ mod tests {
|
|||
assert_eq!(s.send_atomic(b"abc").unwrap(), 0);
|
||||
|
||||
// Assert that STREAM_DATA_BLOCKED is sent.
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, &[]);
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, []);
|
||||
let mut tokens = Vec::new();
|
||||
let mut stats = FrameStats::default();
|
||||
s.write_blocked_frame(
|
||||
|
|
@ -1893,7 +1893,7 @@ mod tests {
|
|||
s.mark_as_lost(len_u64, 0, true);
|
||||
|
||||
// No frame should be sent here.
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, &[]);
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, []);
|
||||
let mut tokens = Vec::new();
|
||||
let mut stats = FrameStats::default();
|
||||
s.write_stream_frame(
|
||||
|
|
@ -1954,7 +1954,7 @@ mod tests {
|
|||
s.close();
|
||||
}
|
||||
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, &[]);
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, []);
|
||||
let header_len = builder.len();
|
||||
builder.set_limit(header_len + space);
|
||||
|
||||
|
|
@ -2055,7 +2055,7 @@ mod tests {
|
|||
s.send(data).unwrap();
|
||||
s.close();
|
||||
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, &[]);
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, []);
|
||||
let header_len = builder.len();
|
||||
// Add 2 for the frame type and stream ID, then add the extra.
|
||||
builder.set_limit(header_len + data.len() + 2 + extra);
|
||||
|
|
|
|||
2
third_party/rust/neqo-transport/src/stats.rs
vendored
2
third_party/rust/neqo-transport/src/stats.rs
vendored
|
|
@ -216,7 +216,7 @@ pub struct StatsCell {
|
|||
impl Deref for StatsCell {
|
||||
type Target = RefCell<Stats>;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&*self.stats
|
||||
&self.stats
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -880,7 +880,7 @@ mod tests {
|
|||
}
|
||||
|
||||
fn write_frame(rp: &mut RecvdPackets) {
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, &[]);
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, []);
|
||||
let mut stats = FrameStats::default();
|
||||
let mut tokens = Vec::new();
|
||||
rp.write_frame(*NOW, &mut builder, &mut tokens, &mut stats);
|
||||
|
|
@ -1013,7 +1013,7 @@ mod tests {
|
|||
#[test]
|
||||
fn drop_spaces() {
|
||||
let mut tracker = AckTracker::default();
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, &[]);
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, []);
|
||||
tracker
|
||||
.get_mut(PacketNumberSpace::Initial)
|
||||
.unwrap()
|
||||
|
|
@ -1072,7 +1072,7 @@ mod tests {
|
|||
.set_received(*NOW, 0, true);
|
||||
assert!(tracker.ack_time(*NOW - Duration::from_millis(1)).is_some());
|
||||
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, &[]);
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, []);
|
||||
builder.set_limit(10);
|
||||
|
||||
let mut stats = FrameStats::default();
|
||||
|
|
@ -1102,7 +1102,7 @@ mod tests {
|
|||
.set_received(*NOW, 2, true);
|
||||
assert!(tracker.ack_time(*NOW - Duration::from_millis(1)).is_some());
|
||||
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, &[]);
|
||||
let mut builder = PacketBuilder::short(Encoder::new(), false, []);
|
||||
builder.set_limit(32);
|
||||
|
||||
let mut stats = FrameStats::default();
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ impl Simulator {
|
|||
}
|
||||
|
||||
if self.nodes.iter().all(|n| n.node.done()) {
|
||||
let real_elapsed = Instant::now() - real_start;
|
||||
let real_elapsed = real_start.elapsed();
|
||||
println!("{}: real elapsed time: {:?}", self.name, real_elapsed);
|
||||
let elapsed = now - start;
|
||||
println!("{}: simulated elapsed time: {:?}", self.name, elapsed);
|
||||
|
|
|
|||
Loading…
Reference in a new issue