Bug 1942325 - update neqo to v0.12.2 r=kershaw,necko-reviewers,supply-chain-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D234901
This commit is contained in:
@@ -105,9 +105,9 @@ git = "https://github.com/mozilla/mp4parse-rust"
|
|||||||
rev = "e64650a686e5c5732395cd059e17cfd3b1e5b63b"
|
rev = "e64650a686e5c5732395cd059e17cfd3b1e5b63b"
|
||||||
replace-with = "vendored-sources"
|
replace-with = "vendored-sources"
|
||||||
|
|
||||||
[source."git+https://github.com/mozilla/neqo?tag=v0.11.0"]
|
[source."git+https://github.com/mozilla/neqo?tag=v0.12.2"]
|
||||||
git = "https://github.com/mozilla/neqo"
|
git = "https://github.com/mozilla/neqo"
|
||||||
tag = "v0.11.0"
|
tag = "v0.12.2"
|
||||||
replace-with = "vendored-sources"
|
replace-with = "vendored-sources"
|
||||||
|
|
||||||
[source."git+https://github.com/servo/unicode-bidi?rev=ca612daf1c08c53abe07327cb3e6ef6e0a760f0c"]
|
[source."git+https://github.com/servo/unicode-bidi?rev=ca612daf1c08c53abe07327cb3e6ef6e0a760f0c"]
|
||||||
|
|||||||
48
Cargo.lock
generated
48
Cargo.lock
generated
@@ -4405,6 +4405,20 @@ dependencies = [
|
|||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mtu"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c30d3771729ec4349aae3b1a7c0b6b4a1500459e60b1fda95fe0657c3711574"
|
||||||
|
dependencies = [
|
||||||
|
"bindgen 0.69.4",
|
||||||
|
"cfg_aliases",
|
||||||
|
"libc",
|
||||||
|
"mozbuild",
|
||||||
|
"static_assertions",
|
||||||
|
"windows",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "murmurhash3"
|
name = "murmurhash3"
|
||||||
version = "0.0.5"
|
version = "0.0.5"
|
||||||
@@ -4436,8 +4450,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "neqo-bin"
|
name = "neqo-bin"
|
||||||
version = "0.11.0"
|
version = "0.12.2"
|
||||||
source = "git+https://github.com/mozilla/neqo?tag=v0.11.0#c6d5502fb5b827473e7c5d7c4c380275cdb3d931"
|
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"clap-verbosity-flag",
|
"clap-verbosity-flag",
|
||||||
@@ -4458,8 +4472,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "neqo-common"
|
name = "neqo-common"
|
||||||
version = "0.11.0"
|
version = "0.12.2"
|
||||||
source = "git+https://github.com/mozilla/neqo?tag=v0.11.0#c6d5502fb5b827473e7c5d7c4c380275cdb3d931"
|
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"enum-map",
|
"enum-map",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
@@ -4470,8 +4484,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "neqo-crypto"
|
name = "neqo-crypto"
|
||||||
version = "0.11.0"
|
version = "0.12.2"
|
||||||
source = "git+https://github.com/mozilla/neqo?tag=v0.11.0#c6d5502fb5b827473e7c5d7c4c380275cdb3d931"
|
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bindgen 0.69.4",
|
"bindgen 0.69.4",
|
||||||
"log",
|
"log",
|
||||||
@@ -4485,8 +4499,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "neqo-http3"
|
name = "neqo-http3"
|
||||||
version = "0.11.0"
|
version = "0.12.2"
|
||||||
source = "git+https://github.com/mozilla/neqo?tag=v0.11.0#c6d5502fb5b827473e7c5d7c4c380275cdb3d931"
|
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"enumset",
|
"enumset",
|
||||||
"log",
|
"log",
|
||||||
@@ -4501,8 +4515,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "neqo-qpack"
|
name = "neqo-qpack"
|
||||||
version = "0.11.0"
|
version = "0.12.2"
|
||||||
source = "git+https://github.com/mozilla/neqo?tag=v0.11.0#c6d5502fb5b827473e7c5d7c4c380275cdb3d931"
|
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"neqo-common",
|
"neqo-common",
|
||||||
@@ -4513,12 +4527,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "neqo-transport"
|
name = "neqo-transport"
|
||||||
version = "0.11.0"
|
version = "0.12.2"
|
||||||
source = "git+https://github.com/mozilla/neqo?tag=v0.11.0#c6d5502fb5b827473e7c5d7c4c380275cdb3d931"
|
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"enum-map",
|
"enum-map",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"log",
|
"log",
|
||||||
|
"mtu",
|
||||||
"neqo-common",
|
"neqo-common",
|
||||||
"neqo-crypto",
|
"neqo-crypto",
|
||||||
"qlog",
|
"qlog",
|
||||||
@@ -4528,9 +4543,10 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "neqo-udp"
|
name = "neqo-udp"
|
||||||
version = "0.11.0"
|
version = "0.12.2"
|
||||||
source = "git+https://github.com/mozilla/neqo?tag=v0.11.0#c6d5502fb5b827473e7c5d7c4c380275cdb3d931"
|
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"cfg_aliases",
|
||||||
"log",
|
"log",
|
||||||
"neqo-common",
|
"neqo-common",
|
||||||
"quinn-udp",
|
"quinn-udp",
|
||||||
@@ -5203,9 +5219,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quinn-udp"
|
name = "quinn-udp"
|
||||||
version = "0.5.9"
|
version = "0.5.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1c40286217b4ba3a71d644d752e6a0b71f13f1b6a2c5311acfcbe0c2418ed904"
|
checksum = "e46f3055866785f6b92bc6164b76be02ca8f2eb4b002c0354b28cf4c119e5944"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg_aliases",
|
"cfg_aliases",
|
||||||
"libc",
|
"libc",
|
||||||
|
|||||||
@@ -199,6 +199,7 @@ features = [
|
|||||||
version = "0.58"
|
version = "0.58"
|
||||||
optional = true
|
optional = true
|
||||||
features = [
|
features = [
|
||||||
|
"Win32_Foundation",
|
||||||
"Win32_Graphics",
|
"Win32_Graphics",
|
||||||
"Win32_Graphics_Direct3D",
|
"Win32_Graphics_Direct3D",
|
||||||
"Win32_Graphics_Direct3D12",
|
"Win32_Graphics_Direct3D12",
|
||||||
@@ -207,6 +208,9 @@ features = [
|
|||||||
"Win32_Graphics_DirectComposition",
|
"Win32_Graphics_DirectComposition",
|
||||||
"Win32_Graphics_Dxgi",
|
"Win32_Graphics_Dxgi",
|
||||||
"Win32_Graphics_Dxgi_Common",
|
"Win32_Graphics_Dxgi_Common",
|
||||||
|
"Win32_NetworkManagement_IpHelper",
|
||||||
|
"Win32_NetworkManagement_Ndis",
|
||||||
|
"Win32_Networking_WinSock",
|
||||||
"Win32_Security",
|
"Win32_Security",
|
||||||
"Win32_System",
|
"Win32_System",
|
||||||
"Win32_System_Diagnostics",
|
"Win32_System_Diagnostics",
|
||||||
|
|||||||
@@ -14629,6 +14629,13 @@
|
|||||||
value: false
|
value: false
|
||||||
mirror: always
|
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
|
# When true, a http request will be upgraded to https when HTTPS RR is
|
||||||
# available.
|
# available.
|
||||||
- name: network.dns.upgrade_with_https_rr
|
- name: network.dns.upgrade_with_https_rr
|
||||||
|
|||||||
@@ -1287,7 +1287,9 @@ networking:
|
|||||||
expires: never
|
expires: never
|
||||||
labels:
|
labels:
|
||||||
- capable
|
- capable
|
||||||
- not-capable
|
- black-hole
|
||||||
|
- bleaching
|
||||||
|
- received-unsent-ect-1
|
||||||
|
|
||||||
http_3_loss_ratio:
|
http_3_loss_ratio:
|
||||||
type: custom_distribution
|
type: custom_distribution
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ name = "neqo_glue"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
firefox-on-glean = { path = "../../../toolkit/components/glean/api" }
|
firefox-on-glean = { path = "../../../toolkit/components/glean/api" }
|
||||||
neqo-udp = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
neqo-udp = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo" }
|
||||||
neqo-http3 = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
neqo-http3 = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo" }
|
||||||
neqo-transport = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
neqo-transport = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo", features = ["gecko"] }
|
||||||
neqo-common = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
neqo-common = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo" }
|
||||||
neqo-qpack = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
neqo-qpack = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo" }
|
||||||
nserror = { path = "../../../xpcom/rust/nserror" }
|
nserror = { path = "../../../xpcom/rust/nserror" }
|
||||||
nsstring = { path = "../../../xpcom/rust/nsstring" }
|
nsstring = { path = "../../../xpcom/rust/nsstring" }
|
||||||
xpcom = { path = "../../../xpcom/rust/xpcom" }
|
xpcom = { path = "../../../xpcom/rust/xpcom" }
|
||||||
@@ -29,10 +29,11 @@ uuid = { version = "1.0", features = ["v4"] }
|
|||||||
winapi = {version = "0.3", features = ["ws2def"] }
|
winapi = {version = "0.3", features = ["ws2def"] }
|
||||||
|
|
||||||
[dependencies.neqo-crypto]
|
[dependencies.neqo-crypto]
|
||||||
tag = "v0.11.0"
|
tag = "v0.12.2"
|
||||||
git = "https://github.com/mozilla/neqo"
|
git = "https://github.com/mozilla/neqo"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["gecko"]
|
features = ["gecko"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
bench = [] # no-op, see <https://github.com/mozilla/neqo/issues/2390>
|
||||||
fuzzing = ["neqo-http3/disable-encryption"]
|
fuzzing = ["neqo-http3/disable-encryption"]
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ use winapi::shared::ws2def::{AF_INET, AF_INET6};
|
|||||||
use xpcom::{interfaces::nsISocketProvider, AtomicRefcnt, RefCounted, RefPtr};
|
use xpcom::{interfaces::nsISocketProvider, AtomicRefcnt, RefCounted, RefPtr};
|
||||||
|
|
||||||
std::thread_local! {
|
std::thread_local! {
|
||||||
static RECV_BUF: RefCell<Vec<u8>> = RefCell::new(vec![0; neqo_udp::RECV_BUF_SIZE]);
|
static RECV_BUF: RefCell<neqo_udp::RecvBuf> = RefCell::new(neqo_udp::RecvBuf::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@@ -203,10 +203,6 @@ impl NeqoHttp3Conn {
|
|||||||
let remote: SocketAddr = netaddr_to_socket_addr(remote_addr)?;
|
let remote: SocketAddr = netaddr_to_socket_addr(remote_addr)?;
|
||||||
|
|
||||||
let quic_version = match alpn_conv {
|
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,
|
"h3" => Version::Version1,
|
||||||
_ => return Err(NS_ERROR_INVALID_ARG),
|
_ => return Err(NS_ERROR_INVALID_ARG),
|
||||||
};
|
};
|
||||||
@@ -232,7 +228,8 @@ impl NeqoHttp3Conn {
|
|||||||
.cc_algorithm(cc_algorithm)
|
.cc_algorithm(cc_algorithm)
|
||||||
.max_data(max_data)
|
.max_data(max_data)
|
||||||
.max_stream_data(StreamType::BiDi, false, max_stream_data)
|
.max_stream_data(StreamType::BiDi, false, max_stream_data)
|
||||||
.grease(static_prefs::pref!("security.tls.grease_http3_enable"));
|
.grease(static_prefs::pref!("security.tls.grease_http3_enable"))
|
||||||
|
.sni_slicing(static_prefs::pref!("network.http.http3.sni-slicing"));
|
||||||
|
|
||||||
// Set a short timeout when fuzzing.
|
// Set a short timeout when fuzzing.
|
||||||
#[cfg(feature = "fuzzing")]
|
#[cfg(feature = "fuzzing")]
|
||||||
@@ -339,6 +336,7 @@ impl NeqoHttp3Conn {
|
|||||||
fn record_stats_in_glean(&self) {
|
fn record_stats_in_glean(&self) {
|
||||||
use firefox_on_glean::metrics::networking as glean;
|
use firefox_on_glean::metrics::networking as glean;
|
||||||
use neqo_common::IpTosEcn;
|
use neqo_common::IpTosEcn;
|
||||||
|
use neqo_transport::ecn;
|
||||||
|
|
||||||
// Metric values must be recorded as integers. Glean does not support
|
// Metric values must be recorded as integers. Glean does not support
|
||||||
// floating point distributions. In order to represent values <1, they
|
// floating point distributions. In order to represent values <1, they
|
||||||
@@ -395,12 +393,32 @@ impl NeqoHttp3Conn {
|
|||||||
glean::http_3_ecn_ce_ect0_ratio_received
|
glean::http_3_ecn_ce_ect0_ratio_received
|
||||||
.accumulate_single_sample_signed(ratio as i64);
|
.accumulate_single_sample_signed(ratio as i64);
|
||||||
}
|
}
|
||||||
glean::http_3_ecn_path_capability
|
for (outcome, value) in stats.ecn_path_validation.into_iter() {
|
||||||
.get(&"capable")
|
match outcome {
|
||||||
.add(stats.ecn_paths_capable as i32);
|
ecn::ValidationOutcome::Capable => {
|
||||||
glean::http_3_ecn_path_capability
|
glean::http_3_ecn_path_capability
|
||||||
.get(&"not-capable")
|
.get(&"capable")
|
||||||
.add(stats.ecn_paths_not_capable as i32);
|
.add(value as i32);
|
||||||
|
}
|
||||||
|
ecn::ValidationOutcome::NotCapable(ecn::ValidationError::BlackHole) => {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore connections into the void.
|
// Ignore connections into the void.
|
||||||
@@ -593,18 +611,15 @@ pub unsafe extern "C" fn neqo_http3conn_process_input(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if dgrams.len() == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attach metric instrumentation to `dgrams` iterator.
|
// Attach metric instrumentation to `dgrams` iterator.
|
||||||
let mut sum = 0;
|
let mut sum = 0;
|
||||||
conn.datagram_segments_received
|
let mut segment_count = 0;
|
||||||
.accumulate(dgrams.len() as u64);
|
|
||||||
let datagram_segment_size_received = &mut conn.datagram_segment_size_received;
|
let datagram_segment_size_received = &mut conn.datagram_segment_size_received;
|
||||||
let dgrams = dgrams.map(|d| {
|
let dgrams = dgrams.map(|d| {
|
||||||
datagram_segment_size_received.accumulate(d.len() as u64);
|
datagram_segment_size_received.accumulate(d.len() as u64);
|
||||||
sum += d.len();
|
sum += d.len();
|
||||||
|
segment_count += 1;
|
||||||
d
|
d
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -620,6 +635,7 @@ pub unsafe extern "C" fn neqo_http3conn_process_input(
|
|||||||
conn.conn.process_multiple_input(dgrams, Instant::now());
|
conn.conn.process_multiple_input(dgrams, Instant::now());
|
||||||
|
|
||||||
conn.datagram_size_received.accumulate(sum as u64);
|
conn.datagram_size_received.accumulate(sum as u64);
|
||||||
|
conn.datagram_segments_received.accumulate(segment_count);
|
||||||
bytes_read += sum;
|
bytes_read += sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1463,7 +1479,7 @@ pub extern "C" fn neqo_http3conn_event(
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
Http3Event::PushPromise {
|
Http3Event::PushPromise {
|
||||||
push_id,
|
push_id: push_id.into(),
|
||||||
request_stream_id: request_stream_id.as_u64(),
|
request_stream_id: request_stream_id.as_u64(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1480,16 +1496,22 @@ pub extern "C" fn neqo_http3conn_event(
|
|||||||
if res != NS_OK {
|
if res != NS_OK {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
Http3Event::PushHeaderReady { push_id, fin }
|
Http3Event::PushHeaderReady {
|
||||||
|
push_id: push_id.into(),
|
||||||
|
fin,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Http3ClientEvent::PushDataReadable { push_id } => {
|
Http3ClientEvent::PushDataReadable { push_id } => Http3Event::PushDataReadable {
|
||||||
Http3Event::PushDataReadable { push_id }
|
push_id: push_id.into(),
|
||||||
}
|
},
|
||||||
Http3ClientEvent::PushCanceled { push_id } => Http3Event::PushCanceled { push_id },
|
Http3ClientEvent::PushCanceled { push_id } => Http3Event::PushCanceled {
|
||||||
Http3ClientEvent::PushReset { push_id, error } => {
|
push_id: push_id.into(),
|
||||||
Http3Event::PushReset { push_id, error }
|
},
|
||||||
}
|
Http3ClientEvent::PushReset { push_id, error } => Http3Event::PushReset {
|
||||||
|
push_id: push_id.into(),
|
||||||
|
error,
|
||||||
|
},
|
||||||
Http3ClientEvent::RequestsCreatable => Http3Event::RequestsCreatable,
|
Http3ClientEvent::RequestsCreatable => Http3Event::RequestsCreatable,
|
||||||
Http3ClientEvent::AuthenticationNeeded => Http3Event::AuthenticationNeeded,
|
Http3ClientEvent::AuthenticationNeeded => Http3Event::AuthenticationNeeded,
|
||||||
Http3ClientEvent::ZeroRttRejected => Http3Event::ZeroRttRejected,
|
Http3ClientEvent::ZeroRttRejected => Http3Event::ZeroRttRejected,
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ edition = "2018"
|
|||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
neqo-bin = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
neqo-bin = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo" }
|
||||||
neqo-transport = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
neqo-transport = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo", features = ["gecko"] }
|
||||||
neqo-common = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
neqo-common = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo" }
|
||||||
neqo-http3 = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
neqo-http3 = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo" }
|
||||||
neqo-qpack = { tag = "v0.11.0", git = "https://github.com/mozilla/neqo" }
|
neqo-qpack = { tag = "v0.12.2", git = "https://github.com/mozilla/neqo" }
|
||||||
log = "0.4.0"
|
log = "0.4.0"
|
||||||
base64 = "0.21"
|
base64 = "0.21"
|
||||||
cfg-if = "1.0"
|
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 }
|
mozilla-central-workspace-hack = { version = "0.1", features = ["http3server"], optional = true }
|
||||||
|
|
||||||
[dependencies.neqo-crypto]
|
[dependencies.neqo-crypto]
|
||||||
tag = "v0.11.0"
|
tag = "v0.12.2"
|
||||||
git = "https://github.com/mozilla/neqo"
|
git = "https://github.com/mozilla/neqo"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["gecko"]
|
features = ["gecko"]
|
||||||
@@ -32,3 +32,6 @@ bindgen = {version = "0.69", default-features = false, features = ["runtime"] }
|
|||||||
[[bin]]
|
[[bin]]
|
||||||
name = "http3server"
|
name = "http3server"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
bench = [] # no-op, see <https://github.com/mozilla/neqo/issues/2390>
|
||||||
|
|||||||
@@ -1227,3 +1227,5 @@ extern "C" fn __tsan_default_suppressions() -> *const std::os::raw::c_char {
|
|||||||
extern "C" {}
|
extern "C" {}
|
||||||
#[cfg_attr(target_os = "windows", link(name = "propsys"))]
|
#[cfg_attr(target_os = "windows", link(name = "propsys"))]
|
||||||
extern "C" {}
|
extern "C" {}
|
||||||
|
#[cfg_attr(target_os = "windows", link(name = "iphlpapi"))]
|
||||||
|
extern "C" {}
|
||||||
|
|||||||
@@ -3399,6 +3399,16 @@ criteria = "safe-to-deploy"
|
|||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
notes = "Developed by Mozilla staff."
|
notes = "Developed by Mozilla staff."
|
||||||
|
|
||||||
|
[[audits.mtu]]
|
||||||
|
who = "Max Inden <mail@max-inden.de>"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
version = "0.2.5"
|
||||||
|
|
||||||
|
[[audits.mtu]]
|
||||||
|
who = "Max Leonard Inden <mail@max-inden.de>"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
delta = "0.2.5 -> 0.2.6"
|
||||||
|
|
||||||
[[audits.naga]]
|
[[audits.naga]]
|
||||||
who = "Dzmitry Malyshau <kvark@fastmail.com>"
|
who = "Dzmitry Malyshau <kvark@fastmail.com>"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
@@ -4049,6 +4059,11 @@ who = "Max Inden <mail@max-inden.de>"
|
|||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
delta = "0.5.8 -> 0.5.9"
|
delta = "0.5.8 -> 0.5.9"
|
||||||
|
|
||||||
|
[[audits.quinn-udp]]
|
||||||
|
who = "Max Leonard Inden <mail@max-inden.de>"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
delta = "0.5.9 -> 0.5.10"
|
||||||
|
|
||||||
[[audits.quote]]
|
[[audits.quote]]
|
||||||
who = "Nika Layzell <nika@thelayzells.com>"
|
who = "Nika Layzell <nika@thelayzells.com>"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
|
|||||||
1
third_party/rust/mtu/.cargo-checksum.json
vendored
Normal file
1
third_party/rust/mtu/.cargo-checksum.json
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"files":{"CODE_OF_CONDUCT.md":"f7b4cba1deaa0a77bd611c04c84ef5b6859e44c8370f7513fe688fb9531b913b","Cargo.lock":"0d7b4f80f302400b5fba9847542ab3a0e94dd50bb0d27111927a6e4037b42eef","Cargo.toml":"82ab8662dd7a9c324bd23a7234fa2b8d6df9a9cab2b9baa778039bb55666bfb8","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"4ad721b5b6a3d39ca3e2202f403d897c4a1d42896486dd58963a81f8e64ef61d","README.md":"2c9cce2eb06f0897e9b2fb68d8fa640da581bf440c26f266f8af5b3edb02dc6a","SECURITY.md":"75455814b6cf997e22a927eb979b4356d788583aa1eb96e90853aaab0f82ad1b","build.rs":"c26ac0385171924eefec5ce864067419bb023961b054abaf060d8da567dc6241","src/bsd.rs":"e680ddb399419bb67219fa1c0d3e6672d32023f325584869bd050e2f2ecc8ff9","src/lib.rs":"a59ae67763bc6bb9e6a4f7e7af61fed722ca032b667276a68e6ad687f1fe1e6e","src/linux.rs":"4e99612a04d744e2ca22b2e353faa500b37cb58caddaecb7566b4748aa1f7209","src/routesocket.rs":"be837947e2c3f9301a174499217fe8920ff492918bf85ca5eb281eb7ad2240e1","src/windows.rs":"b139c7aaa0c39415ce1773f1c9569be1a6b82dfe82334ab0c6cb80e7d232363e"},"package":"4c30d3771729ec4349aae3b1a7c0b6b4a1500459e60b1fda95fe0657c3711574"}
|
||||||
18
third_party/rust/mtu/CODE_OF_CONDUCT.md
vendored
Normal file
18
third_party/rust/mtu/CODE_OF_CONDUCT.md
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# 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
Normal file
369
third_party/rust/mtu/Cargo.lock
generated
vendored
Normal file
@@ -0,0 +1,369 @@
|
|||||||
|
# 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.6"
|
||||||
|
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
Normal file
139
third_party/rust/mtu/Cargo.toml
vendored
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
# 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.6"
|
||||||
|
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
Normal file
201
third_party/rust/mtu/LICENSE-APACHE
vendored
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
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
Normal file
25
third_party/rust/mtu/LICENSE-MIT
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
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
Normal file
46
third_party/rust/mtu/README.md
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
[](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
Normal file
31
third_party/rust/mtu/SECURITY.md
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# 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.
|
||||||
112
third_party/rust/mtu/build.rs
vendored
Normal file
112
third_party/rust/mtu/build.rs
vendored
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
// 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");
|
||||||
|
|
||||||
|
// Platforms currently not supported.
|
||||||
|
//
|
||||||
|
// See <https://github.com/mozilla/mtu/issues/82>.
|
||||||
|
if matches!(target_os.as_str(), "ios" | "tvos" | "visionos") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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! {
|
||||||
|
bsd: {
|
||||||
|
any(
|
||||||
|
target_os = "freebsd",
|
||||||
|
target_os = "openbsd",
|
||||||
|
target_os = "netbsd",
|
||||||
|
target_os = "solaris"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bindgen();
|
||||||
|
}
|
||||||
358
third_party/rust/mtu/src/bsd.rs
vendored
Normal file
358
third_party/rust/mtu/src/bsd.rs
vendored
Normal file
@@ -0,0 +1,358 @@
|
|||||||
|
// 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(target_os = "macos")]
|
||||||
|
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(target_os = "macos", 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)?))
|
||||||
|
}
|
||||||
199
third_party/rust/mtu/src/lib.rs
vendored
Normal file
199
third_party/rust/mtu/src/lib.rs
vendored
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
// 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(target_os = "macos", 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(target_os = "macos", 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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Platforms currently not supported.
|
||||||
|
//
|
||||||
|
// See <https://github.com/mozilla/mtu/issues/82>.
|
||||||
|
#[cfg(any(target_os = "ios", target_os = "tvos", target_os = "visionos"))]
|
||||||
|
pub fn interface_and_mtu_impl(remote: IpAddr) -> Result<(String, usize)> {
|
||||||
|
return Err(default_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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(target_os = "macos", 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
Normal file
351
third_party/rust/mtu/src/linux.rs
vendored
Normal file
@@ -0,0 +1,351 @@
|
|||||||
|
// 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
Normal file
81
third_party/rust/mtu/src/routesocket.rs
vendored
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
// 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
Normal file
143
third_party/rust/mtu/src/windows.rs
vendored
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
// 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":"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}
|
{"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}
|
||||||
60
third_party/rust/neqo-bin/Cargo.toml
vendored
60
third_party/rust/neqo-bin/Cargo.toml
vendored
@@ -13,7 +13,7 @@
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.76.0"
|
rust-version = "1.76.0"
|
||||||
name = "neqo-bin"
|
name = "neqo-bin"
|
||||||
version = "0.11.0"
|
version = "0.12.2"
|
||||||
authors = ["The Neqo Authors <necko@mozilla.com>"]
|
authors = ["The Neqo Authors <necko@mozilla.com>"]
|
||||||
build = false
|
build = false
|
||||||
autolib = false
|
autolib = false
|
||||||
@@ -39,6 +39,9 @@ categories = [
|
|||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
repository = "https://github.com/mozilla/neqo/"
|
repository = "https://github.com/mozilla/neqo/"
|
||||||
|
|
||||||
|
[package.metadata.cargo-machete]
|
||||||
|
ignored = ["log"]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "neqo_bin"
|
name = "neqo_bin"
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
@@ -112,7 +115,10 @@ default-features = false
|
|||||||
|
|
||||||
[dependencies.quinn-udp]
|
[dependencies.quinn-udp]
|
||||||
version = "0.5.6"
|
version = "0.5.6"
|
||||||
features = ["direct-log"]
|
features = [
|
||||||
|
"direct-log",
|
||||||
|
"fast-apple-datapath",
|
||||||
|
]
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
||||||
[dependencies.regex]
|
[dependencies.regex]
|
||||||
@@ -141,16 +147,48 @@ version = "0.5"
|
|||||||
features = ["async_tokio"]
|
features = ["async_tokio"]
|
||||||
default-features = false
|
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]
|
[dev-dependencies.tokio]
|
||||||
version = "1"
|
version = "1"
|
||||||
features = ["sync"]
|
features = ["sync"]
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
bench = ["neqo-transport/bench"]
|
bench = [
|
||||||
|
"neqo-bin/bench",
|
||||||
|
"neqo-http3/bench",
|
||||||
|
"neqo-transport/bench",
|
||||||
|
]
|
||||||
|
draft-29 = []
|
||||||
|
|
||||||
[lints.clippy]
|
[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_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]
|
[lints.clippy.cargo]
|
||||||
level = "warn"
|
level = "warn"
|
||||||
@@ -163,3 +201,19 @@ priority = -1
|
|||||||
[lints.clippy.pedantic]
|
[lints.clippy.pedantic]
|
||||||
level = "warn"
|
level = "warn"
|
||||||
priority = -1
|
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
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::{env, path::PathBuf, str::FromStr};
|
use std::{env, path::PathBuf, str::FromStr as _};
|
||||||
|
|
||||||
use criterion::{criterion_group, criterion_main, BatchSize, Criterion, Throughput};
|
use criterion::{criterion_group, criterion_main, BatchSize, Criterion, Throughput};
|
||||||
use neqo_bin::{client, server};
|
use neqo_bin::{client, server};
|
||||||
@@ -17,7 +17,6 @@ struct Benchmark {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn transfer(c: &mut Criterion) {
|
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();
|
neqo_crypto::init_db(PathBuf::from_str("../test-fixture/db").unwrap()).unwrap();
|
||||||
|
|
||||||
let done_sender = spawn_server();
|
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
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser as _;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), neqo_bin::client::Error> {
|
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
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser as _;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), neqo_bin::server::Error> {
|
async fn main() -> Result<(), neqo_bin::server::Error> {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use std::{
|
|||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::{HashMap, VecDeque},
|
collections::{HashMap, VecDeque},
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{BufWriter, Write},
|
io::{BufWriter, Write as _},
|
||||||
net::SocketAddr,
|
net::SocketAddr,
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
@@ -61,7 +61,7 @@ impl super::Handler for Handler<'_> {
|
|||||||
self.needs_key_update = false;
|
self.needs_key_update = false;
|
||||||
self.download_urls(client);
|
self.download_urls(client);
|
||||||
}
|
}
|
||||||
Err(neqo_transport::Error::KeyUpdateBlocked) => (),
|
Err(Error::KeyUpdateBlocked) => (),
|
||||||
Err(e) => return Err(e.into()),
|
Err(e) => return Err(e.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,7 +213,7 @@ impl super::Client for Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn has_events(&self) -> bool {
|
fn has_events(&self) -> bool {
|
||||||
neqo_common::event::Provider::has_events(self)
|
Provider::has_events(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,8 +301,7 @@ impl<'b> Handler<'b> {
|
|||||||
qdebug!("READ[{stream_id}]: {} bytes", read_buffer.len());
|
qdebug!("READ[{stream_id}]: {} bytes", read_buffer.len());
|
||||||
} else {
|
} else {
|
||||||
qdebug!(
|
qdebug!(
|
||||||
"READ[{}]: {}",
|
"READ[{stream_id}]: {}",
|
||||||
stream_id,
|
|
||||||
std::str::from_utf8(read_buffer).unwrap()
|
std::str::from_utf8(read_buffer).unwrap()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use std::{
|
|||||||
collections::{HashMap, VecDeque},
|
collections::{HashMap, VecDeque},
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{BufWriter, Write},
|
io::{BufWriter, Write as _},
|
||||||
net::SocketAddr,
|
net::SocketAddr,
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
@@ -155,7 +155,7 @@ impl super::Client for Http3Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn has_events(&self) -> bool {
|
fn has_events(&self) -> bool {
|
||||||
neqo_common::event::Provider::has_events(self)
|
Provider::has_events(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,7 +302,7 @@ impl StreamHandler for DownloadStreamHandler {
|
|||||||
} else if let Ok(txt) = std::str::from_utf8(data) {
|
} else if let Ok(txt) = std::str::from_utf8(data) {
|
||||||
qdebug!("READ[{stream_id}]: {txt}");
|
qdebug!("READ[{stream_id}]: {txt}");
|
||||||
} else {
|
} else {
|
||||||
qdebug!("READ[{}]: 0x{}", stream_id, hex(data));
|
qdebug!("READ[{stream_id}]: 0x{}", hex(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
if fin {
|
if fin {
|
||||||
@@ -344,7 +344,7 @@ impl StreamHandler for UploadStreamHandler {
|
|||||||
qinfo!("Stream ID: {stream_id:?}, Upload time: {upload_time:?}");
|
qinfo!("Stream ID: {stream_id:?}, Upload time: {upload_time:?}");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic!("Unexpected data [{}]: 0x{}", stream_id, hex(data));
|
panic!("Unexpected data [{stream_id}]: 0x{}", hex(data));
|
||||||
}
|
}
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|||||||
64
third_party/rust/neqo-bin/src/client/mod.rs
vendored
64
third_party/rust/neqo-bin/src/client/mod.rs
vendored
@@ -11,7 +11,7 @@ use std::{
|
|||||||
fmt::{self, Display},
|
fmt::{self, Display},
|
||||||
fs::{create_dir_all, File, OpenOptions},
|
fs::{create_dir_all, File, OpenOptions},
|
||||||
io::{self, BufWriter},
|
io::{self, BufWriter},
|
||||||
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs},
|
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs as _},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
process::exit,
|
process::exit,
|
||||||
@@ -21,7 +21,7 @@ use std::{
|
|||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use futures::{
|
use futures::{
|
||||||
future::{select, Either},
|
future::{select, Either},
|
||||||
FutureExt, TryFutureExt,
|
FutureExt as _, TryFutureExt as _,
|
||||||
};
|
};
|
||||||
use neqo_common::{qdebug, qerror, qinfo, qlog::NeqoQlog, qwarn, Datagram, Role};
|
use neqo_common::{qdebug, qerror, qinfo, qlog::NeqoQlog, qwarn, Datagram, Role};
|
||||||
use neqo_crypto::{
|
use neqo_crypto::{
|
||||||
@@ -30,6 +30,7 @@ use neqo_crypto::{
|
|||||||
};
|
};
|
||||||
use neqo_http3::Output;
|
use neqo_http3::Output;
|
||||||
use neqo_transport::{AppError, CloseReason, ConnectionId, Version};
|
use neqo_transport::{AppError, CloseReason, ConnectionId, Version};
|
||||||
|
use neqo_udp::RecvBuf;
|
||||||
use tokio::time::Sleep;
|
use tokio::time::Sleep;
|
||||||
use url::{Host, Origin, Url};
|
use url::{Host, Origin, Url};
|
||||||
|
|
||||||
@@ -47,7 +48,7 @@ pub enum Error {
|
|||||||
IoError(io::Error),
|
IoError(io::Error),
|
||||||
QlogError(qlog::Error),
|
QlogError(qlog::Error),
|
||||||
TransportError(neqo_transport::Error),
|
TransportError(neqo_transport::Error),
|
||||||
ApplicationError(neqo_transport::AppError),
|
ApplicationError(AppError),
|
||||||
CryptoError(neqo_crypto::Error),
|
CryptoError(neqo_crypto::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,8 +82,8 @@ impl From<neqo_transport::Error> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<neqo_transport::CloseReason> for Error {
|
impl From<CloseReason> for Error {
|
||||||
fn from(err: neqo_transport::CloseReason) -> Self {
|
fn from(err: CloseReason) -> Self {
|
||||||
match err {
|
match err {
|
||||||
CloseReason::Transport(e) => Self::TransportError(e),
|
CloseReason::Transport(e) => Self::TransportError(e),
|
||||||
CloseReason::Application(e) => Self::ApplicationError(e),
|
CloseReason::Application(e) => Self::ApplicationError(e),
|
||||||
@@ -181,9 +182,9 @@ impl Args {
|
|||||||
#[cfg(any(test, feature = "bench"))]
|
#[cfg(any(test, feature = "bench"))]
|
||||||
#[allow(clippy::missing_panics_doc)]
|
#[allow(clippy::missing_panics_doc)]
|
||||||
pub fn new(requests: &[usize], upload: bool) -> Self {
|
pub fn new(requests: &[usize], upload: bool) -> Self {
|
||||||
use std::str::FromStr;
|
use std::str::FromStr as _;
|
||||||
Self {
|
Self {
|
||||||
shared: crate::SharedArgs::default(),
|
shared: SharedArgs::default(),
|
||||||
urls: requests
|
urls: requests
|
||||||
.iter()
|
.iter()
|
||||||
.map(|r| Url::from_str(&format!("http://[::1]:12345/{r}")).unwrap())
|
.map(|r| Url::from_str(&format!("http://[::1]:12345/{r}")).unwrap())
|
||||||
@@ -238,10 +239,14 @@ impl Args {
|
|||||||
// Only use v1 for most QNS tests.
|
// Only use v1 for most QNS tests.
|
||||||
self.shared.quic_parameters.quic_version = vec![Version::Version1];
|
self.shared.quic_parameters.quic_version = vec![Version::Version1];
|
||||||
// This is the default for all tests except http3.
|
// This is the default for all tests except http3.
|
||||||
self.shared.use_old_http = true;
|
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;
|
||||||
match testcase.as_str() {
|
match testcase.as_str() {
|
||||||
"http3" => {
|
"http3" => {
|
||||||
self.shared.use_old_http = false;
|
self.shared.quic_parameters.no_sni_slicing = false;
|
||||||
|
self.shared.alpn = String::from("h3");
|
||||||
if let Some(testcase) = &self.test {
|
if let Some(testcase) = &self.test {
|
||||||
if testcase.as_str() != "upload" {
|
if testcase.as_str() != "upload" {
|
||||||
qerror!("Unsupported test case: {testcase}");
|
qerror!("Unsupported test case: {testcase}");
|
||||||
@@ -264,6 +269,7 @@ impl Args {
|
|||||||
qerror!("Warning: zerortt test won't work without >1 URL");
|
qerror!("Warning: zerortt test won't work without >1 URL");
|
||||||
exit(127);
|
exit(127);
|
||||||
}
|
}
|
||||||
|
self.shared.quic_parameters.no_sni_slicing = false;
|
||||||
self.resume = true;
|
self.resume = true;
|
||||||
// PMTUD probes inflate what we sent in 1-RTT, causing QNS to fail the test.
|
// PMTUD probes inflate what we sent in 1-RTT, causing QNS to fail the test.
|
||||||
self.shared.quic_parameters.no_pmtud = true;
|
self.shared.quic_parameters.no_pmtud = true;
|
||||||
@@ -284,6 +290,7 @@ impl Args {
|
|||||||
self.key_update = true;
|
self.key_update = true;
|
||||||
}
|
}
|
||||||
"v2" => {
|
"v2" => {
|
||||||
|
self.shared.quic_parameters.no_sni_slicing = false;
|
||||||
// Use default version set for this test (which allows compatible vneg.)
|
// Use default version set for this test (which allows compatible vneg.)
|
||||||
self.shared.quic_parameters.quic_version.clear();
|
self.shared.quic_parameters.quic_version.clear();
|
||||||
}
|
}
|
||||||
@@ -394,7 +401,7 @@ struct Runner<'a, H: Handler> {
|
|||||||
handler: H,
|
handler: H,
|
||||||
timeout: Option<Pin<Box<Sleep>>>,
|
timeout: Option<Pin<Box<Sleep>>>,
|
||||||
args: &'a Args,
|
args: &'a Args,
|
||||||
recv_buf: Vec<u8>,
|
recv_buf: RecvBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, H: Handler> Runner<'a, H> {
|
impl<'a, H: Handler> Runner<'a, H> {
|
||||||
@@ -412,7 +419,7 @@ impl<'a, H: Handler> Runner<'a, H> {
|
|||||||
handler,
|
handler,
|
||||||
args,
|
args,
|
||||||
timeout: None,
|
timeout: None,
|
||||||
recv_buf: vec![0; neqo_udp::RECV_BUF_SIZE],
|
recv_buf: RecvBuf::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -462,7 +469,7 @@ impl<'a, H: Handler> Runner<'a, H> {
|
|||||||
self.socket.send(&dgram)?;
|
self.socket.send(&dgram)?;
|
||||||
}
|
}
|
||||||
Output::Callback(new_timeout) => {
|
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)));
|
self.timeout = Some(Box::pin(tokio::time::sleep(new_timeout)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -481,9 +488,6 @@ impl<'a, H: Handler> Runner<'a, H> {
|
|||||||
let Some(dgrams) = self.socket.recv(self.local_addr, &mut self.recv_buf)? else {
|
let Some(dgrams) = self.socket.recv(self.local_addr, &mut self.recv_buf)? else {
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
if dgrams.len() == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
self.client.process_multiple_input(dgrams, Instant::now());
|
self.client.process_multiple_input(dgrams, Instant::now());
|
||||||
self.process_output().await?;
|
self.process_output().await?;
|
||||||
}
|
}
|
||||||
@@ -508,9 +512,9 @@ fn qlog_new(args: &Args, hostname: &str, cid: &ConnectionId) -> Res<NeqoQlog> {
|
|||||||
NeqoQlog::enabled_with_file(
|
NeqoQlog::enabled_with_file(
|
||||||
qlog_dir,
|
qlog_dir,
|
||||||
Role::Client,
|
Role::Client,
|
||||||
Some("Example qlog".to_string()),
|
Some("Neqo client qlog".to_string()),
|
||||||
Some("Example qlog description".to_string()),
|
Some("Neqo client qlog".to_string()),
|
||||||
format!("{hostname}-{cid}"),
|
format!("client-{hostname}-{cid}"),
|
||||||
)
|
)
|
||||||
.map_err(Error::QlogError)
|
.map_err(Error::QlogError)
|
||||||
}
|
}
|
||||||
@@ -553,7 +557,7 @@ pub async fn client(mut args: Args) -> Res<()> {
|
|||||||
|
|
||||||
for ((host, port), mut urls) in urls_by_origin(&args.urls) {
|
for ((host, port), mut urls) in urls_by_origin(&args.urls) {
|
||||||
if args.resume && urls.len() < 2 {
|
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);
|
exit(127);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,10 +574,8 @@ pub async fn client(mut args: Args) -> Res<()> {
|
|||||||
let mut socket = crate::udp::Socket::bind(local_addr_for(&remote_addr, 0))?;
|
let mut socket = crate::udp::Socket::bind(local_addr_for(&remote_addr, 0))?;
|
||||||
let real_local = socket.local_addr().unwrap();
|
let real_local = socket.local_addr().unwrap();
|
||||||
qinfo!(
|
qinfo!(
|
||||||
"{} Client connecting: {:?} -> {:?}",
|
"{} Client connecting: {real_local:?} -> {remote_addr:?}",
|
||||||
if args.shared.use_old_http { "H9" } else { "H3" },
|
args.shared.alpn
|
||||||
real_local,
|
|
||||||
remote_addr,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let hostname = format!("{host}");
|
let hostname = format!("{host}");
|
||||||
@@ -588,21 +590,21 @@ pub async fn client(mut args: Args) -> Res<()> {
|
|||||||
|
|
||||||
first = false;
|
first = false;
|
||||||
|
|
||||||
token = if args.shared.use_old_http {
|
token = if args.shared.alpn == "h3" {
|
||||||
let client =
|
let client = http3::create_client(&args, real_local, remote_addr, &hostname, token)
|
||||||
http09::create_client(&args, real_local, remote_addr, &hostname, token)
|
.expect("failed to create client");
|
||||||
.expect("failed to create client");
|
|
||||||
|
|
||||||
let handler = http09::Handler::new(to_request, &args);
|
let handler = http3::Handler::new(to_request, &args);
|
||||||
|
|
||||||
Runner::new(real_local, &mut socket, client, handler, &args)
|
Runner::new(real_local, &mut socket, client, handler, &args)
|
||||||
.run()
|
.run()
|
||||||
.await?
|
.await?
|
||||||
} else {
|
} else {
|
||||||
let client = http3::create_client(&args, real_local, remote_addr, &hostname, token)
|
let client =
|
||||||
.expect("failed to create client");
|
http09::create_client(&args, real_local, remote_addr, &hostname, token)
|
||||||
|
.expect("failed to create client");
|
||||||
|
|
||||||
let handler = http3::Handler::new(to_request, &args);
|
let handler = http09::Handler::new(to_request, &args);
|
||||||
|
|
||||||
Runner::new(real_local, &mut socket, client, handler, &args)
|
Runner::new(real_local, &mut socket, client, handler, &args)
|
||||||
.run()
|
.run()
|
||||||
|
|||||||
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::{
|
use std::{
|
||||||
fmt::{self, Display},
|
fmt::{self, Display},
|
||||||
net::{SocketAddr, ToSocketAddrs},
|
net::{SocketAddr, ToSocketAddrs as _},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
@@ -63,10 +63,6 @@ pub struct SharedArgs {
|
|||||||
/// Enable special behavior for use with QUIC Network Simulator
|
/// Enable special behavior for use with QUIC Network Simulator
|
||||||
pub qns_test: Option<String>,
|
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)]
|
#[command(flatten)]
|
||||||
pub quic_parameters: QuicParameters,
|
pub quic_parameters: QuicParameters,
|
||||||
}
|
}
|
||||||
@@ -83,7 +79,6 @@ impl Default for SharedArgs {
|
|||||||
max_blocked_streams: 10,
|
max_blocked_streams: 10,
|
||||||
ciphers: vec![],
|
ciphers: vec![],
|
||||||
qns_test: None,
|
qns_test: None,
|
||||||
use_old_http: false,
|
|
||||||
quic_parameters: QuicParameters::default(),
|
quic_parameters: QuicParameters::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,7 +112,7 @@ pub struct QuicParameters {
|
|||||||
/// The idle timeout for connections, in seconds.
|
/// The idle timeout for connections, in seconds.
|
||||||
pub idle_timeout: u64,
|
pub idle_timeout: u64,
|
||||||
|
|
||||||
#[arg(long = "cc", default_value = "newreno")]
|
#[arg(long = "cc", default_value = "cubic")]
|
||||||
/// The congestion controller to use.
|
/// The congestion controller to use.
|
||||||
pub congestion_control: CongestionControlAlgorithm,
|
pub congestion_control: CongestionControlAlgorithm,
|
||||||
|
|
||||||
@@ -129,6 +124,10 @@ pub struct QuicParameters {
|
|||||||
/// Whether to disable path MTU discovery.
|
/// Whether to disable path MTU discovery.
|
||||||
pub no_pmtud: bool,
|
pub no_pmtud: bool,
|
||||||
|
|
||||||
|
#[arg(long)]
|
||||||
|
/// Whether to slice the SNI.
|
||||||
|
pub no_sni_slicing: bool,
|
||||||
|
|
||||||
#[arg(name = "preferred-address-v4", long)]
|
#[arg(name = "preferred-address-v4", long)]
|
||||||
/// An IPv4 address for the server preferred address.
|
/// An IPv4 address for the server preferred address.
|
||||||
pub preferred_address_v4: Option<String>,
|
pub preferred_address_v4: Option<String>,
|
||||||
@@ -146,11 +145,12 @@ impl Default for QuicParameters {
|
|||||||
max_streams_bidi: 16,
|
max_streams_bidi: 16,
|
||||||
max_streams_uni: 16,
|
max_streams_uni: 16,
|
||||||
idle_timeout: 30,
|
idle_timeout: 30,
|
||||||
congestion_control: CongestionControlAlgorithm::NewReno,
|
congestion_control: CongestionControlAlgorithm::Cubic,
|
||||||
no_pacing: false,
|
no_pacing: false,
|
||||||
no_pmtud: false,
|
no_pmtud: false,
|
||||||
preferred_address_v4: None,
|
preferred_address_v4: None,
|
||||||
preferred_address_v6: None,
|
preferred_address_v6: None,
|
||||||
|
no_sni_slicing: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,9 +168,8 @@ impl QuicParameters {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
opt.is_some(),
|
opt.is_some(),
|
||||||
addr.is_some(),
|
addr.is_some(),
|
||||||
"unable to resolve '{}' to an {} address",
|
"unable to resolve '{}' to an {v} address",
|
||||||
opt.as_ref().unwrap(),
|
opt.as_ref().unwrap(),
|
||||||
v,
|
|
||||||
);
|
);
|
||||||
addr
|
addr
|
||||||
}
|
}
|
||||||
@@ -224,7 +223,8 @@ impl QuicParameters {
|
|||||||
.idle_timeout(Duration::from_secs(self.idle_timeout))
|
.idle_timeout(Duration::from_secs(self.idle_timeout))
|
||||||
.cc_algorithm(self.congestion_control)
|
.cc_algorithm(self.congestion_control)
|
||||||
.pacing(!self.no_pacing)
|
.pacing(!self.no_pacing)
|
||||||
.pmtud(!self.no_pmtud);
|
.pmtud(!self.no_pmtud)
|
||||||
|
.sni_slicing(!self.no_sni_slicing);
|
||||||
params = if let Some(pa) = self.preferred_address() {
|
params = if let Some(pa) = self.preferred_address() {
|
||||||
params.preferred_address(pa)
|
params.preferred_address(pa)
|
||||||
} else {
|
} else {
|
||||||
@@ -240,10 +240,8 @@ impl QuicParameters {
|
|||||||
} else {
|
} else {
|
||||||
let version = match alpn {
|
let version = match alpn {
|
||||||
"h3" | "hq-interop" => Version::Version1,
|
"h3" | "hq-interop" => Version::Version1,
|
||||||
|
#[cfg(feature = "draft-29")]
|
||||||
"h3-29" | "hq-29" => Version::Draft29,
|
"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(),
|
_ => Version::default(),
|
||||||
};
|
};
|
||||||
params.versions(version, Version::all())
|
params.versions(version, Version::all())
|
||||||
@@ -273,7 +271,7 @@ impl std::error::Error for Error {}
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::{fs, path::PathBuf, str::FromStr, time::SystemTime};
|
use std::{fs, path::PathBuf, str::FromStr as _, time::SystemTime};
|
||||||
|
|
||||||
use crate::{client, server};
|
use crate::{client, server};
|
||||||
|
|
||||||
@@ -283,15 +281,14 @@ mod tests {
|
|||||||
|
|
||||||
impl TempDir {
|
impl TempDir {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
let mut dir = std::env::temp_dir();
|
let dir = std::env::temp_dir().join(format!(
|
||||||
dir.push(format!(
|
|
||||||
"neqo-bin-test-{}",
|
"neqo-bin-test-{}",
|
||||||
SystemTime::now()
|
SystemTime::now()
|
||||||
.duration_since(SystemTime::UNIX_EPOCH)
|
.duration_since(SystemTime::UNIX_EPOCH)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_secs()
|
.as_secs()
|
||||||
));
|
));
|
||||||
fs::create_dir(&dir).unwrap();
|
fs::create_dir_all(&dir).unwrap();
|
||||||
Self { path: dir }
|
Self { path: dir }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
use std::{borrow::Cow, cell::RefCell, collections::HashMap, fmt::Display, rc::Rc, time::Instant};
|
use std::{borrow::Cow, cell::RefCell, collections::HashMap, fmt::Display, rc::Rc, time::Instant};
|
||||||
|
|
||||||
use neqo_common::{event::Provider, hex, qdebug, qerror, qinfo, qwarn, Datagram};
|
use neqo_common::{event::Provider as _, hex, qdebug, qerror, qinfo, qwarn, Datagram};
|
||||||
use neqo_crypto::{generate_ech_keys, random, AllowZeroRtt, AntiReplay};
|
use neqo_crypto::{generate_ech_keys, random, AllowZeroRtt, AntiReplay};
|
||||||
use neqo_http3::Error;
|
use neqo_http3::Error;
|
||||||
use neqo_transport::{
|
use neqo_transport::{
|
||||||
@@ -82,17 +82,17 @@ impl HttpServer {
|
|||||||
let url_dbg = String::from_utf8(partial.clone())
|
let url_dbg = String::from_utf8(partial.clone())
|
||||||
.unwrap_or_else(|_| format!("<invalid UTF-8: {}>", hex(&partial)));
|
.unwrap_or_else(|_| format!("<invalid UTF-8: {}>", hex(&partial)));
|
||||||
if partial.len() < 4096 {
|
if partial.len() < 4096 {
|
||||||
qdebug!("Saving partial URL: {}", url_dbg);
|
qdebug!("Saving partial URL: {url_dbg}");
|
||||||
self.read_state.insert(stream_id, partial);
|
self.read_state.insert(stream_id, partial);
|
||||||
} else {
|
} 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();
|
conn.borrow_mut().stream_stop_sending(stream_id, 0).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stream_readable(&mut self, stream_id: StreamId, conn: &ConnectionRef) {
|
fn stream_readable(&mut self, stream_id: StreamId, conn: &ConnectionRef) {
|
||||||
if !stream_id.is_client_initiated() || !stream_id.is_bidi() {
|
if !stream_id.is_client_initiated() || !stream_id.is_bidi() {
|
||||||
qdebug!("Stream {} not client-initiated bidi, ignoring", stream_id);
|
qdebug!("Stream {stream_id} not client-initiated bidi, ignoring");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let (sz, fin) = conn
|
let (sz, fin) = conn
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use std::{
|
|||||||
time::Instant,
|
time::Instant,
|
||||||
};
|
};
|
||||||
|
|
||||||
use neqo_common::{hex, qdebug, qerror, qinfo, Datagram, Header};
|
use neqo_common::{header::HeadersExt as _, hex, qdebug, qerror, qinfo, Datagram, Header};
|
||||||
use neqo_crypto::{generate_ech_keys, random, AntiReplay};
|
use neqo_crypto::{generate_ech_keys, random, AntiReplay};
|
||||||
use neqo_http3::{
|
use neqo_http3::{
|
||||||
Http3OrWebTransportStream, Http3Parameters, Http3Server, Http3ServerEvent, StreamId,
|
Http3OrWebTransportStream, Http3Parameters, Http3Server, Http3ServerEvent, StreamId,
|
||||||
@@ -94,15 +94,12 @@ impl super::HttpServer for HttpServer {
|
|||||||
} => {
|
} => {
|
||||||
qdebug!("Headers (request={stream} fin={fin}): {headers:?}");
|
qdebug!("Headers (request={stream} fin={fin}): {headers:?}");
|
||||||
|
|
||||||
if headers
|
if headers.contains_header(":method", "POST") {
|
||||||
.iter()
|
|
||||||
.any(|h| h.name() == ":method" && h.value() == "POST")
|
|
||||||
{
|
|
||||||
self.posts.insert(stream, 0);
|
self.posts.insert(stream, 0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(path) = headers.iter().find(|&h| h.name() == ":path") else {
|
let Some(path) = headers.find_header(":path") else {
|
||||||
stream
|
stream
|
||||||
.cancel_fetch(neqo_http3::Error::HttpRequestIncomplete.code())
|
.cancel_fetch(neqo_http3::Error::HttpRequestIncomplete.code())
|
||||||
.unwrap();
|
.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,
|
cell::RefCell,
|
||||||
fmt::{self, Display},
|
fmt::{self, Display},
|
||||||
fs, io,
|
fs, io,
|
||||||
net::{SocketAddr, ToSocketAddrs},
|
net::{SocketAddr, ToSocketAddrs as _},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
process::exit,
|
process::exit,
|
||||||
@@ -21,7 +21,7 @@ use std::{
|
|||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use futures::{
|
use futures::{
|
||||||
future::{select, select_all, Either},
|
future::{select, select_all, Either},
|
||||||
FutureExt,
|
FutureExt as _,
|
||||||
};
|
};
|
||||||
use neqo_common::{qdebug, qerror, qinfo, qwarn, Datagram};
|
use neqo_common::{qdebug, qerror, qinfo, qwarn, Datagram};
|
||||||
use neqo_crypto::{
|
use neqo_crypto::{
|
||||||
@@ -29,6 +29,7 @@ use neqo_crypto::{
|
|||||||
init_db, AntiReplay, Cipher,
|
init_db, AntiReplay, Cipher,
|
||||||
};
|
};
|
||||||
use neqo_transport::{Output, RandomConnectionIdGenerator, Version};
|
use neqo_transport::{Output, RandomConnectionIdGenerator, Version};
|
||||||
|
use neqo_udp::RecvBuf;
|
||||||
use tokio::time::Sleep;
|
use tokio::time::Sleep;
|
||||||
|
|
||||||
use crate::SharedArgs;
|
use crate::SharedArgs;
|
||||||
@@ -121,9 +122,9 @@ pub struct Args {
|
|||||||
#[cfg(any(test, feature = "bench"))]
|
#[cfg(any(test, feature = "bench"))]
|
||||||
impl Default for Args {
|
impl Default for Args {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
use std::str::FromStr;
|
use std::str::FromStr as _;
|
||||||
Self {
|
Self {
|
||||||
shared: crate::SharedArgs::default(),
|
shared: SharedArgs::default(),
|
||||||
hosts: vec!["[::]:12345".to_string()],
|
hosts: vec!["[::]:12345".to_string()],
|
||||||
db: PathBuf::from_str("../test-fixture/db").unwrap(),
|
db: PathBuf::from_str("../test-fixture/db").unwrap(),
|
||||||
key: "key".to_string(),
|
key: "key".to_string(),
|
||||||
@@ -202,7 +203,7 @@ pub struct ServerRunner {
|
|||||||
server: Box<dyn HttpServer>,
|
server: Box<dyn HttpServer>,
|
||||||
timeout: Option<Pin<Box<Sleep>>>,
|
timeout: Option<Pin<Box<Sleep>>>,
|
||||||
sockets: Vec<(SocketAddr, crate::udp::Socket)>,
|
sockets: Vec<(SocketAddr, crate::udp::Socket)>,
|
||||||
recv_buf: Vec<u8>,
|
recv_buf: RecvBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerRunner {
|
impl ServerRunner {
|
||||||
@@ -217,7 +218,7 @@ impl ServerRunner {
|
|||||||
server,
|
server,
|
||||||
timeout: None,
|
timeout: None,
|
||||||
sockets,
|
sockets,
|
||||||
recv_buf: vec![0; neqo_udp::RECV_BUF_SIZE],
|
recv_buf: RecvBuf::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,7 +252,7 @@ impl ServerRunner {
|
|||||||
socket.send(&dgram)?;
|
socket.send(&dgram)?;
|
||||||
}
|
}
|
||||||
Output::Callback(new_timeout) => {
|
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)));
|
*timeout = Some(Box::pin(tokio::time::sleep(new_timeout)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -263,7 +264,7 @@ impl ServerRunner {
|
|||||||
|
|
||||||
async fn read_and_process(&mut self, sockets_index: usize) -> Result<(), io::Error> {
|
async fn read_and_process(&mut self, sockets_index: usize) -> Result<(), io::Error> {
|
||||||
loop {
|
loop {
|
||||||
let (host, socket) = self.sockets.get_mut(sockets_index).unwrap();
|
let (host, socket) = &mut self.sockets[sockets_index];
|
||||||
let Some(input_dgrams) = socket.recv(*host, &mut self.recv_buf)? else {
|
let Some(input_dgrams) = socket.recv(*host, &mut self.recv_buf)? else {
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
@@ -341,8 +342,6 @@ enum Ready {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn server(mut args: Args) -> Res<()> {
|
pub async fn server(mut args: Args) -> Res<()> {
|
||||||
const HQ_INTEROP: &str = "hq-interop";
|
|
||||||
|
|
||||||
neqo_common::log::init(
|
neqo_common::log::init(
|
||||||
args.shared
|
args.shared
|
||||||
.verbose
|
.verbose
|
||||||
@@ -362,17 +361,15 @@ pub async fn server(mut args: Args) -> Res<()> {
|
|||||||
args.shared.quic_parameters.quic_version = vec![Version::Version1];
|
args.shared.quic_parameters.quic_version = vec![Version::Version1];
|
||||||
}
|
}
|
||||||
} else {
|
} 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.
|
// These are the default for all tests except http3.
|
||||||
args.shared.use_old_http = true;
|
args.shared.alpn = String::from("hq-interop");
|
||||||
args.shared.alpn = String::from(HQ_INTEROP);
|
|
||||||
// TODO: More options to deduplicate with client?
|
// TODO: More options to deduplicate with client?
|
||||||
match testcase.as_str() {
|
match testcase.as_str() {
|
||||||
"http3" => {
|
"http3" => {
|
||||||
args.shared.use_old_http = false;
|
args.shared.alpn = String::from("h3");
|
||||||
args.shared.alpn = "h3".into();
|
|
||||||
}
|
}
|
||||||
"zerortt" => args.shared.quic_parameters.max_streams_bidi = 100,
|
"zerortt" => args.shared.quic_parameters.max_streams_bidi = 100,
|
||||||
"handshake" | "transfer" | "resumption" | "multiconnect" | "v2" | "ecn" => {}
|
"handshake" | "transfer" | "resumption" | "multiconnect" | "v2" | "ecn" => {}
|
||||||
@@ -396,7 +393,7 @@ pub async fn server(mut args: Args) -> Res<()> {
|
|||||||
let hosts = args.listen_addresses();
|
let hosts = args.listen_addresses();
|
||||||
if hosts.is_empty() {
|
if hosts.is_empty() {
|
||||||
qerror!("No valid hosts defined");
|
qerror!("No valid hosts defined");
|
||||||
Err(io::Error::new(io::ErrorKind::InvalidInput, "No hosts"))?;
|
return Err(io::Error::new(io::ErrorKind::InvalidInput, "No hosts").into());
|
||||||
}
|
}
|
||||||
let sockets = hosts
|
let sockets = hosts
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -414,12 +411,12 @@ pub async fn server(mut args: Args) -> Res<()> {
|
|||||||
.expect("unable to setup anti-replay");
|
.expect("unable to setup anti-replay");
|
||||||
let cid_mgr = Rc::new(RefCell::new(RandomConnectionIdGenerator::new(10)));
|
let cid_mgr = Rc::new(RefCell::new(RandomConnectionIdGenerator::new(10)));
|
||||||
|
|
||||||
let server: Box<dyn HttpServer> = if args.shared.use_old_http {
|
let server: Box<dyn HttpServer> = if args.shared.alpn == "h3" {
|
||||||
|
Box::new(http3::HttpServer::new(&args, anti_replay, cid_mgr))
|
||||||
|
} else {
|
||||||
Box::new(
|
Box::new(
|
||||||
http09::HttpServer::new(&args, anti_replay, cid_mgr).expect("We cannot make a server!"),
|
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)
|
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 std::{io, net::SocketAddr};
|
||||||
|
|
||||||
use neqo_common::Datagram;
|
use neqo_common::Datagram;
|
||||||
use neqo_udp::DatagramIter;
|
use neqo_udp::{DatagramIter, RecvBuf};
|
||||||
|
|
||||||
/// Ideally this would live in [`neqo-udp`]. [`neqo-udp`] is used in Firefox.
|
/// Ideally this would live in [`neqo-udp`]. [`neqo-udp`] is used in Firefox.
|
||||||
///
|
///
|
||||||
@@ -59,7 +59,7 @@ impl Socket {
|
|||||||
pub fn recv<'a>(
|
pub fn recv<'a>(
|
||||||
&self,
|
&self,
|
||||||
local_address: SocketAddr,
|
local_address: SocketAddr,
|
||||||
recv_buf: &'a mut [u8],
|
recv_buf: &'a mut RecvBuf,
|
||||||
) -> Result<Option<DatagramIter<'a>>, io::Error> {
|
) -> Result<Option<DatagramIter<'a>>, io::Error> {
|
||||||
self.inner
|
self.inner
|
||||||
.try_io(tokio::io::Interest::READABLE, || {
|
.try_io(tokio::io::Interest::READABLE, || {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"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}
|
{"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}
|
||||||
51
third_party/rust/neqo-common/Cargo.toml
vendored
51
third_party/rust/neqo-common/Cargo.toml
vendored
@@ -13,7 +13,7 @@
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.76.0"
|
rust-version = "1.76.0"
|
||||||
name = "neqo-common"
|
name = "neqo-common"
|
||||||
version = "0.11.0"
|
version = "0.12.2"
|
||||||
authors = ["The Neqo Authors <necko@mozilla.com>"]
|
authors = ["The Neqo Authors <necko@mozilla.com>"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
autolib = false
|
autolib = false
|
||||||
@@ -48,6 +48,12 @@ bench = false
|
|||||||
name = "log"
|
name = "log"
|
||||||
path = "tests/log.rs"
|
path = "tests/log.rs"
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "decoder"
|
||||||
|
path = "benches/decoder.rs"
|
||||||
|
harness = false
|
||||||
|
required-features = ["bench"]
|
||||||
|
|
||||||
[dependencies.enum-map]
|
[dependencies.enum-map]
|
||||||
version = "2.7"
|
version = "2.7"
|
||||||
default-features = false
|
default-features = false
|
||||||
@@ -70,6 +76,13 @@ default-features = false
|
|||||||
version = "0.13"
|
version = "0.13"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
||||||
|
[dev-dependencies.criterion]
|
||||||
|
version = "0.5"
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[dev-dependencies.neqo-crypto]
|
||||||
|
path = "../neqo-crypto"
|
||||||
|
|
||||||
[dev-dependencies.regex]
|
[dev-dependencies.regex]
|
||||||
version = "1.9"
|
version = "1.9"
|
||||||
features = ["unicode-perl"]
|
features = ["unicode-perl"]
|
||||||
@@ -79,8 +92,13 @@ default-features = false
|
|||||||
path = "../test-fixture"
|
path = "../test-fixture"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
bench = [
|
||||||
|
"neqo-crypto/bench",
|
||||||
|
"test-fixture/bench",
|
||||||
|
]
|
||||||
build-fuzzing-corpus = ["hex"]
|
build-fuzzing-corpus = ["hex"]
|
||||||
ci = []
|
ci = []
|
||||||
|
test-fixture = []
|
||||||
|
|
||||||
[target."cfg(windows)".dependencies.windows]
|
[target."cfg(windows)".dependencies.windows]
|
||||||
version = "0.58"
|
version = "0.58"
|
||||||
@@ -88,7 +106,22 @@ features = ["Win32_Media"]
|
|||||||
default-features = false
|
default-features = false
|
||||||
|
|
||||||
[lints.clippy]
|
[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_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]
|
[lints.clippy.cargo]
|
||||||
level = "warn"
|
level = "warn"
|
||||||
@@ -101,3 +134,19 @@ priority = -1
|
|||||||
[lints.clippy.pedantic]
|
[lints.clippy.pedantic]
|
||||||
level = "warn"
|
level = "warn"
|
||||||
priority = -1
|
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
Normal file
52
third_party/rust/neqo-common/benches/decoder.rs
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// 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);
|
||||||
89
third_party/rust/neqo-common/src/codec.rs
vendored
89
third_party/rust/neqo-common/src/codec.rs
vendored
@@ -44,34 +44,28 @@ impl<'a> Decoder<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Skip helper that panics if `n` is `None` or not able to fit in `usize`.
|
/// 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>) {
|
fn skip_inner(&mut self, n: Option<u64>) {
|
||||||
self.skip(usize::try_from(n.expect("invalid length")).unwrap());
|
self.skip(usize::try_from(n.expect("invalid length")).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Skip a vector. Panics if there isn't enough space.
|
/// Skip a vector. Panics if there isn't enough space.
|
||||||
/// Only use this for tests because we panic rather than reporting a result.
|
/// 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) {
|
pub fn skip_vec(&mut self, n: usize) {
|
||||||
let len = self.decode_uint(n);
|
let len = self.decode_n(n);
|
||||||
self.skip_inner(len);
|
self.skip_inner(len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Skip a variable length vector. Panics if there isn't enough space.
|
/// 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.
|
/// 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) {
|
pub fn skip_vvec(&mut self) {
|
||||||
let len = self.decode_varint();
|
let len = self.decode_varint();
|
||||||
self.skip_inner(len);
|
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.
|
/// Provides the next byte without moving the read position.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn peek_byte(&self) -> Option<u8> {
|
pub const fn peek_byte(&self) -> Option<u8> {
|
||||||
@@ -92,33 +86,43 @@ impl<'a> Decoder<'a> {
|
|||||||
Some(res)
|
Some(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decodes an unsigned integer of length 1..=8.
|
#[inline]
|
||||||
///
|
pub(crate) fn decode_n(&mut self, n: usize) -> Option<u64> {
|
||||||
/// # Panics
|
debug_assert!(n > 0 && n <= 8);
|
||||||
///
|
|
||||||
/// 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 {
|
if self.remaining() < n {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let mut v = 0_u64;
|
Some(if n == 1 {
|
||||||
for i in 0..n {
|
let v = u64::from(self.buf[self.offset]);
|
||||||
let b = self.buf[self.offset + i];
|
self.offset += 1;
|
||||||
v = v << 8 | u64::from(b);
|
v
|
||||||
}
|
} else {
|
||||||
self.offset += n;
|
let mut buf = [0; 8];
|
||||||
Some(v)
|
buf[8 - n..].copy_from_slice(&self.buf[self.offset..self.offset + n]);
|
||||||
|
self.offset += n;
|
||||||
|
u64::from_be_bytes(buf)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decodes a QUIC varint.
|
/// Decodes a QUIC varint.
|
||||||
pub fn decode_varint(&mut self) -> Option<u64> {
|
pub fn decode_varint(&mut self) -> Option<u64> {
|
||||||
let b1 = self.decode_byte()?;
|
let b1 = self.decode_n(1)?;
|
||||||
match b1 >> 6 {
|
match b1 >> 6 {
|
||||||
0 => Some(u64::from(b1 & 0x3f)),
|
0 => Some(b1),
|
||||||
1 => Some((u64::from(b1 & 0x3f) << 8) | self.decode_uint(1)?),
|
1 => Some(((b1 & 0x3f) << 8) | self.decode_n(1)?),
|
||||||
2 => Some((u64::from(b1 & 0x3f) << 24) | self.decode_uint(3)?),
|
2 => Some(((b1 & 0x3f) << 24) | self.decode_n(3)?),
|
||||||
3 => Some((u64::from(b1 & 0x3f) << 56) | self.decode_uint(7)?),
|
3 => Some(((b1 & 0x3f) << 56) | self.decode_n(7)?),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -143,7 +147,7 @@ impl<'a> Decoder<'a> {
|
|||||||
|
|
||||||
/// Decodes a TLS-style length-prefixed buffer.
|
/// Decodes a TLS-style length-prefixed buffer.
|
||||||
pub fn decode_vec(&mut self, n: usize) -> Option<&'a [u8]> {
|
pub fn decode_vec(&mut self, n: usize) -> Option<&'a [u8]> {
|
||||||
let len = self.decode_uint(n);
|
let len = self.decode_n(n);
|
||||||
self.decode_checked(len)
|
self.decode_checked(len)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,6 +276,7 @@ impl Encoder {
|
|||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// When `s` contains non-hex values or an odd number of values.
|
/// When `s` contains non-hex values or an odd number of values.
|
||||||
|
#[cfg(any(test, feature = "test-fixture"))]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn from_hex(s: impl AsRef<str>) -> Self {
|
pub fn from_hex(s: impl AsRef<str>) -> Self {
|
||||||
let s = s.as_ref();
|
let s = s.as_ref();
|
||||||
@@ -481,16 +486,28 @@ mod tests {
|
|||||||
let enc = Encoder::from_hex("0123");
|
let enc = Encoder::from_hex("0123");
|
||||||
let mut dec = enc.as_decoder();
|
let mut dec = enc.as_decoder();
|
||||||
|
|
||||||
assert_eq!(dec.decode_byte().unwrap(), 0x01);
|
assert_eq!(dec.decode_uint::<u8>().unwrap(), 0x01);
|
||||||
assert_eq!(dec.decode_byte().unwrap(), 0x23);
|
assert_eq!(dec.decode_uint::<u8>().unwrap(), 0x23);
|
||||||
assert!(dec.decode_byte().is_none());
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn decode_byte_short() {
|
fn decode_byte_short() {
|
||||||
let enc = Encoder::from_hex("");
|
let enc = Encoder::from_hex("");
|
||||||
let mut dec = enc.as_decoder();
|
let mut dec = enc.as_decoder();
|
||||||
assert!(dec.decode_byte().is_none());
|
assert!(dec.decode_uint::<u8>().is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -501,7 +518,7 @@ mod tests {
|
|||||||
assert!(dec.decode(2).is_none());
|
assert!(dec.decode(2).is_none());
|
||||||
|
|
||||||
let mut dec = Decoder::from(&[]);
|
let mut dec = Decoder::from(&[]);
|
||||||
assert_eq!(dec.decode_remainder().len(), 0);
|
assert!(dec.decode_remainder().is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[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::{
|
use std::{
|
||||||
collections::hash_map::DefaultHasher,
|
collections::hash_map::DefaultHasher,
|
||||||
fs::File,
|
fs::File,
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash as _, Hasher as _},
|
||||||
io::Write,
|
io::Write,
|
||||||
path::Path,
|
path::Path,
|
||||||
};
|
};
|
||||||
|
|||||||
26
third_party/rust/neqo-common/src/header.rs
vendored
26
third_party/rust/neqo-common/src/header.rs
vendored
@@ -46,3 +46,29 @@ impl Header {
|
|||||||
&self.value
|
&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")]
|
#[cfg(target_os = "macos")]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
mod mac {
|
mod mac {
|
||||||
use std::{mem::size_of, ptr::addr_of_mut};
|
use std::ptr::addr_of_mut;
|
||||||
|
|
||||||
// These are manually extracted from the many bindings generated
|
// These are manually extracted from the many bindings generated
|
||||||
// by bindgen when provided with the simple header:
|
// by bindgen when provided with the simple header:
|
||||||
@@ -126,7 +126,7 @@ mod mac {
|
|||||||
const THREAD_TIME_CONSTRAINT_POLICY: thread_policy_flavor_t = 2;
|
const THREAD_TIME_CONSTRAINT_POLICY: thread_policy_flavor_t = 2;
|
||||||
#[allow(clippy::cast_possible_truncation)]
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
const THREAD_TIME_CONSTRAINT_POLICY_COUNT: mach_msg_type_number_t =
|
const THREAD_TIME_CONSTRAINT_POLICY_COUNT: mach_msg_type_number_t =
|
||||||
(size_of::<thread_time_constraint_policy>() / size_of::<integer_t>())
|
(std::mem::size_of::<thread_time_constraint_policy>() / std::mem::size_of::<integer_t>())
|
||||||
as mach_msg_type_number_t;
|
as mach_msg_type_number_t;
|
||||||
|
|
||||||
// These function definitions are taken from a comment in <thread_policy.h>.
|
// These function definitions are taken from a comment in <thread_policy.h>.
|
||||||
@@ -370,14 +370,9 @@ impl Drop for Time {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only run these tests in CI on platforms other than MacOS and Windows, where the timer
|
// Only run these tests in CI on Linux, where the timer accuracies are OK enough to pass the tests,
|
||||||
// inaccuracies are too high to pass the tests.
|
// but only when not running sanitizers.
|
||||||
#[cfg(all(
|
#[cfg(all(test, target_os = "linux", not(neqo_sanitize)))]
|
||||||
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 {
|
mod test {
|
||||||
use std::{
|
use std::{
|
||||||
thread::{sleep, spawn},
|
thread::{sleep, spawn},
|
||||||
|
|||||||
22
third_party/rust/neqo-common/src/incrdecoder.rs
vendored
22
third_party/rust/neqo-common/src/incrdecoder.rs
vendored
@@ -31,15 +31,11 @@ impl IncrementalDecoderUint {
|
|||||||
if amount < 8 {
|
if amount < 8 {
|
||||||
self.v <<= amount * 8;
|
self.v <<= amount * 8;
|
||||||
}
|
}
|
||||||
self.v |= dv.decode_uint(amount).unwrap();
|
self.v |= dv.decode_n(amount).unwrap();
|
||||||
*r -= amount;
|
*r -= amount;
|
||||||
if *r == 0 {
|
(*r == 0).then_some(self.v)
|
||||||
Some(self.v)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let (v, remaining) = dv.decode_byte().map_or_else(
|
let (v, remaining) = dv.decode_uint::<u8>().map_or_else(
|
||||||
|| unreachable!(),
|
|| unreachable!(),
|
||||||
|b| {
|
|b| {
|
||||||
(
|
(
|
||||||
@@ -56,11 +52,7 @@ impl IncrementalDecoderUint {
|
|||||||
);
|
);
|
||||||
self.remaining = Some(remaining);
|
self.remaining = Some(remaining);
|
||||||
self.v = v;
|
self.v = v;
|
||||||
if remaining == 0 {
|
(remaining == 0).then_some(v)
|
||||||
Some(v)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,11 +92,7 @@ impl IncrementalDecoderBuffer {
|
|||||||
let b = dv.decode(amount).unwrap();
|
let b = dv.decode(amount).unwrap();
|
||||||
self.v.extend_from_slice(b);
|
self.v.extend_from_slice(b);
|
||||||
self.remaining -= amount;
|
self.remaining -= amount;
|
||||||
if self.remaining == 0 {
|
(self.remaining == 0).then(|| mem::take(&mut self.v))
|
||||||
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 qlog;
|
||||||
pub mod tos;
|
pub mod tos;
|
||||||
|
|
||||||
use std::fmt::Write;
|
use std::fmt::Write as _;
|
||||||
|
|
||||||
use enum_map::Enum;
|
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,44 +7,13 @@
|
|||||||
#![allow(clippy::module_name_repetitions)]
|
#![allow(clippy::module_name_repetitions)]
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
io::Write,
|
io::Write as _,
|
||||||
sync::{Once, OnceLock},
|
sync::{Once, OnceLock},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use env_logger::Builder;
|
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 {
|
fn since_start() -> Duration {
|
||||||
static START_TIME: OnceLock<Instant> = OnceLock::new();
|
static START_TIME: OnceLock<Instant> = OnceLock::new();
|
||||||
START_TIME.get_or_init(Instant::now).elapsed()
|
START_TIME.get_or_init(Instant::now).elapsed()
|
||||||
@@ -66,7 +35,7 @@ pub fn init(level_filter: Option<log::LevelFilter>) {
|
|||||||
let elapsed = since_start();
|
let elapsed = since_start();
|
||||||
writeln!(
|
writeln!(
|
||||||
buf,
|
buf,
|
||||||
"{}s{:3}ms {} {}",
|
"{}.{:03} {} {}",
|
||||||
elapsed.as_secs(),
|
elapsed.as_secs(),
|
||||||
elapsed.as_millis() % 1000,
|
elapsed.as_millis() % 1000,
|
||||||
record.level(),
|
record.level(),
|
||||||
@@ -74,42 +43,55 @@ pub fn init(level_filter: Option<log::LevelFilter>) {
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
if let Err(e) = builder.try_init() {
|
if let Err(e) = builder.try_init() {
|
||||||
do_log!(::log::Level::Warn, "Logging initialization error {:?}", e);
|
eprintln!("Logging initialization error {e:?}");
|
||||||
} else {
|
} else {
|
||||||
do_log!(::log::Level::Debug, "Logging initialized");
|
::log::debug!("Logging initialized");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! log_invoke {
|
// TODO: Enable `#[clippy::format_args]` once our MSRV is >= 1.84
|
||||||
($lvl:expr, $ctx:expr, $($arg:tt)*) => ( {
|
|
||||||
::neqo_common::log::init(None);
|
|
||||||
::neqo_common::do_log!($lvl, "[{}] {}", $ctx, format!($($arg)*));
|
|
||||||
} )
|
|
||||||
}
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! qerror {
|
macro_rules! qerror {
|
||||||
([$ctx:expr], $($arg:tt)*) => (::neqo_common::log_invoke!(::log::Level::Error, $ctx, $($arg)*););
|
($($arg:tt)*) => ( {
|
||||||
($($arg:tt)*) => ( { ::neqo_common::log::init(None); ::neqo_common::do_log!(::log::Level::Error, $($arg)*); } );
|
#[cfg(any(test, feature = "bench"))]
|
||||||
|
::neqo_common::log::init(None);
|
||||||
|
::log::error!($($arg)*);
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
// TODO: Enable `#[clippy::format_args]` once our MSRV is >= 1.84
|
||||||
macro_rules! qwarn {
|
macro_rules! qwarn {
|
||||||
([$ctx:expr], $($arg:tt)*) => (::neqo_common::log_invoke!(::log::Level::Warn, $ctx, $($arg)*););
|
($($arg:tt)*) => ( {
|
||||||
($($arg:tt)*) => ( { ::neqo_common::log::init(None); ::neqo_common::do_log!(::log::Level::Warn, $($arg)*); } );
|
#[cfg(any(test, feature = "bench"))]
|
||||||
|
::neqo_common::log::init(None);
|
||||||
|
::log::warn!($($arg)*);
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
// TODO: Enable `#[clippy::format_args]` once our MSRV is >= 1.84
|
||||||
macro_rules! qinfo {
|
macro_rules! qinfo {
|
||||||
([$ctx:expr], $($arg:tt)*) => (::neqo_common::log_invoke!(::log::Level::Info, $ctx, $($arg)*););
|
($($arg:tt)*) => ( {
|
||||||
($($arg:tt)*) => ( { ::neqo_common::log::init(None); ::neqo_common::do_log!(::log::Level::Info, $($arg)*); } );
|
#[cfg(any(test, feature = "bench"))]
|
||||||
|
::neqo_common::log::init(None);
|
||||||
|
::log::info!($($arg)*);
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
// TODO: Enable `#[clippy::format_args]` once our MSRV is >= 1.84
|
||||||
macro_rules! qdebug {
|
macro_rules! qdebug {
|
||||||
([$ctx:expr], $($arg:tt)*) => (::neqo_common::log_invoke!(::log::Level::Debug, $ctx, $($arg)*););
|
($($arg:tt)*) => ( {
|
||||||
($($arg:tt)*) => ( { ::neqo_common::log::init(None); ::neqo_common::do_log!(::log::Level::Debug, $($arg)*); } );
|
#[cfg(any(test, feature = "bench"))]
|
||||||
|
::neqo_common::log::init(None);
|
||||||
|
::log::debug!($($arg)*);
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
// TODO: Enable `#[clippy::format_args]` once our MSRV is >= 1.84
|
||||||
macro_rules! qtrace {
|
macro_rules! qtrace {
|
||||||
([$ctx:expr], $($arg:tt)*) => (::neqo_common::log_invoke!(::log::Level::Trace, $ctx, $($arg)*););
|
($($arg:tt)*) => ( {
|
||||||
($($arg:tt)*) => ( { ::neqo_common::log::init(None); ::neqo_common::do_log!(::log::Level::Trace, $($arg)*); } );
|
#[cfg(any(test, feature = "bench"))]
|
||||||
|
::neqo_common::log::init(None);
|
||||||
|
::log::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,
|
title,
|
||||||
description,
|
description,
|
||||||
None,
|
None,
|
||||||
std::time::Instant::now(),
|
Instant::now(),
|
||||||
new_trace(role),
|
new_trace(role),
|
||||||
qlog::events::EventImportance::Base,
|
qlog::events::EventImportance::Base,
|
||||||
Box::new(BufWriter::new(file)),
|
Box::new(BufWriter::new(file)),
|
||||||
@@ -149,11 +149,7 @@ impl NeqoQlog {
|
|||||||
{
|
{
|
||||||
if let Some(inner) = self.inner.borrow_mut().as_mut() {
|
if let Some(inner) = self.inner.borrow_mut().as_mut() {
|
||||||
if let Err(e) = f(&mut inner.streamer) {
|
if let Err(e) = f(&mut inner.streamer) {
|
||||||
crate::do_log!(
|
log::error!("Qlog event generation failed with error {e}; closing qlog.");
|
||||||
::log::Level::Error,
|
|
||||||
"Qlog event generation failed with error {}; closing qlog.",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
*self.inner.borrow_mut() = None;
|
*self.inner.borrow_mut() = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -169,13 +165,13 @@ impl fmt::Debug for NeqoQlogShared {
|
|||||||
impl Drop for NeqoQlogShared {
|
impl Drop for NeqoQlogShared {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Err(e) = self.streamer.finish_log() {
|
if let Err(e) = self.streamer.finish_log() {
|
||||||
crate::do_log!(::log::Level::Error, "Error dropping NeqoQlog: {}", e);
|
log::error!("Error dropping NeqoQlog: {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new_trace(role: Role) -> qlog::TraceSeq {
|
pub fn new_trace(role: Role) -> TraceSeq {
|
||||||
TraceSeq {
|
TraceSeq {
|
||||||
vantage_point: VantagePoint {
|
vantage_point: VantagePoint {
|
||||||
name: Some(format!("neqo-{role}")),
|
name: Some(format!("neqo-{role}")),
|
||||||
@@ -186,7 +182,7 @@ pub fn new_trace(role: Role) -> qlog::TraceSeq {
|
|||||||
flow: None,
|
flow: None,
|
||||||
},
|
},
|
||||||
title: Some(format!("neqo-{role} trace")),
|
title: Some(format!("neqo-{role} trace")),
|
||||||
description: Some("Example qlog trace description".to_string()),
|
description: Some(format!("neqo-{role} trace")),
|
||||||
configuration: Some(Configuration {
|
configuration: Some(Configuration {
|
||||||
time_offset: Some(0.0),
|
time_offset: Some(0.0),
|
||||||
original_uris: None,
|
original_uris: None,
|
||||||
@@ -233,7 +229,7 @@ mod test {
|
|||||||
let (log, contents) = test_fixture::new_neqo_qlog();
|
let (log, contents) = test_fixture::new_neqo_qlog();
|
||||||
log.add_event_with_instant(|| Some(Event::with_time(0.0, EV_DATA)), Instant::now());
|
log.add_event_with_instant(|| Some(Event::with_time(0.0, EV_DATA)), Instant::now());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Regex::new("\"time\":[0-9].[0-9]*,")
|
Regex::new("\"time\":[0-9]+.[0-9]+,")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.replace(&contents.to_string(), "\"time\":0.0,"),
|
.replace(&contents.to_string(), "\"time\":0.0,"),
|
||||||
format!("{EXPECTED_LOG_HEADER}{EXPECTED_LOG_EVENT}"),
|
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>
|
/// <https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml>
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Enum, Default, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Enum, Default, Debug)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
|||||||
41
third_party/rust/neqo-common/tests/log.rs
vendored
41
third_party/rust/neqo-common/tests/log.rs
vendored
@@ -19,40 +19,9 @@ fn basic() {
|
|||||||
fn args() {
|
fn args() {
|
||||||
let num = 1;
|
let num = 1;
|
||||||
let obj = std::time::Instant::now();
|
let obj = std::time::Instant::now();
|
||||||
qerror!("error {} {:?}", num, obj);
|
qerror!("error {num} {obj:?}");
|
||||||
qwarn!("warn {} {:?}", num, obj);
|
qwarn!("warn {num} {obj:?}");
|
||||||
qinfo!("info {} {:?}", num, obj);
|
qinfo!("info {num} {obj:?}");
|
||||||
qdebug!("debug {} {:?}", num, obj);
|
qdebug!("debug {num} {obj:?}");
|
||||||
qtrace!("trace {} {:?}", 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":"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}
|
{"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}
|
||||||
34
third_party/rust/neqo-crypto/Cargo.toml
vendored
34
third_party/rust/neqo-crypto/Cargo.toml
vendored
@@ -13,7 +13,7 @@
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.76.0"
|
rust-version = "1.76.0"
|
||||||
name = "neqo-crypto"
|
name = "neqo-crypto"
|
||||||
version = "0.11.0"
|
version = "0.12.2"
|
||||||
authors = ["The Neqo Authors <necko@mozilla.com>"]
|
authors = ["The Neqo Authors <necko@mozilla.com>"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
autolib = false
|
autolib = false
|
||||||
@@ -113,12 +113,28 @@ version = "0.5"
|
|||||||
default-features = false
|
default-features = false
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
bench = []
|
||||||
disable-encryption = []
|
disable-encryption = []
|
||||||
disable-random = []
|
disable-random = []
|
||||||
gecko = ["mozbuild"]
|
gecko = ["mozbuild"]
|
||||||
|
|
||||||
[lints.clippy]
|
[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_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]
|
[lints.clippy.cargo]
|
||||||
level = "warn"
|
level = "warn"
|
||||||
@@ -131,3 +147,19 @@ priority = -1
|
|||||||
[lints.clippy.pedantic]
|
[lints.clippy.pedantic]
|
||||||
level = "warn"
|
level = "warn"
|
||||||
priority = -1
|
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,
|
experimental_api,
|
||||||
p11::{PK11SymKey, SymKey},
|
p11::{PK11SymKey, SymKey},
|
||||||
scoped_ptr,
|
scoped_ptr,
|
||||||
ssl::{self, PRUint16, PRUint64, PRUint8, SSLAeadContext},
|
ssl::{PRUint16, PRUint64, PRUint8, SSLAeadContext},
|
||||||
};
|
};
|
||||||
|
|
||||||
experimental_api!(SSL_MakeAead(
|
experimental_api!(SSL_MakeAead(
|
||||||
@@ -80,7 +80,7 @@ impl RealAead {
|
|||||||
prefix: &str,
|
prefix: &str,
|
||||||
) -> Res<Self> {
|
) -> Res<Self> {
|
||||||
let p = prefix.as_bytes();
|
let p = prefix.as_bytes();
|
||||||
let mut ctx: *mut ssl::SSLAeadContext = null_mut();
|
let mut ctx: *mut SSLAeadContext = null_mut();
|
||||||
SSL_MakeAead(
|
SSL_MakeAead(
|
||||||
version,
|
version,
|
||||||
cipher,
|
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::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
ffi::{CStr, CString},
|
ffi::{CStr, CString},
|
||||||
mem::{self, MaybeUninit},
|
mem::MaybeUninit,
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
os::raw::{c_uint, c_void},
|
os::raw::{c_uint, c_void},
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
@@ -107,7 +107,7 @@ fn get_alpn(fd: *mut ssl::PRFileDesc, pre: bool) -> Res<Option<String>> {
|
|||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
qtrace!([format!("{fd:p}")], "got ALPN {:?}", alpn);
|
qtrace!("[{fd:p}] got ALPN {alpn:?}");
|
||||||
Ok(alpn)
|
Ok(alpn)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ impl SecretAgentPreInfo {
|
|||||||
ssl::SSL_GetPreliminaryChannelInfo(
|
ssl::SSL_GetPreliminaryChannelInfo(
|
||||||
fd,
|
fd,
|
||||||
info.as_mut_ptr(),
|
info.as_mut_ptr(),
|
||||||
c_uint::try_from(mem::size_of::<ssl::SSLPreliminaryChannelInfo>())?,
|
c_uint::try_from(std::mem::size_of::<ssl::SSLPreliminaryChannelInfo>())?,
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
@@ -222,7 +222,7 @@ impl SecretAgentInfo {
|
|||||||
ssl::SSL_GetChannelInfo(
|
ssl::SSL_GetChannelInfo(
|
||||||
fd,
|
fd,
|
||||||
info.as_mut_ptr(),
|
info.as_mut_ptr(),
|
||||||
c_uint::try_from(mem::size_of::<ssl::SSLChannelInfo>())?,
|
c_uint::try_from(std::mem::size_of::<ssl::SSLChannelInfo>())?,
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
let info = unsafe { info.assume_init() };
|
let info = unsafe { info.assume_init() };
|
||||||
@@ -337,7 +337,9 @@ impl SecretAgent {
|
|||||||
ssl::SSL_ImportFD(null_mut(), base_fd.cast())
|
ssl::SSL_ImportFD(null_mut(), base_fd.cast())
|
||||||
};
|
};
|
||||||
if fd.is_null() {
|
if fd.is_null() {
|
||||||
unsafe { prio::PR_Close(base_fd) };
|
unsafe {
|
||||||
|
prio::PR_Close(base_fd);
|
||||||
|
}
|
||||||
return Err(Error::CreateSslSocket);
|
return Err(Error::CreateSslSocket);
|
||||||
}
|
}
|
||||||
Ok(fd)
|
Ok(fd)
|
||||||
@@ -347,8 +349,8 @@ impl SecretAgent {
|
|||||||
unsafe extern "C" fn auth_complete_hook(
|
unsafe extern "C" fn auth_complete_hook(
|
||||||
arg: *mut c_void,
|
arg: *mut c_void,
|
||||||
_fd: *mut ssl::PRFileDesc,
|
_fd: *mut ssl::PRFileDesc,
|
||||||
_check_sig: ssl::PRBool,
|
_check_sig: PRBool,
|
||||||
_is_server: ssl::PRBool,
|
_is_server: PRBool,
|
||||||
) -> ssl::SECStatus {
|
) -> ssl::SECStatus {
|
||||||
let auth_required_ptr = arg.cast::<bool>();
|
let auth_required_ptr = arg.cast::<bool>();
|
||||||
*auth_required_ptr = true;
|
*auth_required_ptr = true;
|
||||||
@@ -369,7 +371,7 @@ impl SecretAgent {
|
|||||||
if st.is_none() {
|
if st.is_none() {
|
||||||
*st = Some(alert.description);
|
*st = Some(alert.description);
|
||||||
} else {
|
} else {
|
||||||
qwarn!([format!("{fd:p}")], "duplicate alert {}", alert.description);
|
qwarn!("[{fd:p}] duplicate alert {}", alert.description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -394,7 +396,7 @@ impl SecretAgent {
|
|||||||
|
|
||||||
self.now.bind(self.fd)?;
|
self.now.bind(self.fd)?;
|
||||||
self.configure(grease)?;
|
self.configure(grease)?;
|
||||||
secstatus_to_res(unsafe { ssl::SSL_ResetHandshake(self.fd, ssl::PRBool::from(is_server)) })
|
secstatus_to_res(unsafe { ssl::SSL_ResetHandshake(self.fd, PRBool::from(is_server)) })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Default configuration.
|
/// Default configuration.
|
||||||
@@ -429,7 +431,7 @@ impl SecretAgent {
|
|||||||
/// If NSS can't enable or disable ciphers.
|
/// If NSS can't enable or disable ciphers.
|
||||||
pub fn set_ciphers(&mut self, ciphers: &[Cipher]) -> Res<()> {
|
pub fn set_ciphers(&mut self, ciphers: &[Cipher]) -> Res<()> {
|
||||||
if self.state != HandshakeState::New {
|
if self.state != HandshakeState::New {
|
||||||
qwarn!([self], "Cannot enable ciphers in state {:?}", self.state);
|
qwarn!("[{self}] Cannot enable ciphers in state {:?}", self.state);
|
||||||
return Err(Error::InternalError);
|
return Err(Error::InternalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,13 +440,13 @@ impl SecretAgent {
|
|||||||
for i in 0..cipher_count {
|
for i in 0..cipher_count {
|
||||||
let p = all_ciphers.wrapping_add(i);
|
let p = all_ciphers.wrapping_add(i);
|
||||||
secstatus_to_res(unsafe {
|
secstatus_to_res(unsafe {
|
||||||
ssl::SSL_CipherPrefSet(self.fd, i32::from(*p), ssl::PRBool::from(false))
|
ssl::SSL_CipherPrefSet(self.fd, i32::from(*p), PRBool::from(false))
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for c in ciphers {
|
for c in ciphers {
|
||||||
secstatus_to_res(unsafe {
|
secstatus_to_res(unsafe {
|
||||||
ssl::SSL_CipherPrefSet(self.fd, i32::from(*c), ssl::PRBool::from(true))
|
ssl::SSL_CipherPrefSet(self.fd, i32::from(*c), PRBool::from(true))
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -600,8 +602,8 @@ impl SecretAgent {
|
|||||||
/// Calling this function returns None until the connection is complete.
|
/// Calling this function returns None until the connection is complete.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn info(&self) -> Option<&SecretAgentInfo> {
|
pub const fn info(&self) -> Option<&SecretAgentInfo> {
|
||||||
match self.state {
|
match &self.state {
|
||||||
HandshakeState::Complete(ref info) => Some(info),
|
HandshakeState::Complete(info) => Some(info),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -644,7 +646,7 @@ impl SecretAgent {
|
|||||||
fn capture_error<T>(&mut self, res: Res<T>) -> Res<T> {
|
fn capture_error<T>(&mut self, res: Res<T>) -> Res<T> {
|
||||||
if let Err(e) = res {
|
if let Err(e) = res {
|
||||||
let e = ech::convert_ech_error(self.fd, e);
|
let e = ech::convert_ech_error(self.fd, e);
|
||||||
qwarn!([self], "error: {:?}", e);
|
qwarn!("[{self}] error: {e:?}");
|
||||||
self.state = HandshakeState::Failed(e.clone());
|
self.state = HandshakeState::Failed(e.clone());
|
||||||
Err(e)
|
Err(e)
|
||||||
} else {
|
} else {
|
||||||
@@ -669,7 +671,7 @@ impl SecretAgent {
|
|||||||
let info = self.capture_error(SecretAgentInfo::new(self.fd))?;
|
let info = self.capture_error(SecretAgentInfo::new(self.fd))?;
|
||||||
HandshakeState::Complete(info)
|
HandshakeState::Complete(info)
|
||||||
};
|
};
|
||||||
qdebug!([self], "state -> {:?}", self.state);
|
qdebug!("[{self}] state -> {:?}", self.state);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -692,8 +694,8 @@ impl SecretAgent {
|
|||||||
// Within this scope, _h maintains a mutable reference to self.io.
|
// Within this scope, _h maintains a mutable reference to self.io.
|
||||||
let _h = self.io.wrap(input);
|
let _h = self.io.wrap(input);
|
||||||
match self.state {
|
match self.state {
|
||||||
HandshakeState::Authenticated(ref err) => unsafe {
|
HandshakeState::Authenticated(err) => unsafe {
|
||||||
ssl::SSL_AuthCertificateComplete(self.fd, *err)
|
ssl::SSL_AuthCertificateComplete(self.fd, err)
|
||||||
},
|
},
|
||||||
_ => unsafe { ssl::SSL_ForceHandshake(self.fd) },
|
_ => unsafe { ssl::SSL_ForceHandshake(self.fd) },
|
||||||
}
|
}
|
||||||
@@ -726,10 +728,10 @@ impl SecretAgent {
|
|||||||
let records = self.setup_raw()?;
|
let records = self.setup_raw()?;
|
||||||
|
|
||||||
// Fire off any authentication we might need to complete.
|
// Fire off any authentication we might need to complete.
|
||||||
if let HandshakeState::Authenticated(ref err) = self.state {
|
if let HandshakeState::Authenticated(err) = self.state {
|
||||||
let result =
|
let result =
|
||||||
secstatus_to_res(unsafe { ssl::SSL_AuthCertificateComplete(self.fd, *err) });
|
secstatus_to_res(unsafe { ssl::SSL_AuthCertificateComplete(self.fd, err) });
|
||||||
qdebug!([self], "SSL_AuthCertificateComplete: {:?}", result);
|
qdebug!("[{self}] SSL_AuthCertificateComplete: {result:?}");
|
||||||
// This should return SECSuccess, so don't use update_state().
|
// This should return SECSuccess, so don't use update_state().
|
||||||
self.capture_error(result)?;
|
self.capture_error(result)?;
|
||||||
}
|
}
|
||||||
@@ -758,11 +760,15 @@ impl SecretAgent {
|
|||||||
if self.raw == Some(true) {
|
if self.raw == Some(true) {
|
||||||
// Need to hold the record list in scope until the close is done.
|
// Need to hold the record list in scope until the close is done.
|
||||||
let _records = self.setup_raw().expect("Can only close");
|
let _records = self.setup_raw().expect("Can only close");
|
||||||
unsafe { prio::PR_Close(self.fd.cast()) };
|
unsafe {
|
||||||
|
prio::PR_Close(self.fd.cast());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Need to hold the IO wrapper in scope until the close is done.
|
// Need to hold the IO wrapper in scope until the close is done.
|
||||||
let _io = self.io.wrap(&[]);
|
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();
|
let _output = self.io.take_output();
|
||||||
self.fd = null_mut();
|
self.fd = null_mut();
|
||||||
@@ -876,7 +882,7 @@ impl Client {
|
|||||||
token,
|
token,
|
||||||
len,
|
len,
|
||||||
info.as_mut_ptr(),
|
info.as_mut_ptr(),
|
||||||
c_uint::try_from(mem::size_of::<ssl::SSLResumptionTokenInfo>()).unwrap(),
|
c_uint::try_from(std::mem::size_of::<ssl::SSLResumptionTokenInfo>()).unwrap(),
|
||||||
);
|
);
|
||||||
if info_res.is_err() {
|
if info_res.is_err() {
|
||||||
// Ignore the token.
|
// Ignore the token.
|
||||||
@@ -891,11 +897,7 @@ impl Client {
|
|||||||
let len = usize::try_from(len).unwrap();
|
let len = usize::try_from(len).unwrap();
|
||||||
let mut v = Vec::with_capacity(len);
|
let mut v = Vec::with_capacity(len);
|
||||||
v.extend_from_slice(null_safe_slice(token, len));
|
v.extend_from_slice(null_safe_slice(token, len));
|
||||||
qdebug!(
|
qdebug!("[{fd:p}] Got resumption token {}", hex_snip_middle(&v));
|
||||||
[format!("{fd:p}")],
|
|
||||||
"Got resumption token {}",
|
|
||||||
hex_snip_middle(&v)
|
|
||||||
);
|
|
||||||
|
|
||||||
if resumption.len() >= MAX_TICKETS {
|
if resumption.len() >= MAX_TICKETS {
|
||||||
resumption.remove(0);
|
resumption.remove(0);
|
||||||
@@ -965,7 +967,7 @@ impl Client {
|
|||||||
/// Error returned when the configuration is invalid.
|
/// Error returned when the configuration is invalid.
|
||||||
pub fn enable_ech(&mut self, ech_config_list: impl AsRef<[u8]>) -> Res<()> {
|
pub fn enable_ech(&mut self, ech_config_list: impl AsRef<[u8]>) -> Res<()> {
|
||||||
let config = ech_config_list.as_ref();
|
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);
|
self.ech_config = Vec::from(config);
|
||||||
if config.is_empty() {
|
if config.is_empty() {
|
||||||
unsafe { ech::SSL_EnableTls13GreaseEch(self.agent.fd, PRBool::from(true)) }
|
unsafe { ech::SSL_EnableTls13GreaseEch(self.agent.fd, PRBool::from(true)) }
|
||||||
@@ -1016,7 +1018,7 @@ pub enum ZeroRttCheckResult {
|
|||||||
|
|
||||||
/// A `ZeroRttChecker` is used by the agent to validate the application token (as provided by
|
/// A `ZeroRttChecker` is used by the agent to validate the application token (as provided by
|
||||||
/// `send_ticket`)
|
/// `send_ticket`)
|
||||||
pub trait ZeroRttChecker: std::fmt::Debug + std::marker::Unpin {
|
pub trait ZeroRttChecker: std::fmt::Debug + Unpin {
|
||||||
fn check(&self, token: &[u8]) -> ZeroRttCheckResult;
|
fn check(&self, token: &[u8]) -> ZeroRttCheckResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1068,7 +1070,7 @@ impl Server {
|
|||||||
return Err(Error::CertificateLoading);
|
return Err(Error::CertificateLoading);
|
||||||
};
|
};
|
||||||
let key_ptr = unsafe { p11::PK11_FindKeyByAnyCert(*cert, null_mut()) };
|
let key_ptr = unsafe { p11::PK11_FindKeyByAnyCert(*cert, null_mut()) };
|
||||||
let Ok(key) = p11::PrivateKey::from_ptr(key_ptr) else {
|
let Ok(key) = PrivateKey::from_ptr(key_ptr) else {
|
||||||
return Err(Error::CertificateLoading);
|
return Err(Error::CertificateLoading);
|
||||||
};
|
};
|
||||||
secstatus_to_res(unsafe {
|
secstatus_to_res(unsafe {
|
||||||
@@ -1175,7 +1177,7 @@ impl Server {
|
|||||||
pk: &PublicKey,
|
pk: &PublicKey,
|
||||||
) -> Res<()> {
|
) -> Res<()> {
|
||||||
let cfg = ech::encode_config(config, public_name, pk)?;
|
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 {
|
unsafe {
|
||||||
ech::SSL_SetServerEchConfigs(
|
ech::SSL_SetServerEchConfigs(
|
||||||
self.agent.fd,
|
self.agent.fd,
|
||||||
@@ -1213,8 +1215,8 @@ impl ::std::fmt::Display for Server {
|
|||||||
/// A generic container for Client or Server.
|
/// A generic container for Client or Server.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Agent {
|
pub enum Agent {
|
||||||
Client(crate::agent::Client),
|
Client(Client),
|
||||||
Server(crate::agent::Server),
|
Server(Server),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for Agent {
|
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.
|
// Shoves this record into the socket, returns true if blocked.
|
||||||
pub(crate) fn write(self, fd: *mut ssl::PRFileDesc) -> Res<()> {
|
pub(crate) fn write(self, fd: *mut ssl::PRFileDesc) -> Res<()> {
|
||||||
qtrace!("write {:?}", self);
|
qtrace!("write {self:?}");
|
||||||
unsafe {
|
unsafe {
|
||||||
ssl::SSL_RecordLayerData(
|
ssl::SSL_RecordLayerData(
|
||||||
fd,
|
fd,
|
||||||
@@ -177,7 +177,7 @@ impl AgentIoInput {
|
|||||||
|
|
||||||
#[allow(clippy::disallowed_methods)] // We just checked if this was empty.
|
#[allow(clippy::disallowed_methods)] // We just checked if this was empty.
|
||||||
let src = unsafe { std::slice::from_raw_parts(self.input, amount) };
|
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) };
|
let dst = unsafe { std::slice::from_raw_parts_mut(buf, amount) };
|
||||||
dst.copy_from_slice(src);
|
dst.copy_from_slice(src);
|
||||||
self.input = self.input.wrapping_add(amount);
|
self.input = self.input.wrapping_add(amount);
|
||||||
@@ -186,7 +186,7 @@ impl AgentIoInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn reset(&mut self) {
|
fn reset(&mut self) {
|
||||||
qtrace!([self], "reset");
|
qtrace!("[{self}] reset");
|
||||||
self.input = null();
|
self.input = null();
|
||||||
self.available = 0;
|
self.available = 0;
|
||||||
}
|
}
|
||||||
@@ -230,12 +230,12 @@ impl AgentIo {
|
|||||||
// Stage output from TLS into the output buffer.
|
// Stage output from TLS into the output buffer.
|
||||||
fn save_output(&mut self, buf: *const u8, count: usize) {
|
fn save_output(&mut self, buf: *const u8, count: usize) {
|
||||||
let slice = unsafe { null_safe_slice(buf, count) };
|
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);
|
self.output.extend_from_slice(slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn take_output(&mut self) -> Vec<u8> {
|
pub fn take_output(&mut self) -> Vec<u8> {
|
||||||
qtrace!([self], "take output");
|
qtrace!("[{self}] take output");
|
||||||
mem::take(&mut self.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) => {
|
Some(ocsp_ptr) => {
|
||||||
let mut ocsp_helper: Vec<Vec<u8>> = Vec::new();
|
let mut ocsp_helper: Vec<Vec<u8>> = Vec::new();
|
||||||
let Ok(len) = isize::try_from(unsafe { ocsp_ptr.as_ref().len }) else {
|
let Ok(len) = isize::try_from(unsafe { ocsp_ptr.as_ref().len }) else {
|
||||||
qerror!([format!("{fd:p}")], "Received illegal OSCP length");
|
qerror!("[{fd:p}] Received illegal OSCP length");
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
for idx in 0..len {
|
for idx in 0..len {
|
||||||
@@ -72,23 +72,6 @@ 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 {
|
impl<'a> IntoIterator for &'a CertificateInfo {
|
||||||
type IntoIter = ItemArrayIterator<'a>;
|
type IntoIter = ItemArrayIterator<'a>;
|
||||||
type Item = &'a [u8];
|
type Item = &'a [u8];
|
||||||
@@ -98,6 +81,19 @@ impl<'a> IntoIterator for &'a CertificateInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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]
|
#[must_use]
|
||||||
pub const fn stapled_ocsp_responses(&self) -> &Option<Vec<Vec<u8>>> {
|
pub const fn stapled_ocsp_responses(&self) -> &Option<Vec<Vec<u8>>> {
|
||||||
&self.stapled_ocsp_responses
|
&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());
|
assert_eq!(secret_ptr.is_null(), public_ptr.is_null());
|
||||||
let sk = PrivateKey::from_ptr(secret_ptr)?;
|
let sk = PrivateKey::from_ptr(secret_ptr)?;
|
||||||
let pk = PublicKey::from_ptr(public_ptr)?;
|
let pk = PublicKey::from_ptr(public_ptr)?;
|
||||||
qtrace!("Generated key pair: sk={:?} pk={:?}", sk, pk);
|
qtrace!("Generated key pair: sk={sk:?} pk={pk:?}");
|
||||||
Ok((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.
|
// Need to map the types through.
|
||||||
fn secstatus_to_res(code: nss::SECStatus) -> Res<()> {
|
fn secstatus_to_res(code: nss::SECStatus) -> Res<()> {
|
||||||
crate::err::secstatus_to_res(code as crate::ssl::SECStatus)
|
err::secstatus_to_res(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum NssLoaded {
|
enum NssLoaded {
|
||||||
@@ -106,7 +106,7 @@ fn version_check() -> Res<()> {
|
|||||||
/// This allows us to use SSLTRACE in all of our unit tests and programs.
|
/// This allows us to use SSLTRACE in all of our unit tests and programs.
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
fn enable_ssl_trace() -> Res<()> {
|
fn enable_ssl_trace() -> Res<()> {
|
||||||
let opt = ssl::Opt::Locking.as_int();
|
let opt = Opt::Locking.as_int();
|
||||||
let mut v: ::std::os::raw::c_int = 0;
|
let mut v: ::std::os::raw::c_int = 0;
|
||||||
secstatus_to_res(unsafe { ssl::SSL_OptionGetDefault(opt, &mut v) })
|
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,7 +11,6 @@
|
|||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
mem,
|
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
os::raw::c_uint,
|
os::raw::c_uint,
|
||||||
ptr::null_mut,
|
ptr::null_mut,
|
||||||
@@ -265,7 +264,7 @@ impl Item {
|
|||||||
SECItem {
|
SECItem {
|
||||||
type_: SECItemType::siBuffer,
|
type_: SECItemType::siBuffer,
|
||||||
data: data.cast_mut().cast(),
|
data: data.cast_mut().cast(),
|
||||||
len: c_uint::try_from(mem::size_of::<T>()).unwrap(),
|
len: c_uint::try_from(std::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!(code, -12273);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
desc,
|
desc,
|
||||||
"SSL received a record with an incorrect Message Authentication Code."
|
"SSL received a record with an incorrect Message Authentication Code"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => 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) {
|
fn put(&mut self, dir: SecretDirection, epoch: Epoch, key: SymKey) {
|
||||||
qdebug!("{:?} secret available for {:?}: {:?}", dir, epoch, key);
|
qdebug!("{dir:?} secret available for {epoch:?}: {key:?}");
|
||||||
let keys = match dir {
|
let keys = match dir {
|
||||||
SecretDirection::Read => &mut self.r,
|
SecretDirection::Read => &mut self.r,
|
||||||
SecretDirection::Write => &mut self.w,
|
SecretDirection::Write => &mut self.w,
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ impl SelfEncrypt {
|
|||||||
self.old_key = Some(mem::replace(&mut self.key, new_key));
|
self.old_key = Some(mem::replace(&mut self.key, new_key));
|
||||||
let (kid, _) = self.key_id.overflowing_add(1);
|
let (kid, _) = self.key_id.overflowing_add(1);
|
||||||
self.key_id = kid;
|
self.key_id = kid;
|
||||||
qinfo!(["SelfEncrypt"], "Rotated keys to {}", self.key_id);
|
qinfo!("[SelfEncrypt] Rotated keys to {}", self.key_id);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,8 +99,7 @@ impl SelfEncrypt {
|
|||||||
output.resize(encoded_len, 0);
|
output.resize(encoded_len, 0);
|
||||||
cipher.encrypt(0, extended_aad.as_ref(), plaintext, &mut output[offset..])?;
|
cipher.encrypt(0, extended_aad.as_ref(), plaintext, &mut output[offset..])?;
|
||||||
qtrace!(
|
qtrace!(
|
||||||
["SelfEncrypt"],
|
"[SelfEncrypt] seal {} {} -> {}",
|
||||||
"seal {} {} -> {}",
|
|
||||||
hex(aad),
|
hex(aad),
|
||||||
hex(plaintext),
|
hex(plaintext),
|
||||||
hex(&output)
|
hex(&output)
|
||||||
@@ -150,8 +149,7 @@ impl SelfEncrypt {
|
|||||||
let final_len = decrypted.len();
|
let final_len = decrypted.len();
|
||||||
output.truncate(final_len);
|
output.truncate(final_len);
|
||||||
qtrace!(
|
qtrace!(
|
||||||
["SelfEncrypt"],
|
"[SelfEncrypt] open {} {} -> {}",
|
||||||
"open {} {} -> {}",
|
|
||||||
hex(aad),
|
hex(aad),
|
||||||
hex(ciphertext),
|
hex(ciphertext),
|
||||||
hex(&output)
|
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();
|
init();
|
||||||
let base = get_base();
|
let base = get_base();
|
||||||
let delta_micros = PRTime::try_from(DELTA.as_micros()).unwrap();
|
let delta_micros = PRTime::try_from(DELTA.as_micros()).unwrap();
|
||||||
println!("{} - {}", base.prtime, delta_micros);
|
println!("{} - {delta_micros}", base.prtime);
|
||||||
let t = Time::try_from(base.prtime - delta_micros).unwrap();
|
let t = Time::try_from(base.prtime - delta_micros).unwrap();
|
||||||
assert_eq!(Instant::from(t) + DELTA, base.instant);
|
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> {
|
fn zero_rtt_setup(mode: Resumption, client: &Client, server: &mut Server) -> Option<AntiReplay> {
|
||||||
if matches!(mode, Resumption::WithZeroRtt) {
|
matches!(mode, Resumption::WithZeroRtt).then(|| {
|
||||||
client.enable_0rtt().expect("should enable 0-RTT on client");
|
client.enable_0rtt().expect("should enable 0-RTT on client");
|
||||||
|
|
||||||
let anti_replay = anti_replay();
|
let anti_replay = anti_replay();
|
||||||
@@ -127,10 +127,8 @@ fn zero_rtt_setup(mode: Resumption, client: &Client, server: &mut Server) -> Opt
|
|||||||
Box::new(PermissiveZeroRttChecker { resuming: false }),
|
Box::new(PermissiveZeroRttChecker { resuming: false }),
|
||||||
)
|
)
|
||||||
.expect("should enable 0-RTT on server");
|
.expect("should enable 0-RTT on server");
|
||||||
Some(anti_replay)
|
anti_replay
|
||||||
} else {
|
})
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::missing_panics_doc)]
|
#[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,8 +4,6 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
use neqo_crypto::{
|
use neqo_crypto::{
|
||||||
constants::{
|
constants::{
|
||||||
Cipher, TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256,
|
Cipher, TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256,
|
||||||
@@ -71,12 +69,12 @@ fn chacha20_ctr() {
|
|||||||
#[should_panic(expected = "out of range")]
|
#[should_panic(expected = "out of range")]
|
||||||
fn aes_short() {
|
fn aes_short() {
|
||||||
let hp = make_hp(TLS_AES_128_GCM_SHA256);
|
let hp = make_hp(TLS_AES_128_GCM_SHA256);
|
||||||
mem::drop(hp.mask(&[0; 15]));
|
drop(hp.mask(&[0; 15]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic(expected = "out of range")]
|
#[should_panic(expected = "out of range")]
|
||||||
fn chacha20_short() {
|
fn chacha20_short() {
|
||||||
let hp = make_hp(TLS_CHACHA20_POLY1305_SHA256);
|
let hp = make_hp(TLS_CHACHA20_POLY1305_SHA256);
|
||||||
mem::drop(hp.mask(&[0; 15]));
|
drop(hp.mask(&[0; 15]));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"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}
|
{"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}
|
||||||
51
third_party/rust/neqo-http3/Cargo.toml
vendored
51
third_party/rust/neqo-http3/Cargo.toml
vendored
@@ -13,7 +13,7 @@
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.76.0"
|
rust-version = "1.76.0"
|
||||||
name = "neqo-http3"
|
name = "neqo-http3"
|
||||||
version = "0.11.0"
|
version = "0.12.2"
|
||||||
authors = ["The Neqo Authors <necko@mozilla.com>"]
|
authors = ["The Neqo Authors <necko@mozilla.com>"]
|
||||||
build = false
|
build = false
|
||||||
autolib = false
|
autolib = false
|
||||||
@@ -39,6 +39,9 @@ categories = [
|
|||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
repository = "https://github.com/mozilla/neqo/"
|
repository = "https://github.com/mozilla/neqo/"
|
||||||
|
|
||||||
|
[package.metadata.cargo-machete]
|
||||||
|
ignored = ["log"]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "neqo_http3"
|
name = "neqo_http3"
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
@@ -93,17 +96,47 @@ version = "2.5.3"
|
|||||||
features = ["std"]
|
features = ["std"]
|
||||||
default-features = false
|
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]
|
[dev-dependencies.test-fixture]
|
||||||
path = "../test-fixture"
|
path = "../test-fixture"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
bench = [
|
||||||
|
"neqo-common/bench",
|
||||||
|
"neqo-crypto/bench",
|
||||||
|
"neqo-qpack/bench",
|
||||||
|
"neqo-transport/bench",
|
||||||
|
]
|
||||||
disable-encryption = [
|
disable-encryption = [
|
||||||
"neqo-transport/disable-encryption",
|
"neqo-transport/disable-encryption",
|
||||||
"neqo-crypto/disable-encryption",
|
"neqo-crypto/disable-encryption",
|
||||||
]
|
]
|
||||||
|
draft-29 = []
|
||||||
|
|
||||||
[lints.clippy]
|
[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_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]
|
[lints.clippy.cargo]
|
||||||
level = "warn"
|
level = "warn"
|
||||||
@@ -116,3 +149,19 @@ priority = -1
|
|||||||
[lints.clippy.pedantic]
|
[lints.clippy.pedantic]
|
||||||
level = "warn"
|
level = "warn"
|
||||||
priority = -1
|
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
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// This functon cannot be called before the `BufferedStream` is initialized.
|
/// This function cannot be called before the `BufferedStream` is initialized.
|
||||||
pub fn buffer(&mut self, to_buf: &[u8]) {
|
pub fn buffer(&mut self, to_buf: &[u8]) {
|
||||||
if let Self::Initialized { buf, .. } = self {
|
if let Self::Initialized { buf, .. } = self {
|
||||||
buf.extend_from_slice(to_buf);
|
buf.extend_from_slice(to_buf);
|
||||||
@@ -62,14 +62,14 @@ impl BufferedStream {
|
|||||||
///
|
///
|
||||||
/// Returns `neqo_transport` errors.
|
/// Returns `neqo_transport` errors.
|
||||||
pub fn send_buffer(&mut self, conn: &mut Connection) -> Res<usize> {
|
pub fn send_buffer(&mut self, conn: &mut Connection) -> Res<usize> {
|
||||||
let label = ::neqo_common::log_subject!(::log::Level::Debug, self);
|
let label = format!("{self}");
|
||||||
let Self::Initialized { stream_id, buf } = self else {
|
let Self::Initialized { stream_id, buf } = self else {
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
};
|
};
|
||||||
if buf.is_empty() {
|
if buf.is_empty() {
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
}
|
}
|
||||||
qtrace!([label], "sending data.");
|
qtrace!("[{label}] sending data");
|
||||||
let sent = conn.stream_send(*stream_id, &buf[..])?;
|
let sent = conn.stream_send(*stream_id, &buf[..])?;
|
||||||
if sent == 0 {
|
if sent == 0 {
|
||||||
return Ok(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,
|
connection::Http3State,
|
||||||
features::extended_connect::{ExtendedConnectEvents, ExtendedConnectType, SessionCloseReason},
|
features::extended_connect::{ExtendedConnectEvents, ExtendedConnectType, SessionCloseReason},
|
||||||
settings::HSettingType,
|
settings::HSettingType,
|
||||||
CloseType, Http3StreamInfo, HttpRecvStreamEvents, RecvStreamEvents, SendStreamEvents,
|
CloseType, Http3StreamInfo, HttpRecvStreamEvents, PushId, RecvStreamEvents, SendStreamEvents,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
@@ -68,24 +68,24 @@ pub enum Http3ClientEvent {
|
|||||||
},
|
},
|
||||||
/// A new push promise.
|
/// A new push promise.
|
||||||
PushPromise {
|
PushPromise {
|
||||||
push_id: u64,
|
push_id: PushId,
|
||||||
request_stream_id: StreamId,
|
request_stream_id: StreamId,
|
||||||
headers: Vec<Header>,
|
headers: Vec<Header>,
|
||||||
},
|
},
|
||||||
/// A push response headers are ready.
|
/// A push response headers are ready.
|
||||||
PushHeaderReady {
|
PushHeaderReady {
|
||||||
push_id: u64,
|
push_id: PushId,
|
||||||
headers: Vec<Header>,
|
headers: Vec<Header>,
|
||||||
interim: bool,
|
interim: bool,
|
||||||
fin: bool,
|
fin: bool,
|
||||||
},
|
},
|
||||||
/// New bytes are available on a push stream for reading.
|
/// New bytes are available on a push stream for reading.
|
||||||
PushDataReadable { push_id: u64 },
|
PushDataReadable { push_id: PushId },
|
||||||
/// A push has been canceled.
|
/// A push has been canceled.
|
||||||
PushCanceled { push_id: u64 },
|
PushCanceled { push_id: PushId },
|
||||||
/// A push stream was been reset due to a `HttpGeneralProtocol` error.
|
/// A push stream was been reset due to a `HttpGeneralProtocol` error.
|
||||||
/// Most common case are malformed response headers.
|
/// Most common case are malformed response headers.
|
||||||
PushReset { push_id: u64, error: AppError },
|
PushReset { push_id: PushId, error: AppError },
|
||||||
/// New stream can be created
|
/// New stream can be created
|
||||||
RequestsCreatable,
|
RequestsCreatable,
|
||||||
/// Cert authentication needed
|
/// Cert authentication needed
|
||||||
@@ -196,7 +196,7 @@ impl ExtendedConnectEvents for Http3ClientEvents {
|
|||||||
headers,
|
headers,
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
unreachable!("There is only ExtendedConnectType::WebTransport.");
|
unreachable!("There is only ExtendedConnectType::WebTransport");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,7 +216,7 @@ impl ExtendedConnectEvents for Http3ClientEvents {
|
|||||||
},
|
},
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
unreachable!("There are no other types.");
|
unreachable!("There are no other types");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,7 +240,7 @@ impl ExtendedConnectEvents for Http3ClientEvents {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Http3ClientEvents {
|
impl Http3ClientEvents {
|
||||||
pub fn push_promise(&self, push_id: u64, request_stream_id: StreamId, headers: Vec<Header>) {
|
pub fn push_promise(&self, push_id: PushId, request_stream_id: StreamId, headers: Vec<Header>) {
|
||||||
self.insert(Http3ClientEvent::PushPromise {
|
self.insert(Http3ClientEvent::PushPromise {
|
||||||
push_id,
|
push_id,
|
||||||
request_stream_id,
|
request_stream_id,
|
||||||
@@ -248,12 +248,12 @@ impl Http3ClientEvents {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_canceled(&self, push_id: u64) {
|
pub fn push_canceled(&self, push_id: PushId) {
|
||||||
self.remove_events_for_push_id(push_id);
|
self.remove_events_for_push_id(push_id);
|
||||||
self.insert(Http3ClientEvent::PushCanceled { push_id });
|
self.insert(Http3ClientEvent::PushCanceled { push_id });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_reset(&self, push_id: u64, error: AppError) {
|
pub fn push_reset(&self, push_id: PushId, error: AppError) {
|
||||||
self.remove_events_for_push_id(push_id);
|
self.remove_events_for_push_id(push_id);
|
||||||
self.insert(Http3ClientEvent::PushReset { push_id, error });
|
self.insert(Http3ClientEvent::PushReset { push_id, error });
|
||||||
}
|
}
|
||||||
@@ -336,7 +336,7 @@ impl Http3ClientEvents {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_push(&self, push_id: u64) -> bool {
|
pub fn has_push(&self, push_id: PushId) -> bool {
|
||||||
for iter in &*self.events.borrow() {
|
for iter in &*self.events.borrow() {
|
||||||
if matches!(iter, Http3ClientEvent::PushPromise{push_id:x, ..} if *x == push_id) {
|
if matches!(iter, Http3ClientEvent::PushPromise{push_id:x, ..} if *x == push_id) {
|
||||||
return true;
|
return true;
|
||||||
@@ -345,7 +345,7 @@ impl Http3ClientEvents {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_events_for_push_id(&self, push_id: u64) {
|
pub fn remove_events_for_push_id(&self, push_id: PushId) {
|
||||||
self.remove(|evt| {
|
self.remove(|evt| {
|
||||||
matches!(evt,
|
matches!(evt,
|
||||||
Http3ClientEvent::PushPromise{ push_id: x, .. }
|
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_decoder_receiver::DecoderRecvStream,
|
||||||
qpack_encoder_receiver::EncoderRecvStream,
|
qpack_encoder_receiver::EncoderRecvStream,
|
||||||
recv_message::{RecvMessage, RecvMessageInfo},
|
recv_message::{RecvMessage, RecvMessageInfo},
|
||||||
request_target::{AsRequestTarget, RequestTarget},
|
request_target::{AsRequestTarget, RequestTarget as _},
|
||||||
send_message::SendMessage,
|
send_message::SendMessage,
|
||||||
settings::{HSettingType, HSettings, HttpZeroRttChecker},
|
settings::{HSettingType, HSettings, HttpZeroRttChecker},
|
||||||
stream_type_reader::NewStreamHeadReader,
|
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
|
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
|
`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
|
and bidirectional streams are registered in both lists and the 2 handlers are independent, e.g. one
|
||||||
can be closed and removed ane second may still be active.
|
can be closed and removed and second may still be active.
|
||||||
|
|
||||||
The only streams that are not registered are the local control stream, local QPACK decoder stream,
|
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
|
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:
|
type has been decoded. After this point the stream:
|
||||||
- will be regegistered with the appropriate handler,
|
- will be regegistered with the appropriate handler,
|
||||||
- will be canceled if is an unknown stream type or
|
- will be canceled if is an unknown stream type or
|
||||||
- the connection will fail if it is unallowed stream type (receiveing HTTP request on the
|
- the connection will fail if it is unallowed stream type (receiving HTTP request on the
|
||||||
client-side).
|
client-side).
|
||||||
|
|
||||||
The output is handled in `handle_new_stream`, for control, qpack streams and partially
|
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.
|
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
|
Therefore, `WebTransportSession` will internally use a `SendMessage` and `RecvMessage` handler to
|
||||||
handle parsing and sending of HTTP part of the control stream. When HTTP headers are exchenged,
|
handle parsing and sending of HTTP part of the control stream. When HTTP headers are exchanged,
|
||||||
`WebTransportSession` will take over handling of stream data. `WebTransportSession` sets
|
`WebTransportSession` will take over handling of stream data. `WebTransportSession` sets
|
||||||
`WebTransportSessionListener` as the `RecvMessage` event listener.
|
`WebTransportSessionListener` as the `RecvMessage` event listener.
|
||||||
|
|
||||||
`WebTransportSendStream` and `WebTransportRecvStream` are associated with a `WebTransportSession`
|
`WebTransportSendStream` and `WebTransportRecvStream` are associated with a `WebTransportSession`
|
||||||
and they will be canceled if the session is closed. To be avle to do this `WebTransportSession`
|
and they will be canceled if the session is closed. To be able to do this `WebTransportSession`
|
||||||
holds a list of its active streams and clean up is done in `remove_extended_connect`.
|
holds a list of its active streams and clean up is done in `remove_extended_connect`.
|
||||||
|
|
||||||
### `WebTransportSendStream` and `WebTransportRecvStream`
|
### `WebTransportSendStream` and `WebTransportRecvStream`
|
||||||
@@ -352,7 +352,7 @@ impl Http3Connection {
|
|||||||
/// This function creates and initializes, i.e. send stream type, the control and qpack
|
/// This function creates and initializes, i.e. send stream type, the control and qpack
|
||||||
/// streams.
|
/// streams.
|
||||||
fn initialize_http3_connection(&mut self, conn: &mut Connection) -> Res<()> {
|
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.control_stream_local.create(conn)?;
|
||||||
|
|
||||||
self.send_settings();
|
self.send_settings();
|
||||||
@@ -361,7 +361,7 @@ impl Http3Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn send_settings(&mut self) {
|
fn send_settings(&mut self) {
|
||||||
qdebug!([self], "Send settings.");
|
qdebug!("[{self}] Send settings");
|
||||||
self.control_stream_local.queue_frame(&HFrame::Settings {
|
self.control_stream_local.queue_frame(&HFrame::Settings {
|
||||||
settings: HSettings::from(&self.local_params),
|
settings: HSettings::from(&self.local_params),
|
||||||
});
|
});
|
||||||
@@ -374,7 +374,7 @@ impl Http3Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn create_qpack_streams(&self, conn: &mut Connection) -> Res<()> {
|
fn create_qpack_streams(&self, conn: &mut Connection) -> Res<()> {
|
||||||
qdebug!([self], "create_qpack_streams.");
|
qdebug!("[{self}] create_qpack_streams");
|
||||||
self.qpack_encoder
|
self.qpack_encoder
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.add_send_stream(conn.stream_create(StreamType::UniDi)?);
|
.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
|
/// This is called when a `ConnectionEvent::NewStream` event is received. This register the
|
||||||
/// stream with a `NewStreamHeadReader` handler.
|
/// stream with a `NewStreamHeadReader` handler.
|
||||||
pub fn add_new_stream(&mut self, stream_id: StreamId) {
|
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(
|
self.recv_streams.insert(
|
||||||
stream_id,
|
stream_id,
|
||||||
Box::new(NewStreamHeadReader::new(stream_id, self.role)),
|
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
|
/// The function calls `receive` for a stream. It also deals with the outcome of a read by
|
||||||
/// calling `handle_stream_manipulation_output`.
|
/// calling `handle_stream_manipulation_output`.
|
||||||
fn stream_receive(&mut self, conn: &mut Connection, stream_id: StreamId) -> Res<ReceiveOutput> {
|
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) {
|
if let Some(recv_stream) = self.recv_streams.get_mut(&stream_id) {
|
||||||
let res = recv_stream.receive(conn);
|
let res = recv_stream.receive(conn);
|
||||||
@@ -485,7 +485,7 @@ impl Http3Connection {
|
|||||||
conn: &mut Connection,
|
conn: &mut Connection,
|
||||||
) -> Res<()> {
|
) -> Res<()> {
|
||||||
for stream_id in unblocked_streams {
|
for stream_id in unblocked_streams {
|
||||||
qdebug!([self], "Stream {} is unblocked", stream_id);
|
qdebug!("[{self}] Stream {stream_id} is unblocked");
|
||||||
if let Some(r) = self.recv_streams.get_mut(&stream_id) {
|
if let Some(r) = self.recv_streams.get_mut(&stream_id) {
|
||||||
let res = r
|
let res = r
|
||||||
.http_stream()
|
.http_stream()
|
||||||
@@ -501,7 +501,7 @@ impl Http3Connection {
|
|||||||
/// This function handles reading from all streams, i.e. control, qpack, request/response
|
/// 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.
|
/// stream and unidi stream that are still do not have a type.
|
||||||
/// The function cannot handle:
|
/// The function cannot handle:
|
||||||
/// 1) a `Push(_)`, `Htttp` or `WebTransportStream(_)` stream
|
/// 1) a `Push(_)`, `Http` or `WebTransportStream(_)` stream
|
||||||
/// 2) frames `MaxPushId`, `PriorityUpdateRequest`, `PriorityUpdateRequestPush` or `Goaway` must
|
/// 2) frames `MaxPushId`, `PriorityUpdateRequest`, `PriorityUpdateRequestPush` or `Goaway` must
|
||||||
/// be handled by `Http3Client`/`Server`.
|
/// be handled by `Http3Client`/`Server`.
|
||||||
///
|
///
|
||||||
@@ -551,12 +551,7 @@ impl Http3Connection {
|
|||||||
app_error: AppError,
|
app_error: AppError,
|
||||||
conn: &mut Connection,
|
conn: &mut Connection,
|
||||||
) -> Res<()> {
|
) -> Res<()> {
|
||||||
qinfo!(
|
qinfo!("[{self}] Handle a stream reset stream_id={stream_id} app_err={app_error}");
|
||||||
[self],
|
|
||||||
"Handle a stream reset stream_id={} app_err={}",
|
|
||||||
stream_id,
|
|
||||||
app_error
|
|
||||||
);
|
|
||||||
|
|
||||||
self.close_recv(stream_id, CloseType::ResetRemote(app_error), conn)
|
self.close_recv(stream_id, CloseType::ResetRemote(app_error), conn)
|
||||||
}
|
}
|
||||||
@@ -567,12 +562,7 @@ impl Http3Connection {
|
|||||||
app_error: AppError,
|
app_error: AppError,
|
||||||
conn: &mut Connection,
|
conn: &mut Connection,
|
||||||
) -> Res<()> {
|
) -> Res<()> {
|
||||||
qinfo!(
|
qinfo!("[{self}] Handle stream_stop_sending stream_id={stream_id} app_err={app_error}");
|
||||||
[self],
|
|
||||||
"Handle stream_stop_sending stream_id={} app_err={}",
|
|
||||||
stream_id,
|
|
||||||
app_error
|
|
||||||
);
|
|
||||||
|
|
||||||
if self.send_stream_is_critical(stream_id) {
|
if self.send_stream_is_critical(stream_id) {
|
||||||
return Err(Error::HttpClosedCriticalStream);
|
return Err(Error::HttpClosedCriticalStream);
|
||||||
@@ -585,7 +575,7 @@ impl Http3Connection {
|
|||||||
/// This is called when `neqo_transport::Connection` state has been change to take proper
|
/// This is called when `neqo_transport::Connection` state has been change to take proper
|
||||||
/// actions in the HTTP3 layer.
|
/// actions in the HTTP3 layer.
|
||||||
pub fn handle_state_change(&mut self, conn: &mut Connection, state: &State) -> Res<bool> {
|
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 {
|
match state {
|
||||||
State::Handshaking => {
|
State::Handshaking => {
|
||||||
if self.role == Role::Server
|
if self.role == Role::Server
|
||||||
@@ -649,7 +639,7 @@ impl Http3Connection {
|
|||||||
self.recv_streams.clear();
|
self.recv_streams.clear();
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} 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))
|
Err(Error::HttpInternal(3))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -696,15 +686,10 @@ impl Http3Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NewStreamType::Push(push_id) => {
|
NewStreamType::Push(push_id) => {
|
||||||
qinfo!(
|
qinfo!("[{self}] A new push stream {stream_id} push_id:{push_id}");
|
||||||
[self],
|
|
||||||
"A new push stream {} push_id:{}.",
|
|
||||||
stream_id,
|
|
||||||
push_id
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
NewStreamType::Decoder => {
|
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.check_stream_exists(Http3StreamType::Decoder)?;
|
||||||
self.recv_streams.insert(
|
self.recv_streams.insert(
|
||||||
stream_id,
|
stream_id,
|
||||||
@@ -715,7 +700,7 @@ impl Http3Connection {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
NewStreamType::Encoder => {
|
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.check_stream_exists(Http3StreamType::Encoder)?;
|
||||||
self.recv_streams.insert(
|
self.recv_streams.insert(
|
||||||
stream_id,
|
stream_id,
|
||||||
@@ -726,7 +711,7 @@ impl Http3Connection {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
NewStreamType::Http(_) => {
|
NewStreamType::Http(_) => {
|
||||||
qinfo!([self], "A new http stream {}.", stream_id);
|
qinfo!("[{self}] A new http stream {stream_id}");
|
||||||
}
|
}
|
||||||
NewStreamType::WebTransportStream(session_id) => {
|
NewStreamType::WebTransportStream(session_id) => {
|
||||||
let session_exists = self
|
let session_exists = self
|
||||||
@@ -737,14 +722,13 @@ impl Http3Connection {
|
|||||||
conn.stream_stop_sending(stream_id, Error::HttpStreamCreation.code())?;
|
conn.stream_stop_sending(stream_id, Error::HttpStreamCreation.code())?;
|
||||||
return Ok(ReceiveOutput::NoOutput);
|
return Ok(ReceiveOutput::NoOutput);
|
||||||
}
|
}
|
||||||
// set incoming WebTransport streams to be fair (share bandwidth)
|
// Set incoming WebTransport streams to be fair (share bandwidth).
|
||||||
conn.stream_fairness(stream_id, true).ok();
|
// We may call this with an invalid stream ID, so ignore that error.
|
||||||
qinfo!(
|
match conn.stream_fairness(stream_id, true) {
|
||||||
[self],
|
Ok(()) | Err(neqo_transport::Error::InvalidStreamId) => (),
|
||||||
"A new WebTransport stream {} for session {}.",
|
Err(e) => return Err(Error::from(e)),
|
||||||
stream_id,
|
};
|
||||||
session_id
|
qinfo!("[{self}] A new WebTransport stream {stream_id} for session {session_id}");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
NewStreamType::Unknown => {
|
NewStreamType::Unknown => {
|
||||||
conn.stream_stop_sending(stream_id, Error::HttpStreamCreation.code())?;
|
conn.stream_stop_sending(stream_id, Error::HttpStreamCreation.code())?;
|
||||||
@@ -764,7 +748,7 @@ impl Http3Connection {
|
|||||||
|
|
||||||
/// This is called when an application closes the connection.
|
/// This is called when an application closes the connection.
|
||||||
pub fn close(&mut self, error: AppError) {
|
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));
|
self.state = Http3State::Closing(CloseReason::Application(error));
|
||||||
if (!self.send_streams.is_empty() || !self.recv_streams.is_empty()) && (error == 0) {
|
if (!self.send_streams.is_empty() || !self.recv_streams.is_empty()) && (error == 0) {
|
||||||
qwarn!("close(0) called when streams still active");
|
qwarn!("close(0) called when streams still active");
|
||||||
@@ -805,7 +789,7 @@ impl Http3Connection {
|
|||||||
Ok((_, false)) => {}
|
Ok((_, false)) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if e.stream_reset_error() && !self.recv_stream_is_critical(stream_id) {
|
if e.stream_reset_error() && !self.recv_stream_is_critical(stream_id) {
|
||||||
mem::drop(conn.stream_stop_sending(stream_id, e.code()));
|
drop(conn.stream_stop_sending(stream_id, e.code()));
|
||||||
self.close_recv(stream_id, CloseType::LocalError(e.code()), conn)?;
|
self.close_recv(stream_id, CloseType::LocalError(e.code()), conn)?;
|
||||||
return Ok((U::default(), false));
|
return Ok((U::default(), false));
|
||||||
}
|
}
|
||||||
@@ -850,8 +834,7 @@ impl Http3Connection {
|
|||||||
T: AsRequestTarget<'t> + ?Sized + Debug,
|
T: AsRequestTarget<'t> + ?Sized + Debug,
|
||||||
{
|
{
|
||||||
qinfo!(
|
qinfo!(
|
||||||
[self],
|
"[{self}] Fetch method={} target: {:?}",
|
||||||
"Fetch method={} target: {:?}",
|
|
||||||
request.method,
|
request.method,
|
||||||
request.target,
|
request.target,
|
||||||
);
|
);
|
||||||
@@ -902,7 +885,7 @@ impl Http3Connection {
|
|||||||
MessageType::Request,
|
MessageType::Request,
|
||||||
stream_type,
|
stream_type,
|
||||||
stream_id,
|
stream_id,
|
||||||
self.qpack_encoder.clone(),
|
Rc::clone(&self.qpack_encoder),
|
||||||
send_events,
|
send_events,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -951,7 +934,7 @@ impl Http3Connection {
|
|||||||
stream_id: StreamId,
|
stream_id: StreamId,
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
) -> Res<(usize, bool)> {
|
) -> Res<(usize, bool)> {
|
||||||
qdebug!([self], "read_data from stream {}.", stream_id);
|
qdebug!("[{self}] read_data from stream {stream_id}");
|
||||||
let res = self
|
let res = self
|
||||||
.recv_streams
|
.recv_streams
|
||||||
.get_mut(&stream_id)
|
.get_mut(&stream_id)
|
||||||
@@ -968,12 +951,7 @@ impl Http3Connection {
|
|||||||
stream_id: StreamId,
|
stream_id: StreamId,
|
||||||
error: AppError,
|
error: AppError,
|
||||||
) -> Res<()> {
|
) -> Res<()> {
|
||||||
qinfo!(
|
qinfo!("[{self}] Reset sending side of stream {stream_id} error={error}");
|
||||||
[self],
|
|
||||||
"Reset sending side of stream {} error={}.",
|
|
||||||
stream_id,
|
|
||||||
error
|
|
||||||
);
|
|
||||||
|
|
||||||
if self.send_stream_is_critical(stream_id) {
|
if self.send_stream_is_critical(stream_id) {
|
||||||
return Err(Error::InvalidStreamId);
|
return Err(Error::InvalidStreamId);
|
||||||
@@ -990,12 +968,7 @@ impl Http3Connection {
|
|||||||
stream_id: StreamId,
|
stream_id: StreamId,
|
||||||
error: AppError,
|
error: AppError,
|
||||||
) -> Res<()> {
|
) -> Res<()> {
|
||||||
qinfo!(
|
qinfo!("[{self}] Send stop sending for stream {stream_id} error={error}");
|
||||||
[self],
|
|
||||||
"Send stop sending for stream {} error={}.",
|
|
||||||
stream_id,
|
|
||||||
error
|
|
||||||
);
|
|
||||||
if self.recv_stream_is_critical(stream_id) {
|
if self.recv_stream_is_critical(stream_id) {
|
||||||
return Err(Error::InvalidStreamId);
|
return Err(Error::InvalidStreamId);
|
||||||
}
|
}
|
||||||
@@ -1043,7 +1016,7 @@ impl Http3Connection {
|
|||||||
error: AppError,
|
error: AppError,
|
||||||
conn: &mut Connection,
|
conn: &mut Connection,
|
||||||
) -> Res<()> {
|
) -> Res<()> {
|
||||||
qinfo!([self], "cancel_fetch {} error={}.", stream_id, error);
|
qinfo!("[{self}] cancel_fetch {stream_id} error={error}");
|
||||||
let send_stream = self.send_streams.get(&stream_id);
|
let send_stream = self.send_streams.get(&stream_id);
|
||||||
let recv_stream = self.recv_streams.get(&stream_id);
|
let recv_stream = self.recv_streams.get(&stream_id);
|
||||||
match (send_stream, recv_stream) {
|
match (send_stream, recv_stream) {
|
||||||
@@ -1056,7 +1029,7 @@ impl Http3Connection {
|
|||||||
return Err(Error::InvalidStreamId);
|
return Err(Error::InvalidStreamId);
|
||||||
}
|
}
|
||||||
// Stream may be already be closed and we may get an error here, but we do not care.
|
// Stream may be already be closed and we may get an error here, but we do not care.
|
||||||
mem::drop(self.stream_reset_send(conn, stream_id, error));
|
drop(self.stream_reset_send(conn, stream_id, error));
|
||||||
}
|
}
|
||||||
(None, Some(s)) => {
|
(None, Some(s)) => {
|
||||||
if !matches!(
|
if !matches!(
|
||||||
@@ -1069,7 +1042,7 @@ impl Http3Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Stream may be already be closed and we may get an error here, but we do not care.
|
// Stream may be already be closed and we may get an error here, but we do not care.
|
||||||
mem::drop(self.stream_stop_sending(conn, stream_id, error));
|
drop(self.stream_stop_sending(conn, stream_id, error));
|
||||||
}
|
}
|
||||||
(Some(s), Some(r)) => {
|
(Some(s), Some(r)) => {
|
||||||
debug_assert_eq!(s.stream_type(), r.stream_type());
|
debug_assert_eq!(s.stream_type(), r.stream_type());
|
||||||
@@ -1080,9 +1053,9 @@ impl Http3Connection {
|
|||||||
return Err(Error::InvalidStreamId);
|
return Err(Error::InvalidStreamId);
|
||||||
}
|
}
|
||||||
// Stream may be already be closed and we may get an error here, but we do not care.
|
// Stream may be already be closed and we may get an error here, but we do not care.
|
||||||
mem::drop(self.stream_reset_send(conn, stream_id, error));
|
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.
|
// Stream may be already be closed and we may get an error here, but we do not care.
|
||||||
mem::drop(self.stream_stop_sending(conn, stream_id, error));
|
drop(self.stream_stop_sending(conn, stream_id, error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -1090,7 +1063,7 @@ impl Http3Connection {
|
|||||||
|
|
||||||
/// This is called when an application wants to close the sending side of a stream.
|
/// 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<()> {
|
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());
|
debug_assert!(self.state.active());
|
||||||
let send_stream = self
|
let send_stream = self
|
||||||
.send_streams
|
.send_streams
|
||||||
@@ -1098,7 +1071,7 @@ impl Http3Connection {
|
|||||||
.ok_or(Error::InvalidStreamId)?;
|
.ok_or(Error::InvalidStreamId)?;
|
||||||
// The following function may return InvalidStreamId from the transport layer if the stream
|
// The following function may return InvalidStreamId from the transport layer if the stream
|
||||||
// has been closed already. It is ok to ignore it here.
|
// has been closed already. It is ok to ignore it here.
|
||||||
mem::drop(send_stream.close(conn));
|
drop(send_stream.close(conn));
|
||||||
if send_stream.done() {
|
if send_stream.done() {
|
||||||
self.remove_send_stream(stream_id, conn);
|
self.remove_send_stream(stream_id, conn);
|
||||||
} else if send_stream.has_data_to_send() {
|
} else if send_stream.has_data_to_send() {
|
||||||
@@ -1117,7 +1090,7 @@ impl Http3Connection {
|
|||||||
where
|
where
|
||||||
T: AsRequestTarget<'x> + ?Sized + Debug,
|
T: AsRequestTarget<'x> + ?Sized + Debug,
|
||||||
{
|
{
|
||||||
qinfo!([self], "Create WebTransport");
|
qinfo!("[{self}] Create WebTransport");
|
||||||
if !self.webtransport_enabled() {
|
if !self.webtransport_enabled() {
|
||||||
return Err(Error::Unavailable);
|
return Err(Error::Unavailable);
|
||||||
}
|
}
|
||||||
@@ -1133,8 +1106,8 @@ impl Http3Connection {
|
|||||||
)));
|
)));
|
||||||
self.add_streams(
|
self.add_streams(
|
||||||
id,
|
id,
|
||||||
Box::new(extended_conn.clone()),
|
Box::new(Rc::clone(&extended_conn)),
|
||||||
Box::new(extended_conn.clone()),
|
Box::new(Rc::clone(&extended_conn)),
|
||||||
);
|
);
|
||||||
|
|
||||||
let final_headers = Self::create_fetch_headers(&RequestDescription {
|
let final_headers = Self::create_fetch_headers(&RequestDescription {
|
||||||
@@ -1158,10 +1131,7 @@ impl Http3Connection {
|
|||||||
events: Box<dyn ExtendedConnectEvents>,
|
events: Box<dyn ExtendedConnectEvents>,
|
||||||
accept_res: &WebTransportSessionAcceptAction,
|
accept_res: &WebTransportSessionAcceptAction,
|
||||||
) -> Res<()> {
|
) -> Res<()> {
|
||||||
qtrace!(
|
qtrace!("Respond to WebTransport session with accept={accept_res}");
|
||||||
"Respond to WebTransport session with accept={}.",
|
|
||||||
accept_res
|
|
||||||
);
|
|
||||||
if !self.webtransport_enabled() {
|
if !self.webtransport_enabled() {
|
||||||
return Err(Error::Unavailable);
|
return Err(Error::Unavailable);
|
||||||
}
|
}
|
||||||
@@ -1177,6 +1147,7 @@ impl Http3Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let send_stream = self.send_streams.get_mut(&stream_id);
|
let send_stream = self.send_streams.get_mut(&stream_id);
|
||||||
|
conn.stream_keep_alive(stream_id, true)?;
|
||||||
|
|
||||||
match (send_stream, recv_stream, accept_res) {
|
match (send_stream, recv_stream, accept_res) {
|
||||||
(None, None, _) => Err(Error::InvalidStreamId),
|
(None, None, _) => Err(Error::InvalidStreamId),
|
||||||
@@ -1191,7 +1162,7 @@ impl Http3Connection {
|
|||||||
.send_headers(headers, conn)
|
.send_headers(headers, conn)
|
||||||
.is_ok()
|
.is_ok()
|
||||||
{
|
{
|
||||||
mem::drop(self.stream_close_send(conn, stream_id));
|
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
|
// TODO issue 1294: add a timer to clean up the recv_stream if the peer does not
|
||||||
// do that in a short time.
|
// do that in a short time.
|
||||||
self.streams_with_pending_data.insert(stream_id);
|
self.streams_with_pending_data.insert(stream_id);
|
||||||
@@ -1216,7 +1187,7 @@ impl Http3Connection {
|
|||||||
)));
|
)));
|
||||||
self.add_streams(
|
self.add_streams(
|
||||||
stream_id,
|
stream_id,
|
||||||
Box::new(extended_conn.clone()),
|
Box::new(Rc::clone(&extended_conn)),
|
||||||
Box::new(extended_conn),
|
Box::new(extended_conn),
|
||||||
);
|
);
|
||||||
self.streams_with_pending_data.insert(stream_id);
|
self.streams_with_pending_data.insert(stream_id);
|
||||||
@@ -1236,7 +1207,7 @@ impl Http3Connection {
|
|||||||
error: u32,
|
error: u32,
|
||||||
message: &str,
|
message: &str,
|
||||||
) -> Res<()> {
|
) -> Res<()> {
|
||||||
qtrace!("Clos WebTransport session {:?}", session_id);
|
qtrace!("Close WebTransport session {session_id:?}");
|
||||||
let send_stream = self
|
let send_stream = self
|
||||||
.send_streams
|
.send_streams
|
||||||
.get_mut(&session_id)
|
.get_mut(&session_id)
|
||||||
@@ -1262,11 +1233,7 @@ impl Http3Connection {
|
|||||||
send_events: Box<dyn SendStreamEvents>,
|
send_events: Box<dyn SendStreamEvents>,
|
||||||
recv_events: Box<dyn RecvStreamEvents>,
|
recv_events: Box<dyn RecvStreamEvents>,
|
||||||
) -> Res<StreamId> {
|
) -> Res<StreamId> {
|
||||||
qtrace!(
|
qtrace!("Create new WebTransport stream session={session_id} type={stream_type:?}");
|
||||||
"Create new WebTransport stream session={} type={:?}",
|
|
||||||
session_id,
|
|
||||||
stream_type
|
|
||||||
);
|
|
||||||
|
|
||||||
let wt = self
|
let wt = self
|
||||||
.recv_streams
|
.recv_streams
|
||||||
@@ -1282,8 +1249,7 @@ impl Http3Connection {
|
|||||||
.stream_create(stream_type)
|
.stream_create(stream_type)
|
||||||
.map_err(|e| Error::map_stream_create_errors(&e))?;
|
.map_err(|e| Error::map_stream_create_errors(&e))?;
|
||||||
// Set outgoing WebTransport streams to be fair (share bandwidth)
|
// Set outgoing WebTransport streams to be fair (share bandwidth)
|
||||||
// This really can't fail, panics if it does
|
conn.stream_fairness(stream_id, true)?;
|
||||||
conn.stream_fairness(stream_id, true).unwrap();
|
|
||||||
|
|
||||||
self.webtransport_create_stream_internal(
|
self.webtransport_create_stream_internal(
|
||||||
wt,
|
wt,
|
||||||
@@ -1303,11 +1269,7 @@ impl Http3Connection {
|
|||||||
send_events: Box<dyn SendStreamEvents>,
|
send_events: Box<dyn SendStreamEvents>,
|
||||||
recv_events: Box<dyn RecvStreamEvents>,
|
recv_events: Box<dyn RecvStreamEvents>,
|
||||||
) -> Res<()> {
|
) -> Res<()> {
|
||||||
qtrace!(
|
qtrace!("Create new WebTransport stream session={session_id} stream_id={stream_id}");
|
||||||
"Create new WebTransport stream session={} stream_id={}",
|
|
||||||
session_id,
|
|
||||||
stream_id
|
|
||||||
);
|
|
||||||
|
|
||||||
let wt = self
|
let wt = self
|
||||||
.recv_streams
|
.recv_streams
|
||||||
@@ -1336,7 +1298,6 @@ impl Http3Connection {
|
|||||||
recv_events: Box<dyn RecvStreamEvents>,
|
recv_events: Box<dyn RecvStreamEvents>,
|
||||||
local: bool,
|
local: bool,
|
||||||
) {
|
) {
|
||||||
// TODO conn.stream_keep_alive(stream_id, true)?;
|
|
||||||
webtransport_session.borrow_mut().add_stream(stream_id);
|
webtransport_session.borrow_mut().add_stream(stream_id);
|
||||||
if stream_id.stream_type() == StreamType::UniDi {
|
if stream_id.stream_type() == StreamType::UniDi {
|
||||||
if local {
|
if local {
|
||||||
@@ -1368,7 +1329,7 @@ impl Http3Connection {
|
|||||||
stream_id,
|
stream_id,
|
||||||
session_id,
|
session_id,
|
||||||
send_events,
|
send_events,
|
||||||
webtransport_session.clone(),
|
Rc::clone(&webtransport_session),
|
||||||
local,
|
local,
|
||||||
)),
|
)),
|
||||||
Box::new(WebTransportRecvStream::new(
|
Box::new(WebTransportRecvStream::new(
|
||||||
@@ -1401,7 +1362,7 @@ impl Http3Connection {
|
|||||||
/// `PriorityUpdateRequestPush` which handling is specific to the client and server, we must
|
/// `PriorityUpdateRequestPush` which handling is specific to the client and server, we must
|
||||||
/// give them to the specific client/server handler.
|
/// give them to the specific client/server handler.
|
||||||
fn handle_control_frame(&mut self, f: HFrame) -> Res<Option<HFrame>> {
|
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 { .. })
|
if !matches!(f, HFrame::Settings { .. })
|
||||||
&& !matches!(
|
&& !matches!(
|
||||||
self.settings_state,
|
self.settings_state,
|
||||||
@@ -1432,7 +1393,7 @@ impl Http3Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_settings(&mut self, new_settings: HSettings) -> Res<()> {
|
fn handle_settings(&mut self, new_settings: HSettings) -> Res<()> {
|
||||||
qdebug!([self], "Handle SETTINGS frame.");
|
qdebug!("[{self}] Handle SETTINGS frame");
|
||||||
match &self.settings_state {
|
match &self.settings_state {
|
||||||
Http3RemoteSettingsState::NotReceived => {
|
Http3RemoteSettingsState::NotReceived => {
|
||||||
self.set_qpack_settings(&new_settings)?;
|
self.set_qpack_settings(&new_settings)?;
|
||||||
@@ -1455,11 +1416,7 @@ impl Http3Connection {
|
|||||||
}
|
}
|
||||||
if zero_rtt_value > new_value {
|
if zero_rtt_value > new_value {
|
||||||
qerror!(
|
qerror!(
|
||||||
[self],
|
"[{self}] The new({new_value}) and the old value({zero_rtt_value}) of setting {st:?} do not match"
|
||||||
"The new({}) and the old value({}) of setting {:?} do not match",
|
|
||||||
new_value,
|
|
||||||
zero_rtt_value,
|
|
||||||
st
|
|
||||||
);
|
);
|
||||||
return Err(Error::HttpSettings);
|
return Err(Error::HttpSettings);
|
||||||
}
|
}
|
||||||
@@ -1478,7 +1435,7 @@ impl Http3Connection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if qpack_changed {
|
if qpack_changed {
|
||||||
qdebug!([self], "Settings after zero rtt differ.");
|
qdebug!("[{self}] Settings after zero rtt differ");
|
||||||
self.set_qpack_settings(&(new_settings))?;
|
self.set_qpack_settings(&(new_settings))?;
|
||||||
}
|
}
|
||||||
self.settings_state = Http3RemoteSettingsState::Received(new_settings);
|
self.settings_state = Http3RemoteSettingsState::Received(new_settings);
|
||||||
@@ -1577,20 +1534,20 @@ impl Http3Connection {
|
|||||||
let (recv, send) = wt.borrow_mut().take_sub_streams();
|
let (recv, send) = wt.borrow_mut().take_sub_streams();
|
||||||
|
|
||||||
for id in recv {
|
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
|
// Use CloseType::ResetRemote so that an event will be sent. CloseType::LocalError would
|
||||||
// have the same effect.
|
// have the same effect.
|
||||||
if let Some(mut s) = self.recv_streams.remove(&id) {
|
if let Some(mut s) = self.recv_streams.remove(&id) {
|
||||||
mem::drop(s.reset(CloseType::ResetRemote(Error::HttpRequestCancelled.code())));
|
drop(s.reset(CloseType::ResetRemote(Error::HttpRequestCancelled.code())));
|
||||||
}
|
}
|
||||||
mem::drop(conn.stream_stop_sending(id, Error::HttpRequestCancelled.code()));
|
drop(conn.stream_stop_sending(id, Error::HttpRequestCancelled.code()));
|
||||||
}
|
}
|
||||||
for id in send {
|
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) {
|
if let Some(mut s) = self.send_streams.remove(&id) {
|
||||||
s.handle_stop_sending(CloseType::ResetRemote(Error::HttpRequestCancelled.code()));
|
s.handle_stop_sending(CloseType::ResetRemote(Error::HttpRequestCancelled.code()));
|
||||||
}
|
}
|
||||||
mem::drop(conn.stream_reset_send(id, Error::HttpRequestCancelled.code()));
|
drop(conn.stream_reset_send(id, Error::HttpRequestCancelled.code()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1600,7 +1557,7 @@ impl Http3Connection {
|
|||||||
conn: &mut Connection,
|
conn: &mut Connection,
|
||||||
) -> Option<Box<dyn RecvStream>> {
|
) -> Option<Box<dyn RecvStream>> {
|
||||||
let stream = self.recv_streams.remove(&stream_id);
|
let stream = self.recv_streams.remove(&stream_id);
|
||||||
if let Some(ref s) = stream {
|
if let Some(s) = &stream {
|
||||||
if s.stream_type() == Http3StreamType::ExtendedConnect {
|
if s.stream_type() == Http3StreamType::ExtendedConnect {
|
||||||
self.send_streams.remove(&stream_id).unwrap();
|
self.send_streams.remove(&stream_id).unwrap();
|
||||||
if let Some(wt) = s.webtransport() {
|
if let Some(wt) = s.webtransport() {
|
||||||
@@ -1617,7 +1574,7 @@ impl Http3Connection {
|
|||||||
conn: &mut Connection,
|
conn: &mut Connection,
|
||||||
) -> Option<Box<dyn SendStream>> {
|
) -> Option<Box<dyn SendStream>> {
|
||||||
let stream = self.send_streams.remove(&stream_id);
|
let stream = self.send_streams.remove(&stream_id);
|
||||||
if let Some(ref s) = stream {
|
if let Some(s) = &stream {
|
||||||
if s.stream_type() == Http3StreamType::ExtendedConnect {
|
if s.stream_type() == Http3StreamType::ExtendedConnect {
|
||||||
if let Some(wt) = self.recv_streams.remove(&stream_id).unwrap().webtransport() {
|
if let Some(wt) = self.recv_streams.remove(&stream_id).unwrap().webtransport() {
|
||||||
self.remove_extended_connect(&wt, conn);
|
self.remove_extended_connect(&wt, conn);
|
||||||
|
|||||||
770
third_party/rust/neqo-http3/src/connection_client.rs
vendored
770
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 std::{rc::Rc, time::Instant};
|
||||||
|
|
||||||
use neqo_common::{event::Provider, qdebug, qinfo, qtrace, Header, MessageType, Role};
|
use neqo_common::{event::Provider as _, qdebug, qinfo, qtrace, Header, MessageType, Role};
|
||||||
use neqo_transport::{
|
use neqo_transport::{
|
||||||
AppError, Connection, ConnectionEvent, DatagramTracking, StreamId, StreamType,
|
AppError, Connection, ConnectionEvent, DatagramTracking, StreamId, StreamType,
|
||||||
};
|
};
|
||||||
@@ -102,7 +102,7 @@ impl Http3ServerHandler {
|
|||||||
///
|
///
|
||||||
/// An error will be returned if stream does not exist.
|
/// An error will be returned if stream does not exist.
|
||||||
pub fn stream_close_send(&mut self, stream_id: StreamId, conn: &mut Connection) -> Res<()> {
|
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.base_handler.stream_close_send(conn, stream_id)?;
|
||||||
self.needs_processing = true;
|
self.needs_processing = true;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -120,7 +120,7 @@ impl Http3ServerHandler {
|
|||||||
error: AppError,
|
error: AppError,
|
||||||
conn: &mut Connection,
|
conn: &mut Connection,
|
||||||
) -> Res<()> {
|
) -> Res<()> {
|
||||||
qinfo!([self], "cancel_fetch {} error={}.", stream_id, error);
|
qinfo!("[{self}] cancel_fetch {stream_id} error={error}");
|
||||||
self.needs_processing = true;
|
self.needs_processing = true;
|
||||||
self.base_handler.cancel_fetch(stream_id, error, conn)
|
self.base_handler.cancel_fetch(stream_id, error, conn)
|
||||||
}
|
}
|
||||||
@@ -131,7 +131,7 @@ impl Http3ServerHandler {
|
|||||||
error: AppError,
|
error: AppError,
|
||||||
conn: &mut Connection,
|
conn: &mut Connection,
|
||||||
) -> Res<()> {
|
) -> Res<()> {
|
||||||
qinfo!([self], "stream_stop_sending {} error={}.", stream_id, error);
|
qinfo!("[{self}] stream_stop_sending {stream_id} error={error}");
|
||||||
self.needs_processing = true;
|
self.needs_processing = true;
|
||||||
self.base_handler
|
self.base_handler
|
||||||
.stream_stop_sending(conn, stream_id, error)
|
.stream_stop_sending(conn, stream_id, error)
|
||||||
@@ -143,7 +143,7 @@ impl Http3ServerHandler {
|
|||||||
error: AppError,
|
error: AppError,
|
||||||
conn: &mut Connection,
|
conn: &mut Connection,
|
||||||
) -> Res<()> {
|
) -> Res<()> {
|
||||||
qinfo!([self], "stream_reset_send {} error={}.", stream_id, error);
|
qinfo!("[{self}] stream_reset_send {stream_id} error={error}");
|
||||||
self.needs_processing = true;
|
self.needs_processing = true;
|
||||||
self.base_handler.stream_reset_send(conn, stream_id, error)
|
self.base_handler.stream_reset_send(conn, stream_id, error)
|
||||||
}
|
}
|
||||||
@@ -215,7 +215,7 @@ impl Http3ServerHandler {
|
|||||||
|
|
||||||
/// Process HTTTP3 layer.
|
/// Process HTTTP3 layer.
|
||||||
pub fn process_http3(&mut self, conn: &mut Connection, now: Instant) {
|
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(..)) {
|
if matches!(self.base_handler.state(), Http3State::Closed(..)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -254,7 +254,7 @@ impl Http3ServerHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn close(&mut self, conn: &mut Connection, now: Instant, err: &Error) {
|
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}"));
|
conn.close(now, err.code(), format!("{err}"));
|
||||||
self.base_handler.close(err.code());
|
self.base_handler.close(err.code());
|
||||||
self.events
|
self.events
|
||||||
@@ -263,9 +263,9 @@ impl Http3ServerHandler {
|
|||||||
|
|
||||||
// If this return an error the connection must be closed.
|
// If this return an error the connection must be closed.
|
||||||
fn check_connection_events(&mut self, conn: &mut Connection, now: Instant) -> Res<()> {
|
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() {
|
while let Some(e) = conn.next_event() {
|
||||||
qdebug!([self], "check_connection_events - event {e:?}.");
|
qdebug!("[{self}] check_connection_events - event {e:?}");
|
||||||
match e {
|
match e {
|
||||||
ConnectionEvent::NewStream { stream_id } => {
|
ConnectionEvent::NewStream { stream_id } => {
|
||||||
self.base_handler.add_new_stream(stream_id);
|
self.base_handler.add_new_stream(stream_id);
|
||||||
@@ -325,7 +325,7 @@ impl Http3ServerHandler {
|
|||||||
MessageType::Response,
|
MessageType::Response,
|
||||||
Http3StreamType::Http,
|
Http3StreamType::Http,
|
||||||
stream_id,
|
stream_id,
|
||||||
self.base_handler.qpack_encoder.clone(),
|
Rc::clone(&self.base_handler.qpack_encoder),
|
||||||
Box::new(self.events.clone()),
|
Box::new(self.events.clone()),
|
||||||
)),
|
)),
|
||||||
Box::new(RecvMessage::new(
|
Box::new(RecvMessage::new(
|
||||||
@@ -387,7 +387,7 @@ impl Http3ServerHandler {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
_ => unreachable!(
|
_ => 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,
|
stream_id: StreamId,
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
) -> Res<(usize, bool)> {
|
) -> 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);
|
let res = self.base_handler.read_data(conn, stream_id, buf);
|
||||||
if let Err(e) = &res {
|
if let Err(e) = &res {
|
||||||
if e.connection_error() {
|
if e.connection_error() {
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ impl ControlStreamLocal {
|
|||||||
|
|
||||||
/// Create a control stream.
|
/// Create a control stream.
|
||||||
pub fn create(&mut self, conn: &mut Connection) -> Res<()> {
|
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.init(conn.stream_create(StreamType::UniDi)?);
|
||||||
self.stream
|
self.stream
|
||||||
.buffer(&[u8::try_from(HTTP3_UNI_STREAM_TYPE_CONTROL).unwrap()]);
|
.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.
|
/// Check if a stream is the control stream and read received data.
|
||||||
pub fn receive_single(&mut self, conn: &mut Connection) -> Res<Option<HFrame>> {
|
pub fn receive_single(&mut self, conn: &mut Connection) -> Res<Option<HFrame>> {
|
||||||
qdebug!([self], "Receiving data.");
|
qdebug!("[{self}] Receiving data");
|
||||||
match self
|
match self
|
||||||
.frame_reader
|
.frame_reader
|
||||||
.receive(&mut StreamReaderConnectionWrapper::new(
|
.receive(&mut StreamReaderConnectionWrapper::new(
|
||||||
@@ -45,7 +45,7 @@ impl ControlStreamRemote {
|
|||||||
))? {
|
))? {
|
||||||
(_, true) => Err(Error::HttpClosedCriticalStream),
|
(_, true) => Err(Error::HttpClosedCriticalStream),
|
||||||
(s, false) => {
|
(s, false) => {
|
||||||
qdebug!([self], "received {:?}", s);
|
qdebug!("[{self}] received {s:?}");
|
||||||
Ok(s)
|
Ok(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ mod sessions;
|
|||||||
mod streams;
|
mod streams;
|
||||||
use std::{cell::RefCell, rc::Rc, time::Duration};
|
use std::{cell::RefCell, rc::Rc, time::Duration};
|
||||||
|
|
||||||
use neqo_common::event::Provider;
|
use neqo_common::{event::Provider as _, header::HeadersExt as _};
|
||||||
use neqo_crypto::AuthenticationStatus;
|
use neqo_crypto::AuthenticationStatus;
|
||||||
use neqo_transport::{ConnectionParameters, Pmtud, StreamId, StreamType};
|
use neqo_transport::{ConnectionParameters, Pmtud, StreamId, StreamType};
|
||||||
use test_fixture::{
|
use test_fixture::{
|
||||||
@@ -60,6 +60,13 @@ pub fn default_http3_server(server_params: Http3Parameters) -> Http3Server {
|
|||||||
.expect("create a server")
|
.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) {
|
fn exchange_packets(client: &mut Http3Client, server: &mut Http3Server) {
|
||||||
let mut out = None;
|
let mut out = None;
|
||||||
loop {
|
loop {
|
||||||
@@ -71,7 +78,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) {
|
fn connect_with(client: &mut Http3Client, server: &mut Http3Server) {
|
||||||
assert_eq!(client.state(), Http3State::Initializing);
|
assert_eq!(client.state(), Http3State::Initializing);
|
||||||
let out = client.process_output(now());
|
let out = client.process_output(now());
|
||||||
@@ -92,13 +99,13 @@ fn connect_with(client: &mut Http3Client, server: &mut Http3Server) {
|
|||||||
|
|
||||||
assert_eq!(client.state(), Http3State::Connected);
|
assert_eq!(client.state(), Http3State::Connected);
|
||||||
|
|
||||||
// Exchange H3 setttings
|
// Exchange H3 settings
|
||||||
let out = server.process(out.dgram(), now());
|
let out = server.process(out.dgram(), now());
|
||||||
let out = client.process(out.dgram(), now());
|
let out = client.process(out.dgram(), now());
|
||||||
let out = server.process(out.dgram(), now());
|
let out = server.process(out.dgram(), now());
|
||||||
let out = client.process(out.dgram(), now());
|
let out = client.process(out.dgram(), now());
|
||||||
let out = server.process(out.dgram(), now());
|
let out = server.process(out.dgram(), now());
|
||||||
std::mem::drop(client.process(out.dgram(), now()));
|
drop(client.process(out.dgram(), now()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn connect(
|
fn connect(
|
||||||
@@ -148,14 +155,7 @@ impl WtTest {
|
|||||||
session,
|
session,
|
||||||
headers,
|
headers,
|
||||||
}) => {
|
}) => {
|
||||||
assert!(
|
assert_wt(&headers);
|
||||||
headers
|
|
||||||
.iter()
|
|
||||||
.any(|h| h.name() == ":method" && h.value() == "CONNECT")
|
|
||||||
&& headers
|
|
||||||
.iter()
|
|
||||||
.any(|h| h.name() == ":protocol" && h.value() == "webtransport")
|
|
||||||
);
|
|
||||||
session.response(accept).unwrap();
|
session.response(accept).unwrap();
|
||||||
wt_server_session = Some(session);
|
wt_server_session = Some(session);
|
||||||
}
|
}
|
||||||
@@ -183,7 +183,7 @@ impl WtTest {
|
|||||||
}) if (
|
}) if (
|
||||||
stream_id == wt_session_id &&
|
stream_id == wt_session_id &&
|
||||||
status == 200 &&
|
status == 200 &&
|
||||||
headers.contains(&Header::new(":status", "200"))
|
headers.contains_header(":status", "200")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use neqo_common::{event::Provider, Encoder};
|
use neqo_common::{event::Provider as _, Encoder};
|
||||||
use neqo_crypto::AuthenticationStatus;
|
use neqo_crypto::AuthenticationStatus;
|
||||||
use neqo_transport::{CloseReason, Connection, StreamType};
|
use neqo_transport::{CloseReason, Connection, StreamType};
|
||||||
use test_fixture::{default_server_h3, now};
|
use test_fixture::{default_server_h3, now};
|
||||||
@@ -88,7 +88,7 @@ fn zero_rtt(
|
|||||||
// exchange token
|
// exchange token
|
||||||
let out = server.process_output(now());
|
let out = server.process_output(now());
|
||||||
// We do not have a token so we need to wait for a resumption token timer to trigger.
|
// We do not have a token so we need to wait for a resumption token timer to trigger.
|
||||||
std::mem::drop(client.process(out.dgram(), now() + Duration::from_millis(250)));
|
drop(client.process(out.dgram(), now() + Duration::from_millis(250)));
|
||||||
assert_eq!(client.state(), Http3State::Connected);
|
assert_eq!(client.state(), Http3State::Connected);
|
||||||
let token = client
|
let token = client
|
||||||
.events()
|
.events()
|
||||||
@@ -105,7 +105,7 @@ fn zero_rtt(
|
|||||||
let mut server = default_http3_server(Http3Parameters::default().webtransport(server_resumed));
|
let mut server = default_http3_server(Http3Parameters::default().webtransport(server_resumed));
|
||||||
client
|
client
|
||||||
.enable_resumption(now(), &token)
|
.enable_resumption(now(), &token)
|
||||||
.expect("Set resumption token.");
|
.expect("Set resumption token");
|
||||||
assert_eq!(client.state(), Http3State::ZeroRtt);
|
assert_eq!(client.state(), Http3State::ZeroRtt);
|
||||||
|
|
||||||
exchange_packets(&mut client, &mut server);
|
exchange_packets(&mut client, &mut server);
|
||||||
|
|||||||
@@ -4,16 +4,14 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::mem;
|
use neqo_common::{event::Provider as _, header::HeadersExt as _, Encoder};
|
||||||
|
|
||||||
use neqo_common::{event::Provider, Encoder};
|
|
||||||
use neqo_transport::StreamType;
|
use neqo_transport::StreamType;
|
||||||
use test_fixture::now;
|
use test_fixture::now;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
features::extended_connect::{
|
features::extended_connect::{
|
||||||
tests::webtransport::{
|
tests::webtransport::{
|
||||||
default_http3_client, default_http3_server, wt_default_parameters, WtTest,
|
assert_wt, default_http3_client, default_http3_server, wt_default_parameters, WtTest,
|
||||||
},
|
},
|
||||||
SessionCloseReason,
|
SessionCloseReason,
|
||||||
},
|
},
|
||||||
@@ -26,7 +24,7 @@ use crate::{
|
|||||||
#[test]
|
#[test]
|
||||||
fn wt_session() {
|
fn wt_session() {
|
||||||
let mut wt = WtTest::new();
|
let mut wt = WtTest::new();
|
||||||
mem::drop(wt.create_wt_session());
|
drop(wt.create_wt_session());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -134,14 +132,7 @@ fn wt_session_response_with_1xx() {
|
|||||||
headers,
|
headers,
|
||||||
}) = event
|
}) = event
|
||||||
{
|
{
|
||||||
assert!(
|
assert_wt(&headers);
|
||||||
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);
|
wt_server_session = Some(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,7 +159,7 @@ fn wt_session_response_with_1xx() {
|
|||||||
}) if (
|
}) if (
|
||||||
stream_id == wt_session_id &&
|
stream_id == wt_session_id &&
|
||||||
status == 200 &&
|
status == 200 &&
|
||||||
headers.contains(&Header::new(":status", "200"))
|
headers.contains_header(":status", "200")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@@ -209,14 +200,7 @@ fn wt_session_respone_200_with_fin() {
|
|||||||
headers,
|
headers,
|
||||||
}) = event
|
}) = event
|
||||||
{
|
{
|
||||||
assert!(
|
assert_wt(&headers);
|
||||||
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);
|
wt_server_session = Some(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
use neqo_transport::StreamType;
|
use neqo_transport::StreamType;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -94,7 +92,7 @@ fn wt_server_stream_bidi() {
|
|||||||
wt.send_data_server(&wt_server_stream, BUF_SERVER);
|
wt.send_data_server(&wt_server_stream, BUF_SERVER);
|
||||||
wt.receive_data_client(wt_server_stream.stream_id(), true, BUF_SERVER, false);
|
wt.receive_data_client(wt_server_stream.stream_id(), true, BUF_SERVER, false);
|
||||||
wt.send_data_client(wt_server_stream.stream_id(), BUF_CLIENT);
|
wt.send_data_client(wt_server_stream.stream_id(), BUF_CLIENT);
|
||||||
mem::drop(wt.receive_data_server(wt_server_stream.stream_id(), false, BUF_CLIENT, false));
|
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();
|
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_written(), BUF_CLIENT.len() as u64);
|
||||||
assert_eq!(stats.bytes_sent(), BUF_CLIENT.len() as u64);
|
assert_eq!(stats.bytes_sent(), BUF_CLIENT.len() as u64);
|
||||||
@@ -161,7 +159,7 @@ fn wt_server_stream_bidi_close() {
|
|||||||
wt.receive_data_client(wt_server_stream.stream_id(), true, BUF_SERVER, true);
|
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.send_data_client(wt_server_stream.stream_id(), BUF_CLIENT);
|
||||||
wt.close_stream_sending_client(wt_server_stream.stream_id());
|
wt.close_stream_sending_client(wt_server_stream.stream_id());
|
||||||
mem::drop(wt.receive_data_server(wt_server_stream.stream_id(), false, BUF_CLIENT, true));
|
drop(wt.receive_data_server(wt_server_stream.stream_id(), false, BUF_CLIENT, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -172,7 +170,7 @@ fn wt_client_stream_uni_reset() {
|
|||||||
let wt_session = wt.create_wt_session();
|
let wt_session = wt.create_wt_session();
|
||||||
let wt_stream = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::UniDi);
|
let wt_stream = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::UniDi);
|
||||||
wt.send_data_client(wt_stream, BUF_CLIENT);
|
wt.send_data_client(wt_stream, BUF_CLIENT);
|
||||||
mem::drop(wt.receive_data_server(wt_stream, true, BUF_CLIENT, false));
|
drop(wt.receive_data_server(wt_stream, true, BUF_CLIENT, false));
|
||||||
wt.reset_stream_client(wt_stream);
|
wt.reset_stream_client(wt_stream);
|
||||||
wt.receive_reset_server(wt_stream, Error::HttpNoError.code());
|
wt.receive_reset_server(wt_stream, Error::HttpNoError.code());
|
||||||
}
|
}
|
||||||
@@ -315,7 +313,7 @@ fn wt_client_session_close_1() {
|
|||||||
|
|
||||||
let bidi_from_client = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::BiDi);
|
let bidi_from_client = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::BiDi);
|
||||||
wt.send_data_client(bidi_from_client, BUF);
|
wt.send_data_client(bidi_from_client, BUF);
|
||||||
std::mem::drop(wt.receive_data_server(bidi_from_client, true, BUF, false));
|
drop(wt.receive_data_server(bidi_from_client, true, BUF, false));
|
||||||
|
|
||||||
wt.cancel_session_client(wt_session.stream_id());
|
wt.cancel_session_client(wt_session.stream_id());
|
||||||
|
|
||||||
@@ -350,7 +348,7 @@ fn wt_client_session_close_2() {
|
|||||||
let unidi_from_client = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::UniDi);
|
let unidi_from_client = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::UniDi);
|
||||||
|
|
||||||
wt.send_data_client(unidi_from_client, BUF);
|
wt.send_data_client(unidi_from_client, BUF);
|
||||||
std::mem::drop(wt.receive_data_server(unidi_from_client, true, BUF, false));
|
drop(wt.receive_data_server(unidi_from_client, true, BUF, false));
|
||||||
|
|
||||||
wt.cancel_session_client(wt_session.stream_id());
|
wt.cancel_session_client(wt_session.stream_id());
|
||||||
|
|
||||||
@@ -385,7 +383,7 @@ fn wt_client_session_close_3() {
|
|||||||
let unidi_from_client = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::UniDi);
|
let unidi_from_client = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::UniDi);
|
||||||
|
|
||||||
wt.send_data_client(unidi_from_client, BUF);
|
wt.send_data_client(unidi_from_client, BUF);
|
||||||
std::mem::drop(wt.receive_data_server(unidi_from_client, true, BUF, false));
|
drop(wt.receive_data_server(unidi_from_client, true, BUF, false));
|
||||||
wt.close_stream_sending_client(unidi_from_client);
|
wt.close_stream_sending_client(unidi_from_client);
|
||||||
|
|
||||||
wt.cancel_session_client(wt_session.stream_id());
|
wt.cancel_session_client(wt_session.stream_id());
|
||||||
@@ -450,7 +448,7 @@ fn wt_client_session_close_5() {
|
|||||||
let unidi_from_client = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::UniDi);
|
let unidi_from_client = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::UniDi);
|
||||||
|
|
||||||
wt.send_data_client(unidi_from_client, BUF);
|
wt.send_data_client(unidi_from_client, BUF);
|
||||||
mem::drop(wt.receive_data_server(unidi_from_client, true, BUF, false));
|
drop(wt.receive_data_server(unidi_from_client, true, BUF, false));
|
||||||
wt.reset_stream_client(unidi_from_client);
|
wt.reset_stream_client(unidi_from_client);
|
||||||
|
|
||||||
wt.cancel_session_client(wt_session.stream_id());
|
wt.cancel_session_client(wt_session.stream_id());
|
||||||
@@ -700,10 +698,10 @@ fn wt_client_session_close_13() {
|
|||||||
|
|
||||||
let bidi_client_1 = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::BiDi);
|
let bidi_client_1 = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::BiDi);
|
||||||
wt.send_data_client(bidi_client_1, BUF);
|
wt.send_data_client(bidi_client_1, BUF);
|
||||||
std::mem::drop(wt.receive_data_server(bidi_client_1, true, BUF, false));
|
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);
|
let bidi_client_2 = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::BiDi);
|
||||||
wt.send_data_client(bidi_client_2, BUF);
|
wt.send_data_client(bidi_client_2, BUF);
|
||||||
std::mem::drop(wt.receive_data_server(bidi_client_2, true, BUF, false));
|
drop(wt.receive_data_server(bidi_client_2, true, BUF, false));
|
||||||
|
|
||||||
wt.cancel_session_client(wt_session.stream_id());
|
wt.cancel_session_client(wt_session.stream_id());
|
||||||
|
|
||||||
@@ -750,7 +748,7 @@ fn wt_client_session_server_close_1() {
|
|||||||
|
|
||||||
let bidi_client = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::BiDi);
|
let bidi_client = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::BiDi);
|
||||||
wt.send_data_client(bidi_client, BUF);
|
wt.send_data_client(bidi_client, BUF);
|
||||||
std::mem::drop(wt.receive_data_server(bidi_client, true, BUF, false));
|
drop(wt.receive_data_server(bidi_client, true, BUF, false));
|
||||||
|
|
||||||
wt.cancel_session_server(&wt_session);
|
wt.cancel_session_server(&wt_session);
|
||||||
|
|
||||||
@@ -784,7 +782,7 @@ fn wt_client_session_server_close_2() {
|
|||||||
|
|
||||||
let unidi_client = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::UniDi);
|
let unidi_client = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::UniDi);
|
||||||
wt.send_data_client(unidi_client, BUF);
|
wt.send_data_client(unidi_client, BUF);
|
||||||
std::mem::drop(wt.receive_data_server(unidi_client, true, BUF, false));
|
drop(wt.receive_data_server(unidi_client, true, BUF, false));
|
||||||
|
|
||||||
wt.cancel_session_server(&wt_session);
|
wt.cancel_session_server(&wt_session);
|
||||||
|
|
||||||
@@ -1064,10 +1062,10 @@ fn wt_client_session_server_close_11() {
|
|||||||
|
|
||||||
let bidi_client_1 = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::BiDi);
|
let bidi_client_1 = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::BiDi);
|
||||||
wt.send_data_client(bidi_client_1, BUF);
|
wt.send_data_client(bidi_client_1, BUF);
|
||||||
std::mem::drop(wt.receive_data_server(bidi_client_1, true, BUF, false));
|
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);
|
let bidi_client_2 = wt.create_wt_stream_client(wt_session.stream_id(), StreamType::BiDi);
|
||||||
wt.send_data_client(bidi_client_2, BUF);
|
wt.send_data_client(bidi_client_2, BUF);
|
||||||
std::mem::drop(wt.receive_data_server(bidi_client_2, true, BUF, false));
|
drop(wt.receive_data_server(bidi_client_2, true, BUF, false));
|
||||||
|
|
||||||
wt.cancel_session_server(&wt_session);
|
wt.cancel_session_server(&wt_session);
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ impl WebTransportSession {
|
|||||||
first_frame_type: None,
|
first_frame_type: None,
|
||||||
},
|
},
|
||||||
qpack_decoder,
|
qpack_decoder,
|
||||||
Box::new(stream_event_listener.clone()),
|
Box::new(Rc::clone(&stream_event_listener)),
|
||||||
None,
|
None,
|
||||||
PriorityHandler::new(false, Priority::default()),
|
PriorityHandler::new(false, Priority::default()),
|
||||||
)),
|
)),
|
||||||
@@ -82,7 +82,7 @@ impl WebTransportSession {
|
|||||||
Http3StreamType::ExtendedConnect,
|
Http3StreamType::ExtendedConnect,
|
||||||
session_id,
|
session_id,
|
||||||
qpack_encoder,
|
qpack_encoder,
|
||||||
Box::new(stream_event_listener.clone()),
|
Box::new(Rc::clone(&stream_event_listener)),
|
||||||
)),
|
)),
|
||||||
stream_event_listener,
|
stream_event_listener,
|
||||||
session_id,
|
session_id,
|
||||||
@@ -111,11 +111,11 @@ impl WebTransportSession {
|
|||||||
control_stream_recv
|
control_stream_recv
|
||||||
.http_stream()
|
.http_stream()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.set_new_listener(Box::new(stream_event_listener.clone()));
|
.set_new_listener(Box::new(Rc::clone(&stream_event_listener)));
|
||||||
control_stream_send
|
control_stream_send
|
||||||
.http_stream()
|
.http_stream()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.set_new_listener(Box::new(stream_event_listener.clone()));
|
.set_new_listener(Box::new(Rc::clone(&stream_event_listener)));
|
||||||
Self {
|
Self {
|
||||||
control_stream_recv,
|
control_stream_recv,
|
||||||
control_stream_send,
|
control_stream_send,
|
||||||
@@ -146,7 +146,7 @@ impl WebTransportSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn receive(&mut self, conn: &mut Connection) -> Res<(ReceiveOutput, bool)> {
|
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)?;
|
let (out, _) = self.control_stream_recv.receive(conn)?;
|
||||||
debug_assert!(out == ReceiveOutput::NoOutput);
|
debug_assert!(out == ReceiveOutput::NoOutput);
|
||||||
self.maybe_check_headers();
|
self.maybe_check_headers();
|
||||||
@@ -229,11 +229,7 @@ impl WebTransportSession {
|
|||||||
|
|
||||||
if let Some((headers, interim, fin)) = self.stream_event_listener.borrow_mut().get_headers()
|
if let Some((headers, interim, fin)) = self.stream_event_listener.borrow_mut().get_headers()
|
||||||
{
|
{
|
||||||
qtrace!(
|
qtrace!("ExtendedConnect response headers {headers:?}, fin={fin}");
|
||||||
"ExtendedConnect response headers {:?}, fin={}",
|
|
||||||
headers,
|
|
||||||
fin
|
|
||||||
);
|
|
||||||
|
|
||||||
if interim {
|
if interim {
|
||||||
if fin {
|
if fin {
|
||||||
@@ -346,7 +342,7 @@ impl WebTransportSession {
|
|||||||
&mut self.control_stream_recv,
|
&mut self.control_stream_recv,
|
||||||
))
|
))
|
||||||
.map_err(|_| Error::HttpGeneralProtocolStream)?;
|
.map_err(|_| Error::HttpGeneralProtocolStream)?;
|
||||||
qtrace!([self], "Received frame: {:?} fin={}", f, fin);
|
qtrace!("[{self}] Received frame: {f:?} fin={fin}");
|
||||||
if let Some(WebTransportFrame::CloseSession { error, message }) = f {
|
if let Some(WebTransportFrame::CloseSession { error, message }) = f {
|
||||||
self.events.session_end(
|
self.events.session_end(
|
||||||
ExtendedConnectType::WebTransport,
|
ExtendedConnectType::WebTransport,
|
||||||
@@ -410,7 +406,7 @@ impl WebTransportSession {
|
|||||||
buf: &[u8],
|
buf: &[u8],
|
||||||
id: impl Into<DatagramTracking>,
|
id: impl Into<DatagramTracking>,
|
||||||
) -> Res<()> {
|
) -> Res<()> {
|
||||||
qtrace!([self], "send_datagram state={:?}", self.state);
|
qtrace!("[{self}] send_datagram state={:?}", self.state);
|
||||||
if self.state == SessionState::Active {
|
if self.state == SessionState::Active {
|
||||||
let mut dgram_data = Encoder::default();
|
let mut dgram_data = Encoder::default();
|
||||||
dgram_data.encode_varint(self.session_id.as_u64() / 4);
|
dgram_data.encode_varint(self.session_id.as_u64() / 4);
|
||||||
@@ -451,7 +447,7 @@ impl RecvStream for Rc<RefCell<WebTransportSession>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn webtransport(&self) -> Option<Rc<RefCell<WebTransportSession>>> {
|
fn webtransport(&self) -> Option<Rc<RefCell<WebTransportSession>>> {
|
||||||
Some(self.clone())
|
Some(Self::clone(self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,8 +63,7 @@ impl NegotiationState {
|
|||||||
} = self
|
} = self
|
||||||
{
|
{
|
||||||
qtrace!(
|
qtrace!(
|
||||||
"set_negotiated {:?} to {}",
|
"set_negotiated {feature_type:?} to {}",
|
||||||
feature_type,
|
|
||||||
settings.get(*feature_type)
|
settings.get(*feature_type)
|
||||||
);
|
);
|
||||||
let cb = mem::take(listener);
|
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
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::{fmt::Debug, io::Write};
|
use std::{fmt::Debug, io::Write as _};
|
||||||
|
|
||||||
use neqo_common::{Decoder, Encoder};
|
use neqo_common::{Decoder, Encoder};
|
||||||
use neqo_crypto::random;
|
use neqo_crypto::random;
|
||||||
use neqo_transport::StreamId;
|
use neqo_transport::StreamId;
|
||||||
|
|
||||||
use crate::{frames::reader::FrameDecoder, settings::HSettings, Error, Priority, Res};
|
use crate::{frames::reader::FrameDecoder, settings::HSettings, Error, Priority, PushId, Res};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct HFrameType(pub u64);
|
pub struct HFrameType(pub u64);
|
||||||
@@ -48,20 +48,20 @@ pub enum HFrame {
|
|||||||
header_block: Vec<u8>,
|
header_block: Vec<u8>,
|
||||||
},
|
},
|
||||||
CancelPush {
|
CancelPush {
|
||||||
push_id: u64,
|
push_id: PushId,
|
||||||
},
|
},
|
||||||
Settings {
|
Settings {
|
||||||
settings: HSettings,
|
settings: HSettings,
|
||||||
},
|
},
|
||||||
PushPromise {
|
PushPromise {
|
||||||
push_id: u64,
|
push_id: PushId,
|
||||||
header_block: Vec<u8>,
|
header_block: Vec<u8>,
|
||||||
},
|
},
|
||||||
Goaway {
|
Goaway {
|
||||||
stream_id: StreamId,
|
stream_id: StreamId,
|
||||||
},
|
},
|
||||||
MaxPushId {
|
MaxPushId {
|
||||||
push_id: u64,
|
push_id: PushId,
|
||||||
},
|
},
|
||||||
Grease,
|
Grease,
|
||||||
PriorityUpdateRequest {
|
PriorityUpdateRequest {
|
||||||
@@ -87,7 +87,9 @@ impl HFrame {
|
|||||||
Self::PriorityUpdateRequest { .. } => H3_FRAME_TYPE_PRIORITY_UPDATE_REQUEST,
|
Self::PriorityUpdateRequest { .. } => H3_FRAME_TYPE_PRIORITY_UPDATE_REQUEST,
|
||||||
Self::PriorityUpdatePush { .. } => H3_FRAME_TYPE_PRIORITY_UPDATE_PUSH,
|
Self::PriorityUpdatePush { .. } => H3_FRAME_TYPE_PRIORITY_UPDATE_PUSH,
|
||||||
Self::Grease => {
|
Self::Grease => {
|
||||||
HFrameType(Decoder::from(&random::<7>()).decode_uint(7).unwrap() * 0x1f + 0x21)
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,7 +117,9 @@ impl HFrame {
|
|||||||
push_id,
|
push_id,
|
||||||
header_block,
|
header_block,
|
||||||
} => {
|
} => {
|
||||||
enc.encode_varint((header_block.len() + (Encoder::varint_len(*push_id))) as u64);
|
enc.encode_varint(
|
||||||
|
(header_block.len() + (Encoder::varint_len(u64::from(*push_id)))) as u64,
|
||||||
|
);
|
||||||
enc.encode_varint(*push_id);
|
enc.encode_varint(*push_id);
|
||||||
enc.encode(header_block);
|
enc.encode(header_block);
|
||||||
}
|
}
|
||||||
@@ -170,12 +174,12 @@ impl FrameDecoder<Self> for HFrame {
|
|||||||
} else if let Some(payload) = data {
|
} else if let Some(payload) = data {
|
||||||
let mut dec = Decoder::from(payload);
|
let mut dec = Decoder::from(payload);
|
||||||
Ok(match frame_type {
|
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 {
|
H3_FRAME_TYPE_HEADERS => Some(Self::Headers {
|
||||||
header_block: dec.decode_remainder().to_vec(),
|
header_block: dec.decode_remainder().to_vec(),
|
||||||
}),
|
}),
|
||||||
H3_FRAME_TYPE_CANCEL_PUSH => Some(Self::CancelPush {
|
H3_FRAME_TYPE_CANCEL_PUSH => Some(Self::CancelPush {
|
||||||
push_id: dec.decode_varint().ok_or(Error::HttpFrame)?,
|
push_id: dec.decode_varint().ok_or(Error::HttpFrame)?.into(),
|
||||||
}),
|
}),
|
||||||
H3_FRAME_TYPE_SETTINGS => {
|
H3_FRAME_TYPE_SETTINGS => {
|
||||||
let mut settings = HSettings::default();
|
let mut settings = HSettings::default();
|
||||||
@@ -189,14 +193,14 @@ impl FrameDecoder<Self> for HFrame {
|
|||||||
Some(Self::Settings { settings })
|
Some(Self::Settings { settings })
|
||||||
}
|
}
|
||||||
H3_FRAME_TYPE_PUSH_PROMISE => Some(Self::PushPromise {
|
H3_FRAME_TYPE_PUSH_PROMISE => Some(Self::PushPromise {
|
||||||
push_id: dec.decode_varint().ok_or(Error::HttpFrame)?,
|
push_id: dec.decode_varint().ok_or(Error::HttpFrame)?.into(),
|
||||||
header_block: dec.decode_remainder().to_vec(),
|
header_block: dec.decode_remainder().to_vec(),
|
||||||
}),
|
}),
|
||||||
H3_FRAME_TYPE_GOAWAY => Some(Self::Goaway {
|
H3_FRAME_TYPE_GOAWAY => Some(Self::Goaway {
|
||||||
stream_id: StreamId::new(dec.decode_varint().ok_or(Error::HttpFrame)?),
|
stream_id: StreamId::new(dec.decode_varint().ok_or(Error::HttpFrame)?),
|
||||||
}),
|
}),
|
||||||
H3_FRAME_TYPE_MAX_PUSH_ID => Some(Self::MaxPushId {
|
H3_FRAME_TYPE_MAX_PUSH_ID => Some(Self::MaxPushId {
|
||||||
push_id: dec.decode_varint().ok_or(Error::HttpFrame)?,
|
push_id: dec.decode_varint().ok_or(Error::HttpFrame)?.into(),
|
||||||
}),
|
}),
|
||||||
H3_FRAME_TYPE_PRIORITY_UPDATE_REQUEST | H3_FRAME_TYPE_PRIORITY_UPDATE_PUSH => {
|
H3_FRAME_TYPE_PRIORITY_UPDATE_REQUEST | H3_FRAME_TYPE_PRIORITY_UPDATE_PUSH => {
|
||||||
let element_id = dec.decode_varint().ok_or(Error::HttpFrame)?;
|
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
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// Returns `HttpFrameUnexpected` if frames is not alowed, i.e. is a `H3_RESERVED_FRAME_TYPES`.
|
/// Returns `HttpFrameUnexpected` if frames is not allowed, i.e. is a `H3_RESERVED_FRAME_TYPES`.
|
||||||
fn frame_type_allowed(_frame_type: HFrameType) -> Res<()> {
|
fn frame_type_allowed(_frame_type: HFrameType) -> Res<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -154,7 +154,7 @@ impl FrameReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns true if quic stream was closed.
|
/// Returns true if QUIC stream was closed.
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
@@ -173,7 +173,7 @@ impl FrameReader {
|
|||||||
{
|
{
|
||||||
(0, f) => (None, false, f),
|
(0, f) => (None, false, f),
|
||||||
(amount, f) => {
|
(amount, f) => {
|
||||||
qtrace!("FrameReader::receive: reading {} byte, fin={}", amount, f);
|
qtrace!("FrameReader::receive: reading {amount} byte, fin={f}");
|
||||||
(self.consume::<T>(Decoder::from(&buf[..amount]))?, true, f)
|
(self.consume::<T>(Decoder::from(&buf[..amount]))?, true, f)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -203,16 +203,15 @@ impl FrameReader {
|
|||||||
match &mut self.state {
|
match &mut self.state {
|
||||||
FrameReaderState::GetType { decoder } => {
|
FrameReaderState::GetType { decoder } => {
|
||||||
if let Some(v) = decoder.consume(&mut input) {
|
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))?;
|
self.frame_type_decoded::<T>(HFrameType(v))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FrameReaderState::GetLength { decoder } => {
|
FrameReaderState::GetLength { decoder } => {
|
||||||
if let Some(len) = decoder.consume(&mut input) {
|
if let Some(len) = decoder.consume(&mut input) {
|
||||||
qtrace!(
|
qtrace!(
|
||||||
"FrameReader::receive: frame type {:?} length {}",
|
"FrameReader::receive: frame type {:?} length {len}",
|
||||||
self.frame_type,
|
self.frame_type
|
||||||
len
|
|
||||||
);
|
);
|
||||||
return self.frame_length_decoded::<T>(len);
|
return self.frame_length_decoded::<T>(len);
|
||||||
}
|
}
|
||||||
@@ -235,9 +234,6 @@ impl FrameReader {
|
|||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl FrameReader {
|
|
||||||
fn frame_type_decoded<T: FrameDecoder<T>>(&mut self, frame_type: HFrameType) -> Res<()> {
|
fn frame_type_decoded<T: FrameDecoder<T>>(&mut self, frame_type: HFrameType) -> Res<()> {
|
||||||
T::frame_type_allowed(frame_type)?;
|
T::frame_type_allowed(frame_type)?;
|
||||||
self.frame_type = frame_type;
|
self.frame_type = frame_type;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use super::enc_dec_hframe;
|
|||||||
use crate::{
|
use crate::{
|
||||||
frames::HFrame,
|
frames::HFrame,
|
||||||
settings::{HSetting, HSettingType, HSettings},
|
settings::{HSetting, HSettingType, HSettings},
|
||||||
Priority,
|
Priority, PushId,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -31,7 +31,9 @@ fn headers_frame() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn cancel_push_frame4() {
|
fn cancel_push_frame4() {
|
||||||
let f = HFrame::CancelPush { push_id: 5 };
|
let f = HFrame::CancelPush {
|
||||||
|
push_id: PushId::new(5),
|
||||||
|
};
|
||||||
enc_dec_hframe(&f, "030105", 0);
|
enc_dec_hframe(&f, "030105", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +48,7 @@ fn settings_frame4() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn push_promise_frame4() {
|
fn push_promise_frame4() {
|
||||||
let f = HFrame::PushPromise {
|
let f = HFrame::PushPromise {
|
||||||
push_id: 4,
|
push_id: PushId::new(4),
|
||||||
header_block: vec![0x61, 0x62, 0x63, 0x64],
|
header_block: vec![0x61, 0x62, 0x63, 0x64],
|
||||||
};
|
};
|
||||||
enc_dec_hframe(&f, "05050461626364", 0);
|
enc_dec_hframe(&f, "05050461626364", 0);
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
use neqo_common::Encoder;
|
use neqo_common::Encoder;
|
||||||
use neqo_crypto::AuthenticationStatus;
|
use neqo_crypto::AuthenticationStatus;
|
||||||
use neqo_transport::StreamType;
|
use neqo_transport::StreamType;
|
||||||
@@ -25,21 +23,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_c.process_output(now());
|
||||||
let out = conn_s.process(out.dgram(), now());
|
let out = conn_s.process(out.dgram(), now());
|
||||||
let out = conn_c.process(out.dgram(), now());
|
let out = conn_c.process(out.dgram(), now());
|
||||||
mem::drop(conn_s.process(out.dgram(), now()));
|
drop(conn_s.process(out.dgram(), now()));
|
||||||
conn_c.authenticated(AuthenticationStatus::Ok, now());
|
conn_c.authenticated(AuthenticationStatus::Ok, now());
|
||||||
let out = conn_c.process_output(now());
|
let out = conn_c.process_output(now());
|
||||||
mem::drop(conn_s.process(out.dgram(), now()));
|
drop(conn_s.process(out.dgram(), now()));
|
||||||
|
|
||||||
// create a stream
|
// create a stream
|
||||||
let stream_id = conn_s.stream_create(StreamType::BiDi).unwrap();
|
let stream_id = conn_s.stream_create(StreamType::BiDi).unwrap();
|
||||||
|
|
||||||
let mut fr: FrameReader = FrameReader::new();
|
let mut fr = FrameReader::new();
|
||||||
|
|
||||||
// conver string into u8 vector
|
// convert string into u8 vector
|
||||||
let buf = Encoder::from_hex(st);
|
let buf = Encoder::from_hex(st);
|
||||||
conn_s.stream_send(stream_id, buf.as_ref()).unwrap();
|
conn_s.stream_send(stream_id, buf.as_ref()).unwrap();
|
||||||
let out = conn_s.process_output(now());
|
let out = conn_s.process_output(now());
|
||||||
mem::drop(conn_c.process(out.dgram(), now()));
|
drop(conn_c.process(out.dgram(), now()));
|
||||||
|
|
||||||
let (frame, fin) = fr
|
let (frame, fin) = fr
|
||||||
.receive::<T>(&mut StreamReaderConnectionWrapper::new(
|
.receive::<T>(&mut StreamReaderConnectionWrapper::new(
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::{fmt::Debug, mem};
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use neqo_common::Encoder;
|
use neqo_common::Encoder;
|
||||||
use neqo_transport::{Connection, StreamId, StreamType};
|
use neqo_transport::{Connection, StreamId, StreamType};
|
||||||
@@ -15,7 +15,7 @@ use crate::{
|
|||||||
reader::FrameDecoder, FrameReader, HFrame, StreamReaderConnectionWrapper, WebTransportFrame,
|
reader::FrameDecoder, FrameReader, HFrame, StreamReaderConnectionWrapper, WebTransportFrame,
|
||||||
},
|
},
|
||||||
settings::{HSetting, HSettingType, HSettings},
|
settings::{HSetting, HSettingType, HSettings},
|
||||||
Error,
|
Error, PushId,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FrameReaderTest {
|
struct FrameReaderTest {
|
||||||
@@ -40,7 +40,7 @@ impl FrameReaderTest {
|
|||||||
fn process<T: FrameDecoder<T>>(&mut self, v: &[u8]) -> Option<T> {
|
fn process<T: FrameDecoder<T>>(&mut self, v: &[u8]) -> Option<T> {
|
||||||
self.conn_s.stream_send(self.stream_id, v).unwrap();
|
self.conn_s.stream_send(self.stream_id, v).unwrap();
|
||||||
let out = self.conn_s.process_output(now());
|
let out = self.conn_s.process_output(now());
|
||||||
mem::drop(self.conn_c.process(out.dgram(), now()));
|
drop(self.conn_c.process(out.dgram(), now()));
|
||||||
let (frame, fin) = self
|
let (frame, fin) = self
|
||||||
.fr
|
.fr
|
||||||
.receive::<T>(&mut StreamReaderConnectionWrapper::new(
|
.receive::<T>(&mut StreamReaderConnectionWrapper::new(
|
||||||
@@ -112,7 +112,7 @@ fn frame_reading_with_stream_push_promise() {
|
|||||||
header_block,
|
header_block,
|
||||||
} = frame.unwrap()
|
} = frame.unwrap()
|
||||||
{
|
{
|
||||||
assert_eq!(push_id, 257);
|
assert_eq!(push_id, PushId::new(257));
|
||||||
assert_eq!(header_block, &[0x1, 0x2, 0x3]);
|
assert_eq!(header_block, &[0x1, 0x2, 0x3]);
|
||||||
} else {
|
} else {
|
||||||
panic!("wrong frame type");
|
panic!("wrong frame type");
|
||||||
@@ -128,7 +128,7 @@ fn frame_reading_with_stream_data() {
|
|||||||
let frame = fr.process(&[0x0, 0x3, 0x1, 0x2, 0x3]).unwrap();
|
let frame = fr.process(&[0x0, 0x3, 0x1, 0x2, 0x3]).unwrap();
|
||||||
assert!(matches!(frame, HFrame::Data { len } if len == 3));
|
assert!(matches!(frame, HFrame::Data { len } if len == 3));
|
||||||
|
|
||||||
// payloead is still on the stream.
|
// payload is still on the stream.
|
||||||
// assert that we have 3 bytes in the stream
|
// assert that we have 3 bytes in the stream
|
||||||
let mut buf = [0_u8; 100];
|
let mut buf = [0_u8; 100];
|
||||||
let (amount, _) = fr.conn_c.stream_recv(fr.stream_id, &mut buf).unwrap();
|
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);
|
buf.resize(UNKNOWN_FRAME_LEN + buf.len(), 0);
|
||||||
assert!(fr.process::<HFrame>(&buf).is_none());
|
assert!(fr.process::<HFrame>(&buf).is_none());
|
||||||
|
|
||||||
// now receive a CANCEL_PUSH fram to see that frame reader is ok.
|
// now receive a CANCEL_PUSH frame to see that frame reader is ok.
|
||||||
let frame = fr.process(&[0x03, 0x01, 0x05]);
|
let frame = fr.process(&[0x03, 0x01, 0x05]);
|
||||||
assert!(frame.is_some());
|
assert!(frame.is_some());
|
||||||
if let HFrame::CancelPush { push_id } = frame.unwrap() {
|
if let HFrame::CancelPush { push_id } = frame.unwrap() {
|
||||||
assert!(push_id == 5);
|
assert!(push_id == PushId::new(5));
|
||||||
} else {
|
} else {
|
||||||
panic!("wrong frame type");
|
panic!("wrong frame type");
|
||||||
}
|
}
|
||||||
@@ -194,7 +194,7 @@ fn unknown_wt_frame() {
|
|||||||
buf.resize(UNKNOWN_FRAME_LEN + buf.len(), 0);
|
buf.resize(UNKNOWN_FRAME_LEN + buf.len(), 0);
|
||||||
assert!(fr.process::<WebTransportFrame>(&buf).is_none());
|
assert!(fr.process::<WebTransportFrame>(&buf).is_none());
|
||||||
|
|
||||||
// now receive a WT_FRAME_CLOSE_SESSION fram to see that frame reader is ok.
|
// now receive a WT_FRAME_CLOSE_SESSION frame to see that frame reader is ok.
|
||||||
let frame = fr.process(&[
|
let frame = fr.process(&[
|
||||||
0x68, 0x43, 0x09, 0x00, 0x00, 0x00, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f,
|
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());
|
let out = fr.conn_s.process_output(now());
|
||||||
mem::drop(fr.conn_c.process(out.dgram(), now()));
|
drop(fr.conn_c.process(out.dgram(), now()));
|
||||||
|
|
||||||
if matches!(test_to_send, FrameReadingTestSend::DataThenFin) {
|
if matches!(test_to_send, FrameReadingTestSend::DataThenFin) {
|
||||||
fr.conn_s.stream_close_send(fr.stream_id).unwrap();
|
fr.conn_s.stream_close_send(fr.stream_id).unwrap();
|
||||||
let out = fr.conn_s.process_output(now());
|
let out = fr.conn_s.process_output(now());
|
||||||
mem::drop(fr.conn_c.process(out.dgram(), now()));
|
drop(fr.conn_c.process(out.dgram(), now()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let rv = fr.fr.receive::<T>(&mut StreamReaderConnectionWrapper::new(
|
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,
|
done_state: usize,
|
||||||
) {
|
) {
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
// Let's consume partial frames. It is enough to test partal frames
|
// Let's consume partial frames. It is enough to test partial frames
|
||||||
// up to 10 byte. 10 byte is greater than frame type and frame
|
// up to 10 byte. 10 byte is greater than frame type and frame
|
||||||
// length and bit of data.
|
// length and bit of data.
|
||||||
let len = std::cmp::min(buf.len() - 1, 10);
|
let len = std::cmp::min(buf.len() - 1, 10);
|
||||||
@@ -417,7 +417,9 @@ fn complete_and_incomplete_frames() {
|
|||||||
test_complete_and_incomplete_frame::<HFrame>(&buf, buf.len());
|
test_complete_and_incomplete_frame::<HFrame>(&buf, buf.len());
|
||||||
|
|
||||||
// H3_FRAME_TYPE_CANCEL_PUSH
|
// H3_FRAME_TYPE_CANCEL_PUSH
|
||||||
let f = HFrame::CancelPush { push_id: 5 };
|
let f = HFrame::CancelPush {
|
||||||
|
push_id: PushId::new(5),
|
||||||
|
};
|
||||||
let mut enc = Encoder::default();
|
let mut enc = Encoder::default();
|
||||||
f.encode(&mut enc);
|
f.encode(&mut enc);
|
||||||
let buf: Vec<_> = enc.into();
|
let buf: Vec<_> = enc.into();
|
||||||
@@ -434,7 +436,7 @@ fn complete_and_incomplete_frames() {
|
|||||||
|
|
||||||
// H3_FRAME_TYPE_PUSH_PROMISE
|
// H3_FRAME_TYPE_PUSH_PROMISE
|
||||||
let f = HFrame::PushPromise {
|
let f = HFrame::PushPromise {
|
||||||
push_id: 4,
|
push_id: PushId::new(4),
|
||||||
header_block: HEADER_BLOCK.to_vec(),
|
header_block: HEADER_BLOCK.to_vec(),
|
||||||
};
|
};
|
||||||
let mut enc = Encoder::default();
|
let mut enc = Encoder::default();
|
||||||
@@ -452,7 +454,9 @@ fn complete_and_incomplete_frames() {
|
|||||||
test_complete_and_incomplete_frame::<HFrame>(&buf, buf.len());
|
test_complete_and_incomplete_frame::<HFrame>(&buf, buf.len());
|
||||||
|
|
||||||
// H3_FRAME_TYPE_MAX_PUSH_ID
|
// H3_FRAME_TYPE_MAX_PUSH_ID
|
||||||
let f = HFrame::MaxPushId { push_id: 5 };
|
let f = HFrame::MaxPushId {
|
||||||
|
push_id: PushId::new(5),
|
||||||
|
};
|
||||||
let mut enc = Encoder::default();
|
let mut enc = Encoder::default();
|
||||||
f.encode(&mut enc);
|
f.encode(&mut enc);
|
||||||
let buf: Vec<_> = enc.into();
|
let buf: Vec<_> = enc.into();
|
||||||
@@ -479,11 +483,11 @@ fn frame_reading_when_stream_is_closed_before_sending_data() {
|
|||||||
|
|
||||||
fr.conn_s.stream_send(fr.stream_id, &[0x00]).unwrap();
|
fr.conn_s.stream_send(fr.stream_id, &[0x00]).unwrap();
|
||||||
let out = fr.conn_s.process_output(now());
|
let out = fr.conn_s.process_output(now());
|
||||||
mem::drop(fr.conn_c.process(out.dgram(), now()));
|
drop(fr.conn_c.process(out.dgram(), now()));
|
||||||
|
|
||||||
assert_eq!(Ok(()), fr.conn_c.stream_close_send(fr.stream_id));
|
assert_eq!(Ok(()), fr.conn_c.stream_close_send(fr.stream_id));
|
||||||
let out = fr.conn_c.process_output(now());
|
let out = fr.conn_c.process_output(now());
|
||||||
mem::drop(fr.conn_s.process(out.dgram(), now()));
|
drop(fr.conn_s.process(out.dgram(), now()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((None, true)),
|
Ok((None, true)),
|
||||||
fr.fr
|
fr.fr
|
||||||
@@ -502,11 +506,11 @@ fn wt_frame_reading_when_stream_is_closed_before_sending_data() {
|
|||||||
|
|
||||||
fr.conn_s.stream_send(fr.stream_id, &[0x00]).unwrap();
|
fr.conn_s.stream_send(fr.stream_id, &[0x00]).unwrap();
|
||||||
let out = fr.conn_s.process_output(now());
|
let out = fr.conn_s.process_output(now());
|
||||||
mem::drop(fr.conn_c.process(out.dgram(), now()));
|
drop(fr.conn_c.process(out.dgram(), now()));
|
||||||
|
|
||||||
assert_eq!(Ok(()), fr.conn_c.stream_close_send(fr.stream_id));
|
assert_eq!(Ok(()), fr.conn_c.stream_close_send(fr.stream_id));
|
||||||
let out = fr.conn_c.process_output(now());
|
let out = fr.conn_c.process_output(now());
|
||||||
mem::drop(fr.conn_s.process(out.dgram(), now()));
|
drop(fr.conn_s.process(out.dgram(), now()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((None, true)),
|
Ok((None, true)),
|
||||||
fr.fr
|
fr.fr
|
||||||
|
|||||||
@@ -37,8 +37,7 @@ impl FrameDecoder<Self> for WebTransportFrame {
|
|||||||
if frame_len > WT_FRAME_CLOSE_MAX_MESSAGE_SIZE + 4 {
|
if frame_len > WT_FRAME_CLOSE_MAX_MESSAGE_SIZE + 4 {
|
||||||
return Err(Error::HttpMessageError);
|
return Err(Error::HttpMessageError);
|
||||||
}
|
}
|
||||||
let error =
|
let error = dec.decode_uint().ok_or(Error::HttpMessageError)?;
|
||||||
u32::try_from(dec.decode_uint(4).ok_or(Error::HttpMessageError)?).unwrap();
|
|
||||||
let Ok(message) = String::from_utf8(dec.decode_remainder().to_vec()) else {
|
let Ok(message) = String::from_utf8(dec.decode_remainder().to_vec()) else {
|
||||||
return Err(Error::HttpMessageError);
|
return Err(Error::HttpMessageError);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use enumset::{enum_set, EnumSet, EnumSetType};
|
use enumset::{enum_set, EnumSet, EnumSetType};
|
||||||
use neqo_common::Header;
|
use neqo_common::{header::HeadersExt as _, Header};
|
||||||
|
|
||||||
use crate::{Error, MessageType, Res};
|
use crate::{Error, MessageType, Res};
|
||||||
|
|
||||||
@@ -49,10 +49,9 @@ impl TryFrom<(MessageType, &str)> for PseudoHeaderState {
|
|||||||
/// Returns an error if response headers do not contain
|
/// 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.
|
/// a status header or if the value of the header is 101 or cannot be parsed.
|
||||||
pub fn is_interim(headers: &[Header]) -> Res<bool> {
|
pub fn is_interim(headers: &[Header]) -> Res<bool> {
|
||||||
let status = headers.iter().take(1).find(|h| h.name() == ":status");
|
if let Some(h) = headers.iter().take(1).find_header(":status") {
|
||||||
if let Some(h) = status {
|
|
||||||
#[allow(clippy::map_err_ignore)]
|
#[allow(clippy::map_err_ignore)]
|
||||||
let status_code = h.value().parse::<i32>().map_err(|_| Error::InvalidHeader)?;
|
let status_code = h.value().parse::<u16>().map_err(|_| Error::InvalidHeader)?;
|
||||||
if status_code == 101 {
|
if status_code == 101 {
|
||||||
// https://datatracker.ietf.org/doc/html/draft-ietf-quic-http#section-4.3
|
// https://datatracker.ietf.org/doc/html/draft-ietf-quic-http#section-4.3
|
||||||
Err(Error::InvalidHeader)
|
Err(Error::InvalidHeader)
|
||||||
@@ -224,4 +223,18 @@ mod tests {
|
|||||||
fn valid_webtransport_connect() {
|
fn valid_webtransport_connect() {
|
||||||
assert!(headers_valid(&create_connect_headers(), MessageType::Request).is_ok());
|
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,6 +145,7 @@ mod frames;
|
|||||||
mod headers_checks;
|
mod headers_checks;
|
||||||
mod priority;
|
mod priority;
|
||||||
mod push_controller;
|
mod push_controller;
|
||||||
|
mod push_id;
|
||||||
mod qlog;
|
mod qlog;
|
||||||
mod qpack_decoder_receiver;
|
mod qpack_decoder_receiver;
|
||||||
mod qpack_encoder_receiver;
|
mod qpack_encoder_receiver;
|
||||||
@@ -174,6 +175,7 @@ use neqo_transport::{
|
|||||||
AppError, Connection, Error as TransportError, RecvStreamStats, SendStreamStats,
|
AppError, Connection, Error as TransportError, RecvStreamStats, SendStreamStats,
|
||||||
};
|
};
|
||||||
pub use priority::Priority;
|
pub use priority::Priority;
|
||||||
|
pub use push_id::PushId;
|
||||||
pub use server::Http3Server;
|
pub use server::Http3Server;
|
||||||
pub use server_events::{
|
pub use server_events::{
|
||||||
Http3OrWebTransportStream, Http3ServerEvent, WebTransportRequest, WebTransportServerEvent,
|
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},
|
client_events::{Http3ClientEvent, Http3ClientEvents},
|
||||||
connection::Http3Connection,
|
connection::Http3Connection,
|
||||||
frames::HFrame,
|
frames::HFrame,
|
||||||
CloseType, Error, Http3StreamInfo, HttpRecvStreamEvents, RecvStreamEvents, Res,
|
CloseType, Error, Http3StreamInfo, HttpRecvStreamEvents, PushId, RecvStreamEvents, Res,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// `PushStates`:
|
/// `PushStates`:
|
||||||
@@ -57,27 +57,27 @@ enum PushState {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct ActivePushStreams {
|
struct ActivePushStreams {
|
||||||
push_streams: VecDeque<PushState>,
|
push_streams: VecDeque<PushState>,
|
||||||
first_push_id: u64,
|
first_push_id: PushId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActivePushStreams {
|
impl ActivePushStreams {
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
push_streams: VecDeque::new(),
|
push_streams: VecDeque::new(),
|
||||||
first_push_id: 0,
|
first_push_id: PushId::new(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns None if a stream has been closed already.
|
/// Returns None if a stream has been closed already.
|
||||||
pub fn get_mut(
|
pub fn get_mut(
|
||||||
&mut self,
|
&mut self,
|
||||||
push_id: u64,
|
push_id: PushId,
|
||||||
) -> Option<&mut <usize as SliceIndex<[PushState]>>::Output> {
|
) -> Option<&mut <usize as SliceIndex<[PushState]>>::Output> {
|
||||||
if push_id < self.first_push_id {
|
if push_id < self.first_push_id {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let inx = usize::try_from(push_id - self.first_push_id).unwrap();
|
let inx = usize::try_from(u64::from(push_id - self.first_push_id)).unwrap();
|
||||||
if inx >= self.push_streams.len() {
|
if inx >= self.push_streams.len() {
|
||||||
self.push_streams.resize(inx + 1, PushState::Init);
|
self.push_streams.resize(inx + 1, PushState::Init);
|
||||||
}
|
}
|
||||||
@@ -88,19 +88,19 @@ impl ActivePushStreams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns None if a stream has been closed already.
|
/// Returns None if a stream has been closed already.
|
||||||
pub fn get(&mut self, push_id: u64) -> Option<&mut PushState> {
|
pub fn get(&mut self, push_id: PushId) -> Option<&mut PushState> {
|
||||||
self.get_mut(push_id)
|
self.get_mut(push_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the State of a closed push stream or None for already closed streams.
|
/// Returns the State of a closed push stream or None for already closed streams.
|
||||||
pub fn close(&mut self, push_id: u64) -> Option<PushState> {
|
pub fn close(&mut self, push_id: PushId) -> Option<PushState> {
|
||||||
match self.get_mut(push_id) {
|
match self.get_mut(push_id) {
|
||||||
None | Some(PushState::Closed) => None,
|
None | Some(PushState::Closed) => None,
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
let res = mem::replace(s, PushState::Closed);
|
let res = mem::replace(s, PushState::Closed);
|
||||||
while self.push_streams.front() == Some(&PushState::Closed) {
|
while self.push_streams.front() == Some(&PushState::Closed) {
|
||||||
self.push_streams.pop_front();
|
self.push_streams.pop_front();
|
||||||
self.first_push_id += 1;
|
self.first_push_id.next();
|
||||||
}
|
}
|
||||||
Some(res)
|
Some(res)
|
||||||
}
|
}
|
||||||
@@ -108,7 +108,7 @@ impl ActivePushStreams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn number_done(&self) -> u64 {
|
pub fn number_done(&self) -> PushId {
|
||||||
self.first_push_id
|
self.first_push_id
|
||||||
+ u64::try_from(
|
+ u64::try_from(
|
||||||
self.push_streams
|
self.push_streams
|
||||||
@@ -120,7 +120,7 @@ impl ActivePushStreams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
self.first_push_id = 0;
|
self.first_push_id = PushId::new(0);
|
||||||
self.push_streams.clear();
|
self.push_streams.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@ impl ActivePushStreams {
|
|||||||
///
|
///
|
||||||
/// The `PushController` handles:
|
/// The `PushController` handles:
|
||||||
/// `PUSH_PROMISE` frame: frames may change the push state from Init to `PushPromise` and from
|
/// `PUSH_PROMISE` frame: frames may change the push state from Init to `PushPromise` and from
|
||||||
/// `OnlyPushStream` to `Active`. Frames for a closed steams are ignored.
|
/// `OnlyPushStream` to `Active`. Frames for a closed streams are ignored.
|
||||||
/// `CANCEL_PUSH` frame: (`handle_cancel_push` will be called). If a push is in state `PushPromise`
|
/// `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
|
/// 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
|
/// will be posted. If a push is in state `OnlyPushStream` or `Active` the
|
||||||
@@ -146,7 +146,7 @@ impl ActivePushStreams {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PushController {
|
pub struct PushController {
|
||||||
max_concurent_push: u64,
|
max_concurent_push: u64,
|
||||||
current_max_push_id: u64,
|
current_max_push_id: PushId,
|
||||||
// push_streams holds the states of push streams.
|
// push_streams holds the states of push streams.
|
||||||
// We keep a stream until the stream has been closed.
|
// We keep a stream until the stream has been closed.
|
||||||
push_streams: ActivePushStreams,
|
push_streams: ActivePushStreams,
|
||||||
@@ -156,24 +156,22 @@ pub struct PushController {
|
|||||||
conn_events: Http3ClientEvents,
|
conn_events: Http3ClientEvents,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for PushController {
|
||||||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||||
|
write!(f, "Push controller")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PushController {
|
impl PushController {
|
||||||
pub const fn new(max_concurent_push: u64, conn_events: Http3ClientEvents) -> Self {
|
pub const fn new(max_concurent_push: u64, conn_events: Http3ClientEvents) -> Self {
|
||||||
Self {
|
Self {
|
||||||
max_concurent_push,
|
max_concurent_push,
|
||||||
current_max_push_id: 0,
|
current_max_push_id: PushId::new(0),
|
||||||
push_streams: ActivePushStreams::new(),
|
push_streams: ActivePushStreams::new(),
|
||||||
conn_events,
|
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.
|
/// A new `push_promise` has been received.
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
@@ -181,15 +179,12 @@ impl PushController {
|
|||||||
/// `HttpId` if `push_id` greater than it is allowed has been received.
|
/// `HttpId` if `push_id` greater than it is allowed has been received.
|
||||||
pub fn new_push_promise(
|
pub fn new_push_promise(
|
||||||
&mut self,
|
&mut self,
|
||||||
push_id: u64,
|
push_id: PushId,
|
||||||
ref_stream_id: StreamId,
|
ref_stream_id: StreamId,
|
||||||
new_headers: Vec<Header>,
|
new_headers: Vec<Header>,
|
||||||
) -> Res<()> {
|
) -> Res<()> {
|
||||||
qtrace!(
|
qtrace!(
|
||||||
[self],
|
"[{self}] New push promise push_id={push_id} headers={new_headers:?} max_push={}",
|
||||||
"New push promise push_id={} headers={:?} max_push={}",
|
|
||||||
push_id,
|
|
||||||
new_headers,
|
|
||||||
self.max_concurent_push
|
self.max_concurent_push
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -197,7 +192,7 @@ impl PushController {
|
|||||||
|
|
||||||
match self.push_streams.get_mut(push_id) {
|
match self.push_streams.get_mut(push_id) {
|
||||||
None => {
|
None => {
|
||||||
qtrace!("Push has been closed already {}.", push_id);
|
qtrace!("Push has been closed already {push_id}");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Some(push_state) => match push_state {
|
Some(push_state) => match push_state {
|
||||||
@@ -236,18 +231,13 @@ impl PushController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_new_push_stream(&mut self, push_id: u64, stream_id: StreamId) -> Res<bool> {
|
pub fn add_new_push_stream(&mut self, push_id: PushId, stream_id: StreamId) -> Res<bool> {
|
||||||
qtrace!(
|
qtrace!("A new push stream with push_id={push_id} stream_id={stream_id}");
|
||||||
"A new push stream with push_id={} stream_id={}",
|
|
||||||
push_id,
|
|
||||||
stream_id
|
|
||||||
);
|
|
||||||
|
|
||||||
self.check_push_id(push_id)?;
|
self.check_push_id(push_id)?;
|
||||||
|
|
||||||
self.push_streams.get_mut(push_id).map_or_else(
|
self.push_streams.get_mut(push_id).map_or_else(
|
||||||
|| {
|
|| {
|
||||||
qinfo!("Push has been closed already.");
|
qinfo!("Push has been closed already");
|
||||||
Ok(false)
|
Ok(false)
|
||||||
},
|
},
|
||||||
|push_state| match push_state {
|
|push_state| match push_state {
|
||||||
@@ -269,17 +259,17 @@ impl PushController {
|
|||||||
// The following state have already have a push stream:
|
// The following state have already have a push stream:
|
||||||
// PushState::OnlyPushStream | PushState::Active
|
// PushState::OnlyPushStream | PushState::Active
|
||||||
_ => {
|
_ => {
|
||||||
qerror!("Duplicate push stream.");
|
qerror!("Duplicate push stream");
|
||||||
Err(Error::HttpId)
|
Err(Error::HttpId)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_push_id(&self, push_id: u64) -> Res<()> {
|
fn check_push_id(&self, push_id: PushId) -> Res<()> {
|
||||||
// Check if push id is greater than what we allow.
|
// Check if push id is greater than what we allow.
|
||||||
if push_id > self.current_max_push_id {
|
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)
|
Err(Error::HttpId)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -288,17 +278,17 @@ impl PushController {
|
|||||||
|
|
||||||
pub fn handle_cancel_push(
|
pub fn handle_cancel_push(
|
||||||
&mut self,
|
&mut self,
|
||||||
push_id: u64,
|
push_id: PushId,
|
||||||
conn: &mut Connection,
|
conn: &mut Connection,
|
||||||
base_handler: &mut Http3Connection,
|
base_handler: &mut Http3Connection,
|
||||||
) -> Res<()> {
|
) -> 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)?;
|
self.check_push_id(push_id)?;
|
||||||
|
|
||||||
match self.push_streams.close(push_id) {
|
match self.push_streams.close(push_id) {
|
||||||
None => {
|
None => {
|
||||||
qtrace!("Push has already been closed (push_id={}).", push_id);
|
qtrace!("Push has already been closed (push_id={push_id})");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Some(ps) => match ps {
|
Some(ps) => match ps {
|
||||||
@@ -310,7 +300,7 @@ impl PushController {
|
|||||||
}
|
}
|
||||||
PushState::OnlyPushStream { stream_id, .. }
|
PushState::OnlyPushStream { stream_id, .. }
|
||||||
| PushState::Active { stream_id, .. } => {
|
| PushState::Active { stream_id, .. } => {
|
||||||
mem::drop(base_handler.stream_stop_sending(
|
drop(base_handler.stream_stop_sending(
|
||||||
conn,
|
conn,
|
||||||
stream_id,
|
stream_id,
|
||||||
Error::HttpRequestCancelled.code(),
|
Error::HttpRequestCancelled.code(),
|
||||||
@@ -324,8 +314,8 @@ impl PushController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close(&mut self, push_id: u64) {
|
pub fn close(&mut self, push_id: PushId) {
|
||||||
qtrace!("Push stream has been closed.");
|
qtrace!("Push stream has been closed");
|
||||||
if let Some(push_state) = self.push_streams.close(push_id) {
|
if let Some(push_state) = self.push_streams.close(push_id) {
|
||||||
debug_assert!(matches!(push_state, PushState::Active { .. }));
|
debug_assert!(matches!(push_state, PushState::Active { .. }));
|
||||||
} else {
|
} else {
|
||||||
@@ -335,17 +325,17 @@ impl PushController {
|
|||||||
|
|
||||||
pub fn cancel(
|
pub fn cancel(
|
||||||
&mut self,
|
&mut self,
|
||||||
push_id: u64,
|
push_id: PushId,
|
||||||
conn: &mut Connection,
|
conn: &mut Connection,
|
||||||
base_handler: &mut Http3Connection,
|
base_handler: &mut Http3Connection,
|
||||||
) -> Res<()> {
|
) -> Res<()> {
|
||||||
qtrace!("Cancel push_id={}", push_id);
|
qtrace!("Cancel push_id={push_id}");
|
||||||
|
|
||||||
self.check_push_id(push_id)?;
|
self.check_push_id(push_id)?;
|
||||||
|
|
||||||
match self.push_streams.get(push_id) {
|
match self.push_streams.get(push_id) {
|
||||||
None => {
|
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
|
// 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
|
// not not know that the push has been closed. Otherwise return
|
||||||
// InvalidStreamId.
|
// InvalidStreamId.
|
||||||
@@ -365,7 +355,7 @@ impl PushController {
|
|||||||
Some(PushState::Active { stream_id, .. }) => {
|
Some(PushState::Active { stream_id, .. }) => {
|
||||||
self.conn_events.remove_events_for_push_id(push_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.
|
// Cancel the stream. The transport stream may already be done, so ignore an error.
|
||||||
mem::drop(base_handler.stream_stop_sending(
|
drop(base_handler.stream_stop_sending(
|
||||||
conn,
|
conn,
|
||||||
*stream_id,
|
*stream_id,
|
||||||
Error::HttpRequestCancelled.code(),
|
Error::HttpRequestCancelled.code(),
|
||||||
@@ -377,9 +367,8 @@ impl PushController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_stream_reset(&mut self, push_id: u64, close_type: CloseType) {
|
pub fn push_stream_reset(&mut self, push_id: PushId, close_type: CloseType) {
|
||||||
qtrace!("Push stream has been reset, push_id={}", push_id);
|
qtrace!("Push stream has been reset, push_id={push_id}");
|
||||||
|
|
||||||
if let Some(push_state) = self.push_streams.get(push_id) {
|
if let Some(push_state) = self.push_streams.get(push_id) {
|
||||||
match push_state {
|
match push_state {
|
||||||
PushState::OnlyPushStream { .. } => {
|
PushState::OnlyPushStream { .. } => {
|
||||||
@@ -397,14 +386,14 @@ impl PushController {
|
|||||||
_ => {
|
_ => {
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
false,
|
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: u64) -> Option<StreamId> {
|
pub fn get_active_stream_id(&mut self, push_id: PushId) -> Option<StreamId> {
|
||||||
match self.push_streams.get(push_id) {
|
match self.push_streams.get(push_id) {
|
||||||
Some(PushState::Active { stream_id, .. }) => Some(*stream_id),
|
Some(PushState::Active { stream_id, .. }) => Some(*stream_id),
|
||||||
_ => None,
|
_ => None,
|
||||||
@@ -414,7 +403,7 @@ impl PushController {
|
|||||||
pub fn maybe_send_max_push_id_frame(&mut self, base_handler: &mut Http3Connection) {
|
pub fn maybe_send_max_push_id_frame(&mut self, base_handler: &mut Http3Connection) {
|
||||||
let push_done = self.push_streams.number_done();
|
let push_done = self.push_streams.number_done();
|
||||||
if self.max_concurent_push > 0
|
if self.max_concurent_push > 0
|
||||||
&& (self.current_max_push_id - push_done) <= (self.max_concurent_push / 2)
|
&& (self.current_max_push_id - push_done) <= (self.max_concurent_push / 2).into()
|
||||||
{
|
{
|
||||||
self.current_max_push_id = push_done + self.max_concurent_push;
|
self.current_max_push_id = push_done + self.max_concurent_push;
|
||||||
base_handler.queue_control_frame(&HFrame::MaxPushId {
|
base_handler.queue_control_frame(&HFrame::MaxPushId {
|
||||||
@@ -424,7 +413,7 @@ impl PushController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_zero_rtt_rejected(&mut self) {
|
pub fn handle_zero_rtt_rejected(&mut self) {
|
||||||
self.current_max_push_id = 0;
|
self.current_max_push_id = PushId::new(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
@@ -435,10 +424,10 @@ impl PushController {
|
|||||||
self.max_concurent_push > 0
|
self.max_concurent_push > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_stream_event(&mut self, push_id: u64, event: Http3ClientEvent) {
|
pub fn new_stream_event(&mut self, push_id: PushId, event: Http3ClientEvent) {
|
||||||
match self.push_streams.get_mut(push_id) {
|
match self.push_streams.get_mut(push_id) {
|
||||||
None => {
|
None => {
|
||||||
debug_assert!(false, "Push has been closed already.");
|
debug_assert!(false, "Push has been closed already");
|
||||||
}
|
}
|
||||||
Some(PushState::OnlyPushStream { events, .. }) => {
|
Some(PushState::OnlyPushStream { events, .. }) => {
|
||||||
events.push(event);
|
events.push(event);
|
||||||
@@ -460,12 +449,12 @@ impl PushController {
|
|||||||
/// a `push_promise` has not been yet received for the stream.
|
/// a `push_promise` has not been yet received for the stream.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RecvPushEvents {
|
pub struct RecvPushEvents {
|
||||||
push_id: u64,
|
push_id: PushId,
|
||||||
push_handler: Rc<RefCell<PushController>>,
|
push_handler: Rc<RefCell<PushController>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RecvPushEvents {
|
impl RecvPushEvents {
|
||||||
pub const fn new(push_id: u64, push_handler: Rc<RefCell<PushController>>) -> Self {
|
pub const fn new(push_id: PushId, push_handler: Rc<RefCell<PushController>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
push_id,
|
push_id,
|
||||||
push_handler,
|
push_handler,
|
||||||
|
|||||||
55
third_party/rust/neqo-http3/src/push_id.rs
vendored
Normal file
55
third_party/rust/neqo-http3/src/push_id.rs
vendored
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
// 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 std::{cell::RefCell, cmp::min, collections::VecDeque, fmt::Debug, rc::Rc};
|
||||||
|
|
||||||
use neqo_common::{qdebug, qinfo, qtrace, Header};
|
use neqo_common::{header::HeadersExt as _, qdebug, qinfo, qtrace, Header};
|
||||||
use neqo_qpack::decoder::QPackDecoder;
|
use neqo_qpack::decoder::QPackDecoder;
|
||||||
use neqo_transport::{Connection, StreamId};
|
use neqo_transport::{Connection, StreamId};
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ use crate::{
|
|||||||
priority::PriorityHandler,
|
priority::PriorityHandler,
|
||||||
push_controller::PushController,
|
push_controller::PushController,
|
||||||
qlog, CloseType, Error, Http3StreamInfo, Http3StreamType, HttpRecvStream, HttpRecvStreamEvents,
|
qlog, CloseType, Error, Http3StreamInfo, Http3StreamType, HttpRecvStream, HttpRecvStreamEvents,
|
||||||
MessageType, Priority, ReceiveOutput, RecvStream, Res, Stream,
|
MessageType, Priority, PushId, ReceiveOutput, RecvStream, Res, Stream,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[allow(clippy::module_name_repetitions)]
|
#[allow(clippy::module_name_repetitions)]
|
||||||
@@ -61,7 +61,7 @@ enum RecvMessageState {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct PushInfo {
|
struct PushInfo {
|
||||||
push_id: u64,
|
push_id: PushId,
|
||||||
header_block: Vec<u8>,
|
header_block: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ impl RecvMessage {
|
|||||||
RecvMessageState::WaitingForFinAfterTrailers {..} => {
|
RecvMessageState::WaitingForFinAfterTrailers {..} => {
|
||||||
return Err(Error::HttpFrameUnexpected);
|
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(())
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_headers(&mut self, mut headers: Vec<Header>, fin: bool) -> Res<()> {
|
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 {
|
let interim = match self.message_type {
|
||||||
MessageType::Request => false,
|
MessageType::Request => false,
|
||||||
MessageType::Response => is_interim(&headers)?,
|
MessageType::Response => is_interim(&headers)?,
|
||||||
@@ -167,12 +167,8 @@ impl RecvMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let is_web_transport = self.message_type == MessageType::Request
|
let is_web_transport = self.message_type == MessageType::Request
|
||||||
&& headers
|
&& headers.contains_header(":method", "CONNECT")
|
||||||
.iter()
|
&& headers.contains_header(":protocol", "webtransport");
|
||||||
.any(|h| h.name() == ":method" && h.value() == "CONNECT")
|
|
||||||
&& headers
|
|
||||||
.iter()
|
|
||||||
.any(|h| h.name() == ":protocol" && h.value() == "webtransport");
|
|
||||||
if is_web_transport {
|
if is_web_transport {
|
||||||
self.conn_events
|
self.conn_events
|
||||||
.extended_connect_new_session(self.stream_id, headers);
|
.extended_connect_new_session(self.stream_id, headers);
|
||||||
@@ -203,7 +199,10 @@ impl RecvMessage {
|
|||||||
fn set_state_to_close_pending(&mut self, post_readable_event: bool) -> Res<()> {
|
fn set_state_to_close_pending(&mut self, post_readable_event: bool) -> Res<()> {
|
||||||
// Stream has received fin. Depending on headers state set header_ready
|
// Stream has received fin. Depending on headers state set header_ready
|
||||||
// or data_readable event so that app can pick up the fin.
|
// 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 {
|
match self.state {
|
||||||
RecvMessageState::WaitingForResponseHeaders { .. } => {
|
RecvMessageState::WaitingForResponseHeaders { .. } => {
|
||||||
@@ -216,7 +215,7 @@ impl RecvMessage {
|
|||||||
self.conn_events.data_readable(self.get_stream_info());
|
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) {
|
if !matches!(self.state, RecvMessageState::Closed) {
|
||||||
self.state = RecvMessageState::ClosePending;
|
self.state = RecvMessageState::ClosePending;
|
||||||
@@ -224,7 +223,7 @@ impl RecvMessage {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_push_promise(&mut self, push_id: u64, header_block: Vec<u8>) -> Res<()> {
|
fn handle_push_promise(&mut self, push_id: PushId, header_block: Vec<u8>) -> Res<()> {
|
||||||
if self.push_handler.is_none() {
|
if self.push_handler.is_none() {
|
||||||
return Err(Error::HttpFrameUnexpected);
|
return Err(Error::HttpFrameUnexpected);
|
||||||
}
|
}
|
||||||
@@ -254,9 +253,8 @@ impl RecvMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn receive_internal(&mut self, conn: &mut Connection, post_readable_event: bool) -> Res<()> {
|
fn receive_internal(&mut self, conn: &mut Connection, post_readable_event: bool) -> Res<()> {
|
||||||
let label = ::neqo_common::log_subject!(::log::Level::Debug, self);
|
|
||||||
loop {
|
loop {
|
||||||
qdebug!([label], "state={:?}.", self.state);
|
qdebug!("[{self}] state={:?}", self.state);
|
||||||
match &mut self.state {
|
match &mut self.state {
|
||||||
// In the following 3 states we need to read frames.
|
// In the following 3 states we need to read frames.
|
||||||
RecvMessageState::WaitingForResponseHeaders { frame_reader }
|
RecvMessageState::WaitingForResponseHeaders { frame_reader }
|
||||||
@@ -272,11 +270,7 @@ impl RecvMessage {
|
|||||||
(None, false) => break Ok(()),
|
(None, false) => break Ok(()),
|
||||||
(Some(frame), fin) => {
|
(Some(frame), fin) => {
|
||||||
qdebug!(
|
qdebug!(
|
||||||
[self],
|
"[{self}] A new frame has been received: {frame:?}; state={:?} fin={fin}", self.state,
|
||||||
"A new frame has been received: {:?}; state={:?} fin={}",
|
|
||||||
frame,
|
|
||||||
self.state,
|
|
||||||
fin,
|
|
||||||
);
|
);
|
||||||
match frame {
|
match frame {
|
||||||
HFrame::Headers { header_block } => {
|
HFrame::Headers { header_block } => {
|
||||||
@@ -300,10 +294,7 @@ impl RecvMessage {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
RecvMessageState::DecodingHeaders {
|
RecvMessageState::DecodingHeaders { header_block, fin } => {
|
||||||
ref header_block,
|
|
||||||
fin,
|
|
||||||
} => {
|
|
||||||
if self
|
if self
|
||||||
.qpack_decoder
|
.qpack_decoder
|
||||||
.borrow()
|
.borrow()
|
||||||
@@ -311,8 +302,7 @@ impl RecvMessage {
|
|||||||
&& !self.blocked_push_promise.is_empty()
|
&& !self.blocked_push_promise.is_empty()
|
||||||
{
|
{
|
||||||
qinfo!(
|
qinfo!(
|
||||||
[self],
|
"[{self}] decoding header is blocked waiting for a push_promise header block"
|
||||||
"decoding header is blocked waiting for a push_promise header block."
|
|
||||||
);
|
);
|
||||||
break Ok(());
|
break Ok(());
|
||||||
}
|
}
|
||||||
@@ -330,7 +320,7 @@ impl RecvMessage {
|
|||||||
break Ok(());
|
break Ok(());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
qinfo!([self], "decoding header is blocked.");
|
qinfo!("[{self}] decoding header is blocked");
|
||||||
break Ok(());
|
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>>,
|
encoder: Rc<RefCell<QPackEncoder>>,
|
||||||
conn_events: Box<dyn SendStreamEvents>,
|
conn_events: Box<dyn SendStreamEvents>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
qdebug!("Create a request stream_id={}", stream_id);
|
qdebug!("Create a request stream_id={stream_id}");
|
||||||
Self {
|
Self {
|
||||||
state: MessageState::WaitingForHeaders,
|
state: MessageState::WaitingForHeaders,
|
||||||
message_type,
|
message_type,
|
||||||
@@ -166,7 +166,7 @@ impl Stream for SendMessage {
|
|||||||
}
|
}
|
||||||
impl SendStream for SendMessage {
|
impl SendStream for SendMessage {
|
||||||
fn send_data(&mut self, conn: &mut Connection, buf: &[u8]) -> Res<usize> {
|
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()?;
|
self.state.new_data()?;
|
||||||
|
|
||||||
@@ -200,12 +200,7 @@ impl SendStream for SendMessage {
|
|||||||
min(buf.len(), available - 9)
|
min(buf.len(), available - 9)
|
||||||
};
|
};
|
||||||
|
|
||||||
qdebug!(
|
qdebug!("[{self}] send_request_body: available={available} to_send={to_send}");
|
||||||
[self],
|
|
||||||
"send_request_body: available={} to_send={}.",
|
|
||||||
available,
|
|
||||||
to_send
|
|
||||||
);
|
|
||||||
|
|
||||||
let data_frame = HFrame::Data {
|
let data_frame = HFrame::Data {
|
||||||
len: to_send as u64,
|
len: to_send as u64,
|
||||||
@@ -250,14 +245,14 @@ impl SendStream for SendMessage {
|
|||||||
fn send(&mut self, conn: &mut Connection) -> Res<()> {
|
fn send(&mut self, conn: &mut Connection) -> Res<()> {
|
||||||
let sent = Error::map_error(self.stream.send_buffer(conn), Error::HttpInternal(5))?;
|
let sent = Error::map_error(self.stream.send_buffer(conn), Error::HttpInternal(5))?;
|
||||||
|
|
||||||
qtrace!([self], "{} bytes sent", sent);
|
qtrace!("[{self}] {sent} bytes sent");
|
||||||
if !self.stream.has_buffered_data() {
|
if !self.stream.has_buffered_data() {
|
||||||
if self.state.done() {
|
if self.state.done() {
|
||||||
Error::map_error(
|
Error::map_error(
|
||||||
conn.stream_close_send(self.stream_id()),
|
conn.stream_close_send(self.stream_id()),
|
||||||
Error::HttpInternal(6),
|
Error::HttpInternal(6),
|
||||||
)?;
|
)?;
|
||||||
qtrace!([self], "done sending request");
|
qtrace!("[{self}] done sending request");
|
||||||
} else {
|
} else {
|
||||||
// DataWritable is just a signal for an application to try to write more data,
|
// 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
|
// 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 {
|
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);
|
let out = self.server.process(dgram, now);
|
||||||
self.process_http3(now);
|
self.process_http3(now);
|
||||||
// If we do not that a dgram already try again after process_http3.
|
// If we do not that a dgram already try again after process_http3.
|
||||||
match out {
|
match out {
|
||||||
Output::Datagram(d) => {
|
Output::Datagram(d) => {
|
||||||
qtrace!([self], "Send packet: {:?}", d);
|
qtrace!("[{self}] Send packet: {d:?}");
|
||||||
Output::Datagram(d)
|
Output::Datagram(d)
|
||||||
}
|
}
|
||||||
_ => self.server.process(Option::<Datagram>::None, now),
|
_ => self.server.process(Option::<Datagram>::None, now),
|
||||||
@@ -134,7 +134,7 @@ impl Http3Server {
|
|||||||
|
|
||||||
/// Process HTTP3 layer.
|
/// Process HTTP3 layer.
|
||||||
fn process_http3(&mut self, now: Instant) {
|
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
|
// `ActiveConnectionRef` `Hash` implementation doesn’t access any of the interior mutable
|
||||||
// types.
|
// types.
|
||||||
#[allow(clippy::mutable_key_type)]
|
#[allow(clippy::mutable_key_type)]
|
||||||
@@ -152,6 +152,7 @@ impl Http3Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_lines)]
|
||||||
fn process_events(&mut self, conn: &ConnectionRef, now: Instant) {
|
fn process_events(&mut self, conn: &ConnectionRef, now: Instant) {
|
||||||
let mut remove = false;
|
let mut remove = false;
|
||||||
let http3_parameters = &self.http3_parameters;
|
let http3_parameters = &self.http3_parameters;
|
||||||
@@ -172,7 +173,11 @@ impl Http3Server {
|
|||||||
headers,
|
headers,
|
||||||
fin,
|
fin,
|
||||||
} => self.events.headers(
|
} => self.events.headers(
|
||||||
Http3OrWebTransportStream::new(conn.clone(), handler.clone(), stream_info),
|
Http3OrWebTransportStream::new(
|
||||||
|
conn.clone(),
|
||||||
|
Rc::clone(handler),
|
||||||
|
stream_info,
|
||||||
|
),
|
||||||
headers,
|
headers,
|
||||||
fin,
|
fin,
|
||||||
),
|
),
|
||||||
@@ -188,15 +193,19 @@ impl Http3Server {
|
|||||||
}
|
}
|
||||||
Http3ServerConnEvent::DataWritable { stream_info } => self
|
Http3ServerConnEvent::DataWritable { stream_info } => self
|
||||||
.events
|
.events
|
||||||
.data_writable(conn.clone(), handler.clone(), stream_info),
|
.data_writable(conn.clone(), Rc::clone(handler), stream_info),
|
||||||
Http3ServerConnEvent::StreamReset { stream_info, error } => {
|
Http3ServerConnEvent::StreamReset { stream_info, error } => {
|
||||||
self.events
|
self.events.stream_reset(
|
||||||
.stream_reset(conn.clone(), handler.clone(), stream_info, error);
|
conn.clone(),
|
||||||
|
Rc::clone(handler),
|
||||||
|
stream_info,
|
||||||
|
error,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Http3ServerConnEvent::StreamStopSending { stream_info, error } => {
|
Http3ServerConnEvent::StreamStopSending { stream_info, error } => {
|
||||||
self.events.stream_stop_sending(
|
self.events.stream_stop_sending(
|
||||||
conn.clone(),
|
conn.clone(),
|
||||||
handler.clone(),
|
Rc::clone(handler),
|
||||||
stream_info,
|
stream_info,
|
||||||
error,
|
error,
|
||||||
);
|
);
|
||||||
@@ -216,7 +225,7 @@ impl Http3Server {
|
|||||||
}
|
}
|
||||||
Http3ServerConnEvent::ExtendedConnect { stream_id, headers } => {
|
Http3ServerConnEvent::ExtendedConnect { stream_id, headers } => {
|
||||||
self.events.webtransport_new_session(
|
self.events.webtransport_new_session(
|
||||||
WebTransportRequest::new(conn.clone(), handler.clone(), stream_id),
|
WebTransportRequest::new(conn.clone(), Rc::clone(handler), stream_id),
|
||||||
headers,
|
headers,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -226,7 +235,7 @@ impl Http3Server {
|
|||||||
headers,
|
headers,
|
||||||
..
|
..
|
||||||
} => self.events.webtransport_session_closed(
|
} => self.events.webtransport_session_closed(
|
||||||
WebTransportRequest::new(conn.clone(), handler.clone(), stream_id),
|
WebTransportRequest::new(conn.clone(), Rc::clone(handler), stream_id),
|
||||||
reason,
|
reason,
|
||||||
headers,
|
headers,
|
||||||
),
|
),
|
||||||
@@ -234,14 +243,14 @@ impl Http3Server {
|
|||||||
.events
|
.events
|
||||||
.webtransport_new_stream(Http3OrWebTransportStream::new(
|
.webtransport_new_stream(Http3OrWebTransportStream::new(
|
||||||
conn.clone(),
|
conn.clone(),
|
||||||
handler.clone(),
|
Rc::clone(handler),
|
||||||
stream_info,
|
stream_info,
|
||||||
)),
|
)),
|
||||||
Http3ServerConnEvent::ExtendedConnectDatagram {
|
Http3ServerConnEvent::ExtendedConnectDatagram {
|
||||||
session_id,
|
session_id,
|
||||||
datagram,
|
datagram,
|
||||||
} => self.events.webtransport_datagram(
|
} => self.events.webtransport_datagram(
|
||||||
WebTransportRequest::new(conn.clone(), handler.clone(), session_id),
|
WebTransportRequest::new(conn.clone(), Rc::clone(handler), session_id),
|
||||||
datagram,
|
datagram,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@@ -294,7 +303,7 @@ fn prepare_data(
|
|||||||
data.resize(amount, 0);
|
data.resize(amount, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
events.data(conn.clone(), handler.clone(), stream_info, data, fin);
|
events.data(conn.clone(), Rc::clone(handler), stream_info, data, fin);
|
||||||
}
|
}
|
||||||
if amount < MAX_EVENT_DATA_SIZE || fin {
|
if amount < MAX_EVENT_DATA_SIZE || fin {
|
||||||
break;
|
break;
|
||||||
@@ -311,11 +320,10 @@ fn prepare_data(
|
|||||||
mod tests {
|
mod tests {
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
mem,
|
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
};
|
};
|
||||||
|
|
||||||
use neqo_common::{event::Provider, Encoder};
|
use neqo_common::{event::Provider as _, Encoder};
|
||||||
use neqo_crypto::{AuthenticationStatus, ZeroRttCheckResult, ZeroRttChecker};
|
use neqo_crypto::{AuthenticationStatus, ZeroRttCheckResult, ZeroRttChecker};
|
||||||
use neqo_qpack::{encoder::QPackEncoder, QpackSettings};
|
use neqo_qpack::{encoder::QPackEncoder, QpackSettings};
|
||||||
use neqo_transport::{
|
use neqo_transport::{
|
||||||
@@ -502,11 +510,11 @@ mod tests {
|
|||||||
(server, client)
|
(server, client)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test http3 connection inintialization.
|
// Test http3 connection initialization.
|
||||||
// The server will open the control and qpack streams and send SETTINGS frame.
|
// The server will open the control and qpack streams and send SETTINGS frame.
|
||||||
#[test]
|
#[test]
|
||||||
fn server_connect() {
|
fn server_connect() {
|
||||||
mem::drop(connect_and_receive_settings());
|
drop(connect_and_receive_settings());
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PeerConnection {
|
struct PeerConnection {
|
||||||
@@ -559,9 +567,9 @@ mod tests {
|
|||||||
assert_eq!(sent, Ok(1));
|
assert_eq!(sent, Ok(1));
|
||||||
let out1 = neqo_trans_conn.process_output(now());
|
let out1 = neqo_trans_conn.process_output(now());
|
||||||
let out2 = server.process(out1.dgram(), now());
|
let out2 = server.process(out1.dgram(), now());
|
||||||
mem::drop(neqo_trans_conn.process(out2.dgram(), now()));
|
drop(neqo_trans_conn.process(out2.dgram(), now()));
|
||||||
|
|
||||||
// assert no error occured.
|
// assert no error occurred.
|
||||||
assert_not_closed(server);
|
assert_not_closed(server);
|
||||||
|
|
||||||
PeerConnection {
|
PeerConnection {
|
||||||
@@ -579,7 +587,7 @@ mod tests {
|
|||||||
// Server: Test receiving a new control stream and a SETTINGS frame.
|
// Server: Test receiving a new control stream and a SETTINGS frame.
|
||||||
#[test]
|
#[test]
|
||||||
fn server_receive_control_frame() {
|
fn server_receive_control_frame() {
|
||||||
mem::drop(connect());
|
drop(connect());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server: Test that the connection will be closed if control stream
|
// Server: Test that the connection will be closed if control stream
|
||||||
@@ -685,13 +693,13 @@ mod tests {
|
|||||||
test_wrong_frame_on_control_stream(&[0x0, 0x2, 0x1, 0x2]);
|
test_wrong_frame_on_control_stream(&[0x0, 0x2, 0x1, 0x2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// send HEADERS frame on a cortrol stream
|
// send HEADERS frame on a control stream
|
||||||
#[test]
|
#[test]
|
||||||
fn server_headers_frame_on_control_stream() {
|
fn server_headers_frame_on_control_stream() {
|
||||||
test_wrong_frame_on_control_stream(&[0x1, 0x2, 0x1, 0x2]);
|
test_wrong_frame_on_control_stream(&[0x1, 0x2, 0x1, 0x2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// send PUSH_PROMISE frame on a cortrol stream
|
// send PUSH_PROMISE frame on a control stream
|
||||||
#[test]
|
#[test]
|
||||||
fn server_push_promise_frame_on_control_stream() {
|
fn server_push_promise_frame_on_control_stream() {
|
||||||
test_wrong_frame_on_control_stream(&[0x5, 0x2, 0x1, 0x2]);
|
test_wrong_frame_on_control_stream(&[0x5, 0x2, 0x1, 0x2]);
|
||||||
@@ -710,9 +718,9 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let out = peer_conn.process_output(now());
|
let out = peer_conn.process_output(now());
|
||||||
let out = hconn.process(out.dgram(), now());
|
let out = hconn.process(out.dgram(), now());
|
||||||
mem::drop(peer_conn.process(out.dgram(), now()));
|
drop(peer_conn.process(out.dgram(), now()));
|
||||||
let out = hconn.process_output(now());
|
let out = hconn.process_output(now());
|
||||||
mem::drop(peer_conn.process(out.dgram(), now()));
|
drop(peer_conn.process(out.dgram(), now()));
|
||||||
|
|
||||||
// check for stop-sending with Error::HttpStreamCreation.
|
// check for stop-sending with Error::HttpStreamCreation.
|
||||||
let mut stop_sending_event_found = false;
|
let mut stop_sending_event_found = false;
|
||||||
@@ -741,7 +749,7 @@ mod tests {
|
|||||||
_ = peer_conn.stream_send(push_stream_id, &[0x1]).unwrap();
|
_ = peer_conn.stream_send(push_stream_id, &[0x1]).unwrap();
|
||||||
let out = peer_conn.process_output(now());
|
let out = peer_conn.process_output(now());
|
||||||
let out = hconn.process(out.dgram(), now());
|
let out = hconn.process(out.dgram(), now());
|
||||||
mem::drop(peer_conn.conn.process(out.dgram(), now()));
|
drop(peer_conn.conn.process(out.dgram(), now()));
|
||||||
assert_closed(&hconn, &Error::HttpStreamCreation);
|
assert_closed(&hconn, &Error::HttpStreamCreation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -836,7 +844,7 @@ mod tests {
|
|||||||
fn test_incomplete_frame(res: &[u8]) {
|
fn test_incomplete_frame(res: &[u8]) {
|
||||||
let (mut hconn, mut peer_conn) = connect_and_receive_settings();
|
let (mut hconn, mut peer_conn) = connect_and_receive_settings();
|
||||||
|
|
||||||
// send an incomplete reequest.
|
// send an incomplete request.
|
||||||
let stream_id = peer_conn.stream_create(StreamType::BiDi).unwrap();
|
let stream_id = peer_conn.stream_create(StreamType::BiDi).unwrap();
|
||||||
peer_conn.stream_send(stream_id, res).unwrap();
|
peer_conn.stream_send(stream_id, res).unwrap();
|
||||||
peer_conn.stream_close_send(stream_id).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 {
|
impl ::std::fmt::Display for StreamHandler {
|
||||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||||
let conn: &Connection = &self.conn.borrow();
|
let conn: &Connection = &self.conn.borrow();
|
||||||
write!(f, "conn={} stream_info={:?}", conn, self.stream_info)
|
write!(f, "conn={conn} stream_info={:?}", self.stream_info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,10 +115,8 @@ impl StreamHandler {
|
|||||||
/// It may return `InvalidStreamId` if a stream does not exist anymore.
|
/// It may return `InvalidStreamId` if a stream does not exist anymore.
|
||||||
pub fn stream_stop_sending(&self, app_error: AppError) -> Res<()> {
|
pub fn stream_stop_sending(&self, app_error: AppError) -> Res<()> {
|
||||||
qdebug!(
|
qdebug!(
|
||||||
[self],
|
"[{self}] stop sending stream_id:{} error:{app_error}",
|
||||||
"stop sending stream_id:{} error:{}.",
|
self.stream_info.stream_id()
|
||||||
self.stream_info.stream_id(),
|
|
||||||
app_error
|
|
||||||
);
|
);
|
||||||
self.handler.borrow_mut().stream_stop_sending(
|
self.handler.borrow_mut().stream_stop_sending(
|
||||||
self.stream_info.stream_id(),
|
self.stream_info.stream_id(),
|
||||||
@@ -134,10 +132,8 @@ impl StreamHandler {
|
|||||||
/// It may return `InvalidStreamId` if a stream does not exist anymore.
|
/// It may return `InvalidStreamId` if a stream does not exist anymore.
|
||||||
pub fn stream_reset_send(&self, app_error: AppError) -> Res<()> {
|
pub fn stream_reset_send(&self, app_error: AppError) -> Res<()> {
|
||||||
qdebug!(
|
qdebug!(
|
||||||
[self],
|
"[{self}] reset send stream_id:{} error:{app_error}",
|
||||||
"reset send stream_id:{} error:{}.",
|
self.stream_info.stream_id()
|
||||||
self.stream_info.stream_id(),
|
|
||||||
app_error
|
|
||||||
);
|
);
|
||||||
self.handler.borrow_mut().stream_reset_send(
|
self.handler.borrow_mut().stream_reset_send(
|
||||||
self.stream_info.stream_id(),
|
self.stream_info.stream_id(),
|
||||||
@@ -152,7 +148,7 @@ impl StreamHandler {
|
|||||||
///
|
///
|
||||||
/// It may return `InvalidStreamId` if a stream does not exist anymore
|
/// It may return `InvalidStreamId` if a stream does not exist anymore
|
||||||
pub fn cancel_fetch(&self, app_error: AppError) -> Res<()> {
|
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.handler.borrow_mut().cancel_fetch(
|
||||||
self.stream_info.stream_id(),
|
self.stream_info.stream_id(),
|
||||||
app_error,
|
app_error,
|
||||||
@@ -202,7 +198,7 @@ impl Http3OrWebTransportStream {
|
|||||||
///
|
///
|
||||||
/// It may return `InvalidStreamId` if a stream does not exist anymore.
|
/// It may return `InvalidStreamId` if a stream does not exist anymore.
|
||||||
pub fn send_data(&self, data: &[u8]) -> Res<usize> {
|
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)
|
self.stream_handler.send_data(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,7 +208,7 @@ impl Http3OrWebTransportStream {
|
|||||||
///
|
///
|
||||||
/// It may return `InvalidStreamId` if a stream does not exist anymore.
|
/// It may return `InvalidStreamId` if a stream does not exist anymore.
|
||||||
pub fn stream_close_send(&self) -> Res<()> {
|
pub fn stream_close_send(&self) -> Res<()> {
|
||||||
qdebug!([self], "Set new response.");
|
qdebug!("[{self}] Set new response");
|
||||||
self.stream_handler.stream_close_send()
|
self.stream_handler.stream_close_send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -283,7 +279,7 @@ impl WebTransportRequest {
|
|||||||
///
|
///
|
||||||
/// It may return `InvalidStreamId` if a stream does not exist anymore.
|
/// It may return `InvalidStreamId` if a stream does not exist anymore.
|
||||||
pub fn response(&self, accept: &WebTransportSessionAcceptAction) -> Res<()> {
|
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
|
self.stream_handler
|
||||||
.handler
|
.handler
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
@@ -335,7 +331,7 @@ impl WebTransportRequest {
|
|||||||
|
|
||||||
Ok(Http3OrWebTransportStream::new(
|
Ok(Http3OrWebTransportStream::new(
|
||||||
self.stream_handler.conn.clone(),
|
self.stream_handler.conn.clone(),
|
||||||
self.stream_handler.handler.clone(),
|
Rc::clone(&self.stream_handler.handler),
|
||||||
Http3StreamInfo::new(id, Http3StreamType::WebTransport(session_id)),
|
Http3StreamInfo::new(id, Http3StreamType::WebTransport(session_id)),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use neqo_transport::{Connection, StreamId, StreamType};
|
|||||||
use crate::{
|
use crate::{
|
||||||
control_stream_local::HTTP3_UNI_STREAM_TYPE_CONTROL,
|
control_stream_local::HTTP3_UNI_STREAM_TYPE_CONTROL,
|
||||||
frames::{hframe::HFrameType, reader::FrameDecoder, HFrame, H3_FRAME_TYPE_HEADERS},
|
frames::{hframe::HFrameType, reader::FrameDecoder, HFrame, H3_FRAME_TYPE_HEADERS},
|
||||||
CloseType, Error, Http3StreamType, ReceiveOutput, RecvStream, Res, Stream,
|
CloseType, Error, Http3StreamType, PushId, ReceiveOutput, RecvStream, Res, Stream,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const HTTP3_UNI_STREAM_TYPE_PUSH: u64 = 0x1;
|
pub const HTTP3_UNI_STREAM_TYPE_PUSH: u64 = 0x1;
|
||||||
@@ -23,7 +23,7 @@ pub enum NewStreamType {
|
|||||||
Control,
|
Control,
|
||||||
Decoder,
|
Decoder,
|
||||||
Encoder,
|
Encoder,
|
||||||
Push(u64),
|
Push(PushId),
|
||||||
WebTransportStream(u64),
|
WebTransportStream(u64),
|
||||||
Http(u64),
|
Http(u64),
|
||||||
Unknown,
|
Unknown,
|
||||||
@@ -137,7 +137,7 @@ impl NewStreamHeadReader {
|
|||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
qtrace!("Decoded uint {}", output);
|
qtrace!("Decoded uint {output}");
|
||||||
match self {
|
match self {
|
||||||
Self::ReadType {
|
Self::ReadType {
|
||||||
role, stream_id, ..
|
role, stream_id, ..
|
||||||
@@ -178,12 +178,12 @@ impl NewStreamHeadReader {
|
|||||||
Self::ReadId { stream_type, .. } => {
|
Self::ReadId { stream_type, .. } => {
|
||||||
let is_push = *stream_type == HTTP3_UNI_STREAM_TYPE_PUSH;
|
let is_push = *stream_type == HTTP3_UNI_STREAM_TYPE_PUSH;
|
||||||
*self = Self::Done;
|
*self = Self::Done;
|
||||||
qtrace!("New Stream stream push_id={}", output);
|
qtrace!("New Stream stream push_id={output}");
|
||||||
if fin {
|
if fin {
|
||||||
return Err(Error::HttpGeneralProtocol);
|
return Err(Error::HttpGeneralProtocol);
|
||||||
}
|
}
|
||||||
return if is_push {
|
return if is_push {
|
||||||
Ok(Some(NewStreamType::Push(output)))
|
Ok(Some(NewStreamType::Push(PushId::new(output))))
|
||||||
} else {
|
} else {
|
||||||
Ok(Some(NewStreamType::WebTransportStream(output)))
|
Ok(Some(NewStreamType::WebTransportStream(output)))
|
||||||
};
|
};
|
||||||
@@ -204,7 +204,7 @@ impl NewStreamHeadReader {
|
|||||||
Some(NewStreamType::Http(_)) => Err(Error::HttpFrame),
|
Some(NewStreamType::Http(_)) => Err(Error::HttpFrame),
|
||||||
Some(NewStreamType::Unknown) => Ok(decoded),
|
Some(NewStreamType::Unknown) => Ok(decoded),
|
||||||
Some(NewStreamType::Push(_) | NewStreamType::WebTransportStream(_)) => {
|
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,8 +237,6 @@ impl RecvStream for NewStreamHeadReader {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
use neqo_common::{Encoder, Role};
|
use neqo_common::{Encoder, Role};
|
||||||
use neqo_qpack::{
|
use neqo_qpack::{
|
||||||
decoder::QPACK_UNI_STREAM_TYPE_DECODER, encoder::QPACK_UNI_STREAM_TYPE_ENCODER,
|
decoder::QPACK_UNI_STREAM_TYPE_DECODER, encoder::QPACK_UNI_STREAM_TYPE_ENCODER,
|
||||||
@@ -253,7 +251,7 @@ mod tests {
|
|||||||
use crate::{
|
use crate::{
|
||||||
control_stream_local::HTTP3_UNI_STREAM_TYPE_CONTROL,
|
control_stream_local::HTTP3_UNI_STREAM_TYPE_CONTROL,
|
||||||
frames::{H3_FRAME_TYPE_HEADERS, H3_FRAME_TYPE_SETTINGS},
|
frames::{H3_FRAME_TYPE_HEADERS, H3_FRAME_TYPE_SETTINGS},
|
||||||
CloseType, Error, NewStreamType, ReceiveOutput, RecvStream, Res,
|
CloseType, Error, NewStreamType, PushId, ReceiveOutput, RecvStream as _, Res,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Test {
|
struct Test {
|
||||||
@@ -269,7 +267,7 @@ mod tests {
|
|||||||
// create a stream
|
// create a stream
|
||||||
let stream_id = conn_s.stream_create(stream_type).unwrap();
|
let stream_id = conn_s.stream_create(stream_type).unwrap();
|
||||||
let out = conn_s.process_output(now());
|
let out = conn_s.process_output(now());
|
||||||
mem::drop(conn_c.process(out.dgram(), now()));
|
drop(conn_c.process(out.dgram(), now()));
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
conn_c,
|
conn_c,
|
||||||
@@ -292,7 +290,7 @@ mod tests {
|
|||||||
.stream_send(self.stream_id, &enc[i..=i])
|
.stream_send(self.stream_id, &enc[i..=i])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let out = self.conn_s.process_output(now());
|
let out = self.conn_s.process_output(now());
|
||||||
mem::drop(self.conn_c.process(out.dgram(), now()));
|
drop(self.conn_c.process(out.dgram(), now()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
self.decoder.receive(&mut self.conn_c).unwrap(),
|
self.decoder.receive(&mut self.conn_c).unwrap(),
|
||||||
(ReceiveOutput::NoOutput, false)
|
(ReceiveOutput::NoOutput, false)
|
||||||
@@ -306,7 +304,7 @@ mod tests {
|
|||||||
self.conn_s.stream_close_send(self.stream_id).unwrap();
|
self.conn_s.stream_close_send(self.stream_id).unwrap();
|
||||||
}
|
}
|
||||||
let out = self.conn_s.process_output(now());
|
let out = self.conn_s.process_output(now());
|
||||||
mem::drop(self.conn_c.process(out.dgram(), now()));
|
drop(self.conn_c.process(out.dgram(), now()));
|
||||||
assert_eq!(&self.decoder.receive(&mut self.conn_c), outcome);
|
assert_eq!(&self.decoder.receive(&mut self.conn_c), outcome);
|
||||||
assert_eq!(self.decoder.done(), done);
|
assert_eq!(self.decoder.done(), done);
|
||||||
}
|
}
|
||||||
@@ -366,7 +364,7 @@ mod tests {
|
|||||||
&[HTTP3_UNI_STREAM_TYPE_PUSH, 0xaaaa_aaaa],
|
&[HTTP3_UNI_STREAM_TYPE_PUSH, 0xaaaa_aaaa],
|
||||||
false,
|
false,
|
||||||
&Ok((
|
&Ok((
|
||||||
ReceiveOutput::NewStream(NewStreamType::Push(0xaaaa_aaaa)),
|
ReceiveOutput::NewStream(NewStreamType::Push(PushId::new(0xaaaa_aaaa))),
|
||||||
true,
|
true,
|
||||||
)),
|
)),
|
||||||
true,
|
true,
|
||||||
@@ -429,7 +427,7 @@ mod tests {
|
|||||||
* HTTP3_UNI_STREAM_TYPE_PUSH */
|
* HTTP3_UNI_STREAM_TYPE_PUSH */
|
||||||
false,
|
false,
|
||||||
&Ok((
|
&Ok((
|
||||||
ReceiveOutput::NewStream(NewStreamType::Push(0xaaaa_aaaa)),
|
ReceiveOutput::NewStream(NewStreamType::Push(PushId::new(0xaaaa_aaaa))),
|
||||||
true,
|
true,
|
||||||
)),
|
)),
|
||||||
true,
|
true,
|
||||||
|
|||||||
29
third_party/rust/neqo-http3/tests/httpconn.rs
vendored
29
third_party/rust/neqo-http3/tests/httpconn.rs
vendored
@@ -4,12 +4,9 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::{
|
use std::time::{Duration, Instant};
|
||||||
mem,
|
|
||||||
time::{Duration, Instant},
|
|
||||||
};
|
|
||||||
|
|
||||||
use neqo_common::{event::Provider, qtrace, Datagram};
|
use neqo_common::{event::Provider as _, qtrace, Datagram};
|
||||||
use neqo_crypto::{AuthenticationStatus, ResumptionToken};
|
use neqo_crypto::{AuthenticationStatus, ResumptionToken};
|
||||||
use neqo_http3::{
|
use neqo_http3::{
|
||||||
Header, Http3Client, Http3ClientEvent, Http3OrWebTransportStream, Http3Parameters, Http3Server,
|
Header, Http3Client, Http3ClientEvent, Http3OrWebTransportStream, Http3Parameters, Http3Server,
|
||||||
@@ -97,7 +94,7 @@ fn connect_peers(hconn_c: &mut Http3Client, hconn_s: &mut Http3Server) -> Option
|
|||||||
let out = hconn_c.process_output(now()); // Initial
|
let out = hconn_c.process_output(now()); // Initial
|
||||||
let out = hconn_s.process(out.dgram(), now()); // Initial + Handshake
|
let out = hconn_s.process(out.dgram(), now()); // Initial + Handshake
|
||||||
let out = hconn_c.process(out.dgram(), now()); // ACK
|
let out = hconn_c.process(out.dgram(), now()); // ACK
|
||||||
mem::drop(hconn_s.process(out.dgram(), now())); // consume ACK
|
drop(hconn_s.process(out.dgram(), now())); // consume ACK
|
||||||
let authentication_needed = |e| matches!(e, Http3ClientEvent::AuthenticationNeeded);
|
let authentication_needed = |e| matches!(e, Http3ClientEvent::AuthenticationNeeded);
|
||||||
assert!(hconn_c.events().any(authentication_needed));
|
assert!(hconn_c.events().any(authentication_needed));
|
||||||
hconn_c.authenticated(AuthenticationStatus::Ok, now());
|
hconn_c.authenticated(AuthenticationStatus::Ok, now());
|
||||||
@@ -189,14 +186,14 @@ fn fetch() {
|
|||||||
let out = hconn_c.process(dgram, now());
|
let out = hconn_c.process(dgram, now());
|
||||||
qtrace!("-----server");
|
qtrace!("-----server");
|
||||||
let out = hconn_s.process(out.dgram(), now());
|
let out = hconn_s.process(out.dgram(), now());
|
||||||
mem::drop(hconn_c.process(out.dgram(), now()));
|
drop(hconn_c.process(out.dgram(), now()));
|
||||||
process_server_events(&hconn_s);
|
process_server_events(&hconn_s);
|
||||||
let out = hconn_s.process(None::<Datagram>, now());
|
let out = hconn_s.process(None::<Datagram>, now());
|
||||||
|
|
||||||
qtrace!("-----client");
|
qtrace!("-----client");
|
||||||
mem::drop(hconn_c.process(out.dgram(), now()));
|
drop(hconn_c.process(out.dgram(), now()));
|
||||||
let out = hconn_s.process(None::<Datagram>, now());
|
let out = hconn_s.process(None::<Datagram>, now());
|
||||||
mem::drop(hconn_c.process(out.dgram(), now()));
|
drop(hconn_c.process(out.dgram(), now()));
|
||||||
process_client_events(&mut hconn_c);
|
process_client_events(&mut hconn_c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +215,7 @@ fn response_103() {
|
|||||||
let out = hconn_c.process(dgram, now());
|
let out = hconn_c.process(dgram, now());
|
||||||
|
|
||||||
let out = hconn_s.process(out.dgram(), now());
|
let out = hconn_s.process(out.dgram(), now());
|
||||||
mem::drop(hconn_c.process(out.dgram(), now()));
|
drop(hconn_c.process(out.dgram(), now()));
|
||||||
let request = receive_request(&hconn_s).unwrap();
|
let request = receive_request(&hconn_s).unwrap();
|
||||||
let info_headers = [
|
let info_headers = [
|
||||||
Header::new(":status", "103"),
|
Header::new(":status", "103"),
|
||||||
@@ -228,7 +225,7 @@ fn response_103() {
|
|||||||
request.send_headers(&info_headers).unwrap();
|
request.send_headers(&info_headers).unwrap();
|
||||||
let out = hconn_s.process(None::<Datagram>, now());
|
let out = hconn_s.process(None::<Datagram>, now());
|
||||||
|
|
||||||
mem::drop(hconn_c.process(out.dgram(), now()));
|
drop(hconn_c.process(out.dgram(), now()));
|
||||||
|
|
||||||
let info_headers_event = |e| {
|
let info_headers_event = |e| {
|
||||||
matches!(e, Http3ClientEvent::HeaderReady { headers,
|
matches!(e, Http3ClientEvent::HeaderReady { headers,
|
||||||
@@ -239,7 +236,7 @@ fn response_103() {
|
|||||||
|
|
||||||
set_response(&request);
|
set_response(&request);
|
||||||
let out = hconn_s.process(None::<Datagram>, now());
|
let out = hconn_s.process(None::<Datagram>, now());
|
||||||
mem::drop(hconn_c.process(out.dgram(), now()));
|
drop(hconn_c.process(out.dgram(), now()));
|
||||||
process_client_events(&mut hconn_c);
|
process_client_events(&mut hconn_c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,7 +253,7 @@ fn data_writable_events_low_watermark() -> Result<(), Box<dyn std::error::Error>
|
|||||||
ConnectionParameters::default().max_stream_data(StreamType::BiDi, false, STREAM_LIMIT),
|
ConnectionParameters::default().max_stream_data(StreamType::BiDi, false, STREAM_LIMIT),
|
||||||
));
|
));
|
||||||
let mut hconn_s = default_http3_server();
|
let mut hconn_s = default_http3_server();
|
||||||
mem::drop(connect_peers(&mut hconn_c, &mut hconn_s));
|
drop(connect_peers(&mut hconn_c, &mut hconn_s));
|
||||||
|
|
||||||
// Client sends GET to server.
|
// Client sends GET to server.
|
||||||
let stream_id = hconn_c.fetch(
|
let stream_id = hconn_c.fetch(
|
||||||
@@ -298,7 +295,7 @@ fn data_writable_events_low_watermark() -> Result<(), Box<dyn std::error::Error>
|
|||||||
exchange_packets(&mut hconn_c, &mut hconn_s, None);
|
exchange_packets(&mut hconn_c, &mut hconn_s, None);
|
||||||
assert!(hconn_s.events().any(data_writable));
|
assert!(hconn_s.events().any(data_writable));
|
||||||
|
|
||||||
// Sending more fails, given that each data frame needs to be preceeded by a
|
// Sending more fails, given that each data frame needs to be preceded by a
|
||||||
// header, i.e. needs more than 1 byte of send space to send 1 byte payload.
|
// header, i.e. needs more than 1 byte of send space to send 1 byte payload.
|
||||||
assert_eq!(request.available()?, 1);
|
assert_eq!(request.available()?, 1);
|
||||||
assert_eq!(request.send_data(&buf)?, 0);
|
assert_eq!(request.send_data(&buf)?, 0);
|
||||||
@@ -330,7 +327,7 @@ fn data_writable_events() {
|
|||||||
));
|
));
|
||||||
let mut hconn_s = default_http3_server();
|
let mut hconn_s = default_http3_server();
|
||||||
|
|
||||||
mem::drop(connect_peers(&mut hconn_c, &mut hconn_s));
|
drop(connect_peers(&mut hconn_c, &mut hconn_s));
|
||||||
|
|
||||||
// Create a request.
|
// Create a request.
|
||||||
let req = hconn_c
|
let req = hconn_c
|
||||||
@@ -433,7 +430,7 @@ fn zerortt() {
|
|||||||
let mut hconn_c = default_http3_client();
|
let mut hconn_c = default_http3_client();
|
||||||
hconn_c
|
hconn_c
|
||||||
.enable_resumption(now(), &token)
|
.enable_resumption(now(), &token)
|
||||||
.expect("Set resumption token.");
|
.expect("Set resumption token");
|
||||||
let mut hconn_s = default_http3_server();
|
let mut hconn_s = default_http3_server();
|
||||||
|
|
||||||
// Create a request.
|
// 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 std::time::Instant;
|
||||||
|
|
||||||
use neqo_common::event::Provider;
|
use neqo_common::event::Provider as _;
|
||||||
use neqo_crypto::AuthenticationStatus;
|
use neqo_crypto::AuthenticationStatus;
|
||||||
use neqo_http3::{
|
use neqo_http3::{
|
||||||
Header, Http3Client, Http3ClientEvent, Http3Server, Http3ServerEvent, Http3State, Priority,
|
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) {
|
fn connect_with(client: &mut Http3Client, server: &mut Http3Server) {
|
||||||
assert_eq!(client.state(), Http3State::Initializing);
|
assert_eq!(client.state(), Http3State::Initializing);
|
||||||
let out = client.process_output(now());
|
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!(client.events().any(connected));
|
||||||
|
|
||||||
assert_eq!(client.state(), Http3State::Connected);
|
assert_eq!(client.state(), Http3State::Connected);
|
||||||
// Exchange H3 setttings
|
// Exchange H3 settings
|
||||||
let out = server.process(out.dgram(), now());
|
let out = server.process(out.dgram(), now());
|
||||||
let out = client.process(out.dgram(), now());
|
let out = client.process(out.dgram(), now());
|
||||||
let out = server.process(out.dgram(), now());
|
let out = server.process(out.dgram(), now());
|
||||||
@@ -83,11 +83,7 @@ fn priority_update() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match header_event {
|
match header_event {
|
||||||
Http3ServerEvent::Headers {
|
Http3ServerEvent::Headers { headers, fin, .. } => {
|
||||||
stream: _,
|
|
||||||
headers,
|
|
||||||
fin,
|
|
||||||
} => {
|
|
||||||
let expected_headers = &[
|
let expected_headers = &[
|
||||||
Header::new(":method", "GET"),
|
Header::new(":method", "GET"),
|
||||||
Header::new(":scheme", "https"),
|
Header::new(":scheme", "https"),
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
use neqo_common::event::Provider;
|
use neqo_common::event::Provider as _;
|
||||||
use neqo_crypto::AuthenticationStatus;
|
use neqo_crypto::AuthenticationStatus;
|
||||||
use neqo_http3::{
|
use neqo_http3::{
|
||||||
Error, Header, Http3Client, Http3ClientEvent, Http3OrWebTransportStream, Http3Server,
|
Error, Header, Http3Client, Http3ClientEvent, Http3OrWebTransportStream, Http3Server,
|
||||||
|
|||||||
@@ -6,14 +6,14 @@
|
|||||||
|
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use neqo_common::{event::Provider, Header};
|
use neqo_common::{event::Provider as _, header::HeadersExt as _};
|
||||||
use neqo_crypto::AuthenticationStatus;
|
use neqo_crypto::AuthenticationStatus;
|
||||||
use neqo_http3::{
|
use neqo_http3::{
|
||||||
Http3Client, Http3ClientEvent, Http3OrWebTransportStream, Http3Parameters, Http3Server,
|
Http3Client, Http3ClientEvent, Http3OrWebTransportStream, Http3Parameters, Http3Server,
|
||||||
Http3ServerEvent, Http3State, WebTransportEvent, WebTransportRequest, WebTransportServerEvent,
|
Http3ServerEvent, Http3State, WebTransportEvent, WebTransportRequest, WebTransportServerEvent,
|
||||||
WebTransportSessionAcceptAction,
|
WebTransportSessionAcceptAction,
|
||||||
};
|
};
|
||||||
use neqo_transport::{StreamId, StreamType};
|
use neqo_transport::{ConnectionParameters, StreamId, StreamType};
|
||||||
use test_fixture::{
|
use test_fixture::{
|
||||||
anti_replay, fixture_init, now, CountingConnectionIdGenerator, DEFAULT_ADDR, DEFAULT_ALPN_H3,
|
anti_replay, fixture_init, now, CountingConnectionIdGenerator, DEFAULT_ADDR, DEFAULT_ALPN_H3,
|
||||||
DEFAULT_KEYS, DEFAULT_SERVER_NAME,
|
DEFAULT_KEYS, DEFAULT_SERVER_NAME,
|
||||||
@@ -59,7 +59,7 @@ fn connect() -> (Http3Client, Http3Server) {
|
|||||||
|
|
||||||
assert_eq!(client.state(), Http3State::Connected);
|
assert_eq!(client.state(), Http3State::Connected);
|
||||||
|
|
||||||
// Exchange H3 setttings
|
// Exchange H3 settings
|
||||||
loop {
|
loop {
|
||||||
out = server.process(out, now()).dgram();
|
out = server.process(out, now()).dgram();
|
||||||
let dgram_present = out.is_some();
|
let dgram_present = out.is_some();
|
||||||
@@ -96,12 +96,8 @@ fn create_wt_session(client: &mut Http3Client, server: &mut Http3Server) -> WebT
|
|||||||
headers,
|
headers,
|
||||||
}) => {
|
}) => {
|
||||||
assert!(
|
assert!(
|
||||||
headers
|
headers.contains_header(":method", "CONNECT")
|
||||||
.iter()
|
&& headers.contains_header(":protocol", "webtransport")
|
||||||
.any(|h| h.name() == ":method" && h.value() == "CONNECT")
|
|
||||||
&& headers
|
|
||||||
.iter()
|
|
||||||
.any(|h| h.name() == ":protocol" && h.value() == "webtransport")
|
|
||||||
);
|
);
|
||||||
session
|
session
|
||||||
.response(&WebTransportSessionAcceptAction::Accept)
|
.response(&WebTransportSessionAcceptAction::Accept)
|
||||||
@@ -127,7 +123,7 @@ fn create_wt_session(client: &mut Http3Client, server: &mut Http3Server) -> WebT
|
|||||||
}) if (
|
}) if (
|
||||||
stream_id == wt_session_id &&
|
stream_id == wt_session_id &&
|
||||||
status == 200 &&
|
status == 200 &&
|
||||||
headers.contains(&Header::new(":status", "200"))
|
headers.contains_header(":status", "200")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@@ -229,6 +225,17 @@ fn receive_data_server(
|
|||||||
wt_stream.unwrap()
|
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]
|
#[test]
|
||||||
fn wt_client_stream_uni() {
|
fn wt_client_stream_uni() {
|
||||||
const BUF_CLIENT: &[u8] = &[0; 10];
|
const BUF_CLIENT: &[u8] = &[0; 10];
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"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}
|
{"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}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user