Backed out changeset f3cca9b9f4b9 (bug 1942325) for causing xpcshell failures @est_close.js. CLOSED TREE
This commit is contained in:
@@ -115,9 +115,9 @@ git = "https://github.com/mozilla/mp4parse-rust"
|
||||
rev = "a138e40ec1c603615873e524b5b22e11c0ec4820"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/mozilla/neqo?tag=v0.12.2"]
|
||||
[source."git+https://github.com/mozilla/neqo?tag=v0.11.0"]
|
||||
git = "https://github.com/mozilla/neqo"
|
||||
tag = "v0.12.2"
|
||||
tag = "v0.11.0"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/servo/unicode-bidi?rev=ca612daf1c08c53abe07327cb3e6ef6e0a760f0c"]
|
||||
|
||||
44
Cargo.lock
generated
44
Cargo.lock
generated
@@ -4461,20 +4461,6 @@ dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mtu"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "649391c1b28fdca95b1b735b65fe186b658adbab88845d325f135f37b16b9c96"
|
||||
dependencies = [
|
||||
"bindgen 0.69.4",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
"mozbuild",
|
||||
"static_assertions",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "murmurhash3"
|
||||
version = "0.0.5"
|
||||
@@ -4505,8 +4491,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "neqo-bin"
|
||||
version = "0.12.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||
version = "0.11.0"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.11.0#c6d5502fb5b827473e7c5d7c4c380275cdb3d931"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"clap-verbosity-flag",
|
||||
@@ -4527,8 +4513,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "neqo-common"
|
||||
version = "0.12.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||
version = "0.11.0"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.11.0#c6d5502fb5b827473e7c5d7c4c380275cdb3d931"
|
||||
dependencies = [
|
||||
"enum-map",
|
||||
"env_logger",
|
||||
@@ -4539,8 +4525,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "neqo-crypto"
|
||||
version = "0.12.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||
version = "0.11.0"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.11.0#c6d5502fb5b827473e7c5d7c4c380275cdb3d931"
|
||||
dependencies = [
|
||||
"bindgen 0.69.4",
|
||||
"log",
|
||||
@@ -4554,8 +4540,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "neqo-http3"
|
||||
version = "0.12.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||
version = "0.11.0"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.11.0#c6d5502fb5b827473e7c5d7c4c380275cdb3d931"
|
||||
dependencies = [
|
||||
"enumset",
|
||||
"log",
|
||||
@@ -4570,8 +4556,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "neqo-qpack"
|
||||
version = "0.12.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||
version = "0.11.0"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.11.0#c6d5502fb5b827473e7c5d7c4c380275cdb3d931"
|
||||
dependencies = [
|
||||
"log",
|
||||
"neqo-common",
|
||||
@@ -4582,13 +4568,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "neqo-transport"
|
||||
version = "0.12.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||
version = "0.11.0"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.11.0#c6d5502fb5b827473e7c5d7c4c380275cdb3d931"
|
||||
dependencies = [
|
||||
"enum-map",
|
||||
"indexmap 2.2.6",
|
||||
"log",
|
||||
"mtu",
|
||||
"neqo-common",
|
||||
"neqo-crypto",
|
||||
"qlog",
|
||||
@@ -4598,10 +4583,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "neqo-udp"
|
||||
version = "0.12.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||
version = "0.11.0"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.11.0#c6d5502fb5b827473e7c5d7c4c380275cdb3d931"
|
||||
dependencies = [
|
||||
"cfg_aliases",
|
||||
"log",
|
||||
"neqo-common",
|
||||
"quinn-udp",
|
||||
|
||||
@@ -199,7 +199,6 @@ features = [
|
||||
version = "0.58"
|
||||
optional = true
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Graphics",
|
||||
"Win32_Graphics_Direct3D",
|
||||
"Win32_Graphics_Direct3D12",
|
||||
@@ -208,9 +207,6 @@ features = [
|
||||
"Win32_Graphics_DirectComposition",
|
||||
"Win32_Graphics_Dxgi",
|
||||
"Win32_Graphics_Dxgi_Common",
|
||||
"Win32_NetworkManagement_IpHelper",
|
||||
"Win32_NetworkManagement_Ndis",
|
||||
"Win32_Networking_WinSock",
|
||||
"Win32_Security",
|
||||
"Win32_System",
|
||||
"Win32_System_Diagnostics",
|
||||
|
||||
@@ -14590,13 +14590,6 @@
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# When network.http.http3.sni-slicing is set, TLS SNI slicing is enabled.
|
||||
- name: network.http.http3.sni-slicing
|
||||
type: RelaxedAtomicBool
|
||||
value: true
|
||||
mirror: always
|
||||
rust: true
|
||||
|
||||
# When true, a http request will be upgraded to https when HTTPS RR is
|
||||
# available.
|
||||
- name: network.dns.upgrade_with_https_rr
|
||||
|
||||
@@ -1287,9 +1287,7 @@ networking:
|
||||
expires: never
|
||||
labels:
|
||||
- capable
|
||||
- black-hole
|
||||
- bleaching
|
||||
- received-unsent-ect-1
|
||||
- not-capable
|
||||
|
||||
http_3_loss_ratio:
|
||||
type: custom_distribution
|
||||
|
||||
@@ -10,11 +10,11 @@ name = "neqo_glue"
|
||||
|
||||
[dependencies]
|
||||
firefox-on-glean = { path = "../../../toolkit/components/glean/api" }
|
||||
neqo-udp = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-http3 = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-transport = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo", features = ["gecko"] }
|
||||
neqo-common = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-qpack = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-udp = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-http3 = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-transport = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-common = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-qpack = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
||||
nserror = { path = "../../../xpcom/rust/nserror" }
|
||||
nsstring = { path = "../../../xpcom/rust/nsstring" }
|
||||
xpcom = { path = "../../../xpcom/rust/xpcom" }
|
||||
@@ -29,11 +29,10 @@ uuid = { version = "1.0", features = ["v4"] }
|
||||
winapi = {version = "0.3", features = ["ws2def"] }
|
||||
|
||||
[dependencies.neqo-crypto]
|
||||
tag = "v0.12.2"
|
||||
tag = "v0.11.0"
|
||||
git = "https://github.com/mozilla/neqo"
|
||||
default-features = false
|
||||
features = ["gecko"]
|
||||
|
||||
[features]
|
||||
bench = [] # no-op, see <https://github.com/mozilla/neqo/issues/2390>
|
||||
fuzzing = ["neqo-http3/disable-encryption"]
|
||||
|
||||
@@ -42,7 +42,7 @@ use winapi::shared::ws2def::{AF_INET, AF_INET6};
|
||||
use xpcom::{interfaces::nsISocketProvider, AtomicRefcnt, RefCounted, RefPtr};
|
||||
|
||||
std::thread_local! {
|
||||
static RECV_BUF: RefCell<neqo_udp::RecvBuf> = RefCell::new(neqo_udp::RecvBuf::new());
|
||||
static RECV_BUF: RefCell<Vec<u8>> = RefCell::new(vec![0; neqo_udp::RECV_BUF_SIZE]);
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@@ -203,6 +203,10 @@ impl NeqoHttp3Conn {
|
||||
let remote: SocketAddr = netaddr_to_socket_addr(remote_addr)?;
|
||||
|
||||
let quic_version = match alpn_conv {
|
||||
"h3-32" => Version::Draft32,
|
||||
"h3-31" => Version::Draft31,
|
||||
"h3-30" => Version::Draft30,
|
||||
"h3-29" => Version::Draft29,
|
||||
"h3" => Version::Version1,
|
||||
_ => return Err(NS_ERROR_INVALID_ARG),
|
||||
};
|
||||
@@ -228,8 +232,7 @@ impl NeqoHttp3Conn {
|
||||
.cc_algorithm(cc_algorithm)
|
||||
.max_data(max_data)
|
||||
.max_stream_data(StreamType::BiDi, false, max_stream_data)
|
||||
.grease(static_prefs::pref!("security.tls.grease_http3_enable"))
|
||||
.sni_slicing(static_prefs::pref!("network.http.http3.sni-slicing"));
|
||||
.grease(static_prefs::pref!("security.tls.grease_http3_enable"));
|
||||
|
||||
// Set a short timeout when fuzzing.
|
||||
#[cfg(feature = "fuzzing")]
|
||||
@@ -336,7 +339,6 @@ impl NeqoHttp3Conn {
|
||||
fn record_stats_in_glean(&self) {
|
||||
use firefox_on_glean::metrics::networking as glean;
|
||||
use neqo_common::IpTosEcn;
|
||||
use neqo_transport::ecn;
|
||||
|
||||
// Metric values must be recorded as integers. Glean does not support
|
||||
// floating point distributions. In order to represent values <1, they
|
||||
@@ -393,32 +395,12 @@ impl NeqoHttp3Conn {
|
||||
glean::http_3_ecn_ce_ect0_ratio_received
|
||||
.accumulate_single_sample_signed(ratio as i64);
|
||||
}
|
||||
for (outcome, value) in stats.ecn_path_validation.into_iter() {
|
||||
match outcome {
|
||||
ecn::ValidationOutcome::Capable => {
|
||||
glean::http_3_ecn_path_capability
|
||||
.get(&"capable")
|
||||
.add(value as i32);
|
||||
}
|
||||
ecn::ValidationOutcome::NotCapable(ecn::ValidationError::BlackHole) => {
|
||||
.add(stats.ecn_paths_capable as i32);
|
||||
glean::http_3_ecn_path_capability
|
||||
.get(&"black-hole")
|
||||
.add(value as i32);
|
||||
}
|
||||
ecn::ValidationOutcome::NotCapable(ecn::ValidationError::Bleaching) => {
|
||||
glean::http_3_ecn_path_capability
|
||||
.get(&"bleaching")
|
||||
.add(value as i32);
|
||||
}
|
||||
ecn::ValidationOutcome::NotCapable(
|
||||
ecn::ValidationError::ReceivedUnsentECT1,
|
||||
) => {
|
||||
glean::http_3_ecn_path_capability
|
||||
.get(&"received-unsent-ect-1")
|
||||
.add(value as i32);
|
||||
}
|
||||
}
|
||||
}
|
||||
.get(&"not-capable")
|
||||
.add(stats.ecn_paths_not_capable as i32);
|
||||
}
|
||||
|
||||
// Ignore connections into the void.
|
||||
@@ -611,15 +593,18 @@ pub unsafe extern "C" fn neqo_http3conn_process_input(
|
||||
};
|
||||
}
|
||||
};
|
||||
if dgrams.len() == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
// Attach metric instrumentation to `dgrams` iterator.
|
||||
let mut sum = 0;
|
||||
let mut segment_count = 0;
|
||||
conn.datagram_segments_received
|
||||
.accumulate(dgrams.len() as u64);
|
||||
let datagram_segment_size_received = &mut conn.datagram_segment_size_received;
|
||||
let dgrams = dgrams.map(|d| {
|
||||
datagram_segment_size_received.accumulate(d.len() as u64);
|
||||
sum += d.len();
|
||||
segment_count += 1;
|
||||
d
|
||||
});
|
||||
|
||||
@@ -635,7 +620,6 @@ pub unsafe extern "C" fn neqo_http3conn_process_input(
|
||||
conn.conn.process_multiple_input(dgrams, Instant::now());
|
||||
|
||||
conn.datagram_size_received.accumulate(sum as u64);
|
||||
conn.datagram_segments_received.accumulate(segment_count);
|
||||
bytes_read += sum;
|
||||
}
|
||||
|
||||
@@ -1479,7 +1463,7 @@ pub extern "C" fn neqo_http3conn_event(
|
||||
return res;
|
||||
}
|
||||
Http3Event::PushPromise {
|
||||
push_id: push_id.into(),
|
||||
push_id,
|
||||
request_stream_id: request_stream_id.as_u64(),
|
||||
}
|
||||
}
|
||||
@@ -1496,22 +1480,16 @@ pub extern "C" fn neqo_http3conn_event(
|
||||
if res != NS_OK {
|
||||
return res;
|
||||
}
|
||||
Http3Event::PushHeaderReady {
|
||||
push_id: push_id.into(),
|
||||
fin,
|
||||
Http3Event::PushHeaderReady { push_id, fin }
|
||||
}
|
||||
}
|
||||
Http3ClientEvent::PushDataReadable { push_id } => {
|
||||
Http3Event::PushDataReadable { push_id }
|
||||
}
|
||||
Http3ClientEvent::PushCanceled { push_id } => Http3Event::PushCanceled { push_id },
|
||||
Http3ClientEvent::PushReset { push_id, error } => {
|
||||
Http3Event::PushReset { push_id, error }
|
||||
}
|
||||
Http3ClientEvent::PushDataReadable { push_id } => Http3Event::PushDataReadable {
|
||||
push_id: push_id.into(),
|
||||
},
|
||||
Http3ClientEvent::PushCanceled { push_id } => Http3Event::PushCanceled {
|
||||
push_id: push_id.into(),
|
||||
},
|
||||
Http3ClientEvent::PushReset { push_id, error } => Http3Event::PushReset {
|
||||
push_id: push_id.into(),
|
||||
error,
|
||||
},
|
||||
Http3ClientEvent::RequestsCreatable => Http3Event::RequestsCreatable,
|
||||
Http3ClientEvent::AuthenticationNeeded => Http3Event::AuthenticationNeeded,
|
||||
Http3ClientEvent::ZeroRttRejected => Http3Event::ZeroRttRejected,
|
||||
|
||||
@@ -6,11 +6,11 @@ edition = "2018"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[dependencies]
|
||||
neqo-bin = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-transport = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo", features = ["gecko"] }
|
||||
neqo-common = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-http3 = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-qpack = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-bin = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-transport = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-common = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-http3 = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-qpack = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
||||
log = "0.4.0"
|
||||
base64 = "0.21"
|
||||
cfg-if = "1.0"
|
||||
@@ -20,7 +20,7 @@ tokio = { version = "1", features = ["rt-multi-thread"] }
|
||||
mozilla-central-workspace-hack = { version = "0.1", features = ["http3server"], optional = true }
|
||||
|
||||
[dependencies.neqo-crypto]
|
||||
tag = "v0.12.2"
|
||||
tag = "v0.11.0"
|
||||
git = "https://github.com/mozilla/neqo"
|
||||
default-features = false
|
||||
features = ["gecko"]
|
||||
@@ -32,6 +32,3 @@ bindgen = {version = "0.69", default-features = false, features = ["runtime"] }
|
||||
[[bin]]
|
||||
name = "http3server"
|
||||
path = "src/main.rs"
|
||||
|
||||
[features]
|
||||
bench = [] # no-op, see <https://github.com/mozilla/neqo/issues/2390>
|
||||
|
||||
@@ -1227,5 +1227,3 @@ extern "C" fn __tsan_default_suppressions() -> *const std::os::raw::c_char {
|
||||
extern "C" {}
|
||||
#[cfg_attr(target_os = "windows", link(name = "propsys"))]
|
||||
extern "C" {}
|
||||
#[cfg_attr(target_os = "windows", link(name = "iphlpapi"))]
|
||||
extern "C" {}
|
||||
|
||||
@@ -3378,11 +3378,6 @@ criteria = "safe-to-deploy"
|
||||
version = "0.1.2"
|
||||
notes = "Developed by Mozilla staff."
|
||||
|
||||
[[audits.mtu]]
|
||||
who = "Max Inden <mail@max-inden.de>"
|
||||
criteria = "safe-to-deploy"
|
||||
version = "0.2.5"
|
||||
|
||||
[[audits.naga]]
|
||||
who = "Dzmitry Malyshau <kvark@fastmail.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
1
third_party/rust/mtu/.cargo-checksum.json
vendored
1
third_party/rust/mtu/.cargo-checksum.json
vendored
@@ -1 +0,0 @@
|
||||
{"files":{"CODE_OF_CONDUCT.md":"f7b4cba1deaa0a77bd611c04c84ef5b6859e44c8370f7513fe688fb9531b913b","Cargo.lock":"e19a897971d578f52f7b42264c05a049239f78f9a2e4230c5dc8e7472d972884","Cargo.toml":"65df0b8d849b3562577a64f81aa5cdd5a78659aab2dc79eb58cb335035a2594b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"4ad721b5b6a3d39ca3e2202f403d897c4a1d42896486dd58963a81f8e64ef61d","README.md":"2c9cce2eb06f0897e9b2fb68d8fa640da581bf440c26f266f8af5b3edb02dc6a","SECURITY.md":"75455814b6cf997e22a927eb979b4356d788583aa1eb96e90853aaab0f82ad1b","build.rs":"f912d1e5dcd1319e5575ebe4db6c41a5bbef717ca1d4eac32c42b56d64d89824","src/bsd.rs":"635c704a360a146842db3f219266379a7f906069a2d18767ae45c2be4da2e835","src/lib.rs":"15b45f18ebe9b5cb589059ada0e721610fdd65ac62d4b3fcda37ab88e9ca636f","src/linux.rs":"4e99612a04d744e2ca22b2e353faa500b37cb58caddaecb7566b4748aa1f7209","src/routesocket.rs":"be837947e2c3f9301a174499217fe8920ff492918bf85ca5eb281eb7ad2240e1","src/windows.rs":"b139c7aaa0c39415ce1773f1c9569be1a6b82dfe82334ab0c6cb80e7d232363e"},"package":"649391c1b28fdca95b1b735b65fe186b658adbab88845d325f135f37b16b9c96"}
|
||||
18
third_party/rust/mtu/CODE_OF_CONDUCT.md
vendored
18
third_party/rust/mtu/CODE_OF_CONDUCT.md
vendored
@@ -1,18 +0,0 @@
|
||||
# Community Participation Guidelines
|
||||
|
||||
This repository is governed by Mozilla's code of conduct and etiquette
|
||||
guidelines. For more details, please read the [Mozilla Community Participation
|
||||
Guidelines](https://www.mozilla.org/about/governance/policies/participation/).
|
||||
|
||||
## How to Report
|
||||
|
||||
For more information on how to report violations of the Community Participation
|
||||
Guidelines, please read our '[How to
|
||||
Report](https://www.mozilla.org/about/governance/policies/participation/reporting/)'
|
||||
page.
|
||||
|
||||
## Project Specific Etiquette
|
||||
|
||||
Please consider the advice in the [Bugzilla etiquette
|
||||
guide](https://bugzilla.mozilla.org/page.cgi?id=etiquette.html) when
|
||||
contributing to this project.
|
||||
369
third_party/rust/mtu/Cargo.lock
generated
vendored
369
third_party/rust/mtu/Cargo.lock
generated
vendored
@@ -1,369 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f2135563fb5c609d2b2b87c1e8ce7bc41b0b45430fa9661f457981503dd5bf0"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.69.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"lazycell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "lazycell"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.158"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "mozbuild"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "903970ae2f248d7275214cf8f387f8ba0c4ea7e3d87a320e85493db60ce28616"
|
||||
|
||||
[[package]]
|
||||
name = "mtu"
|
||||
version = "0.2.5"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
"mozbuild",
|
||||
"static_assertions",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.87"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
|
||||
dependencies = [
|
||||
"windows-result",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
139
third_party/rust/mtu/Cargo.toml
vendored
139
third_party/rust/mtu/Cargo.toml
vendored
@@ -1,139 +0,0 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2021"
|
||||
rust-version = "1.76.0"
|
||||
name = "mtu"
|
||||
version = "0.2.5"
|
||||
authors = ["The Mozilla Necko Team <necko@mozilla.com>"]
|
||||
build = "build.rs"
|
||||
autolib = false
|
||||
autobins = false
|
||||
autoexamples = false
|
||||
autotests = false
|
||||
autobenches = false
|
||||
description = "Obtain the local network interface MTU towards a given IP address."
|
||||
homepage = "https://github.com/mozilla/mtu/"
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"mozilla",
|
||||
"interface",
|
||||
"mtu",
|
||||
]
|
||||
categories = [
|
||||
"network-programming",
|
||||
"web-programming",
|
||||
]
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/mozilla/mtu/"
|
||||
|
||||
[lib]
|
||||
name = "mtu"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies.libc]
|
||||
version = "0.2"
|
||||
default-features = false
|
||||
|
||||
[dependencies.static_assertions]
|
||||
version = "1.1"
|
||||
default-features = false
|
||||
|
||||
[build-dependencies.bindgen]
|
||||
version = "0.69"
|
||||
features = ["runtime"]
|
||||
default-features = false
|
||||
|
||||
[build-dependencies.cfg_aliases]
|
||||
version = "0.2"
|
||||
default-features = false
|
||||
|
||||
[build-dependencies.mozbuild]
|
||||
version = "0.1"
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[features]
|
||||
gecko = ["dep:mozbuild"]
|
||||
|
||||
[target."cfg(windows)".dependencies.windows]
|
||||
version = ">=0.58,<0.60"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_NetworkManagement_IpHelper",
|
||||
"Win32_NetworkManagement_Ndis",
|
||||
"Win32_Networking_WinSock",
|
||||
]
|
||||
|
||||
[badges.codecov]
|
||||
branch = "main"
|
||||
repository = "mozilla/mtu"
|
||||
|
||||
[badges.is-it-maintained-issue-resolution]
|
||||
branch = "main"
|
||||
repository = "mozilla/mtu"
|
||||
|
||||
[badges.is-it-maintained-open-issues]
|
||||
branch = "main"
|
||||
repository = "mozilla/mtu"
|
||||
|
||||
[badges.maintenance]
|
||||
branch = "main"
|
||||
status = "actively-developed"
|
||||
|
||||
[lints.clippy]
|
||||
cfg_not_test = "warn"
|
||||
clone_on_ref_ptr = "warn"
|
||||
create_dir = "warn"
|
||||
get_unwrap = "warn"
|
||||
if_then_some_else_none = "warn"
|
||||
multiple_crate_versions = "allow"
|
||||
multiple_inherent_impl = "warn"
|
||||
pathbuf_init_then_push = "warn"
|
||||
redundant_type_annotations = "warn"
|
||||
ref_patterns = "warn"
|
||||
renamed_function_params = "warn"
|
||||
semicolon_inside_block = "warn"
|
||||
try_err = "warn"
|
||||
unneeded_field_pattern = "warn"
|
||||
unused_result_ok = "warn"
|
||||
unused_trait_names = "warn"
|
||||
unwrap_in_result = "warn"
|
||||
unwrap_used = "warn"
|
||||
|
||||
[lints.clippy.cargo]
|
||||
level = "warn"
|
||||
priority = -1
|
||||
|
||||
[lints.clippy.nursery]
|
||||
level = "warn"
|
||||
priority = -1
|
||||
|
||||
[lints.clippy.pedantic]
|
||||
level = "warn"
|
||||
priority = -1
|
||||
|
||||
[lints.rust]
|
||||
absolute_paths_not_starting_with_crate = "warn"
|
||||
ambiguous_negative_literals = "warn"
|
||||
closure_returning_async_block = "warn"
|
||||
explicit_outlives_requirements = "warn"
|
||||
macro_use_extern_crate = "warn"
|
||||
missing_abi = "warn"
|
||||
non_ascii_idents = "warn"
|
||||
redundant_imports = "warn"
|
||||
redundant_lifetimes = "warn"
|
||||
trivial_numeric_casts = "warn"
|
||||
unit_bindings = "warn"
|
||||
unused_import_braces = "warn"
|
||||
unused_lifetimes = "warn"
|
||||
unused_macro_rules = "warn"
|
||||
201
third_party/rust/mtu/LICENSE-APACHE
vendored
201
third_party/rust/mtu/LICENSE-APACHE
vendored
@@ -1,201 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
25
third_party/rust/mtu/LICENSE-MIT
vendored
25
third_party/rust/mtu/LICENSE-MIT
vendored
@@ -1,25 +0,0 @@
|
||||
Copyright (c) 2019 Mozilla Foundation
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
46
third_party/rust/mtu/README.md
vendored
46
third_party/rust/mtu/README.md
vendored
@@ -1,46 +0,0 @@
|
||||
[](https://codecov.io/gh/mozilla/mtu)
|
||||
[](https://isitmaintained.com/project/mozilla/mtu "Average time to resolve an issue")
|
||||
[](https://isitmaintained.com/project/mozilla/mtu "Percentage of issues still open")
|
||||

|
||||
|
||||
# mtu
|
||||
|
||||
A crate to return the name and maximum transmission unit (MTU) of the local network interface
|
||||
towards a given destination `SocketAddr`, optionally from a given local `SocketAddr`.
|
||||
|
||||
## Usage
|
||||
|
||||
This crate exports a single function `interface_and_mtu` that returns the name and
|
||||
[maximum transmission unit (MTU)](https://en.wikipedia.org/wiki/Maximum_transmission_unit)
|
||||
of the outgoing network interface towards a remote destination identified by an `IpAddr`.
|
||||
|
||||
## Example
|
||||
```rust
|
||||
let destination = IpAddr::V4(Ipv4Addr::LOCALHOST);
|
||||
let (name, mtu): (String, usize) = mtu::interface_and_mtu(destination).unwrap();
|
||||
println!("MTU towards {destination} is {mtu} on {name}");
|
||||
```
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
* Linux
|
||||
* macOS
|
||||
* Windows
|
||||
* FreeBSD
|
||||
* NetBSD
|
||||
* OpenBSD
|
||||
* Solaris
|
||||
|
||||
## Notes
|
||||
|
||||
The returned MTU may exceed the maximum IP packet size of 65,535 bytes on some platforms for
|
||||
some remote destinations. (For example, loopback destinations on Windows.)
|
||||
|
||||
The returned interface name is obtained from the operating system.
|
||||
|
||||
## Contributing
|
||||
|
||||
We're happy to receive PRs that improve this crate. Please take a look at our [community
|
||||
guidelines](CODE_OF_CONDUCT.md) beforehand.
|
||||
|
||||
License: MIT OR Apache-2.0
|
||||
31
third_party/rust/mtu/SECURITY.md
vendored
31
third_party/rust/mtu/SECURITY.md
vendored
@@ -1,31 +0,0 @@
|
||||
# Security Policy
|
||||
|
||||
This document describes how security vulnerabilities in this project should be reported.
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Support for `mtu` is based on the Firefox version in which it has landed.
|
||||
Versions of `mtu` in [current versions of Firefox](https://whattrainisitnow.com/calendar/) are actively supported.
|
||||
|
||||
The version of `mtu` that is active can be found in the Firefox repositories:
|
||||
|
||||
- [release](https://hg.mozilla.org/mozilla-unified/file/release/third_party/rust/mtu-transport/Cargo.toml),
|
||||
- [beta](https://hg.mozilla.org/mozilla-unified/file/beta/third_party/rust/mtu-transport/Cargo.toml), and
|
||||
- [trunk/central](https://hg.mozilla.org/mozilla-unified/file/central/third_party/rust/mtu-transport/Cargo.toml),
|
||||
- [ESR 115](https://hg.mozilla.org/mozilla-unified/file/esr115/third_party/rust/mtu-transport/Cargo.toml).
|
||||
|
||||
The listed version in these files corresponds to [tags](https://github.com/mozilla/mtu/tags) on this repository.
|
||||
Releases do not always correspond to a branch.
|
||||
|
||||
We welcome reports of security vulnerabilities in any of these released versions or the latest code on the `main` branch.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
To report a security problem with `mtu`, create a bug in Mozilla's Bugzilla instance in the [Core :: Networking](https://bugzilla.mozilla.org/enter_bug.cgi?product=Core&component=Networking) component.
|
||||
|
||||
**IMPORTANT: For security issues, please make sure that you check the box labelled "Many users could be harmed by this security problem".**
|
||||
We advise that you check this option for anything that involves anything security-relevant, including memory safety, crashes, race conditions, and handling of confidential information.
|
||||
|
||||
Review Mozilla's [guides on bug reporting](https://bugzilla.mozilla.org/page.cgi?id=bug-writing.html) before you open a bug.
|
||||
|
||||
Mozilla operates a [bug bounty program](https://www.mozilla.org/en-US/security/bug-bounty/), for which this project is eligible.
|
||||
114
third_party/rust/mtu/build.rs
vendored
114
third_party/rust/mtu/build.rs
vendored
@@ -1,114 +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.
|
||||
|
||||
#![allow(clippy::unwrap_used)] // OK in build scripts.
|
||||
|
||||
use std::env;
|
||||
|
||||
const BINDINGS: &str = "bindings.rs";
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
fn clang_args() -> Vec<String> {
|
||||
use mozbuild::TOPOBJDIR;
|
||||
|
||||
let flags_path = TOPOBJDIR.join("netwerk/socket/neqo/extra-bindgen-flags");
|
||||
println!("cargo:rerun-if-changed={}", flags_path.to_str().unwrap());
|
||||
|
||||
let mut flags: Vec<String> = std::fs::read_to_string(flags_path)
|
||||
.expect("Failed to read extra-bindgen-flags file")
|
||||
.split_whitespace()
|
||||
.map(std::borrow::ToOwned::to_owned)
|
||||
.collect();
|
||||
|
||||
flags.push(String::from("-include"));
|
||||
flags.push(
|
||||
TOPOBJDIR
|
||||
.join("dist")
|
||||
.join("include")
|
||||
.join("mozilla-config.h")
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
);
|
||||
flags
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "gecko"))]
|
||||
const fn clang_args() -> Vec<String> {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
fn bindgen() {
|
||||
let target_os = env::var("CARGO_CFG_TARGET_OS").expect("CARGO_CFG_TARGET_OS was not set");
|
||||
|
||||
if target_os == "windows" {
|
||||
return;
|
||||
}
|
||||
|
||||
let bindings = if matches!(target_os.as_str(), "linux" | "android") {
|
||||
bindgen::Builder::default()
|
||||
.header_contents("rtnetlink.h", "#include <linux/rtnetlink.h>")
|
||||
// Only generate bindings for the following types
|
||||
.allowlist_type("rtattr|rtmsg|ifinfomsg|nlmsghdr")
|
||||
} else {
|
||||
bindgen::Builder::default()
|
||||
.header_contents(
|
||||
"route.h",
|
||||
"#include <sys/types.h>\n#include <sys/socket.h>\n#include <net/route.h>\n#include <net/if.h>",
|
||||
)
|
||||
// Only generate bindings for the following types and items
|
||||
.allowlist_type("rt_msghdr|rt_metrics|if_data")
|
||||
.allowlist_item("RTAX_MAX|RTM_GET|RTM_VERSION|RTA_DST|RTA_IFP")
|
||||
};
|
||||
|
||||
let bindings = bindings
|
||||
.clang_args(clang_args())
|
||||
// Tell cargo to invalidate the built crate whenever any of the
|
||||
// included header files changed.
|
||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
|
||||
// Constants should be generated as &CStr instead of &[u8].
|
||||
.generate_cstr(true)
|
||||
// Always emit explicit padding fields.
|
||||
.explicit_padding(true)
|
||||
// Default trait should be derived when possible
|
||||
.derive_default(true)
|
||||
// Finish the builder and generate the bindings.
|
||||
.generate()
|
||||
// Unwrap the Result and panic on failure.
|
||||
.expect("Unable to generate bindings");
|
||||
|
||||
// Write the bindings to the $OUT_DIR/$BINDINGS file.
|
||||
let out_path = std::path::PathBuf::from(env::var("OUT_DIR").unwrap()).join(BINDINGS);
|
||||
bindings
|
||||
.write_to_file(out_path.clone())
|
||||
.expect("Couldn't write bindings!");
|
||||
println!("cargo:rustc-env=BINDINGS={}", out_path.display());
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Setup cfg aliases
|
||||
cfg_aliases::cfg_aliases! {
|
||||
// Platforms
|
||||
apple: {
|
||||
any(
|
||||
target_os = "macos",
|
||||
target_os = "ios",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos"
|
||||
)
|
||||
},
|
||||
bsd: {
|
||||
any(
|
||||
target_os = "freebsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "solaris"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
bindgen();
|
||||
}
|
||||
358
third_party/rust/mtu/src/bsd.rs
vendored
358
third_party/rust/mtu/src/bsd.rs
vendored
@@ -1,358 +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 std::{
|
||||
ffi::CStr,
|
||||
io::{Error, ErrorKind, Read as _, Result, Write as _},
|
||||
marker::PhantomData,
|
||||
net::IpAddr,
|
||||
num::TryFromIntError,
|
||||
ops::Deref,
|
||||
ptr, slice,
|
||||
};
|
||||
|
||||
use libc::{
|
||||
freeifaddrs, getifaddrs, getpid, if_indextoname, ifaddrs, in6_addr, in_addr, sockaddr,
|
||||
sockaddr_dl, sockaddr_in, sockaddr_in6, sockaddr_storage, AF_UNSPEC, PF_ROUTE,
|
||||
};
|
||||
use static_assertions::{const_assert, const_assert_eq};
|
||||
|
||||
#[allow(
|
||||
non_camel_case_types,
|
||||
clippy::struct_field_names,
|
||||
clippy::too_many_lines,
|
||||
clippy::cognitive_complexity,
|
||||
dead_code // RTA_IFP is only used on NetBSD and Solaris
|
||||
)]
|
||||
mod bindings {
|
||||
include!(env!("BINDINGS"));
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "netbsd", target_os = "solaris"))]
|
||||
use crate::bsd::bindings::RTA_IFP;
|
||||
use crate::{
|
||||
aligned_by,
|
||||
bsd::bindings::{if_data, rt_msghdr, RTAX_MAX, RTA_DST},
|
||||
default_err,
|
||||
routesocket::RouteSocket,
|
||||
unlikely_err,
|
||||
};
|
||||
|
||||
#[cfg(apple)]
|
||||
const ALIGN: usize = std::mem::size_of::<libc::c_int>();
|
||||
|
||||
#[cfg(bsd)]
|
||||
// See https://github.com/freebsd/freebsd-src/blob/524a425d30fce3d5e47614db796046830b1f6a83/sys/net/route.h#L362-L371
|
||||
// See https://github.com/NetBSD/src/blob/4b50954e98313db58d189dd87b4541929efccb09/sys/net/route.h#L329-L331
|
||||
// See https://github.com/Arquivotheca/Solaris-8/blob/2ad1d32f9eeed787c5adb07eb32544276e2e2444/osnet_volume/usr/src/cmd/cmd-inet/usr.sbin/route.c#L238-L239
|
||||
const ALIGN: usize = std::mem::size_of::<libc::c_long>();
|
||||
|
||||
#[cfg(any(apple, target_os = "freebsd", target_os = "openbsd"))]
|
||||
asserted_const_with_type!(RTM_ADDRS, i32, RTA_DST, u32);
|
||||
|
||||
#[cfg(any(target_os = "netbsd", target_os = "solaris"))]
|
||||
asserted_const_with_type!(RTM_ADDRS, i32, RTA_DST | RTA_IFP, u32);
|
||||
|
||||
#[cfg(not(target_os = "solaris"))]
|
||||
type AddressFamily = u8;
|
||||
|
||||
#[cfg(target_os = "solaris")]
|
||||
type AddressFamily = u16;
|
||||
|
||||
asserted_const_with_type!(AF_INET, AddressFamily, libc::AF_INET, i32);
|
||||
asserted_const_with_type!(AF_INET6, AddressFamily, libc::AF_INET6, i32);
|
||||
asserted_const_with_type!(AF_LINK, AddressFamily, libc::AF_LINK, i32);
|
||||
asserted_const_with_type!(RTM_VERSION, u8, bindings::RTM_VERSION, u32);
|
||||
asserted_const_with_type!(RTM_GET, u8, bindings::RTM_GET, u32);
|
||||
|
||||
const_assert!(std::mem::size_of::<sockaddr_in>() + ALIGN <= u8::MAX as usize);
|
||||
const_assert!(std::mem::size_of::<sockaddr_in6>() + ALIGN <= u8::MAX as usize);
|
||||
const_assert!(std::mem::size_of::<rt_msghdr>() <= u8::MAX as usize);
|
||||
|
||||
struct IfAddrs(*mut ifaddrs);
|
||||
|
||||
impl Default for IfAddrs {
|
||||
fn default() -> Self {
|
||||
Self(ptr::null_mut())
|
||||
}
|
||||
}
|
||||
|
||||
impl IfAddrs {
|
||||
fn new() -> Result<Self> {
|
||||
let mut ifap = Self::default();
|
||||
// getifaddrs allocates memory for the linked list of interfaces that is freed by
|
||||
// `IfAddrs::drop`.
|
||||
if unsafe { getifaddrs(ptr::from_mut(&mut ifap.0)) } != 0 {
|
||||
return Err(Error::last_os_error());
|
||||
}
|
||||
Ok(ifap)
|
||||
}
|
||||
|
||||
const fn iter(&self) -> IfAddrPtr {
|
||||
IfAddrPtr {
|
||||
ptr: self.0,
|
||||
_ref: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for IfAddrs {
|
||||
fn drop(&mut self) {
|
||||
if !self.0.is_null() {
|
||||
// Free the memory allocated by `getifaddrs`.
|
||||
unsafe {
|
||||
freeifaddrs(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct IfAddrPtr<'a> {
|
||||
ptr: *mut ifaddrs,
|
||||
_ref: PhantomData<&'a ifaddrs>,
|
||||
}
|
||||
|
||||
impl IfAddrPtr<'_> {
|
||||
fn addr(&self) -> sockaddr {
|
||||
unsafe { *self.ifa_addr }
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
unsafe { CStr::from_ptr(self.ifa_name).to_string_lossy().to_string() }
|
||||
}
|
||||
|
||||
fn data(&self) -> Option<if_data> {
|
||||
if self.ifa_data.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { self.ifa_data.cast::<if_data>().read() })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for IfAddrPtr<'_> {
|
||||
type Target = ifaddrs;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { self.ptr.as_ref().expect("can deref") }
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for IfAddrPtr<'_> {
|
||||
type Item = Self;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
ptr::NonNull::new(self.ptr).map(|p| {
|
||||
self.ptr = unsafe { p.as_ref().ifa_next };
|
||||
IfAddrPtr {
|
||||
ptr: p.as_ptr(),
|
||||
_ref: PhantomData,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn if_name_mtu(idx: u32) -> Result<(String, Option<usize>)> {
|
||||
let mut name = [0; libc::IF_NAMESIZE];
|
||||
// if_indextoname writes into the provided buffer.
|
||||
if unsafe { if_indextoname(idx, name.as_mut_ptr()).is_null() } {
|
||||
return Err(Error::last_os_error());
|
||||
}
|
||||
// Convert to Rust string.
|
||||
let name = unsafe {
|
||||
CStr::from_ptr(name.as_ptr())
|
||||
.to_str()
|
||||
.map_err(|err| Error::new(ErrorKind::Other, err))?
|
||||
};
|
||||
let mtu = IfAddrs::new()?
|
||||
.iter()
|
||||
.find(|ifa| ifa.addr().sa_family == AF_LINK && ifa.name() == name)
|
||||
.and_then(|ifa| ifa.data())
|
||||
.and_then(|ifa_data| usize::try_from(ifa_data.ifi_mtu).ok());
|
||||
Ok((name.to_string(), mtu))
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
union SockaddrStorage {
|
||||
sin: sockaddr_in,
|
||||
sin6: sockaddr_in6,
|
||||
}
|
||||
|
||||
fn sockaddr_len(af: AddressFamily) -> Result<usize> {
|
||||
let sa_len = match af {
|
||||
AF_INET => std::mem::size_of::<sockaddr_in>(),
|
||||
AF_INET6 => std::mem::size_of::<sockaddr_in6>(),
|
||||
_ => {
|
||||
return Err(Error::new(
|
||||
ErrorKind::InvalidInput,
|
||||
format!("Unsupported address family {af:?}"),
|
||||
))
|
||||
}
|
||||
};
|
||||
Ok(aligned_by(sa_len, ALIGN))
|
||||
}
|
||||
|
||||
impl From<IpAddr> for SockaddrStorage {
|
||||
fn from(ip: IpAddr) -> Self {
|
||||
match ip {
|
||||
IpAddr::V4(ip) => SockaddrStorage {
|
||||
sin: sockaddr_in {
|
||||
#[cfg(not(target_os = "solaris"))]
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
// `sockaddr_in` len is <= u8::MAX per `const_assert!` above.
|
||||
sin_len: std::mem::size_of::<sockaddr_in>() as u8,
|
||||
sin_family: AF_INET,
|
||||
sin_addr: in_addr {
|
||||
s_addr: u32::from_ne_bytes(ip.octets()),
|
||||
},
|
||||
sin_port: 0,
|
||||
sin_zero: [0; 8],
|
||||
},
|
||||
},
|
||||
IpAddr::V6(ip) => SockaddrStorage {
|
||||
sin6: sockaddr_in6 {
|
||||
#[cfg(not(target_os = "solaris"))]
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
// `sockaddr_in6` len is <= u8::MAX per `const_assert!` above.
|
||||
sin6_len: std::mem::size_of::<sockaddr_in6>() as u8,
|
||||
sin6_family: AF_INET6,
|
||||
sin6_addr: in6_addr {
|
||||
s6_addr: ip.octets(),
|
||||
},
|
||||
sin6_port: 0,
|
||||
sin6_flowinfo: 0,
|
||||
sin6_scope_id: 0,
|
||||
#[cfg(target_os = "solaris")]
|
||||
__sin6_src_id: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct RouteMessage {
|
||||
rtm: rt_msghdr,
|
||||
sa: SockaddrStorage,
|
||||
}
|
||||
|
||||
impl RouteMessage {
|
||||
fn new(remote: IpAddr, seq: i32) -> Result<Self> {
|
||||
let sa = SockaddrStorage::from(remote);
|
||||
let sa_len = sockaddr_len(match remote {
|
||||
IpAddr::V4(_) => AF_INET,
|
||||
IpAddr::V6(_) => AF_INET6,
|
||||
})?;
|
||||
Ok(Self {
|
||||
rtm: rt_msghdr {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
// `rt_msghdr` len + `ALIGN` is <= u8::MAX per `const_assert!` above.
|
||||
rtm_msglen: (std::mem::size_of::<rt_msghdr>() + sa_len) as u16,
|
||||
rtm_version: RTM_VERSION,
|
||||
rtm_type: RTM_GET,
|
||||
rtm_seq: seq,
|
||||
rtm_addrs: RTM_ADDRS,
|
||||
..Default::default()
|
||||
},
|
||||
sa,
|
||||
})
|
||||
}
|
||||
|
||||
const fn version(&self) -> u8 {
|
||||
self.rtm.rtm_version
|
||||
}
|
||||
|
||||
const fn kind(&self) -> u8 {
|
||||
self.rtm.rtm_type
|
||||
}
|
||||
|
||||
const fn len(&self) -> usize {
|
||||
self.rtm.rtm_msglen as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&RouteMessage> for &[u8] {
|
||||
fn from(value: &RouteMessage) -> Self {
|
||||
debug_assert!(value.len() >= std::mem::size_of::<Self>());
|
||||
unsafe { slice::from_raw_parts(ptr::from_ref(value).cast(), value.len()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&[u8]> for rt_msghdr {
|
||||
fn from(value: &[u8]) -> Self {
|
||||
debug_assert!(value.len() >= std::mem::size_of::<Self>());
|
||||
unsafe { ptr::read_unaligned(value.as_ptr().cast()) }
|
||||
}
|
||||
}
|
||||
|
||||
fn if_index_mtu(remote: IpAddr) -> Result<(u16, Option<usize>)> {
|
||||
// Open route socket.
|
||||
let mut fd = RouteSocket::new(PF_ROUTE, AF_UNSPEC)?;
|
||||
|
||||
// Send route message.
|
||||
let query_seq = RouteSocket::new_seq();
|
||||
let query = RouteMessage::new(remote, query_seq)?;
|
||||
let query_version = query.version();
|
||||
let query_type = query.kind();
|
||||
fd.write_all((&query).into())?;
|
||||
|
||||
// Read route messages.
|
||||
let pid = unsafe { getpid() };
|
||||
loop {
|
||||
let mut buf = vec![
|
||||
0u8;
|
||||
std::mem::size_of::<rt_msghdr>() +
|
||||
// There will never be `RTAX_MAX` sockaddrs attached, but it's a safe upper bound.
|
||||
(RTAX_MAX as usize * std::mem::size_of::<sockaddr_storage>())
|
||||
];
|
||||
let len = fd.read(&mut buf[..])?;
|
||||
if len < std::mem::size_of::<rt_msghdr>() {
|
||||
return Err(default_err());
|
||||
}
|
||||
let (reply, mut sa) = buf.split_at(std::mem::size_of::<rt_msghdr>());
|
||||
let reply: rt_msghdr = reply.into();
|
||||
if !(reply.rtm_version == query_version
|
||||
&& reply.rtm_pid == pid
|
||||
&& reply.rtm_seq == query_seq)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if reply.rtm_type != query_type {
|
||||
return Err(default_err());
|
||||
}
|
||||
|
||||
// This is a reply to our query.
|
||||
// This is the reply we are looking for.
|
||||
// Some BSDs let us get the interface index and MTU directly from the reply.
|
||||
let mtu = (reply.rtm_rmx.rmx_mtu != 0)
|
||||
.then(|| usize::try_from(reply.rtm_rmx.rmx_mtu))
|
||||
.transpose()
|
||||
.map_err(|e: TryFromIntError| unlikely_err(e.to_string()))?;
|
||||
if reply.rtm_index != 0 {
|
||||
// Some BSDs return the interface index directly.
|
||||
return Ok((reply.rtm_index, mtu));
|
||||
}
|
||||
// For others, we need to extract it from the sockaddrs.
|
||||
for i in 0..RTAX_MAX {
|
||||
if (reply.rtm_addrs & (1 << i)) == 0 {
|
||||
continue;
|
||||
}
|
||||
let saddr = unsafe { ptr::read_unaligned(sa.as_ptr().cast::<sockaddr>()) };
|
||||
if saddr.sa_family != AF_LINK {
|
||||
(_, sa) = sa.split_at(sockaddr_len(saddr.sa_family)?);
|
||||
continue;
|
||||
}
|
||||
let sdl = unsafe { ptr::read_unaligned(sa.as_ptr().cast::<sockaddr_dl>()) };
|
||||
return Ok((sdl.sdl_index, mtu));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn interface_and_mtu_impl(remote: IpAddr) -> Result<(String, usize)> {
|
||||
let (if_index, mtu1) = if_index_mtu(remote)?;
|
||||
let (if_name, mtu2) = if_name_mtu(if_index.into())?;
|
||||
Ok((if_name, mtu1.or(mtu2).ok_or_else(default_err)?))
|
||||
}
|
||||
191
third_party/rust/mtu/src/lib.rs
vendored
191
third_party/rust/mtu/src/lib.rs
vendored
@@ -1,191 +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.
|
||||
|
||||
//! A crate to return the name and maximum transmission unit (MTU) of the local network interface
|
||||
//! towards a given destination `SocketAddr`, optionally from a given local `SocketAddr`.
|
||||
//!
|
||||
//! # Usage
|
||||
//!
|
||||
//! This crate exports a single function `interface_and_mtu` that returns the name and
|
||||
//! [maximum transmission unit (MTU)](https://en.wikipedia.org/wiki/Maximum_transmission_unit)
|
||||
//! of the outgoing network interface towards a remote destination identified by an `IpAddr`.
|
||||
//!
|
||||
//! # Example
|
||||
//! ```
|
||||
//! # use std::net::{IpAddr, Ipv4Addr};
|
||||
//! let destination = IpAddr::V4(Ipv4Addr::LOCALHOST);
|
||||
//! let (name, mtu): (String, usize) = mtu::interface_and_mtu(destination).unwrap();
|
||||
//! println!("MTU towards {destination} is {mtu} on {name}");
|
||||
//! ```
|
||||
//!
|
||||
//! # Supported Platforms
|
||||
//!
|
||||
//! * Linux
|
||||
//! * macOS
|
||||
//! * Windows
|
||||
//! * FreeBSD
|
||||
//! * NetBSD
|
||||
//! * OpenBSD
|
||||
//! * Solaris
|
||||
//!
|
||||
//! # Notes
|
||||
//!
|
||||
//! The returned MTU may exceed the maximum IP packet size of 65,535 bytes on some platforms for
|
||||
//! some remote destinations. (For example, loopback destinations on Windows.)
|
||||
//!
|
||||
//! The returned interface name is obtained from the operating system.
|
||||
//!
|
||||
//! # Contributing
|
||||
//!
|
||||
//! We're happy to receive PRs that improve this crate. Please take a look at our [community
|
||||
//! guidelines](CODE_OF_CONDUCT.md) beforehand.
|
||||
|
||||
use std::{
|
||||
io::{Error, ErrorKind, Result},
|
||||
net::IpAddr,
|
||||
};
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
macro_rules! asserted_const_with_type {
|
||||
($name:ident, $t1:ty, $e:expr, $t2:ty) => {
|
||||
#[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)] // Guarded by the following `const_assert_eq!`.
|
||||
const $name: $t1 = $e as $t1;
|
||||
const_assert_eq!($name as $t2, $e);
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(any(apple, bsd))]
|
||||
mod bsd;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
mod linux;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
mod windows;
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
mod routesocket;
|
||||
|
||||
#[cfg(any(apple, bsd))]
|
||||
use bsd::interface_and_mtu_impl;
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
use linux::interface_and_mtu_impl;
|
||||
#[cfg(target_os = "windows")]
|
||||
use windows::interface_and_mtu_impl;
|
||||
|
||||
/// Prepare a default error.
|
||||
fn default_err() -> Error {
|
||||
Error::new(ErrorKind::NotFound, "Local interface MTU not found")
|
||||
}
|
||||
|
||||
/// Prepare an error for cases that "should never happen".
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
fn unlikely_err(msg: String) -> Error {
|
||||
debug_assert!(false, "{msg}");
|
||||
Error::new(ErrorKind::Other, msg)
|
||||
}
|
||||
|
||||
/// Align `size` to the next multiple of `align` (which needs to be a power of two).
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
const fn aligned_by(size: usize, align: usize) -> usize {
|
||||
if size == 0 {
|
||||
align
|
||||
} else {
|
||||
1 + ((size - 1) | (align - 1))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the name and maximum transmission unit (MTU) of the outgoing network interface towards a
|
||||
/// remote destination identified by an [`IpAddr`],
|
||||
///
|
||||
/// The returned MTU may exceed the maximum IP packet size of 65,535 bytes on some platforms for
|
||||
/// some remote destinations. (For example, loopback destinations on Windows.)
|
||||
///
|
||||
/// The returned interface name is obtained from the operating system.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function returns an error if the local interface MTU cannot be determined.
|
||||
pub fn interface_and_mtu(remote: IpAddr) -> Result<(String, usize)> {
|
||||
interface_and_mtu_impl(remote)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::{
|
||||
env,
|
||||
net::{IpAddr, Ipv4Addr, Ipv6Addr},
|
||||
};
|
||||
|
||||
use crate::interface_and_mtu;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct NameMtu<'a>(Option<&'a str>, usize);
|
||||
|
||||
impl PartialEq<NameMtu<'_>> for (String, usize) {
|
||||
fn eq(&self, other: &NameMtu<'_>) -> bool {
|
||||
other.0.map_or(true, |name| name == self.0) && other.1 == self.1
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(apple, target_os = "freebsd",))]
|
||||
const LOOPBACK: &[NameMtu] = &[NameMtu(Some("lo0"), 16_384), NameMtu(Some("lo0"), 16_384)];
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
const LOOPBACK: &[NameMtu] = &[NameMtu(Some("lo"), 65_536), NameMtu(Some("lo"), 65_536)];
|
||||
#[cfg(target_os = "windows")]
|
||||
const LOOPBACK: &[NameMtu] = &[
|
||||
NameMtu(Some("loopback_0"), 4_294_967_295),
|
||||
NameMtu(Some("loopback_0"), 4_294_967_295),
|
||||
];
|
||||
#[cfg(target_os = "openbsd")]
|
||||
const LOOPBACK: &[NameMtu] = &[NameMtu(Some("lo0"), 32_768), NameMtu(Some("lo0"), 32_768)];
|
||||
#[cfg(target_os = "netbsd")]
|
||||
const LOOPBACK: &[NameMtu] = &[NameMtu(Some("lo0"), 33_624), NameMtu(Some("lo0"), 33_624)];
|
||||
#[cfg(target_os = "solaris")]
|
||||
// Note: Different loopback MTUs for IPv4 and IPv6?!
|
||||
const LOOPBACK: &[NameMtu] = &[NameMtu(Some("lo0"), 8_232), NameMtu(Some("lo0"), 8_252)];
|
||||
|
||||
// Non-loopback interface names are unpredictable, so we only check the MTU.
|
||||
const INET: NameMtu = NameMtu(None, 1_500);
|
||||
|
||||
#[test]
|
||||
fn loopback_v4() {
|
||||
assert_eq!(
|
||||
interface_and_mtu(IpAddr::V4(Ipv4Addr::LOCALHOST)).unwrap(),
|
||||
LOOPBACK[0]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn loopback_v6() {
|
||||
assert_eq!(
|
||||
interface_and_mtu(IpAddr::V6(Ipv6Addr::LOCALHOST)).unwrap(),
|
||||
LOOPBACK[1]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inet_v4() {
|
||||
assert_eq!(
|
||||
interface_and_mtu(IpAddr::V4(Ipv4Addr::new(
|
||||
104, 16, 132, 229 // cloudflare.com
|
||||
)))
|
||||
.unwrap(),
|
||||
INET
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inet_v6() {
|
||||
match interface_and_mtu(IpAddr::V6(Ipv6Addr::new(
|
||||
0x2606, 0x4700, 0, 0, 0, 0, 0x6810, 0x84e5, // cloudflare.com
|
||||
))) {
|
||||
Ok(res) => assert_eq!(res, INET),
|
||||
// The GitHub CI environment does not have IPv6 connectivity.
|
||||
Err(_) => assert!(env::var("GITHUB_ACTIONS").is_ok()),
|
||||
}
|
||||
}
|
||||
}
|
||||
351
third_party/rust/mtu/src/linux.rs
vendored
351
third_party/rust/mtu/src/linux.rs
vendored
@@ -1,351 +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 std::{
|
||||
ffi::CStr,
|
||||
io::{Error, ErrorKind, Read as _, Result, Write as _},
|
||||
net::IpAddr,
|
||||
num::TryFromIntError,
|
||||
ptr, slice,
|
||||
};
|
||||
|
||||
use libc::{
|
||||
c_int, AF_NETLINK, ARPHRD_NONE, IFLA_IFNAME, IFLA_MTU, NETLINK_ROUTE, RTA_DST, RTA_OIF,
|
||||
RTM_GETLINK, RTM_GETROUTE, RTM_NEWLINK, RTM_NEWROUTE, RTN_UNICAST, RT_SCOPE_UNIVERSE,
|
||||
RT_TABLE_MAIN,
|
||||
};
|
||||
use static_assertions::{const_assert, const_assert_eq};
|
||||
|
||||
use crate::{aligned_by, default_err, routesocket::RouteSocket, unlikely_err};
|
||||
|
||||
#[allow(
|
||||
clippy::struct_field_names,
|
||||
non_camel_case_types,
|
||||
clippy::too_many_lines
|
||||
)]
|
||||
mod bindings {
|
||||
include!(env!("BINDINGS"));
|
||||
}
|
||||
|
||||
use bindings::{ifinfomsg, nlmsghdr, rtattr, rtmsg};
|
||||
|
||||
asserted_const_with_type!(AF_INET, u8, libc::AF_INET, i32);
|
||||
asserted_const_with_type!(AF_INET6, u8, libc::AF_INET6, i32);
|
||||
asserted_const_with_type!(AF_UNSPEC, u8, libc::AF_UNSPEC, i32);
|
||||
asserted_const_with_type!(NLM_F_REQUEST, u16, libc::NLM_F_REQUEST, c_int);
|
||||
asserted_const_with_type!(NLM_F_ACK, u16, libc::NLM_F_ACK, c_int);
|
||||
asserted_const_with_type!(NLMSG_ERROR, u16, libc::NLMSG_ERROR, c_int);
|
||||
|
||||
const_assert!(std::mem::size_of::<nlmsghdr>() <= u8::MAX as usize);
|
||||
const_assert!(std::mem::size_of::<rtmsg>() <= u8::MAX as usize);
|
||||
const_assert!(std::mem::size_of::<rtattr>() <= u8::MAX as usize);
|
||||
const_assert!(std::mem::size_of::<ifinfomsg>() <= u8::MAX as usize);
|
||||
|
||||
const NETLINK_BUFFER_SIZE: usize = 8192; // See netlink(7) man page.
|
||||
|
||||
#[repr(C)]
|
||||
enum AddrBytes {
|
||||
V4([u8; 4]),
|
||||
V6([u8; 16]),
|
||||
}
|
||||
|
||||
impl AddrBytes {
|
||||
const fn new(ip: IpAddr) -> Self {
|
||||
match ip {
|
||||
IpAddr::V4(ip) => Self::V4(ip.octets()),
|
||||
IpAddr::V6(ip) => Self::V6(ip.octets()),
|
||||
}
|
||||
}
|
||||
|
||||
const fn len(&self) -> usize {
|
||||
match self {
|
||||
Self::V4(_) => 4,
|
||||
Self::V6(_) => 16,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AddrBytes> for [u8; 16] {
|
||||
fn from(addr: AddrBytes) -> Self {
|
||||
match addr {
|
||||
AddrBytes::V4(bytes) => {
|
||||
let mut v6 = [0; 16];
|
||||
v6[..4].copy_from_slice(&bytes);
|
||||
v6
|
||||
}
|
||||
AddrBytes::V6(bytes) => bytes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Default)]
|
||||
struct IfIndexMsg {
|
||||
nlmsg: nlmsghdr,
|
||||
rtm: rtmsg,
|
||||
rt: rtattr,
|
||||
addr: [u8; 16],
|
||||
}
|
||||
|
||||
impl IfIndexMsg {
|
||||
fn new(remote: IpAddr, nlmsg_seq: u32) -> Self {
|
||||
let addr = AddrBytes::new(remote);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
// Structs lens are <= u8::MAX per `const_assert!`s above; `addr_bytes` is max. 16 for IPv6.
|
||||
let nlmsg_len = (std::mem::size_of::<nlmsghdr>()
|
||||
+ std::mem::size_of::<rtmsg>()
|
||||
+ std::mem::size_of::<rtattr>()
|
||||
+ addr.len()) as u32;
|
||||
Self {
|
||||
nlmsg: nlmsghdr {
|
||||
nlmsg_len,
|
||||
nlmsg_type: RTM_GETROUTE,
|
||||
nlmsg_flags: NLM_F_REQUEST | NLM_F_ACK,
|
||||
nlmsg_seq,
|
||||
..Default::default()
|
||||
},
|
||||
rtm: rtmsg {
|
||||
rtm_family: match remote {
|
||||
IpAddr::V4(_) => AF_INET,
|
||||
IpAddr::V6(_) => AF_INET6,
|
||||
},
|
||||
rtm_dst_len: match remote {
|
||||
IpAddr::V4(_) => 32,
|
||||
IpAddr::V6(_) => 128,
|
||||
},
|
||||
rtm_table: RT_TABLE_MAIN,
|
||||
rtm_scope: RT_SCOPE_UNIVERSE,
|
||||
rtm_type: RTN_UNICAST,
|
||||
..Default::default()
|
||||
},
|
||||
rt: rtattr {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
// Structs len is <= u8::MAX per `const_assert!` above; `addr_bytes` is max. 16 for IPv6.
|
||||
rta_len: (std::mem::size_of::<rtattr>() + addr.len()) as u16,
|
||||
rta_type: RTA_DST,
|
||||
},
|
||||
addr: addr.into(),
|
||||
}
|
||||
}
|
||||
|
||||
const fn len(&self) -> usize {
|
||||
let len = self.nlmsg.nlmsg_len as usize;
|
||||
debug_assert!(len <= std::mem::size_of::<Self>());
|
||||
len
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&IfIndexMsg> for &[u8] {
|
||||
fn from(value: &IfIndexMsg) -> Self {
|
||||
unsafe { slice::from_raw_parts(ptr::from_ref(value).cast(), value.len()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for nlmsghdr {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(value: &[u8]) -> Result<Self> {
|
||||
if value.len() < std::mem::size_of::<Self>() {
|
||||
return Err(default_err());
|
||||
}
|
||||
Ok(unsafe { ptr::read_unaligned(value.as_ptr().cast()) })
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_c_int(buf: &[u8]) -> Result<c_int> {
|
||||
let bytes = <&[u8] as TryInto<[u8; std::mem::size_of::<c_int>()]>>::try_into(
|
||||
&buf[..std::mem::size_of::<c_int>()],
|
||||
)
|
||||
.map_err(|_| default_err())?;
|
||||
Ok(c_int::from_ne_bytes(bytes))
|
||||
}
|
||||
|
||||
fn read_msg_with_seq(fd: &mut RouteSocket, seq: u32, kind: u16) -> Result<(nlmsghdr, Vec<u8>)> {
|
||||
loop {
|
||||
let buf = &mut [0u8; NETLINK_BUFFER_SIZE];
|
||||
let len = fd.read(buf.as_mut_slice())?;
|
||||
let mut next = &buf[..len];
|
||||
while std::mem::size_of::<nlmsghdr>() <= next.len() {
|
||||
let (hdr, mut msg) = next.split_at(std::mem::size_of::<nlmsghdr>());
|
||||
let hdr: nlmsghdr = hdr.try_into()?;
|
||||
// `msg` has the remainder of this message plus any following messages.
|
||||
// Strip those it off and assign them to `next`.
|
||||
debug_assert!(std::mem::size_of::<nlmsghdr>() <= hdr.nlmsg_len as usize);
|
||||
(msg, next) = msg.split_at(hdr.nlmsg_len as usize - std::mem::size_of::<nlmsghdr>());
|
||||
|
||||
if hdr.nlmsg_seq != seq {
|
||||
continue;
|
||||
}
|
||||
|
||||
if hdr.nlmsg_type == NLMSG_ERROR {
|
||||
// Extract the error code and return it.
|
||||
let err = parse_c_int(msg)?;
|
||||
if err != 0 {
|
||||
return Err(Error::from_raw_os_error(-err));
|
||||
}
|
||||
} else if hdr.nlmsg_type == kind {
|
||||
// Return the header and the message.
|
||||
return Ok((hdr, msg.to_vec()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for rtattr {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(value: &[u8]) -> Result<Self> {
|
||||
if value.len() < std::mem::size_of::<Self>() {
|
||||
return Err(default_err());
|
||||
}
|
||||
Ok(unsafe { ptr::read_unaligned(value.as_ptr().cast()) })
|
||||
}
|
||||
}
|
||||
|
||||
struct RtAttr<'a> {
|
||||
hdr: rtattr,
|
||||
msg: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a> RtAttr<'a> {
|
||||
fn new(bytes: &'a [u8]) -> Result<Self> {
|
||||
debug_assert!(bytes.len() >= std::mem::size_of::<rtattr>());
|
||||
let (hdr, mut msg) = bytes.split_at(std::mem::size_of::<rtattr>());
|
||||
let hdr: rtattr = hdr.try_into()?;
|
||||
let aligned_len = aligned_by(hdr.rta_len.into(), 4);
|
||||
debug_assert!(std::mem::size_of::<rtattr>() <= aligned_len);
|
||||
(msg, _) = msg.split_at(aligned_len - std::mem::size_of::<rtattr>());
|
||||
Ok(Self { hdr, msg })
|
||||
}
|
||||
}
|
||||
|
||||
struct RtAttrs<'a>(&'a [u8]);
|
||||
|
||||
impl<'a> Iterator for RtAttrs<'a> {
|
||||
type Item = RtAttr<'a>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if std::mem::size_of::<rtattr>() <= self.0.len() {
|
||||
let attr = RtAttr::new(self.0).ok()?;
|
||||
let aligned_len = aligned_by(attr.hdr.rta_len.into(), 4);
|
||||
debug_assert!(self.0.len() >= aligned_len);
|
||||
self.0 = self.0.split_at(aligned_len).1;
|
||||
Some(attr)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn if_index(remote: IpAddr, fd: &mut RouteSocket) -> Result<i32> {
|
||||
// Send RTM_GETROUTE message to get the interface index associated with the destination.
|
||||
let msg_seq = RouteSocket::new_seq();
|
||||
let msg = IfIndexMsg::new(remote, msg_seq);
|
||||
fd.write_all((&msg).into())?;
|
||||
|
||||
// Receive RTM_GETROUTE response.
|
||||
let (_hdr, mut buf) = read_msg_with_seq(fd, msg_seq, RTM_NEWROUTE)?;
|
||||
debug_assert!(std::mem::size_of::<rtmsg>() <= buf.len());
|
||||
let buf = buf.split_off(std::mem::size_of::<rtmsg>());
|
||||
|
||||
// Parse through the attributes to find the interface index.
|
||||
for attr in RtAttrs(buf.as_slice()).by_ref() {
|
||||
if attr.hdr.rta_type == RTA_OIF {
|
||||
// We have our interface index.
|
||||
return parse_c_int(attr.msg);
|
||||
}
|
||||
}
|
||||
Err(default_err())
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct IfInfoMsg {
|
||||
nlmsg: nlmsghdr,
|
||||
ifim: ifinfomsg,
|
||||
}
|
||||
|
||||
impl IfInfoMsg {
|
||||
fn new(if_index: i32, nlmsg_seq: u32) -> Self {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
// Structs lens are <= u8::MAX per `const_assert!`s above.
|
||||
let nlmsg_len = (std::mem::size_of::<nlmsghdr>() + std::mem::size_of::<ifinfomsg>()) as u32;
|
||||
Self {
|
||||
nlmsg: nlmsghdr {
|
||||
nlmsg_len,
|
||||
nlmsg_type: RTM_GETLINK,
|
||||
nlmsg_flags: NLM_F_REQUEST | NLM_F_ACK,
|
||||
nlmsg_seq,
|
||||
..Default::default()
|
||||
},
|
||||
ifim: ifinfomsg {
|
||||
ifi_family: AF_UNSPEC,
|
||||
ifi_type: ARPHRD_NONE,
|
||||
ifi_index: if_index,
|
||||
..Default::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const fn len(&self) -> usize {
|
||||
self.nlmsg.nlmsg_len as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&IfInfoMsg> for &[u8] {
|
||||
fn from(value: &IfInfoMsg) -> Self {
|
||||
debug_assert!(value.len() >= std::mem::size_of::<Self>());
|
||||
unsafe { slice::from_raw_parts(ptr::from_ref(value).cast(), value.len()) }
|
||||
}
|
||||
}
|
||||
|
||||
fn if_name_mtu(if_index: i32, fd: &mut RouteSocket) -> Result<(String, usize)> {
|
||||
// Send RTM_GETLINK message to get interface information for the given interface index.
|
||||
let msg_seq = RouteSocket::new_seq();
|
||||
let msg = IfInfoMsg::new(if_index, msg_seq);
|
||||
fd.write_all((&msg).into())?;
|
||||
|
||||
// Receive RTM_GETLINK response.
|
||||
let (_hdr, mut buf) = read_msg_with_seq(fd, msg_seq, RTM_NEWLINK)?;
|
||||
debug_assert!(std::mem::size_of::<ifinfomsg>() <= buf.len());
|
||||
let buf = buf.split_off(std::mem::size_of::<ifinfomsg>());
|
||||
|
||||
// Parse through the attributes to find the interface name and MTU.
|
||||
let mut ifname = None;
|
||||
let mut mtu = None;
|
||||
for attr in RtAttrs(buf.as_slice()).by_ref() {
|
||||
match attr.hdr.rta_type {
|
||||
IFLA_IFNAME => {
|
||||
let name = CStr::from_bytes_until_nul(attr.msg)
|
||||
.map_err(|err| Error::new(ErrorKind::Other, err))?;
|
||||
ifname = Some(
|
||||
name.to_str()
|
||||
.map_err(|err| Error::new(ErrorKind::Other, err))?
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
IFLA_MTU => {
|
||||
mtu = Some(
|
||||
parse_c_int(attr.msg)?
|
||||
.try_into()
|
||||
.map_err(|e: TryFromIntError| unlikely_err(e.to_string()))?,
|
||||
);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
if let (Some(ifname), Some(mtu)) = (ifname.as_ref(), mtu.as_ref()) {
|
||||
return Ok((ifname.clone(), *mtu));
|
||||
}
|
||||
}
|
||||
|
||||
Err(default_err())
|
||||
}
|
||||
|
||||
pub fn interface_and_mtu_impl(remote: IpAddr) -> Result<(String, usize)> {
|
||||
// Create a netlink socket.
|
||||
let mut fd = RouteSocket::new(AF_NETLINK, NETLINK_ROUTE)?;
|
||||
let if_index = if_index(remote, &mut fd)?;
|
||||
if_name_mtu(if_index, &mut fd)
|
||||
}
|
||||
81
third_party/rust/mtu/src/routesocket.rs
vendored
81
third_party/rust/mtu/src/routesocket.rs
vendored
@@ -1,81 +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 std::{
|
||||
io::{Error, Read, Result, Write},
|
||||
num::TryFromIntError,
|
||||
os::fd::{AsRawFd, FromRawFd as _, OwnedFd},
|
||||
sync::atomic::Ordering,
|
||||
};
|
||||
|
||||
use libc::{fsync, read, socket, write, SOCK_RAW};
|
||||
|
||||
use crate::unlikely_err;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
type AtomicRouteSocketSeq = std::sync::atomic::AtomicU32;
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
type RouteSocketSeq = u32;
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "android")))]
|
||||
type AtomicRouteSocketSeq = std::sync::atomic::AtomicI32;
|
||||
#[cfg(not(any(target_os = "linux", target_os = "android")))]
|
||||
type RouteSocketSeq = i32;
|
||||
|
||||
static SEQ: AtomicRouteSocketSeq = AtomicRouteSocketSeq::new(0);
|
||||
|
||||
pub struct RouteSocket(OwnedFd);
|
||||
|
||||
impl RouteSocket {
|
||||
pub fn new(domain: libc::c_int, protocol: libc::c_int) -> Result<Self> {
|
||||
let fd = unsafe { socket(domain, SOCK_RAW, protocol) };
|
||||
if fd == -1 {
|
||||
return Err(Error::last_os_error());
|
||||
}
|
||||
Ok(Self(unsafe { OwnedFd::from_raw_fd(fd) }))
|
||||
}
|
||||
|
||||
pub fn new_seq() -> RouteSocketSeq {
|
||||
SEQ.fetch_add(1, Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for RouteSocket {
|
||||
fn as_raw_fd(&self) -> i32 {
|
||||
self.0.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
fn check_result(res: isize) -> Result<usize> {
|
||||
if res == -1 {
|
||||
Err(Error::last_os_error())
|
||||
} else {
|
||||
Ok(res
|
||||
.try_into()
|
||||
.map_err(|e: TryFromIntError| unlikely_err(e.to_string()))?)
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for RouteSocket {
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize> {
|
||||
let res = unsafe { write(self.as_raw_fd(), buf.as_ptr().cast(), buf.len()) };
|
||||
check_result(res)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> Result<()> {
|
||||
let res = unsafe { fsync(self.as_raw_fd()) };
|
||||
check_result(res as isize).and(Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for RouteSocket {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
||||
// If we've written a well-formed message into the kernel via `write`, we should be able to
|
||||
// read a well-formed message back out, and not block.
|
||||
let res = unsafe { read(self.as_raw_fd(), buf.as_mut_ptr().cast(), buf.len()) };
|
||||
check_result(res)
|
||||
}
|
||||
}
|
||||
143
third_party/rust/mtu/src/windows.rs
vendored
143
third_party/rust/mtu/src/windows.rs
vendored
@@ -1,143 +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 std::{
|
||||
ffi::CStr,
|
||||
io::{Error, ErrorKind, Result},
|
||||
net::IpAddr,
|
||||
ptr, slice,
|
||||
};
|
||||
|
||||
use windows::Win32::{
|
||||
Foundation::NO_ERROR,
|
||||
NetworkManagement::{
|
||||
IpHelper::{
|
||||
if_indextoname, FreeMibTable, GetBestInterfaceEx, GetIpInterfaceTable,
|
||||
MIB_IPINTERFACE_ROW, MIB_IPINTERFACE_TABLE,
|
||||
},
|
||||
Ndis::IF_MAX_STRING_SIZE,
|
||||
},
|
||||
Networking::WinSock::{
|
||||
AF_INET, AF_INET6, IN6_ADDR, IN6_ADDR_0, IN_ADDR, IN_ADDR_0, SOCKADDR, SOCKADDR_IN,
|
||||
SOCKADDR_IN6, SOCKADDR_INET,
|
||||
},
|
||||
};
|
||||
|
||||
use crate::default_err;
|
||||
|
||||
struct MibTablePtr(*mut MIB_IPINTERFACE_TABLE);
|
||||
|
||||
impl MibTablePtr {
|
||||
fn mut_ptr_ptr(&mut self) -> *mut *mut MIB_IPINTERFACE_TABLE {
|
||||
ptr::from_mut(&mut self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for MibTablePtr {
|
||||
fn default() -> Self {
|
||||
Self(ptr::null_mut())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for MibTablePtr {
|
||||
fn drop(&mut self) {
|
||||
if !self.0.is_null() {
|
||||
// Free the memory allocated by GetIpInterfaceTable.
|
||||
unsafe {
|
||||
FreeMibTable(self.0.cast());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn interface_and_mtu_impl(remote: IpAddr) -> Result<(String, usize)> {
|
||||
// Convert remote to Windows SOCKADDR_INET format. The SOCKADDR_INET union contains an IPv4 or
|
||||
// an IPv6 address.
|
||||
//
|
||||
// See https://learn.microsoft.com/en-us/windows/win32/api/ws2ipdef/ns-ws2ipdef-sockaddr_inet
|
||||
let dst = match remote {
|
||||
IpAddr::V4(ip) => {
|
||||
// Initialize the `SOCKADDR_IN` variant of `SOCKADDR_INET` based on `ip`.
|
||||
SOCKADDR_INET {
|
||||
Ipv4: SOCKADDR_IN {
|
||||
sin_family: AF_INET,
|
||||
sin_addr: IN_ADDR {
|
||||
S_un: IN_ADDR_0 {
|
||||
S_addr: u32::to_be(ip.into()),
|
||||
},
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
IpAddr::V6(ip) => {
|
||||
// Initialize the `SOCKADDR_IN6` variant of `SOCKADDR_INET` based on `ip`.
|
||||
SOCKADDR_INET {
|
||||
Ipv6: SOCKADDR_IN6 {
|
||||
sin6_family: AF_INET6,
|
||||
sin6_addr: IN6_ADDR {
|
||||
u: IN6_ADDR_0 { Byte: ip.octets() },
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Get the interface index of the best outbound interface towards `dst`.
|
||||
let mut idx = 0;
|
||||
let res = unsafe {
|
||||
// We're now casting `&dst` to a `SOCKADDR` pointer. This is OK based on
|
||||
// https://learn.microsoft.com/en-us/windows/win32/winsock/sockaddr-2.
|
||||
// With that, we call `GetBestInterfaceEx` to get the interface index into `idx`.
|
||||
// See https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getbestinterfaceex
|
||||
GetBestInterfaceEx(
|
||||
ptr::from_ref(&dst).cast::<SOCKADDR>(),
|
||||
ptr::from_mut(&mut idx),
|
||||
)
|
||||
};
|
||||
if res != 0 {
|
||||
return Err(Error::last_os_error());
|
||||
}
|
||||
|
||||
// Get a list of all interfaces with associated metadata.
|
||||
let mut if_table = MibTablePtr::default();
|
||||
// GetIpInterfaceTable allocates memory, which MibTablePtr::drop will free.
|
||||
let family = if remote.is_ipv4() { AF_INET } else { AF_INET6 };
|
||||
if unsafe { GetIpInterfaceTable(family, if_table.mut_ptr_ptr()) } != NO_ERROR {
|
||||
return Err(Error::last_os_error());
|
||||
}
|
||||
// Make a slice
|
||||
let ifaces = unsafe {
|
||||
slice::from_raw_parts::<MIB_IPINTERFACE_ROW>(
|
||||
&(*if_table.0).Table[0],
|
||||
(*if_table.0).NumEntries as usize,
|
||||
)
|
||||
};
|
||||
|
||||
// Find the local interface matching `idx`.
|
||||
for iface in ifaces {
|
||||
if iface.InterfaceIndex == idx {
|
||||
// Get the MTU.
|
||||
let mtu: usize = iface.NlMtu.try_into().map_err(|_| default_err())?;
|
||||
// Get the interface name.
|
||||
let mut interfacename = [0u8; IF_MAX_STRING_SIZE as usize];
|
||||
// if_indextoname writes into the provided buffer.
|
||||
if unsafe { if_indextoname(iface.InterfaceIndex, &mut interfacename).is_null() } {
|
||||
return Err(default_err());
|
||||
}
|
||||
// Convert the interface name to a Rust string.
|
||||
let name = CStr::from_bytes_until_nul(interfacename.as_ref())
|
||||
.map_err(|_| default_err())?
|
||||
.to_str()
|
||||
.map_err(|err| Error::new(ErrorKind::Other, err))?
|
||||
.to_string();
|
||||
// We found our interface information.
|
||||
return Ok((name, mtu));
|
||||
}
|
||||
}
|
||||
Err(default_err())
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"30905a8b427891bbf7a6b46b846b49140d553f9dfd978f4e24aaaff43a0d50fa","benches/main.rs":"fcfd00665a1c4eb2118c74dd3e066e451bed655a42ae5c92daee38a31b69c2fb","src/bin/client.rs":"d7dc368d9b3a3a7a391fd982509ce66afa09ede9ca54dc1328bfc222e69379dc","src/bin/server.rs":"f297d7d00613291e5a058772c7e416b55ad8a25e6f0cf438c7b7f836fb470135","src/client/http09.rs":"86726bac98edbcab5a41ee5e4614637944730032fb31354cb68df917992da9bd","src/client/http3.rs":"820d359d83c6d6df1ce463cf2780b4541d0bd880338b8bf7840b6f01f14732ec","src/client/mod.rs":"3a8d426736c892a69acf543ab469540b631a43ab7c18e8f4e1f74aa0f56806e2","src/lib.rs":"68936ae531d5ab903b0063e3c8a7cd49511c2bf87c42706f23e8968e8a5c3d89","src/send_data.rs":"7537b7a0f67e9077cf121cc3d0fcd42edb085801dd4baf25b14c22a01f1bf04f","src/server/http09.rs":"d71cd79bba792799f303abdc15abe10e843bc0dd4de3efa27f3d11bf82798de2","src/server/http3.rs":"56f45922eebcfa30d7d9ceb6bac97d6f725d4c803c7aa0836c6e4d21b8d4588e","src/server/mod.rs":"6286666e692c43e52ddb3e837c9630694a446101c0c8cff520a816ce25c247df","src/udp.rs":"9fbd463a87c7a1f0873a003c36631b3b02af6e1a3d215b5a12a1e2822c207362"},"package":null}
|
||||
{"files":{"Cargo.toml":"f45efe77b2a12f3c4b84a412b25a22ebac2cc97c5fd8df8a774f9757267986b6","benches/main.rs":"1f00060094b0f77ac83b2f0817560bb6198c95742a7bf9330258906f3a4f57fe","src/bin/client.rs":"db77efd75dc0745b6dd983ab8fa3bc8f5f9111967f0d90d23cb19140a940246d","src/bin/server.rs":"2f7ab3c7a98117bd162e6fd07abef1d21791d1bb240db3aae61afa6ff72df83a","src/client/http09.rs":"ac3526f3689dfe61ac336c90f936a2113a47b1112eb6e765d2112898f42ff38f","src/client/http3.rs":"40f6b94a31edceb911609a75929df67dcab87d6c88501b14adfca0e31dbb26c0","src/client/mod.rs":"c15859494d447cd777a0cce41bd7e36d9ffc7bbab494ed2f0c9eb7d058e3bdbe","src/lib.rs":"acbf69e2c99d2ca47d3356fad9b4d08acf4a2a9b481e27af2ccb46dc19cd50e6","src/send_data.rs":"7537b7a0f67e9077cf121cc3d0fcd42edb085801dd4baf25b14c22a01f1bf04f","src/server/http09.rs":"3dbde3e801532b6e83bb86eeea5d87ec91294bb43c05c956c3783a7722780a5e","src/server/http3.rs":"7f30864eb165cb614cd5bdbf4d59f736a2409316fe848e6295b8618099e5cbdd","src/server/mod.rs":"d42c2991f3a2854309785800f007b1dafd72232e1f6870a6e9cf60387202382b","src/udp.rs":"4aadb956e50f961241b2850e6f3bdf715ccbac943e3ab585f4b46e755d03d2de"},"package":null}
|
||||
60
third_party/rust/neqo-bin/Cargo.toml
vendored
60
third_party/rust/neqo-bin/Cargo.toml
vendored
@@ -13,7 +13,7 @@
|
||||
edition = "2021"
|
||||
rust-version = "1.76.0"
|
||||
name = "neqo-bin"
|
||||
version = "0.12.2"
|
||||
version = "0.11.0"
|
||||
authors = ["The Neqo Authors <necko@mozilla.com>"]
|
||||
build = false
|
||||
autolib = false
|
||||
@@ -39,9 +39,6 @@ categories = [
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/mozilla/neqo/"
|
||||
|
||||
[package.metadata.cargo-machete]
|
||||
ignored = ["log"]
|
||||
|
||||
[lib]
|
||||
name = "neqo_bin"
|
||||
path = "src/lib.rs"
|
||||
@@ -115,10 +112,7 @@ default-features = false
|
||||
|
||||
[dependencies.quinn-udp]
|
||||
version = "0.5.6"
|
||||
features = [
|
||||
"direct-log",
|
||||
"fast-apple-datapath",
|
||||
]
|
||||
features = ["direct-log"]
|
||||
default-features = false
|
||||
|
||||
[dependencies.regex]
|
||||
@@ -147,48 +141,16 @@ version = "0.5"
|
||||
features = ["async_tokio"]
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.neqo-bin]
|
||||
path = "."
|
||||
features = ["draft-29"]
|
||||
|
||||
[dev-dependencies.neqo-http3]
|
||||
path = "./../neqo-http3"
|
||||
features = ["draft-29"]
|
||||
|
||||
[dev-dependencies.neqo-transport]
|
||||
path = "./../neqo-transport"
|
||||
features = ["draft-29"]
|
||||
|
||||
[dev-dependencies.tokio]
|
||||
version = "1"
|
||||
features = ["sync"]
|
||||
default-features = false
|
||||
|
||||
[features]
|
||||
bench = [
|
||||
"neqo-bin/bench",
|
||||
"neqo-http3/bench",
|
||||
"neqo-transport/bench",
|
||||
]
|
||||
draft-29 = []
|
||||
bench = ["neqo-transport/bench"]
|
||||
|
||||
[lints.clippy]
|
||||
cfg_not_test = "warn"
|
||||
clone_on_ref_ptr = "warn"
|
||||
create_dir = "warn"
|
||||
get_unwrap = "warn"
|
||||
if_then_some_else_none = "warn"
|
||||
multiple_crate_versions = "allow"
|
||||
multiple_inherent_impl = "warn"
|
||||
pathbuf_init_then_push = "warn"
|
||||
redundant_type_annotations = "warn"
|
||||
ref_patterns = "warn"
|
||||
renamed_function_params = "warn"
|
||||
semicolon_inside_block = "warn"
|
||||
try_err = "warn"
|
||||
unneeded_field_pattern = "warn"
|
||||
unused_result_ok = "warn"
|
||||
unused_trait_names = "warn"
|
||||
|
||||
[lints.clippy.cargo]
|
||||
level = "warn"
|
||||
@@ -201,19 +163,3 @@ priority = -1
|
||||
[lints.clippy.pedantic]
|
||||
level = "warn"
|
||||
priority = -1
|
||||
|
||||
[lints.rust]
|
||||
absolute_paths_not_starting_with_crate = "warn"
|
||||
ambiguous_negative_literals = "warn"
|
||||
closure_returning_async_block = "warn"
|
||||
explicit_outlives_requirements = "warn"
|
||||
macro_use_extern_crate = "warn"
|
||||
missing_abi = "warn"
|
||||
non_ascii_idents = "warn"
|
||||
redundant_imports = "warn"
|
||||
redundant_lifetimes = "warn"
|
||||
trivial_numeric_casts = "warn"
|
||||
unit_bindings = "warn"
|
||||
unused_import_braces = "warn"
|
||||
unused_lifetimes = "warn"
|
||||
unused_macro_rules = "warn"
|
||||
|
||||
3
third_party/rust/neqo-bin/benches/main.rs
vendored
3
third_party/rust/neqo-bin/benches/main.rs
vendored
@@ -4,7 +4,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::{env, path::PathBuf, str::FromStr as _};
|
||||
use std::{env, path::PathBuf, str::FromStr};
|
||||
|
||||
use criterion::{criterion_group, criterion_main, BatchSize, Criterion, Throughput};
|
||||
use neqo_bin::{client, server};
|
||||
@@ -17,6 +17,7 @@ struct Benchmark {
|
||||
}
|
||||
|
||||
fn transfer(c: &mut Criterion) {
|
||||
neqo_common::log::init(Some(log::LevelFilter::Off));
|
||||
neqo_crypto::init_db(PathBuf::from_str("../test-fixture/db").unwrap()).unwrap();
|
||||
|
||||
let done_sender = spawn_server();
|
||||
|
||||
2
third_party/rust/neqo-bin/src/bin/client.rs
vendored
2
third_party/rust/neqo-bin/src/bin/client.rs
vendored
@@ -4,7 +4,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use clap::Parser as _;
|
||||
use clap::Parser;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), neqo_bin::client::Error> {
|
||||
|
||||
2
third_party/rust/neqo-bin/src/bin/server.rs
vendored
2
third_party/rust/neqo-bin/src/bin/server.rs
vendored
@@ -4,7 +4,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use clap::Parser as _;
|
||||
use clap::Parser;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), neqo_bin::server::Error> {
|
||||
|
||||
@@ -10,7 +10,7 @@ use std::{
|
||||
cell::RefCell,
|
||||
collections::{HashMap, VecDeque},
|
||||
fs::File,
|
||||
io::{BufWriter, Write as _},
|
||||
io::{BufWriter, Write},
|
||||
net::SocketAddr,
|
||||
path::PathBuf,
|
||||
rc::Rc,
|
||||
@@ -61,7 +61,7 @@ impl super::Handler for Handler<'_> {
|
||||
self.needs_key_update = false;
|
||||
self.download_urls(client);
|
||||
}
|
||||
Err(Error::KeyUpdateBlocked) => (),
|
||||
Err(neqo_transport::Error::KeyUpdateBlocked) => (),
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
}
|
||||
@@ -213,7 +213,7 @@ impl super::Client for Connection {
|
||||
}
|
||||
|
||||
fn has_events(&self) -> bool {
|
||||
Provider::has_events(self)
|
||||
neqo_common::event::Provider::has_events(self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,7 +301,8 @@ impl<'b> Handler<'b> {
|
||||
qdebug!("READ[{stream_id}]: {} bytes", read_buffer.len());
|
||||
} else {
|
||||
qdebug!(
|
||||
"READ[{stream_id}]: {}",
|
||||
"READ[{}]: {}",
|
||||
stream_id,
|
||||
std::str::from_utf8(read_buffer).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use std::{
|
||||
collections::{HashMap, VecDeque},
|
||||
fmt::Display,
|
||||
fs::File,
|
||||
io::{BufWriter, Write as _},
|
||||
io::{BufWriter, Write},
|
||||
net::SocketAddr,
|
||||
path::PathBuf,
|
||||
rc::Rc,
|
||||
@@ -155,7 +155,7 @@ impl super::Client for Http3Client {
|
||||
}
|
||||
|
||||
fn has_events(&self) -> bool {
|
||||
Provider::has_events(self)
|
||||
neqo_common::event::Provider::has_events(self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,7 +302,7 @@ impl StreamHandler for DownloadStreamHandler {
|
||||
} else if let Ok(txt) = std::str::from_utf8(data) {
|
||||
qdebug!("READ[{stream_id}]: {txt}");
|
||||
} else {
|
||||
qdebug!("READ[{stream_id}]: 0x{}", hex(data));
|
||||
qdebug!("READ[{}]: 0x{}", stream_id, hex(data));
|
||||
}
|
||||
|
||||
if fin {
|
||||
@@ -344,7 +344,7 @@ impl StreamHandler for UploadStreamHandler {
|
||||
qinfo!("Stream ID: {stream_id:?}, Upload time: {upload_time:?}");
|
||||
}
|
||||
} else {
|
||||
panic!("Unexpected data [{stream_id}]: 0x{}", hex(data));
|
||||
panic!("Unexpected data [{}]: 0x{}", stream_id, hex(data));
|
||||
}
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
68
third_party/rust/neqo-bin/src/client/mod.rs
vendored
68
third_party/rust/neqo-bin/src/client/mod.rs
vendored
@@ -11,7 +11,7 @@ use std::{
|
||||
fmt::{self, Display},
|
||||
fs::{create_dir_all, File, OpenOptions},
|
||||
io::{self, BufWriter},
|
||||
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs as _},
|
||||
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs},
|
||||
path::PathBuf,
|
||||
pin::Pin,
|
||||
process::exit,
|
||||
@@ -21,7 +21,7 @@ use std::{
|
||||
use clap::Parser;
|
||||
use futures::{
|
||||
future::{select, Either},
|
||||
FutureExt as _, TryFutureExt as _,
|
||||
FutureExt, TryFutureExt,
|
||||
};
|
||||
use neqo_common::{qdebug, qerror, qinfo, qlog::NeqoQlog, qwarn, Datagram, Role};
|
||||
use neqo_crypto::{
|
||||
@@ -30,7 +30,6 @@ use neqo_crypto::{
|
||||
};
|
||||
use neqo_http3::Output;
|
||||
use neqo_transport::{AppError, CloseReason, ConnectionId, Version};
|
||||
use neqo_udp::RecvBuf;
|
||||
use tokio::time::Sleep;
|
||||
use url::{Host, Origin, Url};
|
||||
|
||||
@@ -48,7 +47,7 @@ pub enum Error {
|
||||
IoError(io::Error),
|
||||
QlogError(qlog::Error),
|
||||
TransportError(neqo_transport::Error),
|
||||
ApplicationError(AppError),
|
||||
ApplicationError(neqo_transport::AppError),
|
||||
CryptoError(neqo_crypto::Error),
|
||||
}
|
||||
|
||||
@@ -82,8 +81,8 @@ impl From<neqo_transport::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CloseReason> for Error {
|
||||
fn from(err: CloseReason) -> Self {
|
||||
impl From<neqo_transport::CloseReason> for Error {
|
||||
fn from(err: neqo_transport::CloseReason) -> Self {
|
||||
match err {
|
||||
CloseReason::Transport(e) => Self::TransportError(e),
|
||||
CloseReason::Application(e) => Self::ApplicationError(e),
|
||||
@@ -182,9 +181,9 @@ impl Args {
|
||||
#[cfg(any(test, feature = "bench"))]
|
||||
#[allow(clippy::missing_panics_doc)]
|
||||
pub fn new(requests: &[usize], upload: bool) -> Self {
|
||||
use std::str::FromStr as _;
|
||||
use std::str::FromStr;
|
||||
Self {
|
||||
shared: SharedArgs::default(),
|
||||
shared: crate::SharedArgs::default(),
|
||||
urls: requests
|
||||
.iter()
|
||||
.map(|r| Url::from_str(&format!("http://[::1]:12345/{r}")).unwrap())
|
||||
@@ -239,14 +238,10 @@ impl Args {
|
||||
// Only use v1 for most QNS tests.
|
||||
self.shared.quic_parameters.quic_version = vec![Version::Version1];
|
||||
// This is the default for all tests except http3.
|
||||
self.shared.alpn = String::from("hq-interop");
|
||||
// Wireshark can't reassemble sliced CRYPTO frames, which causes tests to fail.
|
||||
// So let's turn that off by default, and only enable for some known-good QNS tests.
|
||||
self.shared.quic_parameters.no_sni_slicing = true;
|
||||
self.shared.use_old_http = true;
|
||||
match testcase.as_str() {
|
||||
"http3" => {
|
||||
self.shared.quic_parameters.no_sni_slicing = false;
|
||||
self.shared.alpn = String::from("h3");
|
||||
self.shared.use_old_http = false;
|
||||
if let Some(testcase) = &self.test {
|
||||
if testcase.as_str() != "upload" {
|
||||
qerror!("Unsupported test case: {testcase}");
|
||||
@@ -269,7 +264,6 @@ impl Args {
|
||||
qerror!("Warning: zerortt test won't work without >1 URL");
|
||||
exit(127);
|
||||
}
|
||||
self.shared.quic_parameters.no_sni_slicing = false;
|
||||
self.resume = true;
|
||||
// PMTUD probes inflate what we sent in 1-RTT, causing QNS to fail the test.
|
||||
self.shared.quic_parameters.no_pmtud = true;
|
||||
@@ -290,7 +284,6 @@ impl Args {
|
||||
self.key_update = true;
|
||||
}
|
||||
"v2" => {
|
||||
self.shared.quic_parameters.no_sni_slicing = false;
|
||||
// Use default version set for this test (which allows compatible vneg.)
|
||||
self.shared.quic_parameters.quic_version.clear();
|
||||
}
|
||||
@@ -401,7 +394,7 @@ struct Runner<'a, H: Handler> {
|
||||
handler: H,
|
||||
timeout: Option<Pin<Box<Sleep>>>,
|
||||
args: &'a Args,
|
||||
recv_buf: RecvBuf,
|
||||
recv_buf: Vec<u8>,
|
||||
}
|
||||
|
||||
impl<'a, H: Handler> Runner<'a, H> {
|
||||
@@ -419,7 +412,7 @@ impl<'a, H: Handler> Runner<'a, H> {
|
||||
handler,
|
||||
args,
|
||||
timeout: None,
|
||||
recv_buf: RecvBuf::new(),
|
||||
recv_buf: vec![0; neqo_udp::RECV_BUF_SIZE],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,7 +462,7 @@ impl<'a, H: Handler> Runner<'a, H> {
|
||||
self.socket.send(&dgram)?;
|
||||
}
|
||||
Output::Callback(new_timeout) => {
|
||||
qdebug!("Setting timeout of {new_timeout:?}");
|
||||
qdebug!("Setting timeout of {:?}", new_timeout);
|
||||
self.timeout = Some(Box::pin(tokio::time::sleep(new_timeout)));
|
||||
break;
|
||||
}
|
||||
@@ -488,6 +481,9 @@ impl<'a, H: Handler> Runner<'a, H> {
|
||||
let Some(dgrams) = self.socket.recv(self.local_addr, &mut self.recv_buf)? else {
|
||||
break;
|
||||
};
|
||||
if dgrams.len() == 0 {
|
||||
break;
|
||||
}
|
||||
self.client.process_multiple_input(dgrams, Instant::now());
|
||||
self.process_output().await?;
|
||||
}
|
||||
@@ -512,9 +508,9 @@ fn qlog_new(args: &Args, hostname: &str, cid: &ConnectionId) -> Res<NeqoQlog> {
|
||||
NeqoQlog::enabled_with_file(
|
||||
qlog_dir,
|
||||
Role::Client,
|
||||
Some("Neqo client qlog".to_string()),
|
||||
Some("Neqo client qlog".to_string()),
|
||||
format!("client-{hostname}-{cid}"),
|
||||
Some("Example qlog".to_string()),
|
||||
Some("Example qlog description".to_string()),
|
||||
format!("{hostname}-{cid}"),
|
||||
)
|
||||
.map_err(Error::QlogError)
|
||||
}
|
||||
@@ -557,7 +553,7 @@ pub async fn client(mut args: Args) -> Res<()> {
|
||||
|
||||
for ((host, port), mut urls) in urls_by_origin(&args.urls) {
|
||||
if args.resume && urls.len() < 2 {
|
||||
qerror!("Resumption to {host} cannot work without at least 2 URLs");
|
||||
qerror!("Resumption to {host} cannot work without at least 2 URLs.");
|
||||
exit(127);
|
||||
}
|
||||
|
||||
@@ -574,8 +570,10 @@ pub async fn client(mut args: Args) -> Res<()> {
|
||||
let mut socket = crate::udp::Socket::bind(local_addr_for(&remote_addr, 0))?;
|
||||
let real_local = socket.local_addr().unwrap();
|
||||
qinfo!(
|
||||
"{} Client connecting: {real_local:?} -> {remote_addr:?}",
|
||||
args.shared.alpn
|
||||
"{} Client connecting: {:?} -> {:?}",
|
||||
if args.shared.use_old_http { "H9" } else { "H3" },
|
||||
real_local,
|
||||
remote_addr,
|
||||
);
|
||||
|
||||
let hostname = format!("{host}");
|
||||
@@ -590,22 +588,22 @@ pub async fn client(mut args: Args) -> Res<()> {
|
||||
|
||||
first = false;
|
||||
|
||||
token = if args.shared.alpn == "h3" {
|
||||
let client = http3::create_client(&args, real_local, remote_addr, &hostname, token)
|
||||
.expect("failed to create client");
|
||||
|
||||
let handler = http3::Handler::new(to_request, &args);
|
||||
|
||||
Runner::new(real_local, &mut socket, client, handler, &args)
|
||||
.run()
|
||||
.await?
|
||||
} else {
|
||||
token = if args.shared.use_old_http {
|
||||
let client =
|
||||
http09::create_client(&args, real_local, remote_addr, &hostname, token)
|
||||
.expect("failed to create client");
|
||||
|
||||
let handler = http09::Handler::new(to_request, &args);
|
||||
|
||||
Runner::new(real_local, &mut socket, client, handler, &args)
|
||||
.run()
|
||||
.await?
|
||||
} else {
|
||||
let client = http3::create_client(&args, real_local, remote_addr, &hostname, token)
|
||||
.expect("failed to create client");
|
||||
|
||||
let handler = http3::Handler::new(to_request, &args);
|
||||
|
||||
Runner::new(real_local, &mut socket, client, handler, &args)
|
||||
.run()
|
||||
.await?
|
||||
|
||||
33
third_party/rust/neqo-bin/src/lib.rs
vendored
33
third_party/rust/neqo-bin/src/lib.rs
vendored
@@ -9,7 +9,7 @@
|
||||
|
||||
use std::{
|
||||
fmt::{self, Display},
|
||||
net::{SocketAddr, ToSocketAddrs as _},
|
||||
net::{SocketAddr, ToSocketAddrs},
|
||||
path::PathBuf,
|
||||
time::Duration,
|
||||
};
|
||||
@@ -63,6 +63,10 @@ pub struct SharedArgs {
|
||||
/// Enable special behavior for use with QUIC Network Simulator
|
||||
pub qns_test: Option<String>,
|
||||
|
||||
#[arg(name = "use-old-http", short = 'o', long)]
|
||||
/// Use http 0.9 instead of HTTP/3
|
||||
pub use_old_http: bool,
|
||||
|
||||
#[command(flatten)]
|
||||
pub quic_parameters: QuicParameters,
|
||||
}
|
||||
@@ -79,6 +83,7 @@ impl Default for SharedArgs {
|
||||
max_blocked_streams: 10,
|
||||
ciphers: vec![],
|
||||
qns_test: None,
|
||||
use_old_http: false,
|
||||
quic_parameters: QuicParameters::default(),
|
||||
}
|
||||
}
|
||||
@@ -112,7 +117,7 @@ pub struct QuicParameters {
|
||||
/// The idle timeout for connections, in seconds.
|
||||
pub idle_timeout: u64,
|
||||
|
||||
#[arg(long = "cc", default_value = "cubic")]
|
||||
#[arg(long = "cc", default_value = "newreno")]
|
||||
/// The congestion controller to use.
|
||||
pub congestion_control: CongestionControlAlgorithm,
|
||||
|
||||
@@ -124,10 +129,6 @@ pub struct QuicParameters {
|
||||
/// Whether to disable path MTU discovery.
|
||||
pub no_pmtud: bool,
|
||||
|
||||
#[arg(long)]
|
||||
/// Whether to slice the SNI.
|
||||
pub no_sni_slicing: bool,
|
||||
|
||||
#[arg(name = "preferred-address-v4", long)]
|
||||
/// An IPv4 address for the server preferred address.
|
||||
pub preferred_address_v4: Option<String>,
|
||||
@@ -145,12 +146,11 @@ impl Default for QuicParameters {
|
||||
max_streams_bidi: 16,
|
||||
max_streams_uni: 16,
|
||||
idle_timeout: 30,
|
||||
congestion_control: CongestionControlAlgorithm::Cubic,
|
||||
congestion_control: CongestionControlAlgorithm::NewReno,
|
||||
no_pacing: false,
|
||||
no_pmtud: false,
|
||||
preferred_address_v4: None,
|
||||
preferred_address_v6: None,
|
||||
no_sni_slicing: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,8 +168,9 @@ impl QuicParameters {
|
||||
assert_eq!(
|
||||
opt.is_some(),
|
||||
addr.is_some(),
|
||||
"unable to resolve '{}' to an {v} address",
|
||||
"unable to resolve '{}' to an {} address",
|
||||
opt.as_ref().unwrap(),
|
||||
v,
|
||||
);
|
||||
addr
|
||||
}
|
||||
@@ -223,8 +224,7 @@ impl QuicParameters {
|
||||
.idle_timeout(Duration::from_secs(self.idle_timeout))
|
||||
.cc_algorithm(self.congestion_control)
|
||||
.pacing(!self.no_pacing)
|
||||
.pmtud(!self.no_pmtud)
|
||||
.sni_slicing(!self.no_sni_slicing);
|
||||
.pmtud(!self.no_pmtud);
|
||||
params = if let Some(pa) = self.preferred_address() {
|
||||
params.preferred_address(pa)
|
||||
} else {
|
||||
@@ -240,8 +240,10 @@ impl QuicParameters {
|
||||
} else {
|
||||
let version = match alpn {
|
||||
"h3" | "hq-interop" => Version::Version1,
|
||||
#[cfg(feature = "draft-29")]
|
||||
"h3-29" | "hq-29" => Version::Draft29,
|
||||
"h3-30" | "hq-30" => Version::Draft30,
|
||||
"h3-31" | "hq-31" => Version::Draft31,
|
||||
"h3-32" | "hq-32" => Version::Draft32,
|
||||
_ => Version::default(),
|
||||
};
|
||||
params.versions(version, Version::all())
|
||||
@@ -271,7 +273,7 @@ impl std::error::Error for Error {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{fs, path::PathBuf, str::FromStr as _, time::SystemTime};
|
||||
use std::{fs, path::PathBuf, str::FromStr, time::SystemTime};
|
||||
|
||||
use crate::{client, server};
|
||||
|
||||
@@ -281,14 +283,15 @@ mod tests {
|
||||
|
||||
impl TempDir {
|
||||
fn new() -> Self {
|
||||
let dir = std::env::temp_dir().join(format!(
|
||||
let mut dir = std::env::temp_dir();
|
||||
dir.push(format!(
|
||||
"neqo-bin-test-{}",
|
||||
SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs()
|
||||
));
|
||||
fs::create_dir_all(&dir).unwrap();
|
||||
fs::create_dir(&dir).unwrap();
|
||||
Self { path: dir }
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
use std::{borrow::Cow, cell::RefCell, collections::HashMap, fmt::Display, rc::Rc, time::Instant};
|
||||
|
||||
use neqo_common::{event::Provider as _, hex, qdebug, qerror, qinfo, qwarn, Datagram};
|
||||
use neqo_common::{event::Provider, hex, qdebug, qerror, qinfo, qwarn, Datagram};
|
||||
use neqo_crypto::{generate_ech_keys, random, AllowZeroRtt, AntiReplay};
|
||||
use neqo_http3::Error;
|
||||
use neqo_transport::{
|
||||
@@ -82,17 +82,17 @@ impl HttpServer {
|
||||
let url_dbg = String::from_utf8(partial.clone())
|
||||
.unwrap_or_else(|_| format!("<invalid UTF-8: {}>", hex(&partial)));
|
||||
if partial.len() < 4096 {
|
||||
qdebug!("Saving partial URL: {url_dbg}");
|
||||
qdebug!("Saving partial URL: {}", url_dbg);
|
||||
self.read_state.insert(stream_id, partial);
|
||||
} else {
|
||||
qdebug!("Giving up on partial URL {url_dbg}");
|
||||
qdebug!("Giving up on partial URL {}", url_dbg);
|
||||
conn.borrow_mut().stream_stop_sending(stream_id, 0).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn stream_readable(&mut self, stream_id: StreamId, conn: &ConnectionRef) {
|
||||
if !stream_id.is_client_initiated() || !stream_id.is_bidi() {
|
||||
qdebug!("Stream {stream_id} not client-initiated bidi, ignoring");
|
||||
qdebug!("Stream {} not client-initiated bidi, ignoring", stream_id);
|
||||
return;
|
||||
}
|
||||
let (sz, fin) = conn
|
||||
|
||||
@@ -12,7 +12,7 @@ use std::{
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
use neqo_common::{header::HeadersExt as _, hex, qdebug, qerror, qinfo, Datagram, Header};
|
||||
use neqo_common::{hex, qdebug, qerror, qinfo, Datagram, Header};
|
||||
use neqo_crypto::{generate_ech_keys, random, AntiReplay};
|
||||
use neqo_http3::{
|
||||
Http3OrWebTransportStream, Http3Parameters, Http3Server, Http3ServerEvent, StreamId,
|
||||
@@ -94,12 +94,15 @@ impl super::HttpServer for HttpServer {
|
||||
} => {
|
||||
qdebug!("Headers (request={stream} fin={fin}): {headers:?}");
|
||||
|
||||
if headers.contains_header(":method", "POST") {
|
||||
if headers
|
||||
.iter()
|
||||
.any(|h| h.name() == ":method" && h.value() == "POST")
|
||||
{
|
||||
self.posts.insert(stream, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
let Some(path) = headers.find_header(":path") else {
|
||||
let Some(path) = headers.iter().find(|&h| h.name() == ":path") else {
|
||||
stream
|
||||
.cancel_fetch(neqo_http3::Error::HttpRequestIncomplete.code())
|
||||
.unwrap();
|
||||
|
||||
35
third_party/rust/neqo-bin/src/server/mod.rs
vendored
35
third_party/rust/neqo-bin/src/server/mod.rs
vendored
@@ -10,7 +10,7 @@ use std::{
|
||||
cell::RefCell,
|
||||
fmt::{self, Display},
|
||||
fs, io,
|
||||
net::{SocketAddr, ToSocketAddrs as _},
|
||||
net::{SocketAddr, ToSocketAddrs},
|
||||
path::PathBuf,
|
||||
pin::Pin,
|
||||
process::exit,
|
||||
@@ -21,7 +21,7 @@ use std::{
|
||||
use clap::Parser;
|
||||
use futures::{
|
||||
future::{select, select_all, Either},
|
||||
FutureExt as _,
|
||||
FutureExt,
|
||||
};
|
||||
use neqo_common::{qdebug, qerror, qinfo, qwarn, Datagram};
|
||||
use neqo_crypto::{
|
||||
@@ -29,7 +29,6 @@ use neqo_crypto::{
|
||||
init_db, AntiReplay, Cipher,
|
||||
};
|
||||
use neqo_transport::{Output, RandomConnectionIdGenerator, Version};
|
||||
use neqo_udp::RecvBuf;
|
||||
use tokio::time::Sleep;
|
||||
|
||||
use crate::SharedArgs;
|
||||
@@ -122,9 +121,9 @@ pub struct Args {
|
||||
#[cfg(any(test, feature = "bench"))]
|
||||
impl Default for Args {
|
||||
fn default() -> Self {
|
||||
use std::str::FromStr as _;
|
||||
use std::str::FromStr;
|
||||
Self {
|
||||
shared: SharedArgs::default(),
|
||||
shared: crate::SharedArgs::default(),
|
||||
hosts: vec!["[::]:12345".to_string()],
|
||||
db: PathBuf::from_str("../test-fixture/db").unwrap(),
|
||||
key: "key".to_string(),
|
||||
@@ -203,7 +202,7 @@ pub struct ServerRunner {
|
||||
server: Box<dyn HttpServer>,
|
||||
timeout: Option<Pin<Box<Sleep>>>,
|
||||
sockets: Vec<(SocketAddr, crate::udp::Socket)>,
|
||||
recv_buf: RecvBuf,
|
||||
recv_buf: Vec<u8>,
|
||||
}
|
||||
|
||||
impl ServerRunner {
|
||||
@@ -218,7 +217,7 @@ impl ServerRunner {
|
||||
server,
|
||||
timeout: None,
|
||||
sockets,
|
||||
recv_buf: RecvBuf::new(),
|
||||
recv_buf: vec![0; neqo_udp::RECV_BUF_SIZE],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,7 +251,7 @@ impl ServerRunner {
|
||||
socket.send(&dgram)?;
|
||||
}
|
||||
Output::Callback(new_timeout) => {
|
||||
qdebug!("Setting timeout of {new_timeout:?}");
|
||||
qdebug!("Setting timeout of {:?}", new_timeout);
|
||||
*timeout = Some(Box::pin(tokio::time::sleep(new_timeout)));
|
||||
break;
|
||||
}
|
||||
@@ -264,7 +263,7 @@ impl ServerRunner {
|
||||
|
||||
async fn read_and_process(&mut self, sockets_index: usize) -> Result<(), io::Error> {
|
||||
loop {
|
||||
let (host, socket) = &mut self.sockets[sockets_index];
|
||||
let (host, socket) = self.sockets.get_mut(sockets_index).unwrap();
|
||||
let Some(input_dgrams) = socket.recv(*host, &mut self.recv_buf)? else {
|
||||
break;
|
||||
};
|
||||
@@ -342,6 +341,8 @@ enum Ready {
|
||||
}
|
||||
|
||||
pub async fn server(mut args: Args) -> Res<()> {
|
||||
const HQ_INTEROP: &str = "hq-interop";
|
||||
|
||||
neqo_common::log::init(
|
||||
args.shared
|
||||
.verbose
|
||||
@@ -361,15 +362,17 @@ pub async fn server(mut args: Args) -> Res<()> {
|
||||
args.shared.quic_parameters.quic_version = vec![Version::Version1];
|
||||
}
|
||||
} else {
|
||||
qwarn!("Both -V and --qns-test were set. Ignoring testcase specific versions");
|
||||
qwarn!("Both -V and --qns-test were set. Ignoring testcase specific versions.");
|
||||
}
|
||||
|
||||
// These are the default for all tests except http3.
|
||||
args.shared.alpn = String::from("hq-interop");
|
||||
args.shared.use_old_http = true;
|
||||
args.shared.alpn = String::from(HQ_INTEROP);
|
||||
// TODO: More options to deduplicate with client?
|
||||
match testcase.as_str() {
|
||||
"http3" => {
|
||||
args.shared.alpn = String::from("h3");
|
||||
args.shared.use_old_http = false;
|
||||
args.shared.alpn = "h3".into();
|
||||
}
|
||||
"zerortt" => args.shared.quic_parameters.max_streams_bidi = 100,
|
||||
"handshake" | "transfer" | "resumption" | "multiconnect" | "v2" | "ecn" => {}
|
||||
@@ -393,7 +396,7 @@ pub async fn server(mut args: Args) -> Res<()> {
|
||||
let hosts = args.listen_addresses();
|
||||
if hosts.is_empty() {
|
||||
qerror!("No valid hosts defined");
|
||||
return Err(io::Error::new(io::ErrorKind::InvalidInput, "No hosts").into());
|
||||
Err(io::Error::new(io::ErrorKind::InvalidInput, "No hosts"))?;
|
||||
}
|
||||
let sockets = hosts
|
||||
.into_iter()
|
||||
@@ -411,12 +414,12 @@ pub async fn server(mut args: Args) -> Res<()> {
|
||||
.expect("unable to setup anti-replay");
|
||||
let cid_mgr = Rc::new(RefCell::new(RandomConnectionIdGenerator::new(10)));
|
||||
|
||||
let server: Box<dyn HttpServer> = if args.shared.alpn == "h3" {
|
||||
Box::new(http3::HttpServer::new(&args, anti_replay, cid_mgr))
|
||||
} else {
|
||||
let server: Box<dyn HttpServer> = if args.shared.use_old_http {
|
||||
Box::new(
|
||||
http09::HttpServer::new(&args, anti_replay, cid_mgr).expect("We cannot make a server!"),
|
||||
)
|
||||
} else {
|
||||
Box::new(http3::HttpServer::new(&args, anti_replay, cid_mgr))
|
||||
};
|
||||
|
||||
ServerRunner::new(Box::new(move || args.now()), server, sockets)
|
||||
|
||||
4
third_party/rust/neqo-bin/src/udp.rs
vendored
4
third_party/rust/neqo-bin/src/udp.rs
vendored
@@ -7,7 +7,7 @@
|
||||
use std::{io, net::SocketAddr};
|
||||
|
||||
use neqo_common::Datagram;
|
||||
use neqo_udp::{DatagramIter, RecvBuf};
|
||||
use neqo_udp::DatagramIter;
|
||||
|
||||
/// Ideally this would live in [`neqo-udp`]. [`neqo-udp`] is used in Firefox.
|
||||
///
|
||||
@@ -59,7 +59,7 @@ impl Socket {
|
||||
pub fn recv<'a>(
|
||||
&self,
|
||||
local_address: SocketAddr,
|
||||
recv_buf: &'a mut RecvBuf,
|
||||
recv_buf: &'a mut [u8],
|
||||
) -> Result<Option<DatagramIter<'a>>, io::Error> {
|
||||
self.inner
|
||||
.try_io(tokio::io::Interest::READABLE, || {
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"40a22ca3fd5fd76384120c87a895e923701d78d4b1ec30481f80afff82cbf3f6","benches/decoder.rs":"e7fab506974d7b6b4f41fe51036151b15f0d693b7e45b80cf9e2141bb1f6298f","build.rs":"ee5dc521f3d8e18c2b617192d6b6e678f7f2f9886fdd34c0c1c5ef841419b248","src/codec.rs":"8aea4a5041d1b06e4928d29fefcc8166d515b72f9a744e572d3c92b90e9ea268","src/datagram.rs":"e8bf176d3b120028731388c17344d03b8195e5fd70f4d03e37144ac5ae5951f5","src/event.rs":"289cf8e265c33e7cded58820ac81e5b575e3f84dd52fa18b0761f4094fb361c0","src/fuzz.rs":"9e0f2dca1832ef49b93b214e8d5f1ca2f5f8cb84a856fead344f62a722c370db","src/header.rs":"a316f48735375da268142ad9ac3430d240162c9df67114546f4a094c25a10024","src/hrtime.rs":"754f90ae3f3839e59ccaa34a9f07a2742ec7080f2df539f4b7691c7771dd4856","src/incrdecoder.rs":"2128bb6aa737932b484cdff8213efe8eac46004ef2d9219b6f48ac4d664297ac","src/lib.rs":"002f6a740464b618036e699db4ebea1fc803b9c9c154c0478f6f8721932f4300","src/log.rs":"2ea3f00b1776e085cbf6b46dc7489259b4e58a2dada7edaf94e746de3defb222","src/qlog.rs":"f335b4f4340ae0bfaeb6742bd5a2cb8b6f16292a40b410ed3f72ce309b171106","src/tos.rs":"206410cf0d164a0c1a1c3de19ddcd224e311601707bedc7af100a30a950d12f9","tests/log.rs":"671a963f938599b76c0678f3931592e1782765ed4ea13e6cbfec2ab97c36e2c9"},"package":null}
|
||||
{"files":{"Cargo.toml":"d7f253814c9d1e8fcae6916ca37c18efafd511895d85b6b193b4cc648a1b3fca","build.rs":"ee5dc521f3d8e18c2b617192d6b6e678f7f2f9886fdd34c0c1c5ef841419b248","src/codec.rs":"6c12d9db7066497f2566e83efc825ae984d04a6b5176010c93d394904103aeed","src/datagram.rs":"e8bf176d3b120028731388c17344d03b8195e5fd70f4d03e37144ac5ae5951f5","src/event.rs":"289cf8e265c33e7cded58820ac81e5b575e3f84dd52fa18b0761f4094fb361c0","src/fuzz.rs":"1ca74a34bdc97fedecf8a63c4a13cc487d1b2212398fb76f67792c822002138d","src/header.rs":"480a7848466249a78acddbf0bc0b4a096189abc14a89ad1a0943be571add2c2b","src/hrtime.rs":"37447c51c7fd84baad31bc420bf9170c1f4e71356bb6d102bd5651ddf69a2f89","src/incrdecoder.rs":"5c45034e61e75c76d2bca8b075c3e7a3cdd8af8c82b67c76283a2b08ab11846b","src/lib.rs":"2381fc00127a7eaf2265c3a13dc1e1d5843e048f3a8a1c97f1e6621c038de380","src/log.rs":"6ed99e15707c4256ae793011ed2f4b33aa81fed70205aaf5f8d3cd11ad451cf0","src/qlog.rs":"c230d1e3b6f80489253dc689eab44c9df75ef0c5170ab91ddd2dc9e4dc9234a2","src/tos.rs":"28fd9acfce06f68ac6691efd2609618850182f77ef3717ce2db07bfac19a9396","tests/log.rs":"a11e21fb570258ca93bb40e3923817d381e1e605accbc3aed1df5a0a9918b41d"},"package":null}
|
||||
51
third_party/rust/neqo-common/Cargo.toml
vendored
51
third_party/rust/neqo-common/Cargo.toml
vendored
@@ -13,7 +13,7 @@
|
||||
edition = "2021"
|
||||
rust-version = "1.76.0"
|
||||
name = "neqo-common"
|
||||
version = "0.12.2"
|
||||
version = "0.11.0"
|
||||
authors = ["The Neqo Authors <necko@mozilla.com>"]
|
||||
build = "build.rs"
|
||||
autolib = false
|
||||
@@ -48,12 +48,6 @@ bench = false
|
||||
name = "log"
|
||||
path = "tests/log.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "decoder"
|
||||
path = "benches/decoder.rs"
|
||||
harness = false
|
||||
required-features = ["bench"]
|
||||
|
||||
[dependencies.enum-map]
|
||||
version = "2.7"
|
||||
default-features = false
|
||||
@@ -76,13 +70,6 @@ default-features = false
|
||||
version = "0.13"
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.criterion]
|
||||
version = "0.5"
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.neqo-crypto]
|
||||
path = "../neqo-crypto"
|
||||
|
||||
[dev-dependencies.regex]
|
||||
version = "1.9"
|
||||
features = ["unicode-perl"]
|
||||
@@ -92,13 +79,8 @@ default-features = false
|
||||
path = "../test-fixture"
|
||||
|
||||
[features]
|
||||
bench = [
|
||||
"neqo-crypto/bench",
|
||||
"test-fixture/bench",
|
||||
]
|
||||
build-fuzzing-corpus = ["hex"]
|
||||
ci = []
|
||||
test-fixture = []
|
||||
|
||||
[target."cfg(windows)".dependencies.windows]
|
||||
version = "0.58"
|
||||
@@ -106,22 +88,7 @@ features = ["Win32_Media"]
|
||||
default-features = false
|
||||
|
||||
[lints.clippy]
|
||||
cfg_not_test = "warn"
|
||||
clone_on_ref_ptr = "warn"
|
||||
create_dir = "warn"
|
||||
get_unwrap = "warn"
|
||||
if_then_some_else_none = "warn"
|
||||
multiple_crate_versions = "allow"
|
||||
multiple_inherent_impl = "warn"
|
||||
pathbuf_init_then_push = "warn"
|
||||
redundant_type_annotations = "warn"
|
||||
ref_patterns = "warn"
|
||||
renamed_function_params = "warn"
|
||||
semicolon_inside_block = "warn"
|
||||
try_err = "warn"
|
||||
unneeded_field_pattern = "warn"
|
||||
unused_result_ok = "warn"
|
||||
unused_trait_names = "warn"
|
||||
|
||||
[lints.clippy.cargo]
|
||||
level = "warn"
|
||||
@@ -134,19 +101,3 @@ priority = -1
|
||||
[lints.clippy.pedantic]
|
||||
level = "warn"
|
||||
priority = -1
|
||||
|
||||
[lints.rust]
|
||||
absolute_paths_not_starting_with_crate = "warn"
|
||||
ambiguous_negative_literals = "warn"
|
||||
closure_returning_async_block = "warn"
|
||||
explicit_outlives_requirements = "warn"
|
||||
macro_use_extern_crate = "warn"
|
||||
missing_abi = "warn"
|
||||
non_ascii_idents = "warn"
|
||||
redundant_imports = "warn"
|
||||
redundant_lifetimes = "warn"
|
||||
trivial_numeric_casts = "warn"
|
||||
unit_bindings = "warn"
|
||||
unused_import_braces = "warn"
|
||||
unused_lifetimes = "warn"
|
||||
unused_macro_rules = "warn"
|
||||
|
||||
52
third_party/rust/neqo-common/benches/decoder.rs
vendored
52
third_party/rust/neqo-common/benches/decoder.rs
vendored
@@ -1,52 +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 criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
use neqo_common::Decoder;
|
||||
use neqo_crypto::{init, randomize};
|
||||
|
||||
fn randomize_buffer(n: usize, mask: u8) -> Vec<u8> {
|
||||
let mut buf = vec![0; n];
|
||||
// NSS doesn't like randomizing larger buffers, so chunk them up.
|
||||
// https://searchfox.org/nss/rev/968939484921b0ceecca189cd1b66e97950c39da/lib/freebl/drbg.c#29
|
||||
for chunk in buf.chunks_mut(0x10000) {
|
||||
randomize(chunk);
|
||||
}
|
||||
// Masking the top bits off causes the resulting values to be interpreted as
|
||||
// smaller varints, which stresses the decoder differently.
|
||||
// This is worth testing because most varints contain small values.
|
||||
for x in &mut buf[..] {
|
||||
*x &= mask;
|
||||
}
|
||||
buf
|
||||
}
|
||||
|
||||
fn decoder(c: &mut Criterion, count: usize, mask: u8) {
|
||||
c.bench_function(&format!("decode {count} bytes, mask {mask:x}"), |b| {
|
||||
b.iter_batched_ref(
|
||||
|| randomize_buffer(count, mask),
|
||||
|buf| {
|
||||
let mut dec = Decoder::new(&buf[..]);
|
||||
while black_box(dec.decode_varint()).is_some() {
|
||||
// Do nothing;
|
||||
}
|
||||
},
|
||||
criterion::BatchSize::SmallInput,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn benchmark_decoder(c: &mut Criterion) {
|
||||
init().unwrap();
|
||||
for mask in [0xff, 0x7f, 0x3f] {
|
||||
for exponent in [12, 20] {
|
||||
decoder(c, 1 << exponent, mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
criterion_group!(benches, benchmark_decoder);
|
||||
criterion_main!(benches);
|
||||
87
third_party/rust/neqo-common/src/codec.rs
vendored
87
third_party/rust/neqo-common/src/codec.rs
vendored
@@ -44,28 +44,34 @@ impl<'a> Decoder<'a> {
|
||||
}
|
||||
|
||||
/// Skip helper that panics if `n` is `None` or not able to fit in `usize`.
|
||||
/// Only use this for tests because we panic rather than reporting a result.
|
||||
#[cfg(any(test, feature = "test-fixture"))]
|
||||
fn skip_inner(&mut self, n: Option<u64>) {
|
||||
self.skip(usize::try_from(n.expect("invalid length")).unwrap());
|
||||
}
|
||||
|
||||
/// Skip a vector. Panics if there isn't enough space.
|
||||
/// Only use this for tests because we panic rather than reporting a result.
|
||||
#[cfg(any(test, feature = "test-fixture"))]
|
||||
pub fn skip_vec(&mut self, n: usize) {
|
||||
let len = self.decode_n(n);
|
||||
let len = self.decode_uint(n);
|
||||
self.skip_inner(len);
|
||||
}
|
||||
|
||||
/// Skip a variable length vector. Panics if there isn't enough space.
|
||||
/// Only use this for tests because we panic rather than reporting a result.
|
||||
#[cfg(any(test, feature = "test-fixture"))]
|
||||
pub fn skip_vvec(&mut self) {
|
||||
let len = self.decode_varint();
|
||||
self.skip_inner(len);
|
||||
}
|
||||
|
||||
/// Decodes (reads) a single byte.
|
||||
pub fn decode_byte(&mut self) -> Option<u8> {
|
||||
if self.remaining() < 1 {
|
||||
return None;
|
||||
}
|
||||
let b = self.buf[self.offset];
|
||||
self.offset += 1;
|
||||
Some(b)
|
||||
}
|
||||
|
||||
/// Provides the next byte without moving the read position.
|
||||
#[must_use]
|
||||
pub const fn peek_byte(&self) -> Option<u8> {
|
||||
@@ -86,43 +92,33 @@ impl<'a> Decoder<'a> {
|
||||
Some(res)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn decode_n(&mut self, n: usize) -> Option<u64> {
|
||||
debug_assert!(n > 0 && n <= 8);
|
||||
/// Decodes an unsigned integer of length 1..=8.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This panics if `n` is not in the range `1..=8`.
|
||||
pub fn decode_uint(&mut self, n: usize) -> Option<u64> {
|
||||
assert!(n > 0 && n <= 8);
|
||||
if self.remaining() < n {
|
||||
return None;
|
||||
}
|
||||
Some(if n == 1 {
|
||||
let v = u64::from(self.buf[self.offset]);
|
||||
self.offset += 1;
|
||||
v
|
||||
} else {
|
||||
let mut buf = [0; 8];
|
||||
buf[8 - n..].copy_from_slice(&self.buf[self.offset..self.offset + n]);
|
||||
self.offset += n;
|
||||
u64::from_be_bytes(buf)
|
||||
})
|
||||
let mut v = 0_u64;
|
||||
for i in 0..n {
|
||||
let b = self.buf[self.offset + i];
|
||||
v = v << 8 | u64::from(b);
|
||||
}
|
||||
|
||||
/// Decodes a big-endian, unsigned integer value into the target type.
|
||||
/// This returns `None` if there is not enough data remaining
|
||||
/// or if the conversion to the identified type fails.
|
||||
/// Conversion is via `u64`, so failures are impossible for
|
||||
/// unsigned integer types: `u8`, `u16`, `u32`, or `u64`.
|
||||
/// Signed types will fail if the high bit is set.
|
||||
pub fn decode_uint<T: TryFrom<u64>>(&mut self) -> Option<T> {
|
||||
let v = self.decode_n(std::mem::size_of::<T>());
|
||||
v.and_then(|v| T::try_from(v).ok())
|
||||
self.offset += n;
|
||||
Some(v)
|
||||
}
|
||||
|
||||
/// Decodes a QUIC varint.
|
||||
pub fn decode_varint(&mut self) -> Option<u64> {
|
||||
let b1 = self.decode_n(1)?;
|
||||
let b1 = self.decode_byte()?;
|
||||
match b1 >> 6 {
|
||||
0 => Some(b1),
|
||||
1 => Some(((b1 & 0x3f) << 8) | self.decode_n(1)?),
|
||||
2 => Some(((b1 & 0x3f) << 24) | self.decode_n(3)?),
|
||||
3 => Some(((b1 & 0x3f) << 56) | self.decode_n(7)?),
|
||||
0 => Some(u64::from(b1 & 0x3f)),
|
||||
1 => Some((u64::from(b1 & 0x3f) << 8) | self.decode_uint(1)?),
|
||||
2 => Some((u64::from(b1 & 0x3f) << 24) | self.decode_uint(3)?),
|
||||
3 => Some((u64::from(b1 & 0x3f) << 56) | self.decode_uint(7)?),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
@@ -147,7 +143,7 @@ impl<'a> Decoder<'a> {
|
||||
|
||||
/// Decodes a TLS-style length-prefixed buffer.
|
||||
pub fn decode_vec(&mut self, n: usize) -> Option<&'a [u8]> {
|
||||
let len = self.decode_n(n);
|
||||
let len = self.decode_uint(n);
|
||||
self.decode_checked(len)
|
||||
}
|
||||
|
||||
@@ -276,7 +272,6 @@ impl Encoder {
|
||||
/// # Panics
|
||||
///
|
||||
/// When `s` contains non-hex values or an odd number of values.
|
||||
#[cfg(any(test, feature = "test-fixture"))]
|
||||
#[must_use]
|
||||
pub fn from_hex(s: impl AsRef<str>) -> Self {
|
||||
let s = s.as_ref();
|
||||
@@ -486,28 +481,16 @@ mod tests {
|
||||
let enc = Encoder::from_hex("0123");
|
||||
let mut dec = enc.as_decoder();
|
||||
|
||||
assert_eq!(dec.decode_uint::<u8>().unwrap(), 0x01);
|
||||
assert_eq!(dec.decode_uint::<u8>().unwrap(), 0x23);
|
||||
assert!(dec.decode_uint::<u8>().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn peek_byte() {
|
||||
let enc = Encoder::from_hex("01");
|
||||
let mut dec = enc.as_decoder();
|
||||
|
||||
assert_eq!(dec.offset(), 0);
|
||||
assert_eq!(dec.peek_byte().unwrap(), 0x01);
|
||||
dec.skip(1);
|
||||
assert_eq!(dec.offset(), 1);
|
||||
assert!(dec.peek_byte().is_none());
|
||||
assert_eq!(dec.decode_byte().unwrap(), 0x01);
|
||||
assert_eq!(dec.decode_byte().unwrap(), 0x23);
|
||||
assert!(dec.decode_byte().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_byte_short() {
|
||||
let enc = Encoder::from_hex("");
|
||||
let mut dec = enc.as_decoder();
|
||||
assert!(dec.decode_uint::<u8>().is_none());
|
||||
assert!(dec.decode_byte().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -518,7 +501,7 @@ mod tests {
|
||||
assert!(dec.decode(2).is_none());
|
||||
|
||||
let mut dec = Decoder::from(&[]);
|
||||
assert!(dec.decode_remainder().is_empty());
|
||||
assert_eq!(dec.decode_remainder().len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
2
third_party/rust/neqo-common/src/fuzz.rs
vendored
2
third_party/rust/neqo-common/src/fuzz.rs
vendored
@@ -7,7 +7,7 @@
|
||||
use std::{
|
||||
collections::hash_map::DefaultHasher,
|
||||
fs::File,
|
||||
hash::{Hash as _, Hasher as _},
|
||||
hash::{Hash, Hasher},
|
||||
io::Write,
|
||||
path::Path,
|
||||
};
|
||||
|
||||
26
third_party/rust/neqo-common/src/header.rs
vendored
26
third_party/rust/neqo-common/src/header.rs
vendored
@@ -46,29 +46,3 @@ impl Header {
|
||||
&self.value
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<str>, U: AsRef<str>> PartialEq<(T, U)> for Header {
|
||||
fn eq(&self, other: &(T, U)) -> bool {
|
||||
self.name == other.0.as_ref() && self.value == other.1.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HeadersExt<'h> {
|
||||
fn contains_header<T: AsRef<str>, U: AsRef<str>>(self, name: T, value: U) -> bool;
|
||||
fn find_header<T: AsRef<str> + 'h>(self, name: T) -> Option<&'h Header>;
|
||||
}
|
||||
|
||||
impl<'h, H> HeadersExt<'h> for H
|
||||
where
|
||||
H: IntoIterator<Item = &'h Header> + 'h,
|
||||
{
|
||||
fn contains_header<T: AsRef<str>, U: AsRef<str>>(self, name: T, value: U) -> bool {
|
||||
let (name, value) = (name.as_ref(), value.as_ref());
|
||||
self.into_iter().any(|h| h == &(name, value))
|
||||
}
|
||||
|
||||
fn find_header<T: AsRef<str> + 'h>(self, name: T) -> Option<&'h Header> {
|
||||
let name = name.as_ref();
|
||||
self.into_iter().find(|h| h.name == name)
|
||||
}
|
||||
}
|
||||
|
||||
15
third_party/rust/neqo-common/src/hrtime.rs
vendored
15
third_party/rust/neqo-common/src/hrtime.rs
vendored
@@ -80,7 +80,7 @@ impl PeriodSet {
|
||||
#[cfg(target_os = "macos")]
|
||||
#[allow(non_camel_case_types)]
|
||||
mod mac {
|
||||
use std::ptr::addr_of_mut;
|
||||
use std::{mem::size_of, ptr::addr_of_mut};
|
||||
|
||||
// These are manually extracted from the many bindings generated
|
||||
// by bindgen when provided with the simple header:
|
||||
@@ -126,7 +126,7 @@ mod mac {
|
||||
const THREAD_TIME_CONSTRAINT_POLICY: thread_policy_flavor_t = 2;
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
const THREAD_TIME_CONSTRAINT_POLICY_COUNT: mach_msg_type_number_t =
|
||||
(std::mem::size_of::<thread_time_constraint_policy>() / std::mem::size_of::<integer_t>())
|
||||
(size_of::<thread_time_constraint_policy>() / size_of::<integer_t>())
|
||||
as mach_msg_type_number_t;
|
||||
|
||||
// These function definitions are taken from a comment in <thread_policy.h>.
|
||||
@@ -370,9 +370,14 @@ impl Drop for Time {
|
||||
}
|
||||
}
|
||||
|
||||
// Only run these tests in CI on Linux, where the timer accuracies are OK enough to pass the tests,
|
||||
// but only when not running sanitizers.
|
||||
#[cfg(all(test, target_os = "linux", not(neqo_sanitize)))]
|
||||
// Only run these tests in CI on platforms other than MacOS and Windows, where the timer
|
||||
// inaccuracies are too high to pass the tests.
|
||||
#[cfg(all(
|
||||
test,
|
||||
not(all(any(target_os = "macos", target_os = "windows"), feature = "ci")),
|
||||
// Sanitizers are too slow to uphold timing assumptions.
|
||||
not(neqo_sanitize),
|
||||
))]
|
||||
mod test {
|
||||
use std::{
|
||||
thread::{sleep, spawn},
|
||||
|
||||
22
third_party/rust/neqo-common/src/incrdecoder.rs
vendored
22
third_party/rust/neqo-common/src/incrdecoder.rs
vendored
@@ -31,11 +31,15 @@ impl IncrementalDecoderUint {
|
||||
if amount < 8 {
|
||||
self.v <<= amount * 8;
|
||||
}
|
||||
self.v |= dv.decode_n(amount).unwrap();
|
||||
self.v |= dv.decode_uint(amount).unwrap();
|
||||
*r -= amount;
|
||||
(*r == 0).then_some(self.v)
|
||||
if *r == 0 {
|
||||
Some(self.v)
|
||||
} else {
|
||||
let (v, remaining) = dv.decode_uint::<u8>().map_or_else(
|
||||
None
|
||||
}
|
||||
} else {
|
||||
let (v, remaining) = dv.decode_byte().map_or_else(
|
||||
|| unreachable!(),
|
||||
|b| {
|
||||
(
|
||||
@@ -52,7 +56,11 @@ impl IncrementalDecoderUint {
|
||||
);
|
||||
self.remaining = Some(remaining);
|
||||
self.v = v;
|
||||
(remaining == 0).then_some(v)
|
||||
if remaining == 0 {
|
||||
Some(v)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +100,11 @@ impl IncrementalDecoderBuffer {
|
||||
let b = dv.decode(amount).unwrap();
|
||||
self.v.extend_from_slice(b);
|
||||
self.remaining -= amount;
|
||||
(self.remaining == 0).then(|| mem::take(&mut self.v))
|
||||
if self.remaining == 0 {
|
||||
Some(mem::take(&mut self.v))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
third_party/rust/neqo-common/src/lib.rs
vendored
2
third_party/rust/neqo-common/src/lib.rs
vendored
@@ -18,7 +18,7 @@ pub mod log;
|
||||
pub mod qlog;
|
||||
pub mod tos;
|
||||
|
||||
use std::fmt::Write as _;
|
||||
use std::fmt::Write;
|
||||
|
||||
use enum_map::Enum;
|
||||
|
||||
|
||||
86
third_party/rust/neqo-common/src/log.rs
vendored
86
third_party/rust/neqo-common/src/log.rs
vendored
@@ -7,13 +7,44 @@
|
||||
#![allow(clippy::module_name_repetitions)]
|
||||
|
||||
use std::{
|
||||
io::Write as _,
|
||||
io::Write,
|
||||
sync::{Once, OnceLock},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use env_logger::Builder;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! do_log {
|
||||
(target: $target:expr, $lvl:expr, $($arg:tt)+) => ({
|
||||
let lvl = $lvl;
|
||||
if lvl <= ::log::STATIC_MAX_LEVEL && lvl <= ::log::max_level() {
|
||||
::log::logger().log(
|
||||
&::log::Record::builder()
|
||||
.args(format_args!($($arg)+))
|
||||
.level(lvl)
|
||||
.target($target)
|
||||
.module_path_static(Some(module_path!()))
|
||||
.file_static(Some(file!()))
|
||||
.line(Some(line!()))
|
||||
.build()
|
||||
);
|
||||
}
|
||||
});
|
||||
($lvl:expr, $($arg:tt)+) => ($crate::do_log!(target: module_path!(), $lvl, $($arg)+))
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! log_subject {
|
||||
($lvl:expr, $subject:expr) => {{
|
||||
if $lvl <= ::log::max_level() {
|
||||
format!("{}", $subject)
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
fn since_start() -> Duration {
|
||||
static START_TIME: OnceLock<Instant> = OnceLock::new();
|
||||
START_TIME.get_or_init(Instant::now).elapsed()
|
||||
@@ -35,7 +66,7 @@ pub fn init(level_filter: Option<log::LevelFilter>) {
|
||||
let elapsed = since_start();
|
||||
writeln!(
|
||||
buf,
|
||||
"{}.{:03} {} {}",
|
||||
"{}s{:3}ms {} {}",
|
||||
elapsed.as_secs(),
|
||||
elapsed.as_millis() % 1000,
|
||||
record.level(),
|
||||
@@ -43,55 +74,42 @@ pub fn init(level_filter: Option<log::LevelFilter>) {
|
||||
)
|
||||
});
|
||||
if let Err(e) = builder.try_init() {
|
||||
eprintln!("Logging initialization error {e:?}");
|
||||
do_log!(::log::Level::Warn, "Logging initialization error {:?}", e);
|
||||
} else {
|
||||
::log::debug!("Logging initialized");
|
||||
do_log!(::log::Level::Debug, "Logging initialized");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
// TODO: Enable `#[clippy::format_args]` once our MSRV is >= 1.84
|
||||
macro_rules! log_invoke {
|
||||
($lvl:expr, $ctx:expr, $($arg:tt)*) => ( {
|
||||
::neqo_common::log::init(None);
|
||||
::neqo_common::do_log!($lvl, "[{}] {}", $ctx, format!($($arg)*));
|
||||
} )
|
||||
}
|
||||
#[macro_export]
|
||||
macro_rules! qerror {
|
||||
($($arg:tt)*) => ( {
|
||||
#[cfg(any(test, feature = "bench"))]
|
||||
::neqo_common::log::init(None);
|
||||
::log::error!($($arg)*);
|
||||
} );
|
||||
([$ctx:expr], $($arg:tt)*) => (::neqo_common::log_invoke!(::log::Level::Error, $ctx, $($arg)*););
|
||||
($($arg:tt)*) => ( { ::neqo_common::log::init(None); ::neqo_common::do_log!(::log::Level::Error, $($arg)*); } );
|
||||
}
|
||||
#[macro_export]
|
||||
// TODO: Enable `#[clippy::format_args]` once our MSRV is >= 1.84
|
||||
macro_rules! qwarn {
|
||||
($($arg:tt)*) => ( {
|
||||
#[cfg(any(test, feature = "bench"))]
|
||||
::neqo_common::log::init(None);
|
||||
::log::warn!($($arg)*);
|
||||
} );
|
||||
([$ctx:expr], $($arg:tt)*) => (::neqo_common::log_invoke!(::log::Level::Warn, $ctx, $($arg)*););
|
||||
($($arg:tt)*) => ( { ::neqo_common::log::init(None); ::neqo_common::do_log!(::log::Level::Warn, $($arg)*); } );
|
||||
}
|
||||
#[macro_export]
|
||||
// TODO: Enable `#[clippy::format_args]` once our MSRV is >= 1.84
|
||||
macro_rules! qinfo {
|
||||
($($arg:tt)*) => ( {
|
||||
#[cfg(any(test, feature = "bench"))]
|
||||
::neqo_common::log::init(None);
|
||||
::log::info!($($arg)*);
|
||||
} );
|
||||
([$ctx:expr], $($arg:tt)*) => (::neqo_common::log_invoke!(::log::Level::Info, $ctx, $($arg)*););
|
||||
($($arg:tt)*) => ( { ::neqo_common::log::init(None); ::neqo_common::do_log!(::log::Level::Info, $($arg)*); } );
|
||||
}
|
||||
#[macro_export]
|
||||
// TODO: Enable `#[clippy::format_args]` once our MSRV is >= 1.84
|
||||
macro_rules! qdebug {
|
||||
($($arg:tt)*) => ( {
|
||||
#[cfg(any(test, feature = "bench"))]
|
||||
::neqo_common::log::init(None);
|
||||
::log::debug!($($arg)*);
|
||||
} );
|
||||
([$ctx:expr], $($arg:tt)*) => (::neqo_common::log_invoke!(::log::Level::Debug, $ctx, $($arg)*););
|
||||
($($arg:tt)*) => ( { ::neqo_common::log::init(None); ::neqo_common::do_log!(::log::Level::Debug, $($arg)*); } );
|
||||
}
|
||||
#[macro_export]
|
||||
// TODO: Enable `#[clippy::format_args]` once our MSRV is >= 1.84
|
||||
macro_rules! qtrace {
|
||||
($($arg:tt)*) => ( {
|
||||
#[cfg(any(test, feature = "bench"))]
|
||||
::neqo_common::log::init(None);
|
||||
::log::trace!($($arg)*);
|
||||
} );
|
||||
([$ctx:expr], $($arg:tt)*) => (::neqo_common::log_invoke!(::log::Level::Trace, $ctx, $($arg)*););
|
||||
($($arg:tt)*) => ( { ::neqo_common::log::init(None); ::neqo_common::do_log!(::log::Level::Trace, $($arg)*); } );
|
||||
}
|
||||
|
||||
16
third_party/rust/neqo-common/src/qlog.rs
vendored
16
third_party/rust/neqo-common/src/qlog.rs
vendored
@@ -59,7 +59,7 @@ impl NeqoQlog {
|
||||
title,
|
||||
description,
|
||||
None,
|
||||
Instant::now(),
|
||||
std::time::Instant::now(),
|
||||
new_trace(role),
|
||||
qlog::events::EventImportance::Base,
|
||||
Box::new(BufWriter::new(file)),
|
||||
@@ -149,7 +149,11 @@ impl NeqoQlog {
|
||||
{
|
||||
if let Some(inner) = self.inner.borrow_mut().as_mut() {
|
||||
if let Err(e) = f(&mut inner.streamer) {
|
||||
log::error!("Qlog event generation failed with error {e}; closing qlog.");
|
||||
crate::do_log!(
|
||||
::log::Level::Error,
|
||||
"Qlog event generation failed with error {}; closing qlog.",
|
||||
e
|
||||
);
|
||||
*self.inner.borrow_mut() = None;
|
||||
}
|
||||
}
|
||||
@@ -165,13 +169,13 @@ impl fmt::Debug for NeqoQlogShared {
|
||||
impl Drop for NeqoQlogShared {
|
||||
fn drop(&mut self) {
|
||||
if let Err(e) = self.streamer.finish_log() {
|
||||
log::error!("Error dropping NeqoQlog: {e}");
|
||||
crate::do_log!(::log::Level::Error, "Error dropping NeqoQlog: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn new_trace(role: Role) -> TraceSeq {
|
||||
pub fn new_trace(role: Role) -> qlog::TraceSeq {
|
||||
TraceSeq {
|
||||
vantage_point: VantagePoint {
|
||||
name: Some(format!("neqo-{role}")),
|
||||
@@ -182,7 +186,7 @@ pub fn new_trace(role: Role) -> TraceSeq {
|
||||
flow: None,
|
||||
},
|
||||
title: Some(format!("neqo-{role} trace")),
|
||||
description: Some(format!("neqo-{role} trace")),
|
||||
description: Some("Example qlog trace description".to_string()),
|
||||
configuration: Some(Configuration {
|
||||
time_offset: Some(0.0),
|
||||
original_uris: None,
|
||||
@@ -229,7 +233,7 @@ mod test {
|
||||
let (log, contents) = test_fixture::new_neqo_qlog();
|
||||
log.add_event_with_instant(|| Some(Event::with_time(0.0, EV_DATA)), Instant::now());
|
||||
assert_eq!(
|
||||
Regex::new("\"time\":[0-9]+.[0-9]+,")
|
||||
Regex::new("\"time\":[0-9].[0-9]*,")
|
||||
.unwrap()
|
||||
.replace(&contents.to_string(), "\"time\":0.0,"),
|
||||
format!("{EXPECTED_LOG_HEADER}{EXPECTED_LOG_EVENT}"),
|
||||
|
||||
2
third_party/rust/neqo-common/src/tos.rs
vendored
2
third_party/rust/neqo-common/src/tos.rs
vendored
@@ -62,7 +62,7 @@ impl IpTosEcn {
|
||||
}
|
||||
}
|
||||
|
||||
/// Diffserv codepoints, mapped to the upper six bits of the TOS field.
|
||||
/// Diffserv Codepoints, mapped to the upper six bits of the TOS field.
|
||||
/// <https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml>
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Enum, Default, Debug)]
|
||||
#[repr(u8)]
|
||||
|
||||
41
third_party/rust/neqo-common/tests/log.rs
vendored
41
third_party/rust/neqo-common/tests/log.rs
vendored
@@ -19,9 +19,40 @@ fn basic() {
|
||||
fn args() {
|
||||
let num = 1;
|
||||
let obj = std::time::Instant::now();
|
||||
qerror!("error {num} {obj:?}");
|
||||
qwarn!("warn {num} {obj:?}");
|
||||
qinfo!("info {num} {obj:?}");
|
||||
qdebug!("debug {num} {obj:?}");
|
||||
qtrace!("trace {num} {obj:?}");
|
||||
qerror!("error {} {:?}", num, obj);
|
||||
qwarn!("warn {} {:?}", num, obj);
|
||||
qinfo!("info {} {:?}", num, obj);
|
||||
qdebug!("debug {} {:?}", num, obj);
|
||||
qtrace!("trace {} {:?}", num, obj);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn context() {
|
||||
let context = "context";
|
||||
qerror!([context], "error");
|
||||
qwarn!([context], "warn");
|
||||
qinfo!([context], "info");
|
||||
qdebug!([context], "debug");
|
||||
qtrace!([context], "trace");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn context_comma() {
|
||||
let obj = vec![1, 2, 3];
|
||||
let context = "context";
|
||||
qerror!([context], "error {:?}", obj);
|
||||
qwarn!([context], "warn {:?}", obj);
|
||||
qinfo!([context], "info {:?}", obj);
|
||||
qdebug!([context], "debug {:?}", obj);
|
||||
qtrace!([context], "trace {:?}", obj);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn context_expr() {
|
||||
let context = vec![1, 2, 3];
|
||||
qerror!([format!("{:x?}", context)], "error");
|
||||
qwarn!([format!("{:x?}", context)], "warn");
|
||||
qinfo!([format!("{:x?}", context)], "info");
|
||||
qdebug!([format!("{:x?}", context)], "debug");
|
||||
qtrace!([format!("{:x?}", context)], "trace");
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"6953ac93fcc661e47b15e627f031ac21f4b4ab77fa125871a339cc964b812cb3","bindings/bindings.toml":"e7e4b75736cfcf4d52febacb99a6f6c6c7b1d648ed8bdc424648be876c850e91","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":"dfc3b2c8038c4b1c69d7a10bd06c4226e36935e7597225aba26039f700cc8f4f","min_version.txt":"04b271df436ebebd03df52ef009d6814f6a64e55203988790a6fcee7b2dc27af","src/aead.rs":"018b826284ea4ddba7d65ff56f3ce9744e24ac8d26b1364b08f6e8b12b259be5","src/aead_null.rs":"81163fafef59bd2800bd0a078d53d0f05ee114f0e22165717823a5ff1cb908af","src/agent.rs":"6b6bcd735cb12d3e3ddebbb04ebd705d192a9cbce6e2a967e86e7b41cccf0a8d","src/agentio.rs":"237f85faacdb6ee5b3a6efa8a620fcf109094f5fd9dfb69d2c74986f11ccdb0e","src/auth.rs":"ced1a18f691894984244088020ea25dc1ee678603317f0c7dfc8b8842fa750b4","src/cert.rs":"4fdaa3834d8a72f41198449010fd5c3f6be6a54e429427c37bde5aab9421585c","src/constants.rs":"58e296e314825753b2ab1d6effe9a1386421dc568f6ebfa8e95a95acb87205da","src/ech.rs":"869e36414418b8747e6ebb45af24159c1908fc829439c16d79cdd89e355d2111","src/err.rs":"2366501e0b48933a6a2e1c5b934aa55108c093729c84878b45e1e012e4e45d51","src/exp.rs":"d953873e87430b1c84d4a83c8eb3815041f5585b210bbaf59ae2c4d0057f5edd","src/ext.rs":"cbf7d9f5ecabf4b8c9efd6c334637ab1596ec5266d38ab8d2d6ceae305283deb","src/hkdf.rs":"8745ba761be821c1819cedf6dfd91f8b3148c6718053a4a74f33eb50c7d0cc40","src/hp.rs":"510a4a7f278203aa306ead05608f99397edc3806dc22b0af9e28c665b43ae56c","src/lib.rs":"cfbf92759c6d1b888d89b9c28adbd96839bff60fc8106169a043eafce0f8a21e","src/min_version.rs":"c6e1f98b9f56db0622ac38c1be131c55acf4a0f09ed0d6283f4d6308e2d1301a","src/p11.rs":"120c45dc037c243a1551b79c7a32613acf22e2961f2ea1e11c73bbce9d1f76dc","src/prio.rs":"5cf0105e78b1db43c65283208174abc3714a41dbb4d5cd80ac547a5a5a7c627c","src/replay.rs":"5cda39bc8fa8a07c493b761b8dfb5cbc9f669f97a2df7832a028ab366b3426be","src/result.rs":"5a76688787741de7a935dbbab4bcb917d481d1c9c50a34df7e510036feb3da17","src/secrets.rs":"c09caca2bf7b60fc7855fc2ad56094a291cb0596308eadf46ab51af0e271a9f0","src/selfencrypt.rs":"80efac0f116b22d86f88f07d694ff2f822bd87b792b3dff8d6376a251394de39","src/ssl.rs":"450cf9fb327515de612b29e3a0f6e15499e6c0b523790e5986fd71a9ea5e76af","src/time.rs":"27d0185c16e150dc381cd6c01ef85fdf7881e5349386466e175d641aab9ab30f","tests/aead.rs":"e36ae77802df1ea6d17cfd1bd2178a3706089577d6fd1554ca86e748b8b235b9","tests/agent.rs":"cbd0011f1d33281883a45d433228221062424c94e86decade5697731c08a1c52","tests/ext.rs":"57af4e2df211fa8afdb73125d4344ef5c70c1ea4579107c3e6f5746308ee3e7b","tests/handshake.rs":"efae67a40f87419aea30c7ab7eb1007faf7f56a83dbf1a18e24fbc0cb92ec901","tests/hkdf.rs":"1d2098dc8398395864baf13e4886cfd1da6d36118727c3b264f457ee3da6b048","tests/hp.rs":"c74070a8f877aaa6305b9411f6e60d8b509b0ac1bef2988cc44b8a48552c953c","tests/init.rs":"3e15150c4b324c06ca5e8935618e4008da53dc0ef4b69325d150831e87dc0b63","tests/selfencrypt.rs":"8d10840b41629bf449a6b3a551377315e8a05ca26c6b041548748196652c5909"},"package":null}
|
||||
{"files":{"Cargo.toml":"4c2750f8c99df82e117073f3958e83fd51e03f0d8ca3aaba4c81990f4875fb64","bindings/bindings.toml":"e7e4b75736cfcf4d52febacb99a6f6c6c7b1d648ed8bdc424648be876c850e91","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":"dfc3b2c8038c4b1c69d7a10bd06c4226e36935e7597225aba26039f700cc8f4f","min_version.txt":"04b271df436ebebd03df52ef009d6814f6a64e55203988790a6fcee7b2dc27af","src/aead.rs":"6410bcbe717a6b9ea6f11209b0888033358113ebc05b8a95cec1980d1360be4d","src/aead_null.rs":"81163fafef59bd2800bd0a078d53d0f05ee114f0e22165717823a5ff1cb908af","src/agent.rs":"38eb130b2b66edfaae05f154cdb718aee4a8c4dcffbf349b0ceb2287d4cbbb6e","src/agentio.rs":"6d86ff8d6319bf6c3dd7124b8d60271e3e1accd07a7b43ba54e81be51c8d2a98","src/auth.rs":"ced1a18f691894984244088020ea25dc1ee678603317f0c7dfc8b8842fa750b4","src/cert.rs":"8e75e69ec3544474b21f8915a7559463889c2f608b201dee274a8d701880950e","src/constants.rs":"58e296e314825753b2ab1d6effe9a1386421dc568f6ebfa8e95a95acb87205da","src/ech.rs":"75dd192423e8996d9061da5e9c20d30bff5153b9344132eda4fe321c4c141870","src/err.rs":"2366501e0b48933a6a2e1c5b934aa55108c093729c84878b45e1e012e4e45d51","src/exp.rs":"d953873e87430b1c84d4a83c8eb3815041f5585b210bbaf59ae2c4d0057f5edd","src/ext.rs":"cbf7d9f5ecabf4b8c9efd6c334637ab1596ec5266d38ab8d2d6ceae305283deb","src/hkdf.rs":"8745ba761be821c1819cedf6dfd91f8b3148c6718053a4a74f33eb50c7d0cc40","src/hp.rs":"510a4a7f278203aa306ead05608f99397edc3806dc22b0af9e28c665b43ae56c","src/lib.rs":"30632dacb1b6ed9321e42ca1aaa2b71db8d4878eeb27c608e4eabdc0b76bcdba","src/min_version.rs":"c6e1f98b9f56db0622ac38c1be131c55acf4a0f09ed0d6283f4d6308e2d1301a","src/p11.rs":"375397b18fcdf36dcdd22c164c8572dd83caf01b8d0065be3029444b197e1464","src/prio.rs":"5cf0105e78b1db43c65283208174abc3714a41dbb4d5cd80ac547a5a5a7c627c","src/replay.rs":"5cda39bc8fa8a07c493b761b8dfb5cbc9f669f97a2df7832a028ab366b3426be","src/result.rs":"0587cbb6aace71a7f9765ef7c01dcd9f73a49dcc6331e1d8fe4de2aef6ca65b6","src/secrets.rs":"2c47935c5b8c42363897881eaa0c171e84cf031e57a6e1387b99327080e8dd60","src/selfencrypt.rs":"018c2dacabd3e463fdadd5707715b23c26c261c4c7d86e66c62f0acec986cad9","src/ssl.rs":"450cf9fb327515de612b29e3a0f6e15499e6c0b523790e5986fd71a9ea5e76af","src/time.rs":"ade63a72ae90796d7fcccadbb15efc4594fcdb68913a914a657d4556fde88f62","tests/aead.rs":"e36ae77802df1ea6d17cfd1bd2178a3706089577d6fd1554ca86e748b8b235b9","tests/agent.rs":"cbd0011f1d33281883a45d433228221062424c94e86decade5697731c08a1c52","tests/ext.rs":"57af4e2df211fa8afdb73125d4344ef5c70c1ea4579107c3e6f5746308ee3e7b","tests/handshake.rs":"aa904736d36cc5d5cc0c4f6053b529987f33f944a73411bf08e01d30c4867186","tests/hkdf.rs":"1d2098dc8398395864baf13e4886cfd1da6d36118727c3b264f457ee3da6b048","tests/hp.rs":"ccda23018dac70b3ff3742afcb0fbae0735be9aeb36644a4ae2b1d7c9126801c","tests/init.rs":"3e15150c4b324c06ca5e8935618e4008da53dc0ef4b69325d150831e87dc0b63","tests/selfencrypt.rs":"8d10840b41629bf449a6b3a551377315e8a05ca26c6b041548748196652c5909"},"package":null}
|
||||
34
third_party/rust/neqo-crypto/Cargo.toml
vendored
34
third_party/rust/neqo-crypto/Cargo.toml
vendored
@@ -13,7 +13,7 @@
|
||||
edition = "2021"
|
||||
rust-version = "1.76.0"
|
||||
name = "neqo-crypto"
|
||||
version = "0.12.2"
|
||||
version = "0.11.0"
|
||||
authors = ["The Neqo Authors <necko@mozilla.com>"]
|
||||
build = "build.rs"
|
||||
autolib = false
|
||||
@@ -113,28 +113,12 @@ version = "0.5"
|
||||
default-features = false
|
||||
|
||||
[features]
|
||||
bench = []
|
||||
disable-encryption = []
|
||||
disable-random = []
|
||||
gecko = ["mozbuild"]
|
||||
|
||||
[lints.clippy]
|
||||
cfg_not_test = "warn"
|
||||
clone_on_ref_ptr = "warn"
|
||||
create_dir = "warn"
|
||||
get_unwrap = "warn"
|
||||
if_then_some_else_none = "warn"
|
||||
multiple_crate_versions = "allow"
|
||||
multiple_inherent_impl = "warn"
|
||||
pathbuf_init_then_push = "warn"
|
||||
redundant_type_annotations = "warn"
|
||||
ref_patterns = "warn"
|
||||
renamed_function_params = "warn"
|
||||
semicolon_inside_block = "warn"
|
||||
try_err = "warn"
|
||||
unneeded_field_pattern = "warn"
|
||||
unused_result_ok = "warn"
|
||||
unused_trait_names = "warn"
|
||||
|
||||
[lints.clippy.cargo]
|
||||
level = "warn"
|
||||
@@ -147,19 +131,3 @@ priority = -1
|
||||
[lints.clippy.pedantic]
|
||||
level = "warn"
|
||||
priority = -1
|
||||
|
||||
[lints.rust]
|
||||
absolute_paths_not_starting_with_crate = "warn"
|
||||
ambiguous_negative_literals = "warn"
|
||||
closure_returning_async_block = "warn"
|
||||
explicit_outlives_requirements = "warn"
|
||||
macro_use_extern_crate = "warn"
|
||||
missing_abi = "warn"
|
||||
non_ascii_idents = "warn"
|
||||
redundant_imports = "warn"
|
||||
redundant_lifetimes = "warn"
|
||||
trivial_numeric_casts = "warn"
|
||||
unit_bindings = "warn"
|
||||
unused_import_braces = "warn"
|
||||
unused_lifetimes = "warn"
|
||||
unused_macro_rules = "warn"
|
||||
|
||||
4
third_party/rust/neqo-crypto/src/aead.rs
vendored
4
third_party/rust/neqo-crypto/src/aead.rs
vendored
@@ -17,7 +17,7 @@ use crate::{
|
||||
experimental_api,
|
||||
p11::{PK11SymKey, SymKey},
|
||||
scoped_ptr,
|
||||
ssl::{PRUint16, PRUint64, PRUint8, SSLAeadContext},
|
||||
ssl::{self, PRUint16, PRUint64, PRUint8, SSLAeadContext},
|
||||
};
|
||||
|
||||
experimental_api!(SSL_MakeAead(
|
||||
@@ -80,7 +80,7 @@ impl RealAead {
|
||||
prefix: &str,
|
||||
) -> Res<Self> {
|
||||
let p = prefix.as_bytes();
|
||||
let mut ctx: *mut SSLAeadContext = null_mut();
|
||||
let mut ctx: *mut ssl::SSLAeadContext = null_mut();
|
||||
SSL_MakeAead(
|
||||
version,
|
||||
cipher,
|
||||
|
||||
72
third_party/rust/neqo-crypto/src/agent.rs
vendored
72
third_party/rust/neqo-crypto/src/agent.rs
vendored
@@ -7,7 +7,7 @@
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
ffi::{CStr, CString},
|
||||
mem::MaybeUninit,
|
||||
mem::{self, MaybeUninit},
|
||||
ops::{Deref, DerefMut},
|
||||
os::raw::{c_uint, c_void},
|
||||
pin::Pin,
|
||||
@@ -107,7 +107,7 @@ fn get_alpn(fd: *mut ssl::PRFileDesc, pre: bool) -> Res<Option<String>> {
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
qtrace!("[{fd:p}] got ALPN {alpn:?}");
|
||||
qtrace!([format!("{fd:p}")], "got ALPN {:?}", alpn);
|
||||
Ok(alpn)
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ impl SecretAgentPreInfo {
|
||||
ssl::SSL_GetPreliminaryChannelInfo(
|
||||
fd,
|
||||
info.as_mut_ptr(),
|
||||
c_uint::try_from(std::mem::size_of::<ssl::SSLPreliminaryChannelInfo>())?,
|
||||
c_uint::try_from(mem::size_of::<ssl::SSLPreliminaryChannelInfo>())?,
|
||||
)
|
||||
})?;
|
||||
|
||||
@@ -222,7 +222,7 @@ impl SecretAgentInfo {
|
||||
ssl::SSL_GetChannelInfo(
|
||||
fd,
|
||||
info.as_mut_ptr(),
|
||||
c_uint::try_from(std::mem::size_of::<ssl::SSLChannelInfo>())?,
|
||||
c_uint::try_from(mem::size_of::<ssl::SSLChannelInfo>())?,
|
||||
)
|
||||
})?;
|
||||
let info = unsafe { info.assume_init() };
|
||||
@@ -337,9 +337,7 @@ impl SecretAgent {
|
||||
ssl::SSL_ImportFD(null_mut(), base_fd.cast())
|
||||
};
|
||||
if fd.is_null() {
|
||||
unsafe {
|
||||
prio::PR_Close(base_fd);
|
||||
}
|
||||
unsafe { prio::PR_Close(base_fd) };
|
||||
return Err(Error::CreateSslSocket);
|
||||
}
|
||||
Ok(fd)
|
||||
@@ -349,8 +347,8 @@ impl SecretAgent {
|
||||
unsafe extern "C" fn auth_complete_hook(
|
||||
arg: *mut c_void,
|
||||
_fd: *mut ssl::PRFileDesc,
|
||||
_check_sig: PRBool,
|
||||
_is_server: PRBool,
|
||||
_check_sig: ssl::PRBool,
|
||||
_is_server: ssl::PRBool,
|
||||
) -> ssl::SECStatus {
|
||||
let auth_required_ptr = arg.cast::<bool>();
|
||||
*auth_required_ptr = true;
|
||||
@@ -371,7 +369,7 @@ impl SecretAgent {
|
||||
if st.is_none() {
|
||||
*st = Some(alert.description);
|
||||
} else {
|
||||
qwarn!("[{fd:p}] duplicate alert {}", alert.description);
|
||||
qwarn!([format!("{fd:p}")], "duplicate alert {}", alert.description);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -396,7 +394,7 @@ impl SecretAgent {
|
||||
|
||||
self.now.bind(self.fd)?;
|
||||
self.configure(grease)?;
|
||||
secstatus_to_res(unsafe { ssl::SSL_ResetHandshake(self.fd, PRBool::from(is_server)) })
|
||||
secstatus_to_res(unsafe { ssl::SSL_ResetHandshake(self.fd, ssl::PRBool::from(is_server)) })
|
||||
}
|
||||
|
||||
/// Default configuration.
|
||||
@@ -431,7 +429,7 @@ impl SecretAgent {
|
||||
/// If NSS can't enable or disable ciphers.
|
||||
pub fn set_ciphers(&mut self, ciphers: &[Cipher]) -> Res<()> {
|
||||
if self.state != HandshakeState::New {
|
||||
qwarn!("[{self}] Cannot enable ciphers in state {:?}", self.state);
|
||||
qwarn!([self], "Cannot enable ciphers in state {:?}", self.state);
|
||||
return Err(Error::InternalError);
|
||||
}
|
||||
|
||||
@@ -440,13 +438,13 @@ impl SecretAgent {
|
||||
for i in 0..cipher_count {
|
||||
let p = all_ciphers.wrapping_add(i);
|
||||
secstatus_to_res(unsafe {
|
||||
ssl::SSL_CipherPrefSet(self.fd, i32::from(*p), PRBool::from(false))
|
||||
ssl::SSL_CipherPrefSet(self.fd, i32::from(*p), ssl::PRBool::from(false))
|
||||
})?;
|
||||
}
|
||||
|
||||
for c in ciphers {
|
||||
secstatus_to_res(unsafe {
|
||||
ssl::SSL_CipherPrefSet(self.fd, i32::from(*c), PRBool::from(true))
|
||||
ssl::SSL_CipherPrefSet(self.fd, i32::from(*c), ssl::PRBool::from(true))
|
||||
})?;
|
||||
}
|
||||
Ok(())
|
||||
@@ -602,8 +600,8 @@ impl SecretAgent {
|
||||
/// Calling this function returns None until the connection is complete.
|
||||
#[must_use]
|
||||
pub const fn info(&self) -> Option<&SecretAgentInfo> {
|
||||
match &self.state {
|
||||
HandshakeState::Complete(info) => Some(info),
|
||||
match self.state {
|
||||
HandshakeState::Complete(ref info) => Some(info),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -646,7 +644,7 @@ impl SecretAgent {
|
||||
fn capture_error<T>(&mut self, res: Res<T>) -> Res<T> {
|
||||
if let Err(e) = res {
|
||||
let e = ech::convert_ech_error(self.fd, e);
|
||||
qwarn!("[{self}] error: {e:?}");
|
||||
qwarn!([self], "error: {:?}", e);
|
||||
self.state = HandshakeState::Failed(e.clone());
|
||||
Err(e)
|
||||
} else {
|
||||
@@ -671,7 +669,7 @@ impl SecretAgent {
|
||||
let info = self.capture_error(SecretAgentInfo::new(self.fd))?;
|
||||
HandshakeState::Complete(info)
|
||||
};
|
||||
qdebug!("[{self}] state -> {:?}", self.state);
|
||||
qdebug!([self], "state -> {:?}", self.state);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -694,8 +692,8 @@ impl SecretAgent {
|
||||
// Within this scope, _h maintains a mutable reference to self.io.
|
||||
let _h = self.io.wrap(input);
|
||||
match self.state {
|
||||
HandshakeState::Authenticated(err) => unsafe {
|
||||
ssl::SSL_AuthCertificateComplete(self.fd, err)
|
||||
HandshakeState::Authenticated(ref err) => unsafe {
|
||||
ssl::SSL_AuthCertificateComplete(self.fd, *err)
|
||||
},
|
||||
_ => unsafe { ssl::SSL_ForceHandshake(self.fd) },
|
||||
}
|
||||
@@ -728,10 +726,10 @@ impl SecretAgent {
|
||||
let records = self.setup_raw()?;
|
||||
|
||||
// Fire off any authentication we might need to complete.
|
||||
if let HandshakeState::Authenticated(err) = self.state {
|
||||
if let HandshakeState::Authenticated(ref err) = self.state {
|
||||
let result =
|
||||
secstatus_to_res(unsafe { ssl::SSL_AuthCertificateComplete(self.fd, err) });
|
||||
qdebug!("[{self}] SSL_AuthCertificateComplete: {result:?}");
|
||||
secstatus_to_res(unsafe { ssl::SSL_AuthCertificateComplete(self.fd, *err) });
|
||||
qdebug!([self], "SSL_AuthCertificateComplete: {:?}", result);
|
||||
// This should return SECSuccess, so don't use update_state().
|
||||
self.capture_error(result)?;
|
||||
}
|
||||
@@ -760,15 +758,11 @@ impl SecretAgent {
|
||||
if self.raw == Some(true) {
|
||||
// Need to hold the record list in scope until the close is done.
|
||||
let _records = self.setup_raw().expect("Can only close");
|
||||
unsafe {
|
||||
prio::PR_Close(self.fd.cast());
|
||||
}
|
||||
unsafe { prio::PR_Close(self.fd.cast()) };
|
||||
} else {
|
||||
// Need to hold the IO wrapper in scope until the close is done.
|
||||
let _io = self.io.wrap(&[]);
|
||||
unsafe {
|
||||
prio::PR_Close(self.fd.cast());
|
||||
}
|
||||
unsafe { prio::PR_Close(self.fd.cast()) };
|
||||
};
|
||||
let _output = self.io.take_output();
|
||||
self.fd = null_mut();
|
||||
@@ -882,7 +876,7 @@ impl Client {
|
||||
token,
|
||||
len,
|
||||
info.as_mut_ptr(),
|
||||
c_uint::try_from(std::mem::size_of::<ssl::SSLResumptionTokenInfo>()).unwrap(),
|
||||
c_uint::try_from(mem::size_of::<ssl::SSLResumptionTokenInfo>()).unwrap(),
|
||||
);
|
||||
if info_res.is_err() {
|
||||
// Ignore the token.
|
||||
@@ -897,7 +891,11 @@ impl Client {
|
||||
let len = usize::try_from(len).unwrap();
|
||||
let mut v = Vec::with_capacity(len);
|
||||
v.extend_from_slice(null_safe_slice(token, len));
|
||||
qdebug!("[{fd:p}] Got resumption token {}", hex_snip_middle(&v));
|
||||
qdebug!(
|
||||
[format!("{fd:p}")],
|
||||
"Got resumption token {}",
|
||||
hex_snip_middle(&v)
|
||||
);
|
||||
|
||||
if resumption.len() >= MAX_TICKETS {
|
||||
resumption.remove(0);
|
||||
@@ -967,7 +965,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)) }
|
||||
@@ -1018,7 +1016,7 @@ pub enum ZeroRttCheckResult {
|
||||
|
||||
/// A `ZeroRttChecker` is used by the agent to validate the application token (as provided by
|
||||
/// `send_ticket`)
|
||||
pub trait ZeroRttChecker: std::fmt::Debug + Unpin {
|
||||
pub trait ZeroRttChecker: std::fmt::Debug + std::marker::Unpin {
|
||||
fn check(&self, token: &[u8]) -> ZeroRttCheckResult;
|
||||
}
|
||||
|
||||
@@ -1070,7 +1068,7 @@ impl Server {
|
||||
return Err(Error::CertificateLoading);
|
||||
};
|
||||
let key_ptr = unsafe { p11::PK11_FindKeyByAnyCert(*cert, null_mut()) };
|
||||
let Ok(key) = PrivateKey::from_ptr(key_ptr) else {
|
||||
let Ok(key) = p11::PrivateKey::from_ptr(key_ptr) else {
|
||||
return Err(Error::CertificateLoading);
|
||||
};
|
||||
secstatus_to_res(unsafe {
|
||||
@@ -1177,7 +1175,7 @@ impl Server {
|
||||
pk: &PublicKey,
|
||||
) -> Res<()> {
|
||||
let cfg = ech::encode_config(config, public_name, pk)?;
|
||||
qdebug!("[{self}] Enable ECH for a server: {}", hex_with_len(&cfg));
|
||||
qdebug!([self], "Enable ECH for a server: {}", hex_with_len(&cfg));
|
||||
unsafe {
|
||||
ech::SSL_SetServerEchConfigs(
|
||||
self.agent.fd,
|
||||
@@ -1215,8 +1213,8 @@ impl ::std::fmt::Display for Server {
|
||||
/// A generic container for Client or Server.
|
||||
#[derive(Debug)]
|
||||
pub enum Agent {
|
||||
Client(Client),
|
||||
Server(Server),
|
||||
Client(crate::agent::Client),
|
||||
Server(crate::agent::Server),
|
||||
}
|
||||
|
||||
impl Deref for Agent {
|
||||
|
||||
10
third_party/rust/neqo-crypto/src/agentio.rs
vendored
10
third_party/rust/neqo-crypto/src/agentio.rs
vendored
@@ -52,7 +52,7 @@ impl Record {
|
||||
|
||||
// Shoves this record into the socket, returns true if blocked.
|
||||
pub(crate) fn write(self, fd: *mut ssl::PRFileDesc) -> Res<()> {
|
||||
qtrace!("write {self:?}");
|
||||
qtrace!("write {:?}", self);
|
||||
unsafe {
|
||||
ssl::SSL_RecordLayerData(
|
||||
fd,
|
||||
@@ -177,7 +177,7 @@ impl AgentIoInput {
|
||||
|
||||
#[allow(clippy::disallowed_methods)] // We just checked if this was empty.
|
||||
let src = unsafe { std::slice::from_raw_parts(self.input, amount) };
|
||||
qtrace!("[{self}] read {}", hex(src));
|
||||
qtrace!([self], "read {}", hex(src));
|
||||
let dst = unsafe { std::slice::from_raw_parts_mut(buf, amount) };
|
||||
dst.copy_from_slice(src);
|
||||
self.input = self.input.wrapping_add(amount);
|
||||
@@ -186,7 +186,7 @@ impl AgentIoInput {
|
||||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
qtrace!("[{self}] reset");
|
||||
qtrace!([self], "reset");
|
||||
self.input = null();
|
||||
self.available = 0;
|
||||
}
|
||||
@@ -230,12 +230,12 @@ impl AgentIo {
|
||||
// Stage output from TLS into the output buffer.
|
||||
fn save_output(&mut self, buf: *const u8, count: usize) {
|
||||
let slice = unsafe { null_safe_slice(buf, count) };
|
||||
qtrace!("[{self}] save output {}", hex(slice));
|
||||
qtrace!([self], "save output {}", hex(slice));
|
||||
self.output.extend_from_slice(slice);
|
||||
}
|
||||
|
||||
pub fn take_output(&mut self) -> Vec<u8> {
|
||||
qtrace!("[{self}] take output");
|
||||
qtrace!([self], "take output");
|
||||
mem::take(&mut self.output)
|
||||
}
|
||||
}
|
||||
|
||||
32
third_party/rust/neqo-crypto/src/cert.rs
vendored
32
third_party/rust/neqo-crypto/src/cert.rs
vendored
@@ -46,7 +46,7 @@ fn stapled_ocsp_responses(fd: *mut PRFileDesc) -> Option<Vec<Vec<u8>>> {
|
||||
Some(ocsp_ptr) => {
|
||||
let mut ocsp_helper: Vec<Vec<u8>> = Vec::new();
|
||||
let Ok(len) = isize::try_from(unsafe { ocsp_ptr.as_ref().len }) else {
|
||||
qerror!("[{fd:p}] Received illegal OSCP length");
|
||||
qerror!([format!("{fd:p}")], "Received illegal OSCP length");
|
||||
return None;
|
||||
};
|
||||
for idx in 0..len {
|
||||
@@ -72,6 +72,23 @@ fn signed_cert_timestamp(fd: *mut PRFileDesc) -> Option<Vec<u8>> {
|
||||
})
|
||||
}
|
||||
|
||||
impl CertificateInfo {
|
||||
pub(crate) fn new(fd: *mut PRFileDesc) -> Option<Self> {
|
||||
peer_certificate_chain(fd).map(|certs| Self {
|
||||
certs,
|
||||
stapled_ocsp_responses: stapled_ocsp_responses(fd),
|
||||
signed_cert_timestamp: signed_cert_timestamp(fd),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl CertificateInfo {
|
||||
#[must_use]
|
||||
pub fn iter(&self) -> ItemArrayIterator<'_> {
|
||||
self.certs.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a CertificateInfo {
|
||||
type IntoIter = ItemArrayIterator<'a>;
|
||||
type Item = &'a [u8];
|
||||
@@ -81,19 +98,6 @@ impl<'a> IntoIterator for &'a CertificateInfo {
|
||||
}
|
||||
|
||||
impl CertificateInfo {
|
||||
pub(crate) fn new(fd: *mut PRFileDesc) -> Option<Self> {
|
||||
peer_certificate_chain(fd).map(|certs| Self {
|
||||
certs,
|
||||
stapled_ocsp_responses: stapled_ocsp_responses(fd),
|
||||
signed_cert_timestamp: signed_cert_timestamp(fd),
|
||||
})
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn iter(&self) -> ItemArrayIterator<'_> {
|
||||
self.certs.into_iter()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn stapled_ocsp_responses(&self) -> &Option<Vec<Vec<u8>>> {
|
||||
&self.stapled_ocsp_responses
|
||||
|
||||
2
third_party/rust/neqo-crypto/src/ech.rs
vendored
2
third_party/rust/neqo-crypto/src/ech.rs
vendored
@@ -146,7 +146,7 @@ pub fn generate_keys() -> Res<(PrivateKey, PublicKey)> {
|
||||
assert_eq!(secret_ptr.is_null(), public_ptr.is_null());
|
||||
let sk = PrivateKey::from_ptr(secret_ptr)?;
|
||||
let pk = PublicKey::from_ptr(public_ptr)?;
|
||||
qtrace!("Generated key pair: sk={sk:?} pk={pk:?}");
|
||||
qtrace!("Generated key pair: sk={:?} pk={:?}", sk, pk);
|
||||
Ok((sk, pk))
|
||||
}
|
||||
|
||||
|
||||
4
third_party/rust/neqo-crypto/src/lib.rs
vendored
4
third_party/rust/neqo-crypto/src/lib.rs
vendored
@@ -70,7 +70,7 @@ mod nss {
|
||||
|
||||
// Need to map the types through.
|
||||
fn secstatus_to_res(code: nss::SECStatus) -> Res<()> {
|
||||
err::secstatus_to_res(code)
|
||||
crate::err::secstatus_to_res(code as crate::ssl::SECStatus)
|
||||
}
|
||||
|
||||
enum NssLoaded {
|
||||
@@ -106,7 +106,7 @@ fn version_check() -> Res<()> {
|
||||
/// This allows us to use SSLTRACE in all of our unit tests and programs.
|
||||
#[cfg(debug_assertions)]
|
||||
fn enable_ssl_trace() -> Res<()> {
|
||||
let opt = Opt::Locking.as_int();
|
||||
let opt = ssl::Opt::Locking.as_int();
|
||||
let mut v: ::std::os::raw::c_int = 0;
|
||||
secstatus_to_res(unsafe { ssl::SSL_OptionGetDefault(opt, &mut v) })
|
||||
}
|
||||
|
||||
3
third_party/rust/neqo-crypto/src/p11.rs
vendored
3
third_party/rust/neqo-crypto/src/p11.rs
vendored
@@ -11,6 +11,7 @@
|
||||
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
mem,
|
||||
ops::{Deref, DerefMut},
|
||||
os::raw::c_uint,
|
||||
ptr::null_mut,
|
||||
@@ -264,7 +265,7 @@ impl Item {
|
||||
SECItem {
|
||||
type_: SECItemType::siBuffer,
|
||||
data: data.cast_mut().cast(),
|
||||
len: c_uint::try_from(std::mem::size_of::<T>()).unwrap(),
|
||||
len: c_uint::try_from(mem::size_of::<T>()).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
third_party/rust/neqo-crypto/src/result.rs
vendored
2
third_party/rust/neqo-crypto/src/result.rs
vendored
@@ -83,7 +83,7 @@ mod tests {
|
||||
assert_eq!(code, -12273);
|
||||
assert_eq!(
|
||||
desc,
|
||||
"SSL received a record with an incorrect Message Authentication Code"
|
||||
"SSL received a record with an incorrect Message Authentication Code."
|
||||
);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
|
||||
2
third_party/rust/neqo-crypto/src/secrets.rs
vendored
2
third_party/rust/neqo-crypto/src/secrets.rs
vendored
@@ -88,7 +88,7 @@ impl Secrets {
|
||||
}
|
||||
|
||||
fn put(&mut self, dir: SecretDirection, epoch: Epoch, key: SymKey) {
|
||||
qdebug!("{dir:?} secret available for {epoch:?}: {key:?}");
|
||||
qdebug!("{:?} secret available for {:?}: {:?}", dir, epoch, key);
|
||||
let keys = match dir {
|
||||
SecretDirection::Read => &mut self.r,
|
||||
SecretDirection::Write => &mut self.w,
|
||||
|
||||
@@ -61,7 +61,7 @@ impl SelfEncrypt {
|
||||
self.old_key = Some(mem::replace(&mut self.key, new_key));
|
||||
let (kid, _) = self.key_id.overflowing_add(1);
|
||||
self.key_id = kid;
|
||||
qinfo!("[SelfEncrypt] Rotated keys to {}", self.key_id);
|
||||
qinfo!(["SelfEncrypt"], "Rotated keys to {}", self.key_id);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -99,7 +99,8 @@ impl SelfEncrypt {
|
||||
output.resize(encoded_len, 0);
|
||||
cipher.encrypt(0, extended_aad.as_ref(), plaintext, &mut output[offset..])?;
|
||||
qtrace!(
|
||||
"[SelfEncrypt] seal {} {} -> {}",
|
||||
["SelfEncrypt"],
|
||||
"seal {} {} -> {}",
|
||||
hex(aad),
|
||||
hex(plaintext),
|
||||
hex(&output)
|
||||
@@ -149,7 +150,8 @@ impl SelfEncrypt {
|
||||
let final_len = decrypted.len();
|
||||
output.truncate(final_len);
|
||||
qtrace!(
|
||||
"[SelfEncrypt] open {} {} -> {}",
|
||||
["SelfEncrypt"],
|
||||
"open {} {} -> {}",
|
||||
hex(aad),
|
||||
hex(ciphertext),
|
||||
hex(&output)
|
||||
|
||||
2
third_party/rust/neqo-crypto/src/time.rs
vendored
2
third_party/rust/neqo-crypto/src/time.rs
vendored
@@ -233,7 +233,7 @@ mod test {
|
||||
init();
|
||||
let base = get_base();
|
||||
let delta_micros = PRTime::try_from(DELTA.as_micros()).unwrap();
|
||||
println!("{} - {delta_micros}", base.prtime);
|
||||
println!("{} - {}", base.prtime, delta_micros);
|
||||
let t = Time::try_from(base.prtime - delta_micros).unwrap();
|
||||
assert_eq!(Instant::from(t) + DELTA, base.instant);
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ impl ZeroRttChecker for PermissiveZeroRttChecker {
|
||||
}
|
||||
|
||||
fn zero_rtt_setup(mode: Resumption, client: &Client, server: &mut Server) -> Option<AntiReplay> {
|
||||
matches!(mode, Resumption::WithZeroRtt).then(|| {
|
||||
if matches!(mode, Resumption::WithZeroRtt) {
|
||||
client.enable_0rtt().expect("should enable 0-RTT on client");
|
||||
|
||||
let anti_replay = anti_replay();
|
||||
@@ -127,8 +127,10 @@ fn zero_rtt_setup(mode: Resumption, client: &Client, server: &mut Server) -> Opt
|
||||
Box::new(PermissiveZeroRttChecker { resuming: false }),
|
||||
)
|
||||
.expect("should enable 0-RTT on server");
|
||||
anti_replay
|
||||
})
|
||||
Some(anti_replay)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::missing_panics_doc)]
|
||||
|
||||
6
third_party/rust/neqo-crypto/tests/hp.rs
vendored
6
third_party/rust/neqo-crypto/tests/hp.rs
vendored
@@ -4,6 +4,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::mem;
|
||||
|
||||
use neqo_crypto::{
|
||||
constants::{
|
||||
Cipher, TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256,
|
||||
@@ -69,12 +71,12 @@ fn chacha20_ctr() {
|
||||
#[should_panic(expected = "out of range")]
|
||||
fn aes_short() {
|
||||
let hp = make_hp(TLS_AES_128_GCM_SHA256);
|
||||
drop(hp.mask(&[0; 15]));
|
||||
mem::drop(hp.mask(&[0; 15]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "out of range")]
|
||||
fn chacha20_short() {
|
||||
let hp = make_hp(TLS_CHACHA20_POLY1305_SHA256);
|
||||
drop(hp.mask(&[0; 15]));
|
||||
mem::drop(hp.mask(&[0; 15]));
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"a3bea7b8e1efb0a5a78f4184ffa79bc436836b516e34d313bab8f450cdfb02df","src/buffered_send_stream.rs":"d74c520af97bcdaa48862a396e6510c9f95124358dcf46a7722e4daf821fff2c","src/client_events.rs":"96d38deba366edbbe5f6e73d56d74ae36e239e35393ae3ac094d73063b564f68","src/conn_params.rs":"7f0df52bceda1923aef2b7c5c64a532f49ea083ea45e3dcd5bd4b03031b89643","src/connection.rs":"d225b55f1229988568085f133dac1cfe5d4adfd91864a7e1fc344a784a4b5594","src/connection_client.rs":"9a48949fe885e1139ae2c056a5504a3e336c8d75aae4cdcc2ad92355ad5aa623","src/connection_server.rs":"d16f73685ae29492e2d32321158b6206349fe1b0016d89bc50c2727f47c64140","src/control_stream_local.rs":"9325e5c8857036c68f7e49b81c898d5de51d43cb262e523385e6b2b7366c2cea","src/control_stream_remote.rs":"e7d0b5a195e3ef482b36972eac979b7d761215fcb76699112f2d4919708fcf26","src/features/extended_connect/mod.rs":"f9a08a6ec1dde79133c18c21b85f6b9a01468d98bace838f559340383cc603e7","src/features/extended_connect/tests/mod.rs":"fd6aee37243713e80fc526552f21f0222338cec9890409b6575a2a637b17ec1f","src/features/extended_connect/tests/webtransport/datagrams.rs":"51d6f3828c44b438eb1776e8dcce531af520f28bc0d715807d3f53a0eaa071d1","src/features/extended_connect/tests/webtransport/mod.rs":"9c0de1da3cfe9fac75f2d2faf3e0e0500261519e7862c6b5fec5097ab47f72f1","src/features/extended_connect/tests/webtransport/negotiation.rs":"8b505384d5b8a9c8e17194360a33d9ecbdb350c3359245b9f2bed9dc8cec7423","src/features/extended_connect/tests/webtransport/sessions.rs":"64b29ec9ba34e636b1109d99ab588666d85c85442565faa9071b743f4f764d6e","src/features/extended_connect/tests/webtransport/streams.rs":"eb0e793dc43ca9296334d29ced70d5ab3d90fd0c4ca3a485abad06c14eec29a4","src/features/extended_connect/webtransport_session.rs":"09a06af84e101f628f1ff2e9be344463662212f2d8914fe84b9675d9f0488af5","src/features/extended_connect/webtransport_streams.rs":"9855d77705acb7d21566333c4b297816e363be2ade14b8685fd1df4a4861cf74","src/features/mod.rs":"6f192996e6e2231a97f3fcae2aa02d648e571a6ec5e14b4a23b24b87888d117c","src/frames/hframe.rs":"5fcd9145a88e8ebf9ec1832c8ab61357a9afd362690e26d5a32595b2ae135395","src/frames/mod.rs":"0e6d49888d723b2c2c73df11020ceb88d9f062e9d4dc436eb38173e0b772d905","src/frames/reader.rs":"fff71d4e5a75ac16ed455c5cb7a12f355d56fe8bf7b33d6fb160e4bc48ee94cd","src/frames/tests/hframe.rs":"43a7735fc859692633e7f3c031710a9fb635611756cb4b9f387bac0a38c0fa09","src/frames/tests/mod.rs":"ee2eb2d88132e500640b156d5ae6b6ef5051e86eae09464a9cec827142ef6b73","src/frames/tests/reader.rs":"eaff7faa62aec5caf2ed21c6bd9e869654433b030df7676cc4843e2b15d1a6c1","src/frames/tests/wtframe.rs":"c6598d24f5e12972f02de6e1394362671633982db637a07e1c0bb9b56d93ea2a","src/frames/wtframe.rs":"544bc8fa74e3b15cde6e45ba47bcc52f098658e78664abfda8249a89c88d51b9","src/headers_checks.rs":"42f5bb95c6af9d7e747b3b4e39a2b10c4a323abd7da30cd4db4ebbc47696e060","src/lib.rs":"1fd024d8ec7fed5c4766f8a817531b1a4363bd2eaa60f9a41e4c2fed84682308","src/priority.rs":"946307329f31819d969093406ae5448f7923343ccc112221ea6eedf86cf447dc","src/push_controller.rs":"a03aa8b1e2db588f4342337252e7b7d10f43447498ddbc95733b5304a8e717ab","src/push_id.rs":"cd4cea3102b59918668b66725bbd19b66dc389e35d986132c5ceb72bbc9f3222","src/qlog.rs":"85187b6eee73d0ce085bc42dfc30999f4a51f92daa02a1a1ac1228a490131082","src/qpack_decoder_receiver.rs":"eb06c4be59da567fef70c20daa2c0f165c768131165479a210e69659f168b88f","src/qpack_encoder_receiver.rs":"831f3da9ec17966286786ba3f2c723395a132e65d6a33b4ec341fe7640c1a53d","src/recv_message.rs":"279c1de34d13bc43cfd5c622956d9a1a7e24153918b029c45c0358f384fef8fd","src/request_target.rs":"9720b9f87d66a7c2301bba7de5a5a9300f547613a63153a4d35c7a7506a59b31","src/send_message.rs":"16e688bcffe7aefa43bb5876cdad1f79b9227acad8695afc64f47c1565933e69","src/server.rs":"86c0a012b5dcb4d7c9de69360bf004dd30d75c7827b4cd60c282ca89c7bb2ed3","src/server_connection_events.rs":"1396baab265a814045ccfe63d637a4fdc32a667b5eb2925fa4951f5c3078fb20","src/server_events.rs":"26f3d3585633296a62c3e1e8594e491f45e4c6d17c3cd75847c3cdec5778c2e1","src/settings.rs":"d0f8c546e70161422a029a40564b9e9b953fe671c60835196b16f3364779eaf9","src/stream_type_reader.rs":"5ba77600c5e8c4abdd9443aec20311cf8a812b97ab18a90408aa4e689f42bded","tests/httpconn.rs":"5e2318ac776ce8b4c0d3c44b42fc32e6609b2ef31853767312462eae9a7c659d","tests/priority.rs":"f3869e5fbf63483f04b589d3447e02a4f167b2f3c406028cb30a87ad9a22da53","tests/send_message.rs":"21de05a3c6d516d28df6d77d7e4fb1b05985fc2debde1e8c7fb0607164c74b75","tests/webtransport.rs":"4ae2531c8384120b541198757106954b1dac9f2dcb39ed2231a67a59c1fb94f8"},"package":null}
|
||||
{"files":{"Cargo.toml":"98ce446932fc062c3a45558e73380b08d0dfbeac321ed0111a62062720451b6f","src/buffered_send_stream.rs":"dfb248c66ea65418b0c7798c2ecaa3ed70ef1af818ef58d53ef742b3445077b7","src/client_events.rs":"77fedca72ce54956eaba3fb7103085d196a631b764662584ea2629224c5c234e","src/conn_params.rs":"7f0df52bceda1923aef2b7c5c64a532f49ea083ea45e3dcd5bd4b03031b89643","src/connection.rs":"c82b016f839c5d3b1ec24cd76b372aec4f0e832ed68d792171579f9e649b3824","src/connection_client.rs":"a27423973be27501bb8e8ae169938fa215322fa78f7f5b95cb418adc6fa8b7a1","src/connection_server.rs":"cf4da2cdd823e31d2352e45de84d366c45bd3d8adf38c9151a84d808bda80209","src/control_stream_local.rs":"20917762c7e7c1112c56abf1cbaf0ad7f0eab97d8db9a3b10ff524315a235670","src/control_stream_remote.rs":"3729f67aa0681b1dbd4147063890f8440f27d82454776500ae964a17cda4d6b5","src/features/extended_connect/mod.rs":"f9a08a6ec1dde79133c18c21b85f6b9a01468d98bace838f559340383cc603e7","src/features/extended_connect/tests/mod.rs":"fd6aee37243713e80fc526552f21f0222338cec9890409b6575a2a637b17ec1f","src/features/extended_connect/tests/webtransport/datagrams.rs":"51d6f3828c44b438eb1776e8dcce531af520f28bc0d715807d3f53a0eaa071d1","src/features/extended_connect/tests/webtransport/mod.rs":"7828af3887acc5b141ec1af459069eeb4f2d95e7c9e5639047006c179ce6a355","src/features/extended_connect/tests/webtransport/negotiation.rs":"6ddb604a0aa521335ab84ff07718e485f926a27da730d5697c33d6df62af39d6","src/features/extended_connect/tests/webtransport/sessions.rs":"6ed8c6247a84916cf6bb6dc4eeded20f1d80c6d2ea8f256975786c5f3ab2efcb","src/features/extended_connect/tests/webtransport/streams.rs":"eab84efc920b766ea105a47d34bec565f79f64f6c6be1b7f4945d78bddb462fd","src/features/extended_connect/webtransport_session.rs":"debe63b81c8c3c49da9f2b9abb92ea05fb95745a8ee725a956dfeffa53dc9574","src/features/extended_connect/webtransport_streams.rs":"9855d77705acb7d21566333c4b297816e363be2ade14b8685fd1df4a4861cf74","src/features/mod.rs":"89056df3a868cb0037963c942fc27093cc16d84538ffca2d4759f9a6a6c74c7f","src/frames/hframe.rs":"de2c3d1a9205b0459fe676d7d5e1c0e463d3c1dd9e5f518a07b2e4ebbe66e3ec","src/frames/mod.rs":"0e6d49888d723b2c2c73df11020ceb88d9f062e9d4dc436eb38173e0b772d905","src/frames/reader.rs":"01acff3c6bb9d2a0c2ff68b054276fab8d61a47679bec9084d75c4f680a959b3","src/frames/tests/hframe.rs":"53941fd7656f5e424d499278e6d9ba93ce716f219e86fe6fa08c058ea92f8d7b","src/frames/tests/mod.rs":"6cb78d24bbab27f877d0526deb3e9a26694a23a9ce8ebe664947a852a3d92747","src/frames/tests/reader.rs":"6fb66c7a03acfc2e231e7bb3d020c902b59366a7523e488d118b24440ac68501","src/frames/tests/wtframe.rs":"c6598d24f5e12972f02de6e1394362671633982db637a07e1c0bb9b56d93ea2a","src/frames/wtframe.rs":"0f0366e590f7409580459e8a8b86fc48308ca7585837dddd7c319581a9a5a972","src/headers_checks.rs":"69964deb121721be01df7174c177543c161389295ce1450d348369279e312ba4","src/lib.rs":"3fb980eee46bee8dcb97ad9d55014555d8994a7a2d040ca223f2d28fe7d923ef","src/priority.rs":"946307329f31819d969093406ae5448f7923343ccc112221ea6eedf86cf447dc","src/push_controller.rs":"7f8b668d7ff16372693830ac4d3e6834e77465762a0a8d77ab7f9e883c2fb919","src/qlog.rs":"85187b6eee73d0ce085bc42dfc30999f4a51f92daa02a1a1ac1228a490131082","src/qpack_decoder_receiver.rs":"eb06c4be59da567fef70c20daa2c0f165c768131165479a210e69659f168b88f","src/qpack_encoder_receiver.rs":"831f3da9ec17966286786ba3f2c723395a132e65d6a33b4ec341fe7640c1a53d","src/recv_message.rs":"8b2fb49850560b32dcdd7a90933361ef7d61bc42daad3f2952462913d49e8787","src/request_target.rs":"9720b9f87d66a7c2301bba7de5a5a9300f547613a63153a4d35c7a7506a59b31","src/send_message.rs":"be4e9f64db2c25eb7176b84695e608e768115d62e615d389a33d26f7cd5b0c6c","src/server.rs":"c6a231fea182acd4f7e064578a1ad85a5fa0f618f3e0842d499f84f841bbf9da","src/server_connection_events.rs":"1396baab265a814045ccfe63d637a4fdc32a667b5eb2925fa4951f5c3078fb20","src/server_events.rs":"02fc8c0711efd758fb1ddee27d257c12ed35e2a989e7bf3de44bd662dc8234e3","src/settings.rs":"d0f8c546e70161422a029a40564b9e9b953fe671c60835196b16f3364779eaf9","src/stream_type_reader.rs":"115d50bbaa304a74d601614b755bcb626572ab89d5db7bfae9fff8ad64270722","tests/httpconn.rs":"72b4f66fc9b9efeb070907da35f1db2d320d232ef74380fd36ad7c2ddd213076","tests/priority.rs":"3b0e03d6a8fbde52c695130bb3e40d3b70cb74ee826af28db577060911bcbc03","tests/send_message.rs":"9540259485e8b7df1d07ff8abdc8cb86d5f32d736aea3bce28e8b0ecc00a9f5b","tests/webtransport.rs":"3bfcfddd57a8fe262c597b756982d671065a593d99d09d42b04f954a27a2a5fa"},"package":null}
|
||||
51
third_party/rust/neqo-http3/Cargo.toml
vendored
51
third_party/rust/neqo-http3/Cargo.toml
vendored
@@ -13,7 +13,7 @@
|
||||
edition = "2021"
|
||||
rust-version = "1.76.0"
|
||||
name = "neqo-http3"
|
||||
version = "0.12.2"
|
||||
version = "0.11.0"
|
||||
authors = ["The Neqo Authors <necko@mozilla.com>"]
|
||||
build = false
|
||||
autolib = false
|
||||
@@ -39,9 +39,6 @@ categories = [
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/mozilla/neqo/"
|
||||
|
||||
[package.metadata.cargo-machete]
|
||||
ignored = ["log"]
|
||||
|
||||
[lib]
|
||||
name = "neqo_http3"
|
||||
path = "src/lib.rs"
|
||||
@@ -96,47 +93,17 @@ version = "2.5.3"
|
||||
features = ["std"]
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.neqo-http3]
|
||||
path = "."
|
||||
features = ["draft-29"]
|
||||
|
||||
[dev-dependencies.neqo-transport]
|
||||
path = "./../neqo-transport"
|
||||
features = ["draft-29"]
|
||||
|
||||
[dev-dependencies.test-fixture]
|
||||
path = "../test-fixture"
|
||||
|
||||
[features]
|
||||
bench = [
|
||||
"neqo-common/bench",
|
||||
"neqo-crypto/bench",
|
||||
"neqo-qpack/bench",
|
||||
"neqo-transport/bench",
|
||||
]
|
||||
disable-encryption = [
|
||||
"neqo-transport/disable-encryption",
|
||||
"neqo-crypto/disable-encryption",
|
||||
]
|
||||
draft-29 = []
|
||||
|
||||
[lints.clippy]
|
||||
cfg_not_test = "warn"
|
||||
clone_on_ref_ptr = "warn"
|
||||
create_dir = "warn"
|
||||
get_unwrap = "warn"
|
||||
if_then_some_else_none = "warn"
|
||||
multiple_crate_versions = "allow"
|
||||
multiple_inherent_impl = "warn"
|
||||
pathbuf_init_then_push = "warn"
|
||||
redundant_type_annotations = "warn"
|
||||
ref_patterns = "warn"
|
||||
renamed_function_params = "warn"
|
||||
semicolon_inside_block = "warn"
|
||||
try_err = "warn"
|
||||
unneeded_field_pattern = "warn"
|
||||
unused_result_ok = "warn"
|
||||
unused_trait_names = "warn"
|
||||
|
||||
[lints.clippy.cargo]
|
||||
level = "warn"
|
||||
@@ -149,19 +116,3 @@ priority = -1
|
||||
[lints.clippy.pedantic]
|
||||
level = "warn"
|
||||
priority = -1
|
||||
|
||||
[lints.rust]
|
||||
absolute_paths_not_starting_with_crate = "warn"
|
||||
ambiguous_negative_literals = "warn"
|
||||
closure_returning_async_block = "warn"
|
||||
explicit_outlives_requirements = "warn"
|
||||
macro_use_extern_crate = "warn"
|
||||
missing_abi = "warn"
|
||||
non_ascii_idents = "warn"
|
||||
redundant_imports = "warn"
|
||||
redundant_lifetimes = "warn"
|
||||
trivial_numeric_casts = "warn"
|
||||
unit_bindings = "warn"
|
||||
unused_import_braces = "warn"
|
||||
unused_lifetimes = "warn"
|
||||
unused_macro_rules = "warn"
|
||||
|
||||
@@ -49,7 +49,7 @@ impl BufferedStream {
|
||||
|
||||
/// # Panics
|
||||
///
|
||||
/// This function cannot be called before the `BufferedStream` is initialized.
|
||||
/// This functon cannot be called before the `BufferedStream` is initialized.
|
||||
pub fn buffer(&mut self, to_buf: &[u8]) {
|
||||
if let Self::Initialized { buf, .. } = self {
|
||||
buf.extend_from_slice(to_buf);
|
||||
@@ -62,14 +62,14 @@ impl BufferedStream {
|
||||
///
|
||||
/// Returns `neqo_transport` errors.
|
||||
pub fn send_buffer(&mut self, conn: &mut Connection) -> Res<usize> {
|
||||
let label = format!("{self}");
|
||||
let label = ::neqo_common::log_subject!(::log::Level::Debug, self);
|
||||
let Self::Initialized { stream_id, buf } = self else {
|
||||
return Ok(0);
|
||||
};
|
||||
if buf.is_empty() {
|
||||
return Ok(0);
|
||||
}
|
||||
qtrace!("[{label}] sending data");
|
||||
qtrace!([label], "sending data.");
|
||||
let sent = conn.stream_send(*stream_id, &buf[..])?;
|
||||
if sent == 0 {
|
||||
return Ok(0);
|
||||
|
||||
26
third_party/rust/neqo-http3/src/client_events.rs
vendored
26
third_party/rust/neqo-http3/src/client_events.rs
vendored
@@ -16,7 +16,7 @@ use crate::{
|
||||
connection::Http3State,
|
||||
features::extended_connect::{ExtendedConnectEvents, ExtendedConnectType, SessionCloseReason},
|
||||
settings::HSettingType,
|
||||
CloseType, Http3StreamInfo, HttpRecvStreamEvents, PushId, RecvStreamEvents, SendStreamEvents,
|
||||
CloseType, Http3StreamInfo, HttpRecvStreamEvents, RecvStreamEvents, SendStreamEvents,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
@@ -68,24 +68,24 @@ pub enum Http3ClientEvent {
|
||||
},
|
||||
/// A new push promise.
|
||||
PushPromise {
|
||||
push_id: PushId,
|
||||
push_id: u64,
|
||||
request_stream_id: StreamId,
|
||||
headers: Vec<Header>,
|
||||
},
|
||||
/// A push response headers are ready.
|
||||
PushHeaderReady {
|
||||
push_id: PushId,
|
||||
push_id: u64,
|
||||
headers: Vec<Header>,
|
||||
interim: bool,
|
||||
fin: bool,
|
||||
},
|
||||
/// New bytes are available on a push stream for reading.
|
||||
PushDataReadable { push_id: PushId },
|
||||
PushDataReadable { push_id: u64 },
|
||||
/// A push has been canceled.
|
||||
PushCanceled { push_id: PushId },
|
||||
PushCanceled { push_id: u64 },
|
||||
/// A push stream was been reset due to a `HttpGeneralProtocol` error.
|
||||
/// Most common case are malformed response headers.
|
||||
PushReset { push_id: PushId, error: AppError },
|
||||
PushReset { push_id: u64, error: AppError },
|
||||
/// New stream can be created
|
||||
RequestsCreatable,
|
||||
/// Cert authentication needed
|
||||
@@ -196,7 +196,7 @@ impl ExtendedConnectEvents for Http3ClientEvents {
|
||||
headers,
|
||||
}));
|
||||
} else {
|
||||
unreachable!("There is only ExtendedConnectType::WebTransport");
|
||||
unreachable!("There is only ExtendedConnectType::WebTransport.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ impl ExtendedConnectEvents for Http3ClientEvents {
|
||||
},
|
||||
));
|
||||
} else {
|
||||
unreachable!("There are no other types");
|
||||
unreachable!("There are no other types.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ impl ExtendedConnectEvents for Http3ClientEvents {
|
||||
}
|
||||
|
||||
impl Http3ClientEvents {
|
||||
pub fn push_promise(&self, push_id: PushId, request_stream_id: StreamId, headers: Vec<Header>) {
|
||||
pub fn push_promise(&self, push_id: u64, request_stream_id: StreamId, headers: Vec<Header>) {
|
||||
self.insert(Http3ClientEvent::PushPromise {
|
||||
push_id,
|
||||
request_stream_id,
|
||||
@@ -248,12 +248,12 @@ impl Http3ClientEvents {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn push_canceled(&self, push_id: PushId) {
|
||||
pub fn push_canceled(&self, push_id: u64) {
|
||||
self.remove_events_for_push_id(push_id);
|
||||
self.insert(Http3ClientEvent::PushCanceled { push_id });
|
||||
}
|
||||
|
||||
pub fn push_reset(&self, push_id: PushId, error: AppError) {
|
||||
pub fn push_reset(&self, push_id: u64, error: AppError) {
|
||||
self.remove_events_for_push_id(push_id);
|
||||
self.insert(Http3ClientEvent::PushReset { push_id, error });
|
||||
}
|
||||
@@ -336,7 +336,7 @@ impl Http3ClientEvents {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn has_push(&self, push_id: PushId) -> bool {
|
||||
pub fn has_push(&self, push_id: u64) -> bool {
|
||||
for iter in &*self.events.borrow() {
|
||||
if matches!(iter, Http3ClientEvent::PushPromise{push_id:x, ..} if *x == push_id) {
|
||||
return true;
|
||||
@@ -345,7 +345,7 @@ impl Http3ClientEvents {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn remove_events_for_push_id(&self, push_id: PushId) {
|
||||
pub fn remove_events_for_push_id(&self, push_id: u64) {
|
||||
self.remove(|evt| {
|
||||
matches!(evt,
|
||||
Http3ClientEvent::PushPromise{ push_id: x, .. }
|
||||
|
||||
171
third_party/rust/neqo-http3/src/connection.rs
vendored
171
third_party/rust/neqo-http3/src/connection.rs
vendored
@@ -35,7 +35,7 @@ use crate::{
|
||||
qpack_decoder_receiver::DecoderRecvStream,
|
||||
qpack_encoder_receiver::EncoderRecvStream,
|
||||
recv_message::{RecvMessage, RecvMessageInfo},
|
||||
request_target::{AsRequestTarget, RequestTarget as _},
|
||||
request_target::{AsRequestTarget, RequestTarget},
|
||||
send_message::SendMessage,
|
||||
settings::{HSettingType, HSettings, HttpZeroRttChecker},
|
||||
stream_type_reader::NewStreamHeadReader,
|
||||
@@ -159,7 +159,7 @@ The API consists of:
|
||||
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 and second may still be active.
|
||||
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
|
||||
@@ -195,7 +195,7 @@ are local or remote:
|
||||
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 (receiving HTTP request on the
|
||||
- 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
|
||||
@@ -277,12 +277,12 @@ For example for `Http` stream the listener will produce `HeaderReady` and `Da
|
||||
|
||||
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 exchanged,
|
||||
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 able to do this `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`
|
||||
@@ -352,7 +352,7 @@ impl Http3Connection {
|
||||
/// 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<()> {
|
||||
qdebug!("[{self}] Initialize the http3 connection");
|
||||
qdebug!([self], "Initialize the http3 connection.");
|
||||
self.control_stream_local.create(conn)?;
|
||||
|
||||
self.send_settings();
|
||||
@@ -361,7 +361,7 @@ impl Http3Connection {
|
||||
}
|
||||
|
||||
fn send_settings(&mut self) {
|
||||
qdebug!("[{self}] Send settings");
|
||||
qdebug!([self], "Send settings.");
|
||||
self.control_stream_local.queue_frame(&HFrame::Settings {
|
||||
settings: HSettings::from(&self.local_params),
|
||||
});
|
||||
@@ -374,7 +374,7 @@ impl Http3Connection {
|
||||
}
|
||||
|
||||
fn create_qpack_streams(&self, conn: &mut Connection) -> Res<()> {
|
||||
qdebug!("[{self}] create_qpack_streams");
|
||||
qdebug!([self], "create_qpack_streams.");
|
||||
self.qpack_encoder
|
||||
.borrow_mut()
|
||||
.add_send_stream(conn.stream_create(StreamType::UniDi)?);
|
||||
@@ -458,7 +458,7 @@ 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}");
|
||||
qtrace!([self], "A new stream: {}.", stream_id);
|
||||
self.recv_streams.insert(
|
||||
stream_id,
|
||||
Box::new(NewStreamHeadReader::new(stream_id, self.role)),
|
||||
@@ -468,7 +468,7 @@ impl Http3Connection {
|
||||
/// The function calls `receive` for a stream. It also deals with the outcome of a read by
|
||||
/// calling `handle_stream_manipulation_output`.
|
||||
fn stream_receive(&mut self, conn: &mut Connection, stream_id: StreamId) -> Res<ReceiveOutput> {
|
||||
qtrace!("[{self}] Readable stream {stream_id}");
|
||||
qtrace!([self], "Readable stream {}.", stream_id);
|
||||
|
||||
if let Some(recv_stream) = self.recv_streams.get_mut(&stream_id) {
|
||||
let res = recv_stream.receive(conn);
|
||||
@@ -485,7 +485,7 @@ impl Http3Connection {
|
||||
conn: &mut Connection,
|
||||
) -> Res<()> {
|
||||
for stream_id in unblocked_streams {
|
||||
qdebug!("[{self}] Stream {stream_id} is unblocked");
|
||||
qdebug!([self], "Stream {} is unblocked", stream_id);
|
||||
if let Some(r) = self.recv_streams.get_mut(&stream_id) {
|
||||
let res = r
|
||||
.http_stream()
|
||||
@@ -501,7 +501,7 @@ 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(_)`, `Http` or `WebTransportStream(_)` stream
|
||||
/// 1) a `Push(_)`, `Htttp` or `WebTransportStream(_)` stream
|
||||
/// 2) frames `MaxPushId`, `PriorityUpdateRequest`, `PriorityUpdateRequestPush` or `Goaway` must
|
||||
/// be handled by `Http3Client`/`Server`.
|
||||
///
|
||||
@@ -551,7 +551,12 @@ impl Http3Connection {
|
||||
app_error: AppError,
|
||||
conn: &mut Connection,
|
||||
) -> Res<()> {
|
||||
qinfo!("[{self}] Handle a stream reset stream_id={stream_id} app_err={app_error}");
|
||||
qinfo!(
|
||||
[self],
|
||||
"Handle a stream reset stream_id={} app_err={}",
|
||||
stream_id,
|
||||
app_error
|
||||
);
|
||||
|
||||
self.close_recv(stream_id, CloseType::ResetRemote(app_error), conn)
|
||||
}
|
||||
@@ -562,7 +567,12 @@ impl Http3Connection {
|
||||
app_error: AppError,
|
||||
conn: &mut Connection,
|
||||
) -> Res<()> {
|
||||
qinfo!("[{self}] Handle stream_stop_sending stream_id={stream_id} app_err={app_error}");
|
||||
qinfo!(
|
||||
[self],
|
||||
"Handle stream_stop_sending stream_id={} app_err={}",
|
||||
stream_id,
|
||||
app_error
|
||||
);
|
||||
|
||||
if self.send_stream_is_critical(stream_id) {
|
||||
return Err(Error::HttpClosedCriticalStream);
|
||||
@@ -575,7 +585,7 @@ impl Http3Connection {
|
||||
/// This is called when `neqo_transport::Connection` state has been change to take proper
|
||||
/// actions in the HTTP3 layer.
|
||||
pub fn handle_state_change(&mut self, conn: &mut Connection, state: &State) -> Res<bool> {
|
||||
qdebug!("[{self}] Handle state change {state:?}");
|
||||
qdebug!([self], "Handle state change {:?}", state);
|
||||
match state {
|
||||
State::Handshaking => {
|
||||
if self.role == Role::Server
|
||||
@@ -639,7 +649,7 @@ impl Http3Connection {
|
||||
self.recv_streams.clear();
|
||||
Ok(())
|
||||
} else {
|
||||
debug_assert!(false, "Zero rtt rejected in the wrong state");
|
||||
debug_assert!(false, "Zero rtt rejected in the wrong state.");
|
||||
Err(Error::HttpInternal(3))
|
||||
}
|
||||
}
|
||||
@@ -686,10 +696,15 @@ impl Http3Connection {
|
||||
}
|
||||
|
||||
NewStreamType::Push(push_id) => {
|
||||
qinfo!("[{self}] A new push stream {stream_id} push_id:{push_id}");
|
||||
qinfo!(
|
||||
[self],
|
||||
"A new push stream {} push_id:{}.",
|
||||
stream_id,
|
||||
push_id
|
||||
);
|
||||
}
|
||||
NewStreamType::Decoder => {
|
||||
qdebug!("[{self}] A new remote qpack encoder stream {stream_id}");
|
||||
qdebug!([self], "A new remote qpack encoder stream {}", stream_id);
|
||||
self.check_stream_exists(Http3StreamType::Decoder)?;
|
||||
self.recv_streams.insert(
|
||||
stream_id,
|
||||
@@ -700,7 +715,7 @@ impl Http3Connection {
|
||||
);
|
||||
}
|
||||
NewStreamType::Encoder => {
|
||||
qdebug!("[{self}] A new remote qpack decoder stream {stream_id}");
|
||||
qdebug!([self], "A new remote qpack decoder stream {}", stream_id);
|
||||
self.check_stream_exists(Http3StreamType::Encoder)?;
|
||||
self.recv_streams.insert(
|
||||
stream_id,
|
||||
@@ -711,7 +726,7 @@ impl Http3Connection {
|
||||
);
|
||||
}
|
||||
NewStreamType::Http(_) => {
|
||||
qinfo!("[{self}] A new http stream {stream_id}");
|
||||
qinfo!([self], "A new http stream {}.", stream_id);
|
||||
}
|
||||
NewStreamType::WebTransportStream(session_id) => {
|
||||
let session_exists = self
|
||||
@@ -722,13 +737,14 @@ impl Http3Connection {
|
||||
conn.stream_stop_sending(stream_id, Error::HttpStreamCreation.code())?;
|
||||
return Ok(ReceiveOutput::NoOutput);
|
||||
}
|
||||
// Set incoming WebTransport streams to be fair (share bandwidth).
|
||||
// We may call this with an invalid stream ID, so ignore that error.
|
||||
match conn.stream_fairness(stream_id, true) {
|
||||
Ok(()) | Err(neqo_transport::Error::InvalidStreamId) => (),
|
||||
Err(e) => return Err(Error::from(e)),
|
||||
};
|
||||
qinfo!("[{self}] A new WebTransport stream {stream_id} for session {session_id}");
|
||||
// set incoming WebTransport streams to be fair (share bandwidth)
|
||||
conn.stream_fairness(stream_id, true).ok();
|
||||
qinfo!(
|
||||
[self],
|
||||
"A new WebTransport stream {} for session {}.",
|
||||
stream_id,
|
||||
session_id
|
||||
);
|
||||
}
|
||||
NewStreamType::Unknown => {
|
||||
conn.stream_stop_sending(stream_id, Error::HttpStreamCreation.code())?;
|
||||
@@ -748,7 +764,7 @@ impl Http3Connection {
|
||||
|
||||
/// This is called when an application closes the connection.
|
||||
pub fn close(&mut self, error: AppError) {
|
||||
qdebug!("[{self}] Close connection error {error:?}");
|
||||
qdebug!([self], "Close connection error {:?}.", error);
|
||||
self.state = Http3State::Closing(CloseReason::Application(error));
|
||||
if (!self.send_streams.is_empty() || !self.recv_streams.is_empty()) && (error == 0) {
|
||||
qwarn!("close(0) called when streams still active");
|
||||
@@ -789,7 +805,7 @@ impl Http3Connection {
|
||||
Ok((_, false)) => {}
|
||||
Err(e) => {
|
||||
if e.stream_reset_error() && !self.recv_stream_is_critical(stream_id) {
|
||||
drop(conn.stream_stop_sending(stream_id, e.code()));
|
||||
mem::drop(conn.stream_stop_sending(stream_id, e.code()));
|
||||
self.close_recv(stream_id, CloseType::LocalError(e.code()), conn)?;
|
||||
return Ok((U::default(), false));
|
||||
}
|
||||
@@ -834,7 +850,8 @@ impl Http3Connection {
|
||||
T: AsRequestTarget<'t> + ?Sized + Debug,
|
||||
{
|
||||
qinfo!(
|
||||
"[{self}] Fetch method={} target: {:?}",
|
||||
[self],
|
||||
"Fetch method={} target: {:?}",
|
||||
request.method,
|
||||
request.target,
|
||||
);
|
||||
@@ -885,7 +902,7 @@ impl Http3Connection {
|
||||
MessageType::Request,
|
||||
stream_type,
|
||||
stream_id,
|
||||
Rc::clone(&self.qpack_encoder),
|
||||
self.qpack_encoder.clone(),
|
||||
send_events,
|
||||
);
|
||||
|
||||
@@ -934,7 +951,7 @@ impl Http3Connection {
|
||||
stream_id: StreamId,
|
||||
buf: &mut [u8],
|
||||
) -> Res<(usize, bool)> {
|
||||
qdebug!("[{self}] read_data from stream {stream_id}");
|
||||
qdebug!([self], "read_data from stream {}.", stream_id);
|
||||
let res = self
|
||||
.recv_streams
|
||||
.get_mut(&stream_id)
|
||||
@@ -951,7 +968,12 @@ impl Http3Connection {
|
||||
stream_id: StreamId,
|
||||
error: AppError,
|
||||
) -> Res<()> {
|
||||
qinfo!("[{self}] Reset sending side of stream {stream_id} error={error}");
|
||||
qinfo!(
|
||||
[self],
|
||||
"Reset sending side of stream {} error={}.",
|
||||
stream_id,
|
||||
error
|
||||
);
|
||||
|
||||
if self.send_stream_is_critical(stream_id) {
|
||||
return Err(Error::InvalidStreamId);
|
||||
@@ -968,7 +990,12 @@ impl Http3Connection {
|
||||
stream_id: StreamId,
|
||||
error: AppError,
|
||||
) -> Res<()> {
|
||||
qinfo!("[{self}] Send stop sending for stream {stream_id} error={error}");
|
||||
qinfo!(
|
||||
[self],
|
||||
"Send stop sending for stream {} error={}.",
|
||||
stream_id,
|
||||
error
|
||||
);
|
||||
if self.recv_stream_is_critical(stream_id) {
|
||||
return Err(Error::InvalidStreamId);
|
||||
}
|
||||
@@ -1016,7 +1043,7 @@ impl Http3Connection {
|
||||
error: AppError,
|
||||
conn: &mut Connection,
|
||||
) -> Res<()> {
|
||||
qinfo!("[{self}] cancel_fetch {stream_id} error={error}");
|
||||
qinfo!([self], "cancel_fetch {} error={}.", stream_id, error);
|
||||
let send_stream = self.send_streams.get(&stream_id);
|
||||
let recv_stream = self.recv_streams.get(&stream_id);
|
||||
match (send_stream, recv_stream) {
|
||||
@@ -1029,7 +1056,7 @@ impl Http3Connection {
|
||||
return Err(Error::InvalidStreamId);
|
||||
}
|
||||
// Stream may be already be closed and we may get an error here, but we do not care.
|
||||
drop(self.stream_reset_send(conn, stream_id, error));
|
||||
mem::drop(self.stream_reset_send(conn, stream_id, error));
|
||||
}
|
||||
(None, Some(s)) => {
|
||||
if !matches!(
|
||||
@@ -1042,7 +1069,7 @@ impl Http3Connection {
|
||||
}
|
||||
|
||||
// Stream may be already be closed and we may get an error here, but we do not care.
|
||||
drop(self.stream_stop_sending(conn, stream_id, error));
|
||||
mem::drop(self.stream_stop_sending(conn, stream_id, error));
|
||||
}
|
||||
(Some(s), Some(r)) => {
|
||||
debug_assert_eq!(s.stream_type(), r.stream_type());
|
||||
@@ -1053,9 +1080,9 @@ impl Http3Connection {
|
||||
return Err(Error::InvalidStreamId);
|
||||
}
|
||||
// Stream may be already be closed and we may get an error here, but we do not care.
|
||||
drop(self.stream_reset_send(conn, stream_id, error));
|
||||
mem::drop(self.stream_reset_send(conn, stream_id, error));
|
||||
// Stream may be already be closed and we may get an error here, but we do not care.
|
||||
drop(self.stream_stop_sending(conn, stream_id, error));
|
||||
mem::drop(self.stream_stop_sending(conn, stream_id, error));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -1063,7 +1090,7 @@ impl Http3Connection {
|
||||
|
||||
/// This is called when an application wants to close the sending side of a stream.
|
||||
pub fn stream_close_send(&mut self, conn: &mut Connection, stream_id: StreamId) -> Res<()> {
|
||||
qdebug!("[{self}] Close the sending side for stream {stream_id}");
|
||||
qdebug!([self], "Close the sending side for stream {}.", stream_id);
|
||||
debug_assert!(self.state.active());
|
||||
let send_stream = self
|
||||
.send_streams
|
||||
@@ -1071,7 +1098,7 @@ impl Http3Connection {
|
||||
.ok_or(Error::InvalidStreamId)?;
|
||||
// The following function may return InvalidStreamId from the transport layer if the stream
|
||||
// has been closed already. It is ok to ignore it here.
|
||||
drop(send_stream.close(conn));
|
||||
mem::drop(send_stream.close(conn));
|
||||
if send_stream.done() {
|
||||
self.remove_send_stream(stream_id, conn);
|
||||
} else if send_stream.has_data_to_send() {
|
||||
@@ -1090,7 +1117,7 @@ impl Http3Connection {
|
||||
where
|
||||
T: AsRequestTarget<'x> + ?Sized + Debug,
|
||||
{
|
||||
qinfo!("[{self}] Create WebTransport");
|
||||
qinfo!([self], "Create WebTransport");
|
||||
if !self.webtransport_enabled() {
|
||||
return Err(Error::Unavailable);
|
||||
}
|
||||
@@ -1106,8 +1133,8 @@ impl Http3Connection {
|
||||
)));
|
||||
self.add_streams(
|
||||
id,
|
||||
Box::new(Rc::clone(&extended_conn)),
|
||||
Box::new(Rc::clone(&extended_conn)),
|
||||
Box::new(extended_conn.clone()),
|
||||
Box::new(extended_conn.clone()),
|
||||
);
|
||||
|
||||
let final_headers = Self::create_fetch_headers(&RequestDescription {
|
||||
@@ -1131,7 +1158,10 @@ impl Http3Connection {
|
||||
events: Box<dyn ExtendedConnectEvents>,
|
||||
accept_res: &WebTransportSessionAcceptAction,
|
||||
) -> Res<()> {
|
||||
qtrace!("Respond to WebTransport session with accept={accept_res}");
|
||||
qtrace!(
|
||||
"Respond to WebTransport session with accept={}.",
|
||||
accept_res
|
||||
);
|
||||
if !self.webtransport_enabled() {
|
||||
return Err(Error::Unavailable);
|
||||
}
|
||||
@@ -1147,7 +1177,6 @@ impl Http3Connection {
|
||||
}
|
||||
|
||||
let send_stream = self.send_streams.get_mut(&stream_id);
|
||||
conn.stream_keep_alive(stream_id, true)?;
|
||||
|
||||
match (send_stream, recv_stream, accept_res) {
|
||||
(None, None, _) => Err(Error::InvalidStreamId),
|
||||
@@ -1162,7 +1191,7 @@ impl Http3Connection {
|
||||
.send_headers(headers, conn)
|
||||
.is_ok()
|
||||
{
|
||||
drop(self.stream_close_send(conn, stream_id));
|
||||
mem::drop(self.stream_close_send(conn, stream_id));
|
||||
// TODO issue 1294: add a timer to clean up the recv_stream if the peer does not
|
||||
// do that in a short time.
|
||||
self.streams_with_pending_data.insert(stream_id);
|
||||
@@ -1187,7 +1216,7 @@ impl Http3Connection {
|
||||
)));
|
||||
self.add_streams(
|
||||
stream_id,
|
||||
Box::new(Rc::clone(&extended_conn)),
|
||||
Box::new(extended_conn.clone()),
|
||||
Box::new(extended_conn),
|
||||
);
|
||||
self.streams_with_pending_data.insert(stream_id);
|
||||
@@ -1207,7 +1236,7 @@ impl Http3Connection {
|
||||
error: u32,
|
||||
message: &str,
|
||||
) -> Res<()> {
|
||||
qtrace!("Close WebTransport session {session_id:?}");
|
||||
qtrace!("Clos WebTransport session {:?}", session_id);
|
||||
let send_stream = self
|
||||
.send_streams
|
||||
.get_mut(&session_id)
|
||||
@@ -1233,7 +1262,11 @@ impl Http3Connection {
|
||||
send_events: Box<dyn SendStreamEvents>,
|
||||
recv_events: Box<dyn RecvStreamEvents>,
|
||||
) -> Res<StreamId> {
|
||||
qtrace!("Create new WebTransport stream session={session_id} type={stream_type:?}");
|
||||
qtrace!(
|
||||
"Create new WebTransport stream session={} type={:?}",
|
||||
session_id,
|
||||
stream_type
|
||||
);
|
||||
|
||||
let wt = self
|
||||
.recv_streams
|
||||
@@ -1249,7 +1282,8 @@ impl Http3Connection {
|
||||
.stream_create(stream_type)
|
||||
.map_err(|e| Error::map_stream_create_errors(&e))?;
|
||||
// Set outgoing WebTransport streams to be fair (share bandwidth)
|
||||
conn.stream_fairness(stream_id, true)?;
|
||||
// This really can't fail, panics if it does
|
||||
conn.stream_fairness(stream_id, true).unwrap();
|
||||
|
||||
self.webtransport_create_stream_internal(
|
||||
wt,
|
||||
@@ -1269,7 +1303,11 @@ impl Http3Connection {
|
||||
send_events: Box<dyn SendStreamEvents>,
|
||||
recv_events: Box<dyn RecvStreamEvents>,
|
||||
) -> Res<()> {
|
||||
qtrace!("Create new WebTransport stream session={session_id} stream_id={stream_id}");
|
||||
qtrace!(
|
||||
"Create new WebTransport stream session={} stream_id={}",
|
||||
session_id,
|
||||
stream_id
|
||||
);
|
||||
|
||||
let wt = self
|
||||
.recv_streams
|
||||
@@ -1298,6 +1336,7 @@ impl Http3Connection {
|
||||
recv_events: Box<dyn RecvStreamEvents>,
|
||||
local: bool,
|
||||
) {
|
||||
// TODO conn.stream_keep_alive(stream_id, true)?;
|
||||
webtransport_session.borrow_mut().add_stream(stream_id);
|
||||
if stream_id.stream_type() == StreamType::UniDi {
|
||||
if local {
|
||||
@@ -1329,7 +1368,7 @@ impl Http3Connection {
|
||||
stream_id,
|
||||
session_id,
|
||||
send_events,
|
||||
Rc::clone(&webtransport_session),
|
||||
webtransport_session.clone(),
|
||||
local,
|
||||
)),
|
||||
Box::new(WebTransportRecvStream::new(
|
||||
@@ -1362,7 +1401,7 @@ impl Http3Connection {
|
||||
/// `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>> {
|
||||
qdebug!("[{self}] Handle a control frame {f:?}");
|
||||
qdebug!([self], "Handle a control frame {:?}", f);
|
||||
if !matches!(f, HFrame::Settings { .. })
|
||||
&& !matches!(
|
||||
self.settings_state,
|
||||
@@ -1393,7 +1432,7 @@ impl Http3Connection {
|
||||
}
|
||||
|
||||
fn handle_settings(&mut self, new_settings: HSettings) -> Res<()> {
|
||||
qdebug!("[{self}] Handle SETTINGS frame");
|
||||
qdebug!([self], "Handle SETTINGS frame.");
|
||||
match &self.settings_state {
|
||||
Http3RemoteSettingsState::NotReceived => {
|
||||
self.set_qpack_settings(&new_settings)?;
|
||||
@@ -1416,7 +1455,11 @@ impl Http3Connection {
|
||||
}
|
||||
if zero_rtt_value > new_value {
|
||||
qerror!(
|
||||
"[{self}] The new({new_value}) and the old value({zero_rtt_value}) of setting {st:?} do not match"
|
||||
[self],
|
||||
"The new({}) and the old value({}) of setting {:?} do not match",
|
||||
new_value,
|
||||
zero_rtt_value,
|
||||
st
|
||||
);
|
||||
return Err(Error::HttpSettings);
|
||||
}
|
||||
@@ -1435,7 +1478,7 @@ impl Http3Connection {
|
||||
}
|
||||
}
|
||||
if qpack_changed {
|
||||
qdebug!("[{self}] Settings after zero rtt differ");
|
||||
qdebug!([self], "Settings after zero rtt differ.");
|
||||
self.set_qpack_settings(&(new_settings))?;
|
||||
}
|
||||
self.settings_state = Http3RemoteSettingsState::Received(new_settings);
|
||||
@@ -1534,20 +1577,20 @@ impl Http3Connection {
|
||||
let (recv, send) = wt.borrow_mut().take_sub_streams();
|
||||
|
||||
for id in recv {
|
||||
qtrace!("Remove the extended connect sub receiver stream {id}");
|
||||
qtrace!("Remove the extended connect sub receiver stream {}", id);
|
||||
// Use CloseType::ResetRemote so that an event will be sent. CloseType::LocalError would
|
||||
// have the same effect.
|
||||
if let Some(mut s) = self.recv_streams.remove(&id) {
|
||||
drop(s.reset(CloseType::ResetRemote(Error::HttpRequestCancelled.code())));
|
||||
mem::drop(s.reset(CloseType::ResetRemote(Error::HttpRequestCancelled.code())));
|
||||
}
|
||||
drop(conn.stream_stop_sending(id, Error::HttpRequestCancelled.code()));
|
||||
mem::drop(conn.stream_stop_sending(id, Error::HttpRequestCancelled.code()));
|
||||
}
|
||||
for id in send {
|
||||
qtrace!("Remove the extended connect sub send stream {id}");
|
||||
qtrace!("Remove the extended connect sub send stream {}", id);
|
||||
if let Some(mut s) = self.send_streams.remove(&id) {
|
||||
s.handle_stop_sending(CloseType::ResetRemote(Error::HttpRequestCancelled.code()));
|
||||
}
|
||||
drop(conn.stream_reset_send(id, Error::HttpRequestCancelled.code()));
|
||||
mem::drop(conn.stream_reset_send(id, Error::HttpRequestCancelled.code()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1557,7 +1600,7 @@ impl Http3Connection {
|
||||
conn: &mut Connection,
|
||||
) -> Option<Box<dyn RecvStream>> {
|
||||
let stream = self.recv_streams.remove(&stream_id);
|
||||
if let Some(s) = &stream {
|
||||
if let Some(ref s) = stream {
|
||||
if s.stream_type() == Http3StreamType::ExtendedConnect {
|
||||
self.send_streams.remove(&stream_id).unwrap();
|
||||
if let Some(wt) = s.webtransport() {
|
||||
@@ -1574,7 +1617,7 @@ impl Http3Connection {
|
||||
conn: &mut Connection,
|
||||
) -> Option<Box<dyn SendStream>> {
|
||||
let stream = self.send_streams.remove(&stream_id);
|
||||
if let Some(s) = &stream {
|
||||
if let Some(ref s) = stream {
|
||||
if s.stream_type() == Http3StreamType::ExtendedConnect {
|
||||
if let Some(wt) = self.recv_streams.remove(&stream_id).unwrap().webtransport() {
|
||||
self.remove_extended_connect(&wt, conn);
|
||||
|
||||
766
third_party/rust/neqo-http3/src/connection_client.rs
vendored
766
third_party/rust/neqo-http3/src/connection_client.rs
vendored
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@
|
||||
|
||||
use std::{rc::Rc, time::Instant};
|
||||
|
||||
use neqo_common::{event::Provider as _, qdebug, qinfo, qtrace, Header, MessageType, Role};
|
||||
use neqo_common::{event::Provider, qdebug, qinfo, qtrace, Header, MessageType, Role};
|
||||
use neqo_transport::{
|
||||
AppError, Connection, ConnectionEvent, DatagramTracking, StreamId, StreamType,
|
||||
};
|
||||
@@ -102,7 +102,7 @@ impl Http3ServerHandler {
|
||||
///
|
||||
/// An error will be returned if stream does not exist.
|
||||
pub fn stream_close_send(&mut self, stream_id: StreamId, conn: &mut Connection) -> Res<()> {
|
||||
qdebug!("[{self}] Close sending side stream={stream_id}");
|
||||
qdebug!([self], "Close sending side stream={}.", stream_id);
|
||||
self.base_handler.stream_close_send(conn, stream_id)?;
|
||||
self.needs_processing = true;
|
||||
Ok(())
|
||||
@@ -120,7 +120,7 @@ impl Http3ServerHandler {
|
||||
error: AppError,
|
||||
conn: &mut Connection,
|
||||
) -> Res<()> {
|
||||
qinfo!("[{self}] cancel_fetch {stream_id} error={error}");
|
||||
qinfo!([self], "cancel_fetch {} error={}.", stream_id, error);
|
||||
self.needs_processing = true;
|
||||
self.base_handler.cancel_fetch(stream_id, error, conn)
|
||||
}
|
||||
@@ -131,7 +131,7 @@ impl Http3ServerHandler {
|
||||
error: AppError,
|
||||
conn: &mut Connection,
|
||||
) -> Res<()> {
|
||||
qinfo!("[{self}] stream_stop_sending {stream_id} error={error}");
|
||||
qinfo!([self], "stream_stop_sending {} error={}.", stream_id, error);
|
||||
self.needs_processing = true;
|
||||
self.base_handler
|
||||
.stream_stop_sending(conn, stream_id, error)
|
||||
@@ -143,7 +143,7 @@ impl Http3ServerHandler {
|
||||
error: AppError,
|
||||
conn: &mut Connection,
|
||||
) -> Res<()> {
|
||||
qinfo!("[{self}] stream_reset_send {stream_id} error={error}");
|
||||
qinfo!([self], "stream_reset_send {} error={}.", stream_id, error);
|
||||
self.needs_processing = true;
|
||||
self.base_handler.stream_reset_send(conn, stream_id, error)
|
||||
}
|
||||
@@ -215,7 +215,7 @@ impl Http3ServerHandler {
|
||||
|
||||
/// Process HTTTP3 layer.
|
||||
pub fn process_http3(&mut self, conn: &mut Connection, now: Instant) {
|
||||
qtrace!("[{self}] Process http3 internal");
|
||||
qtrace!([self], "Process http3 internal.");
|
||||
if matches!(self.base_handler.state(), Http3State::Closed(..)) {
|
||||
return;
|
||||
}
|
||||
@@ -254,7 +254,7 @@ impl Http3ServerHandler {
|
||||
}
|
||||
|
||||
fn close(&mut self, conn: &mut Connection, now: Instant, err: &Error) {
|
||||
qinfo!("[{self}] Connection error: {err}");
|
||||
qinfo!([self], "Connection error: {}.", err);
|
||||
conn.close(now, err.code(), format!("{err}"));
|
||||
self.base_handler.close(err.code());
|
||||
self.events
|
||||
@@ -263,9 +263,9 @@ impl Http3ServerHandler {
|
||||
|
||||
// If this return an error the connection must be closed.
|
||||
fn check_connection_events(&mut self, conn: &mut Connection, now: Instant) -> Res<()> {
|
||||
qtrace!("[{self}] Check connection events");
|
||||
qtrace!([self], "Check connection events.");
|
||||
while let Some(e) = conn.next_event() {
|
||||
qdebug!("[{self}] check_connection_events - event {e:?}");
|
||||
qdebug!([self], "check_connection_events - event {e:?}.");
|
||||
match e {
|
||||
ConnectionEvent::NewStream { stream_id } => {
|
||||
self.base_handler.add_new_stream(stream_id);
|
||||
@@ -325,7 +325,7 @@ impl Http3ServerHandler {
|
||||
MessageType::Response,
|
||||
Http3StreamType::Http,
|
||||
stream_id,
|
||||
Rc::clone(&self.base_handler.qpack_encoder),
|
||||
self.base_handler.qpack_encoder.clone(),
|
||||
Box::new(self.events.clone()),
|
||||
)),
|
||||
Box::new(RecvMessage::new(
|
||||
@@ -387,7 +387,7 @@ impl Http3ServerHandler {
|
||||
Ok(())
|
||||
}
|
||||
_ => unreachable!(
|
||||
"we should only put MaxPushId, Goaway and PriorityUpdates into control_frames"
|
||||
"we should only put MaxPushId, Goaway and PriorityUpdates into control_frames."
|
||||
),
|
||||
}?;
|
||||
}
|
||||
@@ -411,7 +411,7 @@ impl Http3ServerHandler {
|
||||
stream_id: StreamId,
|
||||
buf: &mut [u8],
|
||||
) -> Res<(usize, bool)> {
|
||||
qdebug!("[{self}] read_data from stream {stream_id}");
|
||||
qdebug!([self], "read_data from stream {}.", stream_id);
|
||||
let res = self.base_handler.read_data(conn, stream_id, buf);
|
||||
if let Err(e) = &res {
|
||||
if e.connection_error() {
|
||||
|
||||
@@ -92,7 +92,7 @@ impl ControlStreamLocal {
|
||||
|
||||
/// Create a control stream.
|
||||
pub fn create(&mut self, conn: &mut Connection) -> Res<()> {
|
||||
qtrace!("[{self}] Create a control stream");
|
||||
qtrace!([self], "Create a control stream.");
|
||||
self.stream.init(conn.stream_create(StreamType::UniDi)?);
|
||||
self.stream
|
||||
.buffer(&[u8::try_from(HTTP3_UNI_STREAM_TYPE_CONTROL).unwrap()]);
|
||||
|
||||
@@ -36,7 +36,7 @@ impl ControlStreamRemote {
|
||||
|
||||
/// Check if a stream is the control stream and read received data.
|
||||
pub fn receive_single(&mut self, conn: &mut Connection) -> Res<Option<HFrame>> {
|
||||
qdebug!("[{self}] Receiving data");
|
||||
qdebug!([self], "Receiving data.");
|
||||
match self
|
||||
.frame_reader
|
||||
.receive(&mut StreamReaderConnectionWrapper::new(
|
||||
@@ -45,7 +45,7 @@ impl ControlStreamRemote {
|
||||
))? {
|
||||
(_, true) => Err(Error::HttpClosedCriticalStream),
|
||||
(s, false) => {
|
||||
qdebug!("[{self}] received {s:?}");
|
||||
qdebug!([self], "received {:?}", s);
|
||||
Ok(s)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ mod sessions;
|
||||
mod streams;
|
||||
use std::{cell::RefCell, rc::Rc, time::Duration};
|
||||
|
||||
use neqo_common::{event::Provider as _, header::HeadersExt as _};
|
||||
use neqo_common::event::Provider;
|
||||
use neqo_crypto::AuthenticationStatus;
|
||||
use neqo_transport::{ConnectionParameters, Pmtud, StreamId, StreamType};
|
||||
use test_fixture::{
|
||||
@@ -60,13 +60,6 @@ pub fn default_http3_server(server_params: Http3Parameters) -> Http3Server {
|
||||
.expect("create a server")
|
||||
}
|
||||
|
||||
pub fn assert_wt(headers: &[Header]) {
|
||||
assert!(
|
||||
headers.contains_header(":method", "CONNECT")
|
||||
&& headers.contains_header(":protocol", "webtransport")
|
||||
);
|
||||
}
|
||||
|
||||
fn exchange_packets(client: &mut Http3Client, server: &mut Http3Server) {
|
||||
let mut out = None;
|
||||
loop {
|
||||
@@ -78,7 +71,7 @@ fn exchange_packets(client: &mut Http3Client, server: &mut Http3Server) {
|
||||
}
|
||||
}
|
||||
|
||||
// Perform only QUIC transport handshake.
|
||||
// Perform only Quic transport handshake.
|
||||
fn connect_with(client: &mut Http3Client, server: &mut Http3Server) {
|
||||
assert_eq!(client.state(), Http3State::Initializing);
|
||||
let out = client.process_output(now());
|
||||
@@ -99,13 +92,13 @@ fn connect_with(client: &mut Http3Client, server: &mut Http3Server) {
|
||||
|
||||
assert_eq!(client.state(), Http3State::Connected);
|
||||
|
||||
// Exchange H3 settings
|
||||
// Exchange H3 setttings
|
||||
let out = server.process(out.dgram(), now());
|
||||
let out = client.process(out.dgram(), now());
|
||||
let out = server.process(out.dgram(), now());
|
||||
let out = client.process(out.dgram(), now());
|
||||
let out = server.process(out.dgram(), now());
|
||||
drop(client.process(out.dgram(), now()));
|
||||
std::mem::drop(client.process(out.dgram(), now()));
|
||||
}
|
||||
|
||||
fn connect(
|
||||
@@ -155,7 +148,14 @@ impl WtTest {
|
||||
session,
|
||||
headers,
|
||||
}) => {
|
||||
assert_wt(&headers);
|
||||
assert!(
|
||||
headers
|
||||
.iter()
|
||||
.any(|h| h.name() == ":method" && h.value() == "CONNECT")
|
||||
&& headers
|
||||
.iter()
|
||||
.any(|h| h.name() == ":protocol" && h.value() == "webtransport")
|
||||
);
|
||||
session.response(accept).unwrap();
|
||||
wt_server_session = Some(session);
|
||||
}
|
||||
@@ -183,7 +183,7 @@ impl WtTest {
|
||||
}) if (
|
||||
stream_id == wt_session_id &&
|
||||
status == 200 &&
|
||||
headers.contains_header(":status", "200")
|
||||
headers.contains(&Header::new(":status", "200"))
|
||||
)
|
||||
)
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use neqo_common::{event::Provider as _, Encoder};
|
||||
use neqo_common::{event::Provider, Encoder};
|
||||
use neqo_crypto::AuthenticationStatus;
|
||||
use neqo_transport::{CloseReason, Connection, StreamType};
|
||||
use test_fixture::{default_server_h3, now};
|
||||
@@ -88,7 +88,7 @@ fn zero_rtt(
|
||||
// exchange token
|
||||
let out = server.process_output(now());
|
||||
// We do not have a token so we need to wait for a resumption token timer to trigger.
|
||||
drop(client.process(out.dgram(), now() + Duration::from_millis(250)));
|
||||
std::mem::drop(client.process(out.dgram(), now() + Duration::from_millis(250)));
|
||||
assert_eq!(client.state(), Http3State::Connected);
|
||||
let token = client
|
||||
.events()
|
||||
@@ -105,7 +105,7 @@ fn zero_rtt(
|
||||
let mut server = default_http3_server(Http3Parameters::default().webtransport(server_resumed));
|
||||
client
|
||||
.enable_resumption(now(), &token)
|
||||
.expect("Set resumption token");
|
||||
.expect("Set resumption token.");
|
||||
assert_eq!(client.state(), Http3State::ZeroRtt);
|
||||
|
||||
exchange_packets(&mut client, &mut server);
|
||||
|
||||
@@ -4,14 +4,16 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use neqo_common::{event::Provider as _, header::HeadersExt as _, Encoder};
|
||||
use std::mem;
|
||||
|
||||
use neqo_common::{event::Provider, Encoder};
|
||||
use neqo_transport::StreamType;
|
||||
use test_fixture::now;
|
||||
|
||||
use crate::{
|
||||
features::extended_connect::{
|
||||
tests::webtransport::{
|
||||
assert_wt, default_http3_client, default_http3_server, wt_default_parameters, WtTest,
|
||||
default_http3_client, default_http3_server, wt_default_parameters, WtTest,
|
||||
},
|
||||
SessionCloseReason,
|
||||
},
|
||||
@@ -24,7 +26,7 @@ use crate::{
|
||||
#[test]
|
||||
fn wt_session() {
|
||||
let mut wt = WtTest::new();
|
||||
drop(wt.create_wt_session());
|
||||
mem::drop(wt.create_wt_session());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -132,7 +134,14 @@ fn wt_session_response_with_1xx() {
|
||||
headers,
|
||||
}) = event
|
||||
{
|
||||
assert_wt(&headers);
|
||||
assert!(
|
||||
headers
|
||||
.iter()
|
||||
.any(|h| h.name() == ":method" && h.value() == "CONNECT")
|
||||
&& headers
|
||||
.iter()
|
||||
.any(|h| h.name() == ":protocol" && h.value() == "webtransport")
|
||||
);
|
||||
wt_server_session = Some(session);
|
||||
}
|
||||
}
|
||||
@@ -159,7 +168,7 @@ fn wt_session_response_with_1xx() {
|
||||
}) if (
|
||||
stream_id == wt_session_id &&
|
||||
status == 200 &&
|
||||
headers.contains_header(":status", "200")
|
||||
headers.contains(&Header::new(":status", "200"))
|
||||
)
|
||||
)
|
||||
};
|
||||
@@ -200,7 +209,14 @@ fn wt_session_respone_200_with_fin() {
|
||||
headers,
|
||||
}) = event
|
||||
{
|
||||
assert_wt(&headers);
|
||||
assert!(
|
||||
headers
|
||||
.iter()
|
||||
.any(|h| h.name() == ":method" && h.value() == "CONNECT")
|
||||
&& headers
|
||||
.iter()
|
||||
.any(|h| h.name() == ":protocol" && h.value() == "webtransport")
|
||||
);
|
||||
wt_server_session = Some(session);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::mem;
|
||||
|
||||
use neqo_transport::StreamType;
|
||||
|
||||
use crate::{
|
||||
@@ -92,7 +94,7 @@ fn wt_server_stream_bidi() {
|
||||
wt.send_data_server(&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);
|
||||
drop(wt.receive_data_server(wt_server_stream.stream_id(), false, BUF_CLIENT, false));
|
||||
mem::drop(wt.receive_data_server(wt_server_stream.stream_id(), false, BUF_CLIENT, false));
|
||||
let stats = wt.send_stream_stats(wt_server_stream.stream_id()).unwrap();
|
||||
assert_eq!(stats.bytes_written(), BUF_CLIENT.len() as u64);
|
||||
assert_eq!(stats.bytes_sent(), BUF_CLIENT.len() as u64);
|
||||
@@ -159,7 +161,7 @@ fn wt_server_stream_bidi_close() {
|
||||
wt.receive_data_client(wt_server_stream.stream_id(), true, BUF_SERVER, true);
|
||||
wt.send_data_client(wt_server_stream.stream_id(), BUF_CLIENT);
|
||||
wt.close_stream_sending_client(wt_server_stream.stream_id());
|
||||
drop(wt.receive_data_server(wt_server_stream.stream_id(), false, BUF_CLIENT, true));
|
||||
mem::drop(wt.receive_data_server(wt_server_stream.stream_id(), false, BUF_CLIENT, true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -170,7 +172,7 @@ fn wt_client_stream_uni_reset() {
|
||||
let wt_session = wt.create_wt_session();
|
||||
let wt_stream = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::UniDi);
|
||||
wt.send_data_client(wt_stream, BUF_CLIENT);
|
||||
drop(wt.receive_data_server(wt_stream, true, BUF_CLIENT, false));
|
||||
mem::drop(wt.receive_data_server(wt_stream, true, BUF_CLIENT, false));
|
||||
wt.reset_stream_client(wt_stream);
|
||||
wt.receive_reset_server(wt_stream, Error::HttpNoError.code());
|
||||
}
|
||||
@@ -313,7 +315,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);
|
||||
drop(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());
|
||||
|
||||
@@ -348,7 +350,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);
|
||||
drop(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());
|
||||
|
||||
@@ -383,7 +385,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);
|
||||
drop(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());
|
||||
@@ -448,7 +450,7 @@ fn wt_client_session_close_5() {
|
||||
let unidi_from_client = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::UniDi);
|
||||
|
||||
wt.send_data_client(unidi_from_client, BUF);
|
||||
drop(wt.receive_data_server(unidi_from_client, true, BUF, false));
|
||||
mem::drop(wt.receive_data_server(unidi_from_client, true, BUF, false));
|
||||
wt.reset_stream_client(unidi_from_client);
|
||||
|
||||
wt.cancel_session_client(wt_session.stream_id());
|
||||
@@ -698,10 +700,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);
|
||||
drop(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);
|
||||
drop(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());
|
||||
|
||||
@@ -748,7 +750,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);
|
||||
drop(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(&wt_session);
|
||||
|
||||
@@ -782,7 +784,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);
|
||||
drop(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(&wt_session);
|
||||
|
||||
@@ -1062,10 +1064,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);
|
||||
drop(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);
|
||||
drop(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(&wt_session);
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ impl WebTransportSession {
|
||||
first_frame_type: None,
|
||||
},
|
||||
qpack_decoder,
|
||||
Box::new(Rc::clone(&stream_event_listener)),
|
||||
Box::new(stream_event_listener.clone()),
|
||||
None,
|
||||
PriorityHandler::new(false, Priority::default()),
|
||||
)),
|
||||
@@ -82,7 +82,7 @@ impl WebTransportSession {
|
||||
Http3StreamType::ExtendedConnect,
|
||||
session_id,
|
||||
qpack_encoder,
|
||||
Box::new(Rc::clone(&stream_event_listener)),
|
||||
Box::new(stream_event_listener.clone()),
|
||||
)),
|
||||
stream_event_listener,
|
||||
session_id,
|
||||
@@ -111,11 +111,11 @@ impl WebTransportSession {
|
||||
control_stream_recv
|
||||
.http_stream()
|
||||
.unwrap()
|
||||
.set_new_listener(Box::new(Rc::clone(&stream_event_listener)));
|
||||
.set_new_listener(Box::new(stream_event_listener.clone()));
|
||||
control_stream_send
|
||||
.http_stream()
|
||||
.unwrap()
|
||||
.set_new_listener(Box::new(Rc::clone(&stream_event_listener)));
|
||||
.set_new_listener(Box::new(stream_event_listener.clone()));
|
||||
Self {
|
||||
control_stream_recv,
|
||||
control_stream_send,
|
||||
@@ -146,7 +146,7 @@ impl WebTransportSession {
|
||||
}
|
||||
|
||||
fn receive(&mut self, conn: &mut Connection) -> Res<(ReceiveOutput, bool)> {
|
||||
qtrace!("[{self}] receive control data");
|
||||
qtrace!([self], "receive control data");
|
||||
let (out, _) = self.control_stream_recv.receive(conn)?;
|
||||
debug_assert!(out == ReceiveOutput::NoOutput);
|
||||
self.maybe_check_headers();
|
||||
@@ -229,7 +229,11 @@ impl WebTransportSession {
|
||||
|
||||
if let Some((headers, interim, fin)) = self.stream_event_listener.borrow_mut().get_headers()
|
||||
{
|
||||
qtrace!("ExtendedConnect response headers {headers:?}, fin={fin}");
|
||||
qtrace!(
|
||||
"ExtendedConnect response headers {:?}, fin={}",
|
||||
headers,
|
||||
fin
|
||||
);
|
||||
|
||||
if interim {
|
||||
if fin {
|
||||
@@ -342,7 +346,7 @@ impl WebTransportSession {
|
||||
&mut self.control_stream_recv,
|
||||
))
|
||||
.map_err(|_| Error::HttpGeneralProtocolStream)?;
|
||||
qtrace!("[{self}] Received frame: {f:?} fin={fin}");
|
||||
qtrace!([self], "Received frame: {:?} fin={}", f, fin);
|
||||
if let Some(WebTransportFrame::CloseSession { error, message }) = f {
|
||||
self.events.session_end(
|
||||
ExtendedConnectType::WebTransport,
|
||||
@@ -406,7 +410,7 @@ impl WebTransportSession {
|
||||
buf: &[u8],
|
||||
id: impl Into<DatagramTracking>,
|
||||
) -> Res<()> {
|
||||
qtrace!("[{self}] send_datagram state={:?}", self.state);
|
||||
qtrace!([self], "send_datagram state={:?}", self.state);
|
||||
if self.state == SessionState::Active {
|
||||
let mut dgram_data = Encoder::default();
|
||||
dgram_data.encode_varint(self.session_id.as_u64() / 4);
|
||||
@@ -447,7 +451,7 @@ impl RecvStream for Rc<RefCell<WebTransportSession>> {
|
||||
}
|
||||
|
||||
fn webtransport(&self) -> Option<Rc<RefCell<WebTransportSession>>> {
|
||||
Some(Self::clone(self))
|
||||
Some(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,8 @@ impl NegotiationState {
|
||||
} = self
|
||||
{
|
||||
qtrace!(
|
||||
"set_negotiated {feature_type:?} to {}",
|
||||
"set_negotiated {:?} to {}",
|
||||
feature_type,
|
||||
settings.get(*feature_type)
|
||||
);
|
||||
let cb = mem::take(listener);
|
||||
|
||||
26
third_party/rust/neqo-http3/src/frames/hframe.rs
vendored
26
third_party/rust/neqo-http3/src/frames/hframe.rs
vendored
@@ -4,13 +4,13 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::{fmt::Debug, io::Write as _};
|
||||
use std::{fmt::Debug, io::Write};
|
||||
|
||||
use neqo_common::{Decoder, Encoder};
|
||||
use neqo_crypto::random;
|
||||
use neqo_transport::StreamId;
|
||||
|
||||
use crate::{frames::reader::FrameDecoder, settings::HSettings, Error, Priority, PushId, Res};
|
||||
use crate::{frames::reader::FrameDecoder, settings::HSettings, Error, Priority, Res};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct HFrameType(pub u64);
|
||||
@@ -48,20 +48,20 @@ pub enum HFrame {
|
||||
header_block: Vec<u8>,
|
||||
},
|
||||
CancelPush {
|
||||
push_id: PushId,
|
||||
push_id: u64,
|
||||
},
|
||||
Settings {
|
||||
settings: HSettings,
|
||||
},
|
||||
PushPromise {
|
||||
push_id: PushId,
|
||||
push_id: u64,
|
||||
header_block: Vec<u8>,
|
||||
},
|
||||
Goaway {
|
||||
stream_id: StreamId,
|
||||
},
|
||||
MaxPushId {
|
||||
push_id: PushId,
|
||||
push_id: u64,
|
||||
},
|
||||
Grease,
|
||||
PriorityUpdateRequest {
|
||||
@@ -87,9 +87,7 @@ impl HFrame {
|
||||
Self::PriorityUpdateRequest { .. } => H3_FRAME_TYPE_PRIORITY_UPDATE_REQUEST,
|
||||
Self::PriorityUpdatePush { .. } => H3_FRAME_TYPE_PRIORITY_UPDATE_PUSH,
|
||||
Self::Grease => {
|
||||
let r = Decoder::from(&random::<8>()).decode_uint::<u64>().unwrap();
|
||||
// Zero out the top 7 bits: 2 for being a varint; 5 to account for the *0x1f.
|
||||
HFrameType((r >> 7) * 0x1f + 0x21)
|
||||
HFrameType(Decoder::from(&random::<7>()).decode_uint(7).unwrap() * 0x1f + 0x21)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,9 +115,7 @@ impl HFrame {
|
||||
push_id,
|
||||
header_block,
|
||||
} => {
|
||||
enc.encode_varint(
|
||||
(header_block.len() + (Encoder::varint_len(u64::from(*push_id)))) as u64,
|
||||
);
|
||||
enc.encode_varint((header_block.len() + (Encoder::varint_len(*push_id))) as u64);
|
||||
enc.encode_varint(*push_id);
|
||||
enc.encode(header_block);
|
||||
}
|
||||
@@ -174,12 +170,12 @@ impl FrameDecoder<Self> for HFrame {
|
||||
} else if let Some(payload) = data {
|
||||
let mut dec = Decoder::from(payload);
|
||||
Ok(match frame_type {
|
||||
H3_FRAME_TYPE_DATA => unreachable!("DATA frame has been handled already"),
|
||||
H3_FRAME_TYPE_DATA => unreachable!("DATA frame has been handled already."),
|
||||
H3_FRAME_TYPE_HEADERS => Some(Self::Headers {
|
||||
header_block: dec.decode_remainder().to_vec(),
|
||||
}),
|
||||
H3_FRAME_TYPE_CANCEL_PUSH => Some(Self::CancelPush {
|
||||
push_id: dec.decode_varint().ok_or(Error::HttpFrame)?.into(),
|
||||
push_id: dec.decode_varint().ok_or(Error::HttpFrame)?,
|
||||
}),
|
||||
H3_FRAME_TYPE_SETTINGS => {
|
||||
let mut settings = HSettings::default();
|
||||
@@ -193,14 +189,14 @@ impl FrameDecoder<Self> for HFrame {
|
||||
Some(Self::Settings { settings })
|
||||
}
|
||||
H3_FRAME_TYPE_PUSH_PROMISE => Some(Self::PushPromise {
|
||||
push_id: dec.decode_varint().ok_or(Error::HttpFrame)?.into(),
|
||||
push_id: dec.decode_varint().ok_or(Error::HttpFrame)?,
|
||||
header_block: dec.decode_remainder().to_vec(),
|
||||
}),
|
||||
H3_FRAME_TYPE_GOAWAY => Some(Self::Goaway {
|
||||
stream_id: StreamId::new(dec.decode_varint().ok_or(Error::HttpFrame)?),
|
||||
}),
|
||||
H3_FRAME_TYPE_MAX_PUSH_ID => Some(Self::MaxPushId {
|
||||
push_id: dec.decode_varint().ok_or(Error::HttpFrame)?.into(),
|
||||
push_id: dec.decode_varint().ok_or(Error::HttpFrame)?,
|
||||
}),
|
||||
H3_FRAME_TYPE_PRIORITY_UPDATE_REQUEST | H3_FRAME_TYPE_PRIORITY_UPDATE_PUSH => {
|
||||
let element_id = dec.decode_varint().ok_or(Error::HttpFrame)?;
|
||||
|
||||
16
third_party/rust/neqo-http3/src/frames/reader.rs
vendored
16
third_party/rust/neqo-http3/src/frames/reader.rs
vendored
@@ -24,7 +24,7 @@ pub trait FrameDecoder<T> {
|
||||
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns `HttpFrameUnexpected` if frames is not allowed, i.e. is a `H3_RESERVED_FRAME_TYPES`.
|
||||
/// Returns `HttpFrameUnexpected` if frames is not alowed, i.e. is a `H3_RESERVED_FRAME_TYPES`.
|
||||
fn frame_type_allowed(_frame_type: HFrameType) -> Res<()> {
|
||||
Ok(())
|
||||
}
|
||||
@@ -154,7 +154,7 @@ impl FrameReader {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if QUIC stream was closed.
|
||||
/// returns true if quic stream was closed.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
@@ -173,7 +173,7 @@ impl FrameReader {
|
||||
{
|
||||
(0, f) => (None, false, f),
|
||||
(amount, f) => {
|
||||
qtrace!("FrameReader::receive: reading {amount} byte, fin={f}");
|
||||
qtrace!("FrameReader::receive: reading {} byte, fin={}", amount, f);
|
||||
(self.consume::<T>(Decoder::from(&buf[..amount]))?, true, f)
|
||||
}
|
||||
};
|
||||
@@ -203,15 +203,16 @@ impl FrameReader {
|
||||
match &mut self.state {
|
||||
FrameReaderState::GetType { decoder } => {
|
||||
if let Some(v) = decoder.consume(&mut input) {
|
||||
qtrace!("FrameReader::receive: read frame type {v}");
|
||||
qtrace!("FrameReader::receive: read frame type {}", v);
|
||||
self.frame_type_decoded::<T>(HFrameType(v))?;
|
||||
}
|
||||
}
|
||||
FrameReaderState::GetLength { decoder } => {
|
||||
if let Some(len) = decoder.consume(&mut input) {
|
||||
qtrace!(
|
||||
"FrameReader::receive: frame type {:?} length {len}",
|
||||
self.frame_type
|
||||
"FrameReader::receive: frame type {:?} length {}",
|
||||
self.frame_type,
|
||||
len
|
||||
);
|
||||
return self.frame_length_decoded::<T>(len);
|
||||
}
|
||||
@@ -234,6 +235,9 @@ impl FrameReader {
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
impl FrameReader {
|
||||
fn frame_type_decoded<T: FrameDecoder<T>>(&mut self, frame_type: HFrameType) -> Res<()> {
|
||||
T::frame_type_allowed(frame_type)?;
|
||||
self.frame_type = frame_type;
|
||||
|
||||
@@ -12,7 +12,7 @@ use super::enc_dec_hframe;
|
||||
use crate::{
|
||||
frames::HFrame,
|
||||
settings::{HSetting, HSettingType, HSettings},
|
||||
Priority, PushId,
|
||||
Priority,
|
||||
};
|
||||
|
||||
#[test]
|
||||
@@ -31,9 +31,7 @@ fn headers_frame() {
|
||||
|
||||
#[test]
|
||||
fn cancel_push_frame4() {
|
||||
let f = HFrame::CancelPush {
|
||||
push_id: PushId::new(5),
|
||||
};
|
||||
let f = HFrame::CancelPush { push_id: 5 };
|
||||
enc_dec_hframe(&f, "030105", 0);
|
||||
}
|
||||
|
||||
@@ -48,7 +46,7 @@ fn settings_frame4() {
|
||||
#[test]
|
||||
fn push_promise_frame4() {
|
||||
let f = HFrame::PushPromise {
|
||||
push_id: PushId::new(4),
|
||||
push_id: 4,
|
||||
header_block: vec![0x61, 0x62, 0x63, 0x64],
|
||||
};
|
||||
enc_dec_hframe(&f, "05050461626364", 0);
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::mem;
|
||||
|
||||
use neqo_common::Encoder;
|
||||
use neqo_crypto::AuthenticationStatus;
|
||||
use neqo_transport::StreamType;
|
||||
@@ -23,21 +25,21 @@ pub fn enc_dec<T: FrameDecoder<T>>(d: &Encoder, st: &str, remaining: usize) -> T
|
||||
let out = conn_c.process_output(now());
|
||||
let out = conn_s.process(out.dgram(), now());
|
||||
let out = conn_c.process(out.dgram(), now());
|
||||
drop(conn_s.process(out.dgram(), now()));
|
||||
mem::drop(conn_s.process(out.dgram(), now()));
|
||||
conn_c.authenticated(AuthenticationStatus::Ok, now());
|
||||
let out = conn_c.process_output(now());
|
||||
drop(conn_s.process(out.dgram(), now()));
|
||||
mem::drop(conn_s.process(out.dgram(), now()));
|
||||
|
||||
// create a stream
|
||||
let stream_id = conn_s.stream_create(StreamType::BiDi).unwrap();
|
||||
|
||||
let mut fr = FrameReader::new();
|
||||
let mut fr: FrameReader = FrameReader::new();
|
||||
|
||||
// convert string into u8 vector
|
||||
// conver string into u8 vector
|
||||
let buf = Encoder::from_hex(st);
|
||||
conn_s.stream_send(stream_id, buf.as_ref()).unwrap();
|
||||
let out = conn_s.process_output(now());
|
||||
drop(conn_c.process(out.dgram(), now()));
|
||||
mem::drop(conn_c.process(out.dgram(), now()));
|
||||
|
||||
let (frame, fin) = fr
|
||||
.receive::<T>(&mut StreamReaderConnectionWrapper::new(
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::{fmt::Debug, mem};
|
||||
|
||||
use neqo_common::Encoder;
|
||||
use neqo_transport::{Connection, StreamId, StreamType};
|
||||
@@ -15,7 +15,7 @@ use crate::{
|
||||
reader::FrameDecoder, FrameReader, HFrame, StreamReaderConnectionWrapper, WebTransportFrame,
|
||||
},
|
||||
settings::{HSetting, HSettingType, HSettings},
|
||||
Error, PushId,
|
||||
Error,
|
||||
};
|
||||
|
||||
struct FrameReaderTest {
|
||||
@@ -40,7 +40,7 @@ impl FrameReaderTest {
|
||||
fn process<T: FrameDecoder<T>>(&mut self, v: &[u8]) -> Option<T> {
|
||||
self.conn_s.stream_send(self.stream_id, v).unwrap();
|
||||
let out = self.conn_s.process_output(now());
|
||||
drop(self.conn_c.process(out.dgram(), now()));
|
||||
mem::drop(self.conn_c.process(out.dgram(), now()));
|
||||
let (frame, fin) = self
|
||||
.fr
|
||||
.receive::<T>(&mut StreamReaderConnectionWrapper::new(
|
||||
@@ -112,7 +112,7 @@ fn frame_reading_with_stream_push_promise() {
|
||||
header_block,
|
||||
} = frame.unwrap()
|
||||
{
|
||||
assert_eq!(push_id, PushId::new(257));
|
||||
assert_eq!(push_id, 257);
|
||||
assert_eq!(header_block, &[0x1, 0x2, 0x3]);
|
||||
} else {
|
||||
panic!("wrong frame type");
|
||||
@@ -128,7 +128,7 @@ fn frame_reading_with_stream_data() {
|
||||
let frame = fr.process(&[0x0, 0x3, 0x1, 0x2, 0x3]).unwrap();
|
||||
assert!(matches!(frame, HFrame::Data { len } if len == 3));
|
||||
|
||||
// payload is still on the stream.
|
||||
// payloead is still on the stream.
|
||||
// assert that we have 3 bytes in the stream
|
||||
let mut buf = [0_u8; 100];
|
||||
let (amount, _) = fr.conn_c.stream_recv(fr.stream_id, &mut buf).unwrap();
|
||||
@@ -150,11 +150,11 @@ fn unknown_frame() {
|
||||
buf.resize(UNKNOWN_FRAME_LEN + buf.len(), 0);
|
||||
assert!(fr.process::<HFrame>(&buf).is_none());
|
||||
|
||||
// now receive a CANCEL_PUSH frame to see that frame reader is ok.
|
||||
// now receive a CANCEL_PUSH fram to see that frame reader is ok.
|
||||
let frame = fr.process(&[0x03, 0x01, 0x05]);
|
||||
assert!(frame.is_some());
|
||||
if let HFrame::CancelPush { push_id } = frame.unwrap() {
|
||||
assert!(push_id == PushId::new(5));
|
||||
assert!(push_id == 5);
|
||||
} else {
|
||||
panic!("wrong frame type");
|
||||
}
|
||||
@@ -194,7 +194,7 @@ fn unknown_wt_frame() {
|
||||
buf.resize(UNKNOWN_FRAME_LEN + buf.len(), 0);
|
||||
assert!(fr.process::<WebTransportFrame>(&buf).is_none());
|
||||
|
||||
// now receive a WT_FRAME_CLOSE_SESSION frame to see that frame reader is ok.
|
||||
// now receive a WT_FRAME_CLOSE_SESSION fram to see that frame reader is ok.
|
||||
let frame = fr.process(&[
|
||||
0x68, 0x43, 0x09, 0x00, 0x00, 0x00, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f,
|
||||
]);
|
||||
@@ -231,12 +231,12 @@ fn test_reading_frame<T: FrameDecoder<T> + PartialEq + Debug>(
|
||||
}
|
||||
|
||||
let out = fr.conn_s.process_output(now());
|
||||
drop(fr.conn_c.process(out.dgram(), now()));
|
||||
mem::drop(fr.conn_c.process(out.dgram(), now()));
|
||||
|
||||
if matches!(test_to_send, FrameReadingTestSend::DataThenFin) {
|
||||
fr.conn_s.stream_close_send(fr.stream_id).unwrap();
|
||||
let out = fr.conn_s.process_output(now());
|
||||
drop(fr.conn_c.process(out.dgram(), now()));
|
||||
mem::drop(fr.conn_c.process(out.dgram(), now()));
|
||||
}
|
||||
|
||||
let rv = fr.fr.receive::<T>(&mut StreamReaderConnectionWrapper::new(
|
||||
@@ -318,7 +318,7 @@ fn test_complete_and_incomplete_frame<T: FrameDecoder<T> + PartialEq + Debug>(
|
||||
done_state: usize,
|
||||
) {
|
||||
use std::cmp::Ordering;
|
||||
// Let's consume partial frames. It is enough to test partial frames
|
||||
// Let's consume partial frames. It is enough to test partal frames
|
||||
// up to 10 byte. 10 byte is greater than frame type and frame
|
||||
// length and bit of data.
|
||||
let len = std::cmp::min(buf.len() - 1, 10);
|
||||
@@ -417,9 +417,7 @@ fn complete_and_incomplete_frames() {
|
||||
test_complete_and_incomplete_frame::<HFrame>(&buf, buf.len());
|
||||
|
||||
// H3_FRAME_TYPE_CANCEL_PUSH
|
||||
let f = HFrame::CancelPush {
|
||||
push_id: PushId::new(5),
|
||||
};
|
||||
let f = HFrame::CancelPush { push_id: 5 };
|
||||
let mut enc = Encoder::default();
|
||||
f.encode(&mut enc);
|
||||
let buf: Vec<_> = enc.into();
|
||||
@@ -436,7 +434,7 @@ fn complete_and_incomplete_frames() {
|
||||
|
||||
// H3_FRAME_TYPE_PUSH_PROMISE
|
||||
let f = HFrame::PushPromise {
|
||||
push_id: PushId::new(4),
|
||||
push_id: 4,
|
||||
header_block: HEADER_BLOCK.to_vec(),
|
||||
};
|
||||
let mut enc = Encoder::default();
|
||||
@@ -454,9 +452,7 @@ fn complete_and_incomplete_frames() {
|
||||
test_complete_and_incomplete_frame::<HFrame>(&buf, buf.len());
|
||||
|
||||
// H3_FRAME_TYPE_MAX_PUSH_ID
|
||||
let f = HFrame::MaxPushId {
|
||||
push_id: PushId::new(5),
|
||||
};
|
||||
let f = HFrame::MaxPushId { push_id: 5 };
|
||||
let mut enc = Encoder::default();
|
||||
f.encode(&mut enc);
|
||||
let buf: Vec<_> = enc.into();
|
||||
@@ -483,11 +479,11 @@ fn frame_reading_when_stream_is_closed_before_sending_data() {
|
||||
|
||||
fr.conn_s.stream_send(fr.stream_id, &[0x00]).unwrap();
|
||||
let out = fr.conn_s.process_output(now());
|
||||
drop(fr.conn_c.process(out.dgram(), now()));
|
||||
mem::drop(fr.conn_c.process(out.dgram(), now()));
|
||||
|
||||
assert_eq!(Ok(()), fr.conn_c.stream_close_send(fr.stream_id));
|
||||
let out = fr.conn_c.process_output(now());
|
||||
drop(fr.conn_s.process(out.dgram(), now()));
|
||||
mem::drop(fr.conn_s.process(out.dgram(), now()));
|
||||
assert_eq!(
|
||||
Ok((None, true)),
|
||||
fr.fr
|
||||
@@ -506,11 +502,11 @@ fn wt_frame_reading_when_stream_is_closed_before_sending_data() {
|
||||
|
||||
fr.conn_s.stream_send(fr.stream_id, &[0x00]).unwrap();
|
||||
let out = fr.conn_s.process_output(now());
|
||||
drop(fr.conn_c.process(out.dgram(), now()));
|
||||
mem::drop(fr.conn_c.process(out.dgram(), now()));
|
||||
|
||||
assert_eq!(Ok(()), fr.conn_c.stream_close_send(fr.stream_id));
|
||||
let out = fr.conn_c.process_output(now());
|
||||
drop(fr.conn_s.process(out.dgram(), now()));
|
||||
mem::drop(fr.conn_s.process(out.dgram(), now()));
|
||||
assert_eq!(
|
||||
Ok((None, true)),
|
||||
fr.fr
|
||||
|
||||
@@ -37,7 +37,8 @@ impl FrameDecoder<Self> for WebTransportFrame {
|
||||
if frame_len > WT_FRAME_CLOSE_MAX_MESSAGE_SIZE + 4 {
|
||||
return Err(Error::HttpMessageError);
|
||||
}
|
||||
let error = dec.decode_uint().ok_or(Error::HttpMessageError)?;
|
||||
let error =
|
||||
u32::try_from(dec.decode_uint(4).ok_or(Error::HttpMessageError)?).unwrap();
|
||||
let Ok(message) = String::from_utf8(dec.decode_remainder().to_vec()) else {
|
||||
return Err(Error::HttpMessageError);
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
use enumset::{enum_set, EnumSet, EnumSetType};
|
||||
use neqo_common::{header::HeadersExt as _, Header};
|
||||
use neqo_common::Header;
|
||||
|
||||
use crate::{Error, MessageType, Res};
|
||||
|
||||
@@ -49,9 +49,10 @@ impl TryFrom<(MessageType, &str)> for PseudoHeaderState {
|
||||
/// Returns an error if response headers do not contain
|
||||
/// a status header or if the value of the header is 101 or cannot be parsed.
|
||||
pub fn is_interim(headers: &[Header]) -> Res<bool> {
|
||||
if let Some(h) = headers.iter().take(1).find_header(":status") {
|
||||
let status = headers.iter().take(1).find(|h| h.name() == ":status");
|
||||
if let Some(h) = status {
|
||||
#[allow(clippy::map_err_ignore)]
|
||||
let status_code = h.value().parse::<u16>().map_err(|_| Error::InvalidHeader)?;
|
||||
let status_code = h.value().parse::<i32>().map_err(|_| Error::InvalidHeader)?;
|
||||
if status_code == 101 {
|
||||
// https://datatracker.ietf.org/doc/html/draft-ietf-quic-http#section-4.3
|
||||
Err(Error::InvalidHeader)
|
||||
@@ -223,18 +224,4 @@ mod tests {
|
||||
fn valid_webtransport_connect() {
|
||||
assert!(headers_valid(&create_connect_headers(), MessageType::Request).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_webtransport_connect_with_status() {
|
||||
assert!(headers_valid(
|
||||
[
|
||||
create_connect_headers(),
|
||||
vec![Header::new(":status", "200")]
|
||||
]
|
||||
.concat()
|
||||
.as_slice(),
|
||||
MessageType::Request
|
||||
)
|
||||
.is_err());
|
||||
}
|
||||
}
|
||||
|
||||
2
third_party/rust/neqo-http3/src/lib.rs
vendored
2
third_party/rust/neqo-http3/src/lib.rs
vendored
@@ -145,7 +145,6 @@ mod frames;
|
||||
mod headers_checks;
|
||||
mod priority;
|
||||
mod push_controller;
|
||||
mod push_id;
|
||||
mod qlog;
|
||||
mod qpack_decoder_receiver;
|
||||
mod qpack_encoder_receiver;
|
||||
@@ -175,7 +174,6 @@ use neqo_transport::{
|
||||
AppError, Connection, Error as TransportError, RecvStreamStats, SendStreamStats,
|
||||
};
|
||||
pub use priority::Priority;
|
||||
pub use push_id::PushId;
|
||||
pub use server::Http3Server;
|
||||
pub use server_events::{
|
||||
Http3OrWebTransportStream, Http3ServerEvent, WebTransportRequest, WebTransportServerEvent,
|
||||
|
||||
107
third_party/rust/neqo-http3/src/push_controller.rs
vendored
107
third_party/rust/neqo-http3/src/push_controller.rs
vendored
@@ -20,7 +20,7 @@ use crate::{
|
||||
client_events::{Http3ClientEvent, Http3ClientEvents},
|
||||
connection::Http3Connection,
|
||||
frames::HFrame,
|
||||
CloseType, Error, Http3StreamInfo, HttpRecvStreamEvents, PushId, RecvStreamEvents, Res,
|
||||
CloseType, Error, Http3StreamInfo, HttpRecvStreamEvents, RecvStreamEvents, Res,
|
||||
};
|
||||
|
||||
/// `PushStates`:
|
||||
@@ -57,27 +57,27 @@ enum PushState {
|
||||
#[derive(Debug)]
|
||||
struct ActivePushStreams {
|
||||
push_streams: VecDeque<PushState>,
|
||||
first_push_id: PushId,
|
||||
first_push_id: u64,
|
||||
}
|
||||
|
||||
impl ActivePushStreams {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
push_streams: VecDeque::new(),
|
||||
first_push_id: PushId::new(0),
|
||||
first_push_id: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns None if a stream has been closed already.
|
||||
pub fn get_mut(
|
||||
&mut self,
|
||||
push_id: PushId,
|
||||
push_id: u64,
|
||||
) -> Option<&mut <usize as SliceIndex<[PushState]>>::Output> {
|
||||
if push_id < self.first_push_id {
|
||||
return None;
|
||||
}
|
||||
|
||||
let inx = usize::try_from(u64::from(push_id - self.first_push_id)).unwrap();
|
||||
let inx = usize::try_from(push_id - self.first_push_id).unwrap();
|
||||
if inx >= self.push_streams.len() {
|
||||
self.push_streams.resize(inx + 1, PushState::Init);
|
||||
}
|
||||
@@ -88,19 +88,19 @@ impl ActivePushStreams {
|
||||
}
|
||||
|
||||
/// Returns None if a stream has been closed already.
|
||||
pub fn get(&mut self, push_id: PushId) -> Option<&mut PushState> {
|
||||
pub fn get(&mut self, push_id: u64) -> Option<&mut PushState> {
|
||||
self.get_mut(push_id)
|
||||
}
|
||||
|
||||
/// Returns the State of a closed push stream or None for already closed streams.
|
||||
pub fn close(&mut self, push_id: PushId) -> Option<PushState> {
|
||||
pub fn close(&mut self, push_id: u64) -> Option<PushState> {
|
||||
match self.get_mut(push_id) {
|
||||
None | Some(PushState::Closed) => None,
|
||||
Some(s) => {
|
||||
let res = mem::replace(s, PushState::Closed);
|
||||
while self.push_streams.front() == Some(&PushState::Closed) {
|
||||
self.push_streams.pop_front();
|
||||
self.first_push_id.next();
|
||||
self.first_push_id += 1;
|
||||
}
|
||||
Some(res)
|
||||
}
|
||||
@@ -108,7 +108,7 @@ impl ActivePushStreams {
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn number_done(&self) -> PushId {
|
||||
pub fn number_done(&self) -> u64 {
|
||||
self.first_push_id
|
||||
+ u64::try_from(
|
||||
self.push_streams
|
||||
@@ -120,7 +120,7 @@ impl ActivePushStreams {
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.first_push_id = PushId::new(0);
|
||||
self.first_push_id = 0;
|
||||
self.push_streams.clear();
|
||||
}
|
||||
}
|
||||
@@ -135,7 +135,7 @@ impl ActivePushStreams {
|
||||
///
|
||||
/// The `PushController` handles:
|
||||
/// `PUSH_PROMISE` frame: frames may change the push state from Init to `PushPromise` and from
|
||||
/// `OnlyPushStream` to `Active`. Frames for a closed streams are ignored.
|
||||
/// `OnlyPushStream` to `Active`. Frames for a closed steams are ignored.
|
||||
/// `CANCEL_PUSH` frame: (`handle_cancel_push` will be called). If a push is in state `PushPromise`
|
||||
/// or `Active`, any posted events will be removed and a `PushCanceled` event
|
||||
/// will be posted. If a push is in state `OnlyPushStream` or `Active` the
|
||||
@@ -146,7 +146,7 @@ impl ActivePushStreams {
|
||||
#[derive(Debug)]
|
||||
pub struct PushController {
|
||||
max_concurent_push: u64,
|
||||
current_max_push_id: PushId,
|
||||
current_max_push_id: u64,
|
||||
// push_streams holds the states of push streams.
|
||||
// We keep a stream until the stream has been closed.
|
||||
push_streams: ActivePushStreams,
|
||||
@@ -156,22 +156,24 @@ pub struct PushController {
|
||||
conn_events: Http3ClientEvents,
|
||||
}
|
||||
|
||||
impl Display for PushController {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
write!(f, "Push controller")
|
||||
}
|
||||
}
|
||||
|
||||
impl PushController {
|
||||
pub const fn new(max_concurent_push: u64, conn_events: Http3ClientEvents) -> Self {
|
||||
Self {
|
||||
max_concurent_push,
|
||||
current_max_push_id: PushId::new(0),
|
||||
current_max_push_id: 0,
|
||||
push_streams: ActivePushStreams::new(),
|
||||
conn_events,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for PushController {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
write!(f, "Push controler")
|
||||
}
|
||||
}
|
||||
|
||||
impl PushController {
|
||||
/// A new `push_promise` has been received.
|
||||
///
|
||||
/// # Errors
|
||||
@@ -179,12 +181,15 @@ impl PushController {
|
||||
/// `HttpId` if `push_id` greater than it is allowed has been received.
|
||||
pub fn new_push_promise(
|
||||
&mut self,
|
||||
push_id: PushId,
|
||||
push_id: u64,
|
||||
ref_stream_id: StreamId,
|
||||
new_headers: Vec<Header>,
|
||||
) -> Res<()> {
|
||||
qtrace!(
|
||||
"[{self}] New push promise push_id={push_id} headers={new_headers:?} max_push={}",
|
||||
[self],
|
||||
"New push promise push_id={} headers={:?} max_push={}",
|
||||
push_id,
|
||||
new_headers,
|
||||
self.max_concurent_push
|
||||
);
|
||||
|
||||
@@ -192,7 +197,7 @@ impl PushController {
|
||||
|
||||
match self.push_streams.get_mut(push_id) {
|
||||
None => {
|
||||
qtrace!("Push has been closed already {push_id}");
|
||||
qtrace!("Push has been closed already {}.", push_id);
|
||||
Ok(())
|
||||
}
|
||||
Some(push_state) => match push_state {
|
||||
@@ -231,13 +236,18 @@ impl PushController {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_new_push_stream(&mut self, push_id: PushId, stream_id: StreamId) -> Res<bool> {
|
||||
qtrace!("A new push stream with push_id={push_id} stream_id={stream_id}");
|
||||
pub fn add_new_push_stream(&mut self, push_id: u64, stream_id: StreamId) -> Res<bool> {
|
||||
qtrace!(
|
||||
"A new push stream with push_id={} stream_id={}",
|
||||
push_id,
|
||||
stream_id
|
||||
);
|
||||
|
||||
self.check_push_id(push_id)?;
|
||||
|
||||
self.push_streams.get_mut(push_id).map_or_else(
|
||||
|| {
|
||||
qinfo!("Push has been closed already");
|
||||
qinfo!("Push has been closed already.");
|
||||
Ok(false)
|
||||
},
|
||||
|push_state| match push_state {
|
||||
@@ -259,17 +269,17 @@ impl PushController {
|
||||
// The following state have already have a push stream:
|
||||
// PushState::OnlyPushStream | PushState::Active
|
||||
_ => {
|
||||
qerror!("Duplicate push stream");
|
||||
qerror!("Duplicate push stream.");
|
||||
Err(Error::HttpId)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn check_push_id(&self, push_id: PushId) -> Res<()> {
|
||||
fn check_push_id(&self, push_id: u64) -> Res<()> {
|
||||
// Check if push id is greater than what we allow.
|
||||
if push_id > self.current_max_push_id {
|
||||
qerror!("Push id is greater than current_max_push_id");
|
||||
qerror!("Push id is greater than current_max_push_id.");
|
||||
Err(Error::HttpId)
|
||||
} else {
|
||||
Ok(())
|
||||
@@ -278,17 +288,17 @@ impl PushController {
|
||||
|
||||
pub fn handle_cancel_push(
|
||||
&mut self,
|
||||
push_id: PushId,
|
||||
push_id: u64,
|
||||
conn: &mut Connection,
|
||||
base_handler: &mut Http3Connection,
|
||||
) -> Res<()> {
|
||||
qtrace!("CANCEL_PUSH frame has been received, push_id={push_id}");
|
||||
qtrace!("CANCEL_PUSH frame has been received, push_id={}", push_id);
|
||||
|
||||
self.check_push_id(push_id)?;
|
||||
|
||||
match self.push_streams.close(push_id) {
|
||||
None => {
|
||||
qtrace!("Push has already been closed (push_id={push_id})");
|
||||
qtrace!("Push has already been closed (push_id={}).", push_id);
|
||||
Ok(())
|
||||
}
|
||||
Some(ps) => match ps {
|
||||
@@ -300,7 +310,7 @@ impl PushController {
|
||||
}
|
||||
PushState::OnlyPushStream { stream_id, .. }
|
||||
| PushState::Active { stream_id, .. } => {
|
||||
drop(base_handler.stream_stop_sending(
|
||||
mem::drop(base_handler.stream_stop_sending(
|
||||
conn,
|
||||
stream_id,
|
||||
Error::HttpRequestCancelled.code(),
|
||||
@@ -314,8 +324,8 @@ impl PushController {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn close(&mut self, push_id: PushId) {
|
||||
qtrace!("Push stream has been closed");
|
||||
pub fn close(&mut self, push_id: u64) {
|
||||
qtrace!("Push stream has been closed.");
|
||||
if let Some(push_state) = self.push_streams.close(push_id) {
|
||||
debug_assert!(matches!(push_state, PushState::Active { .. }));
|
||||
} else {
|
||||
@@ -325,17 +335,17 @@ impl PushController {
|
||||
|
||||
pub fn cancel(
|
||||
&mut self,
|
||||
push_id: PushId,
|
||||
push_id: u64,
|
||||
conn: &mut Connection,
|
||||
base_handler: &mut Http3Connection,
|
||||
) -> Res<()> {
|
||||
qtrace!("Cancel push_id={push_id}");
|
||||
qtrace!("Cancel push_id={}", push_id);
|
||||
|
||||
self.check_push_id(push_id)?;
|
||||
|
||||
match self.push_streams.get(push_id) {
|
||||
None => {
|
||||
qtrace!("Push has already been closed");
|
||||
qtrace!("Push has already been closed.");
|
||||
// If we have some events for the push_id in the event queue, the caller still does
|
||||
// not not know that the push has been closed. Otherwise return
|
||||
// InvalidStreamId.
|
||||
@@ -355,7 +365,7 @@ impl PushController {
|
||||
Some(PushState::Active { stream_id, .. }) => {
|
||||
self.conn_events.remove_events_for_push_id(push_id);
|
||||
// Cancel the stream. The transport stream may already be done, so ignore an error.
|
||||
drop(base_handler.stream_stop_sending(
|
||||
mem::drop(base_handler.stream_stop_sending(
|
||||
conn,
|
||||
*stream_id,
|
||||
Error::HttpRequestCancelled.code(),
|
||||
@@ -367,8 +377,9 @@ impl PushController {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_stream_reset(&mut self, push_id: PushId, close_type: CloseType) {
|
||||
qtrace!("Push stream has been reset, push_id={push_id}");
|
||||
pub fn push_stream_reset(&mut self, push_id: u64, close_type: CloseType) {
|
||||
qtrace!("Push stream has been reset, push_id={}", push_id);
|
||||
|
||||
if let Some(push_state) = self.push_streams.get(push_id) {
|
||||
match push_state {
|
||||
PushState::OnlyPushStream { .. } => {
|
||||
@@ -386,14 +397,14 @@ impl PushController {
|
||||
_ => {
|
||||
debug_assert!(
|
||||
false,
|
||||
"Reset cannot actually happen because we do not have a stream"
|
||||
"Reset cannot actually happen because we do not have a stream."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_active_stream_id(&mut self, push_id: PushId) -> Option<StreamId> {
|
||||
pub fn get_active_stream_id(&mut self, push_id: u64) -> Option<StreamId> {
|
||||
match self.push_streams.get(push_id) {
|
||||
Some(PushState::Active { stream_id, .. }) => Some(*stream_id),
|
||||
_ => None,
|
||||
@@ -403,7 +414,7 @@ impl PushController {
|
||||
pub fn maybe_send_max_push_id_frame(&mut self, base_handler: &mut Http3Connection) {
|
||||
let push_done = self.push_streams.number_done();
|
||||
if self.max_concurent_push > 0
|
||||
&& (self.current_max_push_id - push_done) <= (self.max_concurent_push / 2).into()
|
||||
&& (self.current_max_push_id - push_done) <= (self.max_concurent_push / 2)
|
||||
{
|
||||
self.current_max_push_id = push_done + self.max_concurent_push;
|
||||
base_handler.queue_control_frame(&HFrame::MaxPushId {
|
||||
@@ -413,7 +424,7 @@ impl PushController {
|
||||
}
|
||||
|
||||
pub fn handle_zero_rtt_rejected(&mut self) {
|
||||
self.current_max_push_id = PushId::new(0);
|
||||
self.current_max_push_id = 0;
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
@@ -424,10 +435,10 @@ impl PushController {
|
||||
self.max_concurent_push > 0
|
||||
}
|
||||
|
||||
pub fn new_stream_event(&mut self, push_id: PushId, event: Http3ClientEvent) {
|
||||
pub fn new_stream_event(&mut self, push_id: u64, event: Http3ClientEvent) {
|
||||
match self.push_streams.get_mut(push_id) {
|
||||
None => {
|
||||
debug_assert!(false, "Push has been closed already");
|
||||
debug_assert!(false, "Push has been closed already.");
|
||||
}
|
||||
Some(PushState::OnlyPushStream { events, .. }) => {
|
||||
events.push(event);
|
||||
@@ -449,12 +460,12 @@ impl PushController {
|
||||
/// a `push_promise` has not been yet received for the stream.
|
||||
#[derive(Debug)]
|
||||
pub struct RecvPushEvents {
|
||||
push_id: PushId,
|
||||
push_id: u64,
|
||||
push_handler: Rc<RefCell<PushController>>,
|
||||
}
|
||||
|
||||
impl RecvPushEvents {
|
||||
pub const fn new(push_id: PushId, push_handler: Rc<RefCell<PushController>>) -> Self {
|
||||
pub const fn new(push_id: u64, push_handler: Rc<RefCell<PushController>>) -> Self {
|
||||
Self {
|
||||
push_id,
|
||||
push_handler,
|
||||
|
||||
55
third_party/rust/neqo-http3/src/push_id.rs
vendored
55
third_party/rust/neqo-http3/src/push_id.rs
vendored
@@ -1,55 +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 std::ops::{Add, Sub};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd)]
|
||||
pub struct PushId(u64);
|
||||
|
||||
impl PushId {
|
||||
#[must_use]
|
||||
pub const fn new(id: u64) -> Self {
|
||||
Self(id)
|
||||
}
|
||||
|
||||
pub fn next(&mut self) {
|
||||
self.0 += 1;
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for PushId {
|
||||
fn from(id: u64) -> Self {
|
||||
Self(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PushId> for u64 {
|
||||
fn from(id: PushId) -> Self {
|
||||
id.0
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for PushId {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for PushId {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self {
|
||||
Self(self.0 - rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<u64> for PushId {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: u64) -> Self {
|
||||
Self(self.0 + rhs)
|
||||
}
|
||||
}
|
||||
48
third_party/rust/neqo-http3/src/recv_message.rs
vendored
48
third_party/rust/neqo-http3/src/recv_message.rs
vendored
@@ -6,7 +6,7 @@
|
||||
|
||||
use std::{cell::RefCell, cmp::min, collections::VecDeque, fmt::Debug, rc::Rc};
|
||||
|
||||
use neqo_common::{header::HeadersExt as _, qdebug, qinfo, qtrace, Header};
|
||||
use neqo_common::{qdebug, qinfo, qtrace, Header};
|
||||
use neqo_qpack::decoder::QPackDecoder;
|
||||
use neqo_transport::{Connection, StreamId};
|
||||
|
||||
@@ -16,7 +16,7 @@ use crate::{
|
||||
priority::PriorityHandler,
|
||||
push_controller::PushController,
|
||||
qlog, CloseType, Error, Http3StreamInfo, Http3StreamType, HttpRecvStream, HttpRecvStreamEvents,
|
||||
MessageType, Priority, PushId, ReceiveOutput, RecvStream, Res, Stream,
|
||||
MessageType, Priority, ReceiveOutput, RecvStream, Res, Stream,
|
||||
};
|
||||
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
@@ -61,7 +61,7 @@ enum RecvMessageState {
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PushInfo {
|
||||
push_id: PushId,
|
||||
push_id: u64,
|
||||
header_block: Vec<u8>,
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ impl RecvMessage {
|
||||
RecvMessageState::WaitingForFinAfterTrailers {..} => {
|
||||
return Err(Error::HttpFrameUnexpected);
|
||||
}
|
||||
_ => unreachable!("This functions is only called in WaitingForResponseHeaders | WaitingForData | WaitingForFinAfterTrailers state")
|
||||
_ => unreachable!("This functions is only called in WaitingForResponseHeaders | WaitingForData | WaitingForFinAfterTrailers state.")
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -146,13 +146,13 @@ impl RecvMessage {
|
||||
};
|
||||
}
|
||||
}
|
||||
_ => unreachable!("This functions is only called in WaitingForResponseHeaders | WaitingForData | WaitingForFinAfterTrailers state")
|
||||
_ => unreachable!("This functions is only called in WaitingForResponseHeaders | WaitingForData | WaitingForFinAfterTrailers state.")
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_headers(&mut self, mut headers: Vec<Header>, fin: bool) -> Res<()> {
|
||||
qtrace!("[{self}] Add new headers fin={fin}");
|
||||
qtrace!([self], "Add new headers fin={}", fin);
|
||||
let interim = match self.message_type {
|
||||
MessageType::Request => false,
|
||||
MessageType::Response => is_interim(&headers)?,
|
||||
@@ -167,8 +167,12 @@ impl RecvMessage {
|
||||
}
|
||||
|
||||
let is_web_transport = self.message_type == MessageType::Request
|
||||
&& headers.contains_header(":method", "CONNECT")
|
||||
&& headers.contains_header(":protocol", "webtransport");
|
||||
&& headers
|
||||
.iter()
|
||||
.any(|h| h.name() == ":method" && h.value() == "CONNECT")
|
||||
&& headers
|
||||
.iter()
|
||||
.any(|h| h.name() == ":protocol" && h.value() == "webtransport");
|
||||
if is_web_transport {
|
||||
self.conn_events
|
||||
.extended_connect_new_session(self.stream_id, headers);
|
||||
@@ -199,10 +203,7 @@ impl RecvMessage {
|
||||
fn set_state_to_close_pending(&mut self, post_readable_event: bool) -> Res<()> {
|
||||
// Stream has received fin. Depending on headers state set header_ready
|
||||
// or data_readable event so that app can pick up the fin.
|
||||
qtrace!(
|
||||
"[{self}] set_state_to_close_pending: state={:?}",
|
||||
self.state
|
||||
);
|
||||
qtrace!([self], "set_state_to_close_pending: state={:?}", self.state);
|
||||
|
||||
match self.state {
|
||||
RecvMessageState::WaitingForResponseHeaders { .. } => {
|
||||
@@ -215,7 +216,7 @@ impl RecvMessage {
|
||||
self.conn_events.data_readable(self.get_stream_info());
|
||||
}
|
||||
}
|
||||
_ => unreachable!("Closing an already closed transaction"),
|
||||
_ => unreachable!("Closing an already closed transaction."),
|
||||
}
|
||||
if !matches!(self.state, RecvMessageState::Closed) {
|
||||
self.state = RecvMessageState::ClosePending;
|
||||
@@ -223,7 +224,7 @@ impl RecvMessage {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_push_promise(&mut self, push_id: PushId, header_block: Vec<u8>) -> Res<()> {
|
||||
fn handle_push_promise(&mut self, push_id: u64, header_block: Vec<u8>) -> Res<()> {
|
||||
if self.push_handler.is_none() {
|
||||
return Err(Error::HttpFrameUnexpected);
|
||||
}
|
||||
@@ -253,8 +254,9 @@ impl RecvMessage {
|
||||
}
|
||||
|
||||
fn receive_internal(&mut self, conn: &mut Connection, post_readable_event: bool) -> Res<()> {
|
||||
let label = ::neqo_common::log_subject!(::log::Level::Debug, self);
|
||||
loop {
|
||||
qdebug!("[{self}] state={:?}", self.state);
|
||||
qdebug!([label], "state={:?}.", self.state);
|
||||
match &mut self.state {
|
||||
// In the following 3 states we need to read frames.
|
||||
RecvMessageState::WaitingForResponseHeaders { frame_reader }
|
||||
@@ -270,7 +272,11 @@ impl RecvMessage {
|
||||
(None, false) => break Ok(()),
|
||||
(Some(frame), fin) => {
|
||||
qdebug!(
|
||||
"[{self}] A new frame has been received: {frame:?}; state={:?} fin={fin}", self.state,
|
||||
[self],
|
||||
"A new frame has been received: {:?}; state={:?} fin={}",
|
||||
frame,
|
||||
self.state,
|
||||
fin,
|
||||
);
|
||||
match frame {
|
||||
HFrame::Headers { header_block } => {
|
||||
@@ -294,7 +300,10 @@ impl RecvMessage {
|
||||
}
|
||||
};
|
||||
}
|
||||
RecvMessageState::DecodingHeaders { header_block, fin } => {
|
||||
RecvMessageState::DecodingHeaders {
|
||||
ref header_block,
|
||||
fin,
|
||||
} => {
|
||||
if self
|
||||
.qpack_decoder
|
||||
.borrow()
|
||||
@@ -302,7 +311,8 @@ impl RecvMessage {
|
||||
&& !self.blocked_push_promise.is_empty()
|
||||
{
|
||||
qinfo!(
|
||||
"[{self}] decoding header is blocked waiting for a push_promise header block"
|
||||
[self],
|
||||
"decoding header is blocked waiting for a push_promise header block."
|
||||
);
|
||||
break Ok(());
|
||||
}
|
||||
@@ -320,7 +330,7 @@ impl RecvMessage {
|
||||
break Ok(());
|
||||
}
|
||||
} else {
|
||||
qinfo!("[{self}] decoding header is blocked");
|
||||
qinfo!([self], "decoding header is blocked.");
|
||||
break Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
15
third_party/rust/neqo-http3/src/send_message.rs
vendored
15
third_party/rust/neqo-http3/src/send_message.rs
vendored
@@ -119,7 +119,7 @@ impl SendMessage {
|
||||
encoder: Rc<RefCell<QPackEncoder>>,
|
||||
conn_events: Box<dyn SendStreamEvents>,
|
||||
) -> Self {
|
||||
qdebug!("Create a request stream_id={stream_id}");
|
||||
qdebug!("Create a request stream_id={}", stream_id);
|
||||
Self {
|
||||
state: MessageState::WaitingForHeaders,
|
||||
message_type,
|
||||
@@ -166,7 +166,7 @@ impl Stream for SendMessage {
|
||||
}
|
||||
impl SendStream for SendMessage {
|
||||
fn send_data(&mut self, conn: &mut Connection, buf: &[u8]) -> Res<usize> {
|
||||
qtrace!("[{self}] send_body: len={}", buf.len());
|
||||
qtrace!([self], "send_body: len={}", buf.len());
|
||||
|
||||
self.state.new_data()?;
|
||||
|
||||
@@ -200,7 +200,12 @@ impl SendStream for SendMessage {
|
||||
min(buf.len(), available - 9)
|
||||
};
|
||||
|
||||
qdebug!("[{self}] send_request_body: available={available} to_send={to_send}");
|
||||
qdebug!(
|
||||
[self],
|
||||
"send_request_body: available={} to_send={}.",
|
||||
available,
|
||||
to_send
|
||||
);
|
||||
|
||||
let data_frame = HFrame::Data {
|
||||
len: to_send as u64,
|
||||
@@ -245,14 +250,14 @@ impl SendStream for SendMessage {
|
||||
fn send(&mut self, conn: &mut Connection) -> Res<()> {
|
||||
let sent = Error::map_error(self.stream.send_buffer(conn), Error::HttpInternal(5))?;
|
||||
|
||||
qtrace!("[{self}] {sent} bytes sent");
|
||||
qtrace!([self], "{} bytes sent", sent);
|
||||
if !self.stream.has_buffered_data() {
|
||||
if self.state.done() {
|
||||
Error::map_error(
|
||||
conn.stream_close_send(self.stream_id()),
|
||||
Error::HttpInternal(6),
|
||||
)?;
|
||||
qtrace!("[{self}] done sending request");
|
||||
qtrace!([self], "done sending request");
|
||||
} else {
|
||||
// DataWritable is just a signal for an application to try to write more data,
|
||||
// if writing fails it is fine. Therefore we do not need to properly check
|
||||
|
||||
60
third_party/rust/neqo-http3/src/server.rs
vendored
60
third_party/rust/neqo-http3/src/server.rs
vendored
@@ -119,13 +119,13 @@ impl Http3Server {
|
||||
}
|
||||
|
||||
pub fn process(&mut self, dgram: Option<Datagram<impl AsRef<[u8]>>>, now: Instant) -> Output {
|
||||
qtrace!("[{self}] Process");
|
||||
qtrace!([self], "Process.");
|
||||
let out = self.server.process(dgram, now);
|
||||
self.process_http3(now);
|
||||
// If we do not that a dgram already try again after process_http3.
|
||||
match out {
|
||||
Output::Datagram(d) => {
|
||||
qtrace!("[{self}] Send packet: {d:?}");
|
||||
qtrace!([self], "Send packet: {:?}", d);
|
||||
Output::Datagram(d)
|
||||
}
|
||||
_ => self.server.process(Option::<Datagram>::None, now),
|
||||
@@ -134,7 +134,7 @@ impl Http3Server {
|
||||
|
||||
/// Process HTTP3 layer.
|
||||
fn process_http3(&mut self, now: Instant) {
|
||||
qtrace!("[{self}] Process http3 internal");
|
||||
qtrace!([self], "Process http3 internal.");
|
||||
// `ActiveConnectionRef` `Hash` implementation doesn’t access any of the interior mutable
|
||||
// types.
|
||||
#[allow(clippy::mutable_key_type)]
|
||||
@@ -152,7 +152,6 @@ impl Http3Server {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn process_events(&mut self, conn: &ConnectionRef, now: Instant) {
|
||||
let mut remove = false;
|
||||
let http3_parameters = &self.http3_parameters;
|
||||
@@ -173,11 +172,7 @@ impl Http3Server {
|
||||
headers,
|
||||
fin,
|
||||
} => self.events.headers(
|
||||
Http3OrWebTransportStream::new(
|
||||
conn.clone(),
|
||||
Rc::clone(handler),
|
||||
stream_info,
|
||||
),
|
||||
Http3OrWebTransportStream::new(conn.clone(), handler.clone(), stream_info),
|
||||
headers,
|
||||
fin,
|
||||
),
|
||||
@@ -193,19 +188,15 @@ impl Http3Server {
|
||||
}
|
||||
Http3ServerConnEvent::DataWritable { stream_info } => self
|
||||
.events
|
||||
.data_writable(conn.clone(), Rc::clone(handler), stream_info),
|
||||
.data_writable(conn.clone(), handler.clone(), stream_info),
|
||||
Http3ServerConnEvent::StreamReset { stream_info, error } => {
|
||||
self.events.stream_reset(
|
||||
conn.clone(),
|
||||
Rc::clone(handler),
|
||||
stream_info,
|
||||
error,
|
||||
);
|
||||
self.events
|
||||
.stream_reset(conn.clone(), handler.clone(), stream_info, error);
|
||||
}
|
||||
Http3ServerConnEvent::StreamStopSending { stream_info, error } => {
|
||||
self.events.stream_stop_sending(
|
||||
conn.clone(),
|
||||
Rc::clone(handler),
|
||||
handler.clone(),
|
||||
stream_info,
|
||||
error,
|
||||
);
|
||||
@@ -225,7 +216,7 @@ impl Http3Server {
|
||||
}
|
||||
Http3ServerConnEvent::ExtendedConnect { stream_id, headers } => {
|
||||
self.events.webtransport_new_session(
|
||||
WebTransportRequest::new(conn.clone(), Rc::clone(handler), stream_id),
|
||||
WebTransportRequest::new(conn.clone(), handler.clone(), stream_id),
|
||||
headers,
|
||||
);
|
||||
}
|
||||
@@ -235,7 +226,7 @@ impl Http3Server {
|
||||
headers,
|
||||
..
|
||||
} => self.events.webtransport_session_closed(
|
||||
WebTransportRequest::new(conn.clone(), Rc::clone(handler), stream_id),
|
||||
WebTransportRequest::new(conn.clone(), handler.clone(), stream_id),
|
||||
reason,
|
||||
headers,
|
||||
),
|
||||
@@ -243,14 +234,14 @@ impl Http3Server {
|
||||
.events
|
||||
.webtransport_new_stream(Http3OrWebTransportStream::new(
|
||||
conn.clone(),
|
||||
Rc::clone(handler),
|
||||
handler.clone(),
|
||||
stream_info,
|
||||
)),
|
||||
Http3ServerConnEvent::ExtendedConnectDatagram {
|
||||
session_id,
|
||||
datagram,
|
||||
} => self.events.webtransport_datagram(
|
||||
WebTransportRequest::new(conn.clone(), Rc::clone(handler), session_id),
|
||||
WebTransportRequest::new(conn.clone(), handler.clone(), session_id),
|
||||
datagram,
|
||||
),
|
||||
}
|
||||
@@ -303,7 +294,7 @@ fn prepare_data(
|
||||
data.resize(amount, 0);
|
||||
}
|
||||
|
||||
events.data(conn.clone(), Rc::clone(handler), stream_info, data, fin);
|
||||
events.data(conn.clone(), handler.clone(), stream_info, data, fin);
|
||||
}
|
||||
if amount < MAX_EVENT_DATA_SIZE || fin {
|
||||
break;
|
||||
@@ -320,10 +311,11 @@ fn prepare_data(
|
||||
mod tests {
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
mem,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
use neqo_common::{event::Provider as _, Encoder};
|
||||
use neqo_common::{event::Provider, Encoder};
|
||||
use neqo_crypto::{AuthenticationStatus, ZeroRttCheckResult, ZeroRttChecker};
|
||||
use neqo_qpack::{encoder::QPackEncoder, QpackSettings};
|
||||
use neqo_transport::{
|
||||
@@ -510,11 +502,11 @@ mod tests {
|
||||
(server, client)
|
||||
}
|
||||
|
||||
// Test http3 connection initialization.
|
||||
// Test http3 connection inintialization.
|
||||
// The server will open the control and qpack streams and send SETTINGS frame.
|
||||
#[test]
|
||||
fn server_connect() {
|
||||
drop(connect_and_receive_settings());
|
||||
mem::drop(connect_and_receive_settings());
|
||||
}
|
||||
|
||||
struct PeerConnection {
|
||||
@@ -567,9 +559,9 @@ mod tests {
|
||||
assert_eq!(sent, Ok(1));
|
||||
let out1 = neqo_trans_conn.process_output(now());
|
||||
let out2 = server.process(out1.dgram(), now());
|
||||
drop(neqo_trans_conn.process(out2.dgram(), now()));
|
||||
mem::drop(neqo_trans_conn.process(out2.dgram(), now()));
|
||||
|
||||
// assert no error occurred.
|
||||
// assert no error occured.
|
||||
assert_not_closed(server);
|
||||
|
||||
PeerConnection {
|
||||
@@ -587,7 +579,7 @@ mod tests {
|
||||
// Server: Test receiving a new control stream and a SETTINGS frame.
|
||||
#[test]
|
||||
fn server_receive_control_frame() {
|
||||
drop(connect());
|
||||
mem::drop(connect());
|
||||
}
|
||||
|
||||
// Server: Test that the connection will be closed if control stream
|
||||
@@ -693,13 +685,13 @@ mod tests {
|
||||
test_wrong_frame_on_control_stream(&[0x0, 0x2, 0x1, 0x2]);
|
||||
}
|
||||
|
||||
// send HEADERS frame on a control stream
|
||||
// send HEADERS frame on a cortrol stream
|
||||
#[test]
|
||||
fn server_headers_frame_on_control_stream() {
|
||||
test_wrong_frame_on_control_stream(&[0x1, 0x2, 0x1, 0x2]);
|
||||
}
|
||||
|
||||
// send PUSH_PROMISE frame on a control stream
|
||||
// send PUSH_PROMISE frame on a cortrol stream
|
||||
#[test]
|
||||
fn server_push_promise_frame_on_control_stream() {
|
||||
test_wrong_frame_on_control_stream(&[0x5, 0x2, 0x1, 0x2]);
|
||||
@@ -718,9 +710,9 @@ mod tests {
|
||||
.unwrap();
|
||||
let out = peer_conn.process_output(now());
|
||||
let out = hconn.process(out.dgram(), now());
|
||||
drop(peer_conn.process(out.dgram(), now()));
|
||||
mem::drop(peer_conn.process(out.dgram(), now()));
|
||||
let out = hconn.process_output(now());
|
||||
drop(peer_conn.process(out.dgram(), now()));
|
||||
mem::drop(peer_conn.process(out.dgram(), now()));
|
||||
|
||||
// check for stop-sending with Error::HttpStreamCreation.
|
||||
let mut stop_sending_event_found = false;
|
||||
@@ -749,7 +741,7 @@ mod tests {
|
||||
_ = peer_conn.stream_send(push_stream_id, &[0x1]).unwrap();
|
||||
let out = peer_conn.process_output(now());
|
||||
let out = hconn.process(out.dgram(), now());
|
||||
drop(peer_conn.conn.process(out.dgram(), now()));
|
||||
mem::drop(peer_conn.conn.process(out.dgram(), now()));
|
||||
assert_closed(&hconn, &Error::HttpStreamCreation);
|
||||
}
|
||||
|
||||
@@ -844,7 +836,7 @@ mod tests {
|
||||
fn test_incomplete_frame(res: &[u8]) {
|
||||
let (mut hconn, mut peer_conn) = connect_and_receive_settings();
|
||||
|
||||
// send an incomplete request.
|
||||
// send an incomplete reequest.
|
||||
let stream_id = peer_conn.stream_create(StreamType::BiDi).unwrap();
|
||||
peer_conn.stream_send(stream_id, res).unwrap();
|
||||
peer_conn.stream_close_send(stream_id).unwrap();
|
||||
|
||||
24
third_party/rust/neqo-http3/src/server_events.rs
vendored
24
third_party/rust/neqo-http3/src/server_events.rs
vendored
@@ -35,7 +35,7 @@ pub struct StreamHandler {
|
||||
impl ::std::fmt::Display for StreamHandler {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
let conn: &Connection = &self.conn.borrow();
|
||||
write!(f, "conn={conn} stream_info={:?}", self.stream_info)
|
||||
write!(f, "conn={} stream_info={:?}", conn, self.stream_info)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,8 +115,10 @@ impl StreamHandler {
|
||||
/// It may return `InvalidStreamId` if a stream does not exist anymore.
|
||||
pub fn stream_stop_sending(&self, app_error: AppError) -> Res<()> {
|
||||
qdebug!(
|
||||
"[{self}] stop sending stream_id:{} error:{app_error}",
|
||||
self.stream_info.stream_id()
|
||||
[self],
|
||||
"stop sending stream_id:{} error:{}.",
|
||||
self.stream_info.stream_id(),
|
||||
app_error
|
||||
);
|
||||
self.handler.borrow_mut().stream_stop_sending(
|
||||
self.stream_info.stream_id(),
|
||||
@@ -132,8 +134,10 @@ impl StreamHandler {
|
||||
/// It may return `InvalidStreamId` if a stream does not exist anymore.
|
||||
pub fn stream_reset_send(&self, app_error: AppError) -> Res<()> {
|
||||
qdebug!(
|
||||
"[{self}] reset send stream_id:{} error:{app_error}",
|
||||
self.stream_info.stream_id()
|
||||
[self],
|
||||
"reset send stream_id:{} error:{}.",
|
||||
self.stream_info.stream_id(),
|
||||
app_error
|
||||
);
|
||||
self.handler.borrow_mut().stream_reset_send(
|
||||
self.stream_info.stream_id(),
|
||||
@@ -148,7 +152,7 @@ impl StreamHandler {
|
||||
///
|
||||
/// It may return `InvalidStreamId` if a stream does not exist anymore
|
||||
pub fn cancel_fetch(&self, app_error: AppError) -> Res<()> {
|
||||
qdebug!("[{self}] reset error:{app_error}");
|
||||
qdebug!([self], "reset error:{}.", app_error);
|
||||
self.handler.borrow_mut().cancel_fetch(
|
||||
self.stream_info.stream_id(),
|
||||
app_error,
|
||||
@@ -198,7 +202,7 @@ impl Http3OrWebTransportStream {
|
||||
///
|
||||
/// It may return `InvalidStreamId` if a stream does not exist anymore.
|
||||
pub fn send_data(&self, data: &[u8]) -> Res<usize> {
|
||||
qdebug!("[{self}] Set new response");
|
||||
qdebug!([self], "Set new response.");
|
||||
self.stream_handler.send_data(data)
|
||||
}
|
||||
|
||||
@@ -208,7 +212,7 @@ impl Http3OrWebTransportStream {
|
||||
///
|
||||
/// It may return `InvalidStreamId` if a stream does not exist anymore.
|
||||
pub fn stream_close_send(&self) -> Res<()> {
|
||||
qdebug!("[{self}] Set new response");
|
||||
qdebug!([self], "Set new response.");
|
||||
self.stream_handler.stream_close_send()
|
||||
}
|
||||
}
|
||||
@@ -279,7 +283,7 @@ impl WebTransportRequest {
|
||||
///
|
||||
/// It may return `InvalidStreamId` if a stream does not exist anymore.
|
||||
pub fn response(&self, accept: &WebTransportSessionAcceptAction) -> Res<()> {
|
||||
qdebug!("[{self}] Set a response for a WebTransport session");
|
||||
qdebug!([self], "Set a response for a WebTransport session.");
|
||||
self.stream_handler
|
||||
.handler
|
||||
.borrow_mut()
|
||||
@@ -331,7 +335,7 @@ impl WebTransportRequest {
|
||||
|
||||
Ok(Http3OrWebTransportStream::new(
|
||||
self.stream_handler.conn.clone(),
|
||||
Rc::clone(&self.stream_handler.handler),
|
||||
self.stream_handler.handler.clone(),
|
||||
Http3StreamInfo::new(id, Http3StreamType::WebTransport(session_id)),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use neqo_transport::{Connection, StreamId, StreamType};
|
||||
use crate::{
|
||||
control_stream_local::HTTP3_UNI_STREAM_TYPE_CONTROL,
|
||||
frames::{hframe::HFrameType, reader::FrameDecoder, HFrame, H3_FRAME_TYPE_HEADERS},
|
||||
CloseType, Error, Http3StreamType, PushId, ReceiveOutput, RecvStream, Res, Stream,
|
||||
CloseType, Error, Http3StreamType, ReceiveOutput, RecvStream, Res, Stream,
|
||||
};
|
||||
|
||||
pub const HTTP3_UNI_STREAM_TYPE_PUSH: u64 = 0x1;
|
||||
@@ -23,7 +23,7 @@ pub enum NewStreamType {
|
||||
Control,
|
||||
Decoder,
|
||||
Encoder,
|
||||
Push(PushId),
|
||||
Push(u64),
|
||||
WebTransportStream(u64),
|
||||
Http(u64),
|
||||
Unknown,
|
||||
@@ -137,7 +137,7 @@ impl NewStreamHeadReader {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
qtrace!("Decoded uint {output}");
|
||||
qtrace!("Decoded uint {}", output);
|
||||
match self {
|
||||
Self::ReadType {
|
||||
role, stream_id, ..
|
||||
@@ -178,12 +178,12 @@ impl NewStreamHeadReader {
|
||||
Self::ReadId { stream_type, .. } => {
|
||||
let is_push = *stream_type == HTTP3_UNI_STREAM_TYPE_PUSH;
|
||||
*self = Self::Done;
|
||||
qtrace!("New Stream stream push_id={output}");
|
||||
qtrace!("New Stream stream push_id={}", output);
|
||||
if fin {
|
||||
return Err(Error::HttpGeneralProtocol);
|
||||
}
|
||||
return if is_push {
|
||||
Ok(Some(NewStreamType::Push(PushId::new(output))))
|
||||
Ok(Some(NewStreamType::Push(output)))
|
||||
} else {
|
||||
Ok(Some(NewStreamType::WebTransportStream(output)))
|
||||
};
|
||||
@@ -204,7 +204,7 @@ impl NewStreamHeadReader {
|
||||
Some(NewStreamType::Http(_)) => Err(Error::HttpFrame),
|
||||
Some(NewStreamType::Unknown) => Ok(decoded),
|
||||
Some(NewStreamType::Push(_) | NewStreamType::WebTransportStream(_)) => {
|
||||
unreachable!("PushStream and WebTransport are mapped to None at this stage")
|
||||
unreachable!("PushStream and WebTransport are mapped to None at this stage.")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -237,6 +237,8 @@ impl RecvStream for NewStreamHeadReader {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::mem;
|
||||
|
||||
use neqo_common::{Encoder, Role};
|
||||
use neqo_qpack::{
|
||||
decoder::QPACK_UNI_STREAM_TYPE_DECODER, encoder::QPACK_UNI_STREAM_TYPE_ENCODER,
|
||||
@@ -251,7 +253,7 @@ mod tests {
|
||||
use crate::{
|
||||
control_stream_local::HTTP3_UNI_STREAM_TYPE_CONTROL,
|
||||
frames::{H3_FRAME_TYPE_HEADERS, H3_FRAME_TYPE_SETTINGS},
|
||||
CloseType, Error, NewStreamType, PushId, ReceiveOutput, RecvStream as _, Res,
|
||||
CloseType, Error, NewStreamType, ReceiveOutput, RecvStream, Res,
|
||||
};
|
||||
|
||||
struct Test {
|
||||
@@ -267,7 +269,7 @@ mod tests {
|
||||
// create a stream
|
||||
let stream_id = conn_s.stream_create(stream_type).unwrap();
|
||||
let out = conn_s.process_output(now());
|
||||
drop(conn_c.process(out.dgram(), now()));
|
||||
mem::drop(conn_c.process(out.dgram(), now()));
|
||||
|
||||
Self {
|
||||
conn_c,
|
||||
@@ -290,7 +292,7 @@ mod tests {
|
||||
.stream_send(self.stream_id, &enc[i..=i])
|
||||
.unwrap();
|
||||
let out = self.conn_s.process_output(now());
|
||||
drop(self.conn_c.process(out.dgram(), now()));
|
||||
mem::drop(self.conn_c.process(out.dgram(), now()));
|
||||
assert_eq!(
|
||||
self.decoder.receive(&mut self.conn_c).unwrap(),
|
||||
(ReceiveOutput::NoOutput, false)
|
||||
@@ -304,7 +306,7 @@ mod tests {
|
||||
self.conn_s.stream_close_send(self.stream_id).unwrap();
|
||||
}
|
||||
let out = self.conn_s.process_output(now());
|
||||
drop(self.conn_c.process(out.dgram(), now()));
|
||||
mem::drop(self.conn_c.process(out.dgram(), now()));
|
||||
assert_eq!(&self.decoder.receive(&mut self.conn_c), outcome);
|
||||
assert_eq!(self.decoder.done(), done);
|
||||
}
|
||||
@@ -364,7 +366,7 @@ mod tests {
|
||||
&[HTTP3_UNI_STREAM_TYPE_PUSH, 0xaaaa_aaaa],
|
||||
false,
|
||||
&Ok((
|
||||
ReceiveOutput::NewStream(NewStreamType::Push(PushId::new(0xaaaa_aaaa))),
|
||||
ReceiveOutput::NewStream(NewStreamType::Push(0xaaaa_aaaa)),
|
||||
true,
|
||||
)),
|
||||
true,
|
||||
@@ -427,7 +429,7 @@ mod tests {
|
||||
* HTTP3_UNI_STREAM_TYPE_PUSH */
|
||||
false,
|
||||
&Ok((
|
||||
ReceiveOutput::NewStream(NewStreamType::Push(PushId::new(0xaaaa_aaaa))),
|
||||
ReceiveOutput::NewStream(NewStreamType::Push(0xaaaa_aaaa)),
|
||||
true,
|
||||
)),
|
||||
true,
|
||||
|
||||
29
third_party/rust/neqo-http3/tests/httpconn.rs
vendored
29
third_party/rust/neqo-http3/tests/httpconn.rs
vendored
@@ -4,9 +4,12 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{
|
||||
mem,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use neqo_common::{event::Provider as _, qtrace, Datagram};
|
||||
use neqo_common::{event::Provider, qtrace, Datagram};
|
||||
use neqo_crypto::{AuthenticationStatus, ResumptionToken};
|
||||
use neqo_http3::{
|
||||
Header, Http3Client, Http3ClientEvent, Http3OrWebTransportStream, Http3Parameters, Http3Server,
|
||||
@@ -94,7 +97,7 @@ fn connect_peers(hconn_c: &mut Http3Client, hconn_s: &mut Http3Server) -> Option
|
||||
let out = hconn_c.process_output(now()); // Initial
|
||||
let out = hconn_s.process(out.dgram(), now()); // Initial + Handshake
|
||||
let out = hconn_c.process(out.dgram(), now()); // ACK
|
||||
drop(hconn_s.process(out.dgram(), now())); // consume ACK
|
||||
mem::drop(hconn_s.process(out.dgram(), now())); // consume ACK
|
||||
let authentication_needed = |e| matches!(e, Http3ClientEvent::AuthenticationNeeded);
|
||||
assert!(hconn_c.events().any(authentication_needed));
|
||||
hconn_c.authenticated(AuthenticationStatus::Ok, now());
|
||||
@@ -186,14 +189,14 @@ fn fetch() {
|
||||
let out = hconn_c.process(dgram, now());
|
||||
qtrace!("-----server");
|
||||
let out = hconn_s.process(out.dgram(), now());
|
||||
drop(hconn_c.process(out.dgram(), now()));
|
||||
mem::drop(hconn_c.process(out.dgram(), now()));
|
||||
process_server_events(&hconn_s);
|
||||
let out = hconn_s.process(None::<Datagram>, now());
|
||||
|
||||
qtrace!("-----client");
|
||||
drop(hconn_c.process(out.dgram(), now()));
|
||||
mem::drop(hconn_c.process(out.dgram(), now()));
|
||||
let out = hconn_s.process(None::<Datagram>, now());
|
||||
drop(hconn_c.process(out.dgram(), now()));
|
||||
mem::drop(hconn_c.process(out.dgram(), now()));
|
||||
process_client_events(&mut hconn_c);
|
||||
}
|
||||
|
||||
@@ -215,7 +218,7 @@ fn response_103() {
|
||||
let out = hconn_c.process(dgram, now());
|
||||
|
||||
let out = hconn_s.process(out.dgram(), now());
|
||||
drop(hconn_c.process(out.dgram(), now()));
|
||||
mem::drop(hconn_c.process(out.dgram(), now()));
|
||||
let request = receive_request(&hconn_s).unwrap();
|
||||
let info_headers = [
|
||||
Header::new(":status", "103"),
|
||||
@@ -225,7 +228,7 @@ fn response_103() {
|
||||
request.send_headers(&info_headers).unwrap();
|
||||
let out = hconn_s.process(None::<Datagram>, now());
|
||||
|
||||
drop(hconn_c.process(out.dgram(), now()));
|
||||
mem::drop(hconn_c.process(out.dgram(), now()));
|
||||
|
||||
let info_headers_event = |e| {
|
||||
matches!(e, Http3ClientEvent::HeaderReady { headers,
|
||||
@@ -236,7 +239,7 @@ fn response_103() {
|
||||
|
||||
set_response(&request);
|
||||
let out = hconn_s.process(None::<Datagram>, now());
|
||||
drop(hconn_c.process(out.dgram(), now()));
|
||||
mem::drop(hconn_c.process(out.dgram(), now()));
|
||||
process_client_events(&mut hconn_c);
|
||||
}
|
||||
|
||||
@@ -253,7 +256,7 @@ fn data_writable_events_low_watermark() -> Result<(), Box<dyn std::error::Error>
|
||||
ConnectionParameters::default().max_stream_data(StreamType::BiDi, false, STREAM_LIMIT),
|
||||
));
|
||||
let mut hconn_s = default_http3_server();
|
||||
drop(connect_peers(&mut hconn_c, &mut hconn_s));
|
||||
mem::drop(connect_peers(&mut hconn_c, &mut hconn_s));
|
||||
|
||||
// Client sends GET to server.
|
||||
let stream_id = hconn_c.fetch(
|
||||
@@ -295,7 +298,7 @@ fn data_writable_events_low_watermark() -> Result<(), Box<dyn std::error::Error>
|
||||
exchange_packets(&mut hconn_c, &mut hconn_s, None);
|
||||
assert!(hconn_s.events().any(data_writable));
|
||||
|
||||
// Sending more fails, given that each data frame needs to be preceded by a
|
||||
// Sending more fails, given that each data frame needs to be preceeded by a
|
||||
// header, i.e. needs more than 1 byte of send space to send 1 byte payload.
|
||||
assert_eq!(request.available()?, 1);
|
||||
assert_eq!(request.send_data(&buf)?, 0);
|
||||
@@ -327,7 +330,7 @@ fn data_writable_events() {
|
||||
));
|
||||
let mut hconn_s = default_http3_server();
|
||||
|
||||
drop(connect_peers(&mut hconn_c, &mut hconn_s));
|
||||
mem::drop(connect_peers(&mut hconn_c, &mut hconn_s));
|
||||
|
||||
// Create a request.
|
||||
let req = hconn_c
|
||||
@@ -430,7 +433,7 @@ fn zerortt() {
|
||||
let mut hconn_c = default_http3_client();
|
||||
hconn_c
|
||||
.enable_resumption(now(), &token)
|
||||
.expect("Set resumption token");
|
||||
.expect("Set resumption token.");
|
||||
let mut hconn_s = default_http3_server();
|
||||
|
||||
// Create a request.
|
||||
|
||||
12
third_party/rust/neqo-http3/tests/priority.rs
vendored
12
third_party/rust/neqo-http3/tests/priority.rs
vendored
@@ -6,7 +6,7 @@
|
||||
|
||||
use std::time::Instant;
|
||||
|
||||
use neqo_common::event::Provider as _;
|
||||
use neqo_common::event::Provider;
|
||||
use neqo_crypto::AuthenticationStatus;
|
||||
use neqo_http3::{
|
||||
Header, Http3Client, Http3ClientEvent, Http3Server, Http3ServerEvent, Http3State, Priority,
|
||||
@@ -25,7 +25,7 @@ fn exchange_packets(client: &mut Http3Client, server: &mut Http3Server) {
|
||||
}
|
||||
}
|
||||
|
||||
// Perform only QUIC transport handshake.
|
||||
// Perform only Quic transport handshake.
|
||||
fn connect_with(client: &mut Http3Client, server: &mut Http3Server) {
|
||||
assert_eq!(client.state(), Http3State::Initializing);
|
||||
let out = client.process_output(now());
|
||||
@@ -45,7 +45,7 @@ fn connect_with(client: &mut Http3Client, server: &mut Http3Server) {
|
||||
assert!(client.events().any(connected));
|
||||
|
||||
assert_eq!(client.state(), Http3State::Connected);
|
||||
// Exchange H3 settings
|
||||
// Exchange H3 setttings
|
||||
let out = server.process(out.dgram(), now());
|
||||
let out = client.process(out.dgram(), now());
|
||||
let out = server.process(out.dgram(), now());
|
||||
@@ -83,7 +83,11 @@ fn priority_update() {
|
||||
};
|
||||
|
||||
match header_event {
|
||||
Http3ServerEvent::Headers { headers, fin, .. } => {
|
||||
Http3ServerEvent::Headers {
|
||||
stream: _,
|
||||
headers,
|
||||
fin,
|
||||
} => {
|
||||
let expected_headers = &[
|
||||
Header::new(":method", "GET"),
|
||||
Header::new(":scheme", "https"),
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use neqo_common::event::Provider as _;
|
||||
use neqo_common::event::Provider;
|
||||
use neqo_crypto::AuthenticationStatus;
|
||||
use neqo_http3::{
|
||||
Error, Header, Http3Client, Http3ClientEvent, Http3OrWebTransportStream, Http3Server,
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use neqo_common::{event::Provider as _, header::HeadersExt as _};
|
||||
use neqo_common::{event::Provider, Header};
|
||||
use neqo_crypto::AuthenticationStatus;
|
||||
use neqo_http3::{
|
||||
Http3Client, Http3ClientEvent, Http3OrWebTransportStream, Http3Parameters, Http3Server,
|
||||
Http3ServerEvent, Http3State, WebTransportEvent, WebTransportRequest, WebTransportServerEvent,
|
||||
WebTransportSessionAcceptAction,
|
||||
};
|
||||
use neqo_transport::{ConnectionParameters, StreamId, StreamType};
|
||||
use neqo_transport::{StreamId, StreamType};
|
||||
use test_fixture::{
|
||||
anti_replay, fixture_init, now, CountingConnectionIdGenerator, DEFAULT_ADDR, DEFAULT_ALPN_H3,
|
||||
DEFAULT_KEYS, DEFAULT_SERVER_NAME,
|
||||
@@ -59,7 +59,7 @@ fn connect() -> (Http3Client, Http3Server) {
|
||||
|
||||
assert_eq!(client.state(), Http3State::Connected);
|
||||
|
||||
// Exchange H3 settings
|
||||
// Exchange H3 setttings
|
||||
loop {
|
||||
out = server.process(out, now()).dgram();
|
||||
let dgram_present = out.is_some();
|
||||
@@ -96,8 +96,12 @@ fn create_wt_session(client: &mut Http3Client, server: &mut Http3Server) -> WebT
|
||||
headers,
|
||||
}) => {
|
||||
assert!(
|
||||
headers.contains_header(":method", "CONNECT")
|
||||
&& headers.contains_header(":protocol", "webtransport")
|
||||
headers
|
||||
.iter()
|
||||
.any(|h| h.name() == ":method" && h.value() == "CONNECT")
|
||||
&& headers
|
||||
.iter()
|
||||
.any(|h| h.name() == ":protocol" && h.value() == "webtransport")
|
||||
);
|
||||
session
|
||||
.response(&WebTransportSessionAcceptAction::Accept)
|
||||
@@ -123,7 +127,7 @@ fn create_wt_session(client: &mut Http3Client, server: &mut Http3Server) -> WebT
|
||||
}) if (
|
||||
stream_id == wt_session_id &&
|
||||
status == 200 &&
|
||||
headers.contains_header(":status", "200")
|
||||
headers.contains(&Header::new(":status", "200"))
|
||||
)
|
||||
)
|
||||
};
|
||||
@@ -225,17 +229,6 @@ fn receive_data_server(
|
||||
wt_stream.unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wt_keepalive() {
|
||||
let (mut client, mut server) = connect();
|
||||
let _wt_session = create_wt_session(&mut client, &mut server);
|
||||
let idle_timeout = ConnectionParameters::default().get_idle_timeout();
|
||||
// Expect client and server to send PING after half of the idle timeout in order to keep
|
||||
// connection alive.
|
||||
assert_eq!(client.process_output(now()).callback(), idle_timeout / 2);
|
||||
assert_eq!(server.process_output(now()).callback(), idle_timeout / 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wt_client_stream_uni() {
|
||||
const BUF_CLIENT: &[u8] = &[0; 10];
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"5c1632f128048c857a1aceed231a744069576011d582a55271744f8e5d41a68e","src/decoder.rs":"4d83a4f375cd6fdd01af5e9f3ad03deb7a6362c4ad1cf56d1c693e76946ae84d","src/decoder_instructions.rs":"0e6c2036372061b16f71b172e3b6f7796683c0992f5f6a39e6c4b37d9fff349a","src/encoder.rs":"77f4229ce9cb0b466ea0cd5108bb0128824f34962d87e94f76b757ce821a281f","src/encoder_instructions.rs":"033b7aeda62f8df2cf9b09a93d449cbae74376e9f49791683543874d46f64e08","src/header_block.rs":"4285d03556b6eba3a00715c9450b00af676a3ee5f3aa07a9f4e5e33944695ee3","src/huffman.rs":"6976f1b4d3e5ef849a6b080cfb2e8804bf01cfe3b9bd9e3994a319d5405cd8f3","src/huffman_decode_helper.rs":"9ce470e318b3664f58aa109bed483ab15bfd9e0b17d261ea2b609668a42a9d80","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"f9bad0fe7643c618d034c4941ebd30ad5f6015b8b87b484b0ea79681d13d8b49","src/prefix.rs":"1655af52fcc58c27984d78af6639d66a26c2307995e7ff22eb309fd7e4d50a81","src/qlog.rs":"d8e8482624f0cc4388546169772846d37a0422ce10287ee2f716dfc5f7a56c3d","src/qpack_send_buf.rs":"c0c2bc22ffd72b0dc2fb2f6d5590fc6a2fa4a19cc32b1407e9373140cbf44414","src/reader.rs":"ae15506441a52ad522f15048796c37ad791680e3ca020a50f7c84f54ab95435e","src/static_table.rs":"6e5ec26e2b6bd63375d2d77e72748151d430d1629a8e497ec0d0ea21c078524a","src/stats.rs":"cb01723249f60e15a5cd7efd9cbab409fddc588d1df655ed06ba8c80e3d5d28e","src/table.rs":"f7aac571794f192ef4bed1dc4c1ddd96dac5553b0341a5a99ff2fadcc46d8f7d"},"package":null}
|
||||
{"files":{"Cargo.toml":"f58a82c0437489fabe141b44181a181af4f0d0ff83855d4d844c7dece45fab4f","src/decoder.rs":"5c76a8407e02999a805ecaeae0ec2743121abe1e35b75126994d52ff7deb6af7","src/decoder_instructions.rs":"addf304fbd566ca387e5111cbe25784f7f50e0112ce0372b1ad6d18185b45a02","src/encoder.rs":"b6b9e3b87d2e56c07bf8e2ca3ad1688b313dd716f2239de89cf2b54242841a7a","src/encoder_instructions.rs":"746569e9f90f07af1aa49ed93f48c3fa3c41f13cea5f0ae88485a78a43a59470","src/header_block.rs":"47ad4a03d7a78e6d2269f8e004a884cb1e001c272a206121f479e29b8446f824","src/huffman.rs":"6976f1b4d3e5ef849a6b080cfb2e8804bf01cfe3b9bd9e3994a319d5405cd8f3","src/huffman_decode_helper.rs":"9ce470e318b3664f58aa109bed483ab15bfd9e0b17d261ea2b609668a42a9d80","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"f9bad0fe7643c618d034c4941ebd30ad5f6015b8b87b484b0ea79681d13d8b49","src/prefix.rs":"d9ad12838d61b38dc2300948e3da01fd65371215edde1c370cf54ccd87d64d46","src/qlog.rs":"d8e8482624f0cc4388546169772846d37a0422ce10287ee2f716dfc5f7a56c3d","src/qpack_send_buf.rs":"48f8d0e011e0fb8e4bd0774279d3465e2be01fd9480eaf374ae2adada6be430d","src/reader.rs":"937e9db6ca4dd8d6f599e58bc2123f3b76b269b089b4e98e3922efd80861dd92","src/static_table.rs":"6e5ec26e2b6bd63375d2d77e72748151d430d1629a8e497ec0d0ea21c078524a","src/stats.rs":"624dfa3b40858c304097bb0ce5b1be1bb4d7916b1abfc222f1aa705907009730","src/table.rs":"2d2c9e6070a1e90048a4ad7c8279f9e1ce7615b44d7d8145fb0f140e554f5ca2"},"package":null}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user