Bug 1926928 - update to neqo v0.10.0 r=necko-reviewers,sunil,valentin

Differential Revision: https://phabricator.services.mozilla.com/D226823
This commit is contained in:
Max Inden 2024-11-06 08:21:25 +00:00
Родитель 06d2615a13
Коммит 72924760ab
74 изменённых файлов: 1820 добавлений и 1588 удалений

Просмотреть файл

@ -90,9 +90,9 @@ git = "https://github.com/mozilla/mp4parse-rust"
rev = "a138e40ec1c603615873e524b5b22e11c0ec4820" rev = "a138e40ec1c603615873e524b5b22e11c0ec4820"
replace-with = "vendored-sources" replace-with = "vendored-sources"
[source."git+https://github.com/mozilla/neqo?tag=v0.9.2"] [source."git+https://github.com/mozilla/neqo?tag=v0.10.0"]
git = "https://github.com/mozilla/neqo" git = "https://github.com/mozilla/neqo"
tag = "v0.9.2" tag = "v0.10.0"
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"]

28
Cargo.lock сгенерированный
Просмотреть файл

@ -4281,8 +4281,8 @@ dependencies = [
[[package]] [[package]]
name = "neqo-bin" name = "neqo-bin"
version = "0.9.2" version = "0.10.0"
source = "git+https://github.com/mozilla/neqo?tag=v0.9.2#aca20d3890c0a8af2658c95d2634cab2b5badf08" source = "git+https://github.com/mozilla/neqo?tag=v0.10.0#214ad48e0dbb8cc35c7148b225fbc6f58eb85f36"
dependencies = [ dependencies = [
"clap", "clap",
"clap-verbosity-flag", "clap-verbosity-flag",
@ -4303,8 +4303,8 @@ dependencies = [
[[package]] [[package]]
name = "neqo-common" name = "neqo-common"
version = "0.9.2" version = "0.10.0"
source = "git+https://github.com/mozilla/neqo?tag=v0.9.2#aca20d3890c0a8af2658c95d2634cab2b5badf08" source = "git+https://github.com/mozilla/neqo?tag=v0.10.0#214ad48e0dbb8cc35c7148b225fbc6f58eb85f36"
dependencies = [ dependencies = [
"enum-map", "enum-map",
"env_logger", "env_logger",
@ -4315,8 +4315,8 @@ dependencies = [
[[package]] [[package]]
name = "neqo-crypto" name = "neqo-crypto"
version = "0.9.2" version = "0.10.0"
source = "git+https://github.com/mozilla/neqo?tag=v0.9.2#aca20d3890c0a8af2658c95d2634cab2b5badf08" source = "git+https://github.com/mozilla/neqo?tag=v0.10.0#214ad48e0dbb8cc35c7148b225fbc6f58eb85f36"
dependencies = [ dependencies = [
"bindgen 0.69.4", "bindgen 0.69.4",
"log", "log",
@ -4330,8 +4330,8 @@ dependencies = [
[[package]] [[package]]
name = "neqo-http3" name = "neqo-http3"
version = "0.9.2" version = "0.10.0"
source = "git+https://github.com/mozilla/neqo?tag=v0.9.2#aca20d3890c0a8af2658c95d2634cab2b5badf08" source = "git+https://github.com/mozilla/neqo?tag=v0.10.0#214ad48e0dbb8cc35c7148b225fbc6f58eb85f36"
dependencies = [ dependencies = [
"enumset", "enumset",
"log", "log",
@ -4346,8 +4346,8 @@ dependencies = [
[[package]] [[package]]
name = "neqo-qpack" name = "neqo-qpack"
version = "0.9.2" version = "0.10.0"
source = "git+https://github.com/mozilla/neqo?tag=v0.9.2#aca20d3890c0a8af2658c95d2634cab2b5badf08" source = "git+https://github.com/mozilla/neqo?tag=v0.10.0#214ad48e0dbb8cc35c7148b225fbc6f58eb85f36"
dependencies = [ dependencies = [
"log", "log",
"neqo-common", "neqo-common",
@ -4358,8 +4358,8 @@ dependencies = [
[[package]] [[package]]
name = "neqo-transport" name = "neqo-transport"
version = "0.9.2" version = "0.10.0"
source = "git+https://github.com/mozilla/neqo?tag=v0.9.2#aca20d3890c0a8af2658c95d2634cab2b5badf08" source = "git+https://github.com/mozilla/neqo?tag=v0.10.0#214ad48e0dbb8cc35c7148b225fbc6f58eb85f36"
dependencies = [ dependencies = [
"enum-map", "enum-map",
"indexmap 2.2.6", "indexmap 2.2.6",
@ -4373,8 +4373,8 @@ dependencies = [
[[package]] [[package]]
name = "neqo-udp" name = "neqo-udp"
version = "0.9.2" version = "0.10.0"
source = "git+https://github.com/mozilla/neqo?tag=v0.9.2#aca20d3890c0a8af2658c95d2634cab2b5badf08" source = "git+https://github.com/mozilla/neqo?tag=v0.10.0#214ad48e0dbb8cc35c7148b225fbc6f58eb85f36"
dependencies = [ dependencies = [
"log", "log",
"neqo-common", "neqo-common",

Просмотреть файл

@ -1166,7 +1166,6 @@ networking:
- DecodingFrame - DecodingFrame
- DecryptError - DecryptError
- DisabledVersion - DisabledVersion
- HandshakeFailed
- IdleTimeout - IdleTimeout
- IntegerOverflow - IntegerOverflow
- InvalidInput - InvalidInput

Просмотреть файл

@ -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.9.2", git = "https://github.com/mozilla/neqo" } neqo-udp = { tag = "v0.10.0", git = "https://github.com/mozilla/neqo" }
neqo-http3 = { tag = "v0.9.2", git = "https://github.com/mozilla/neqo" } neqo-http3 = { tag = "v0.10.0", git = "https://github.com/mozilla/neqo" }
neqo-transport = { tag = "v0.9.2", git = "https://github.com/mozilla/neqo" } neqo-transport = { tag = "v0.10.0", git = "https://github.com/mozilla/neqo" }
neqo-common = { tag = "v0.9.2", git = "https://github.com/mozilla/neqo" } neqo-common = { tag = "v0.10.0", git = "https://github.com/mozilla/neqo" }
neqo-qpack = { tag = "v0.9.2", git = "https://github.com/mozilla/neqo" } neqo-qpack = { tag = "v0.10.0", 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,7 +29,7 @@ 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.9.2" tag = "v0.10.0"
git = "https://github.com/mozilla/neqo" git = "https://github.com/mozilla/neqo"
default-features = false default-features = false
features = ["gecko"] features = ["gecko"]

Просмотреть файл

@ -41,6 +41,10 @@ use uuid::Uuid;
use winapi::shared::ws2def::{AF_INET, AF_INET6}; 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! {
static RECV_BUF: RefCell<Vec<u8>> = RefCell::new(vec![0; neqo_udp::RECV_BUF_SIZE]);
}
#[repr(C)] #[repr(C)]
pub struct NeqoHttp3Conn { pub struct NeqoHttp3Conn {
conn: Http3Client, conn: Http3Client,
@ -517,10 +521,10 @@ pub unsafe extern "C" fn neqo_http3conn_process_input_use_nspr_for_io(
remote, remote,
conn.local_addr, conn.local_addr,
IpTos::default(), IpTos::default(),
(*packet).to_vec(), (*packet).as_slice(),
); );
conn.conn conn.conn
.process_input(&d, get_current_or_last_output_time(&conn.last_output_time)); .process_input(d, get_current_or_last_output_time(&conn.last_output_time));
return NS_OK; return NS_OK;
} }
@ -538,52 +542,61 @@ pub unsafe extern "C" fn neqo_http3conn_process_input(
) -> ProcessInputResult { ) -> ProcessInputResult {
let mut bytes_read = 0; let mut bytes_read = 0;
loop { RECV_BUF.with_borrow_mut(|recv_buf| {
let mut dgrams = match conn loop {
.socket let dgrams = match conn
.as_mut() .socket
.expect("non NSPR IO") .as_mut()
.recv(&conn.local_addr) .expect("non NSPR IO")
{ .recv(conn.local_addr, recv_buf)
Ok(dgrams) => dgrams, {
Err(e) if e.kind() == io::ErrorKind::WouldBlock => { Ok(dgrams) => dgrams,
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
break;
}
Err(e) => {
qwarn!("failed to receive datagrams: {}", e);
return ProcessInputResult {
result: NS_ERROR_FAILURE,
bytes_read: 0,
};
}
};
if dgrams.len() == 0 {
break; break;
} }
Err(e) => {
qwarn!("failed to receive datagrams: {}", e); // Attach metric instrumentation to `dgrams` iterator.
return ProcessInputResult { let mut sum = 0;
result: NS_ERROR_FAILURE, conn.datagram_segments_received
bytes_read: 0, .accumulate(dgrams.len() as u64);
}; let datagram_segment_size_received = &mut conn.datagram_segment_size_received;
} let dgrams = dgrams.map(|d| {
datagram_segment_size_received.accumulate(d.len() as u64);
sum += d.len();
d
});
// Override `dgrams` ECN marks according to prefs.
let ecn_enabled = static_prefs::pref!("network.http.http3.ecn");
let dgrams = dgrams.map(|mut d| {
if !ecn_enabled {
d.set_tos(Default::default());
}
d
});
conn.conn.process_multiple_input(dgrams, Instant::now());
conn.datagram_size_received.accumulate(sum as u64);
bytes_read += sum;
}
return ProcessInputResult {
result: NS_OK,
bytes_read: bytes_read.try_into().unwrap_or(u32::MAX),
}; };
if dgrams.is_empty() { })
break;
}
let mut sum = 0;
let ecn_enabled = static_prefs::pref!("network.http.http3.ecn");
for dgram in &mut dgrams {
if !ecn_enabled {
dgram.set_tos(Default::default());
}
conn.datagram_segment_size_received
.accumulate(dgram.len() as u64);
sum += dgram.len();
}
conn.datagram_size_received.accumulate(sum as u64);
conn.datagram_segments_received
.accumulate(dgrams.len() as u64);
bytes_read += sum;
conn.conn
.process_multiple_input(dgrams.iter(), Instant::now());
}
return ProcessInputResult {
result: NS_OK,
bytes_read: bytes_read.try_into().unwrap_or(u32::MAX),
};
} }
#[no_mangle] #[no_mangle]
@ -1001,7 +1014,6 @@ impl From<TransportError> for CloseError {
TransportError::ConnectionState => CloseError::TransportInternalErrorOther(3), TransportError::ConnectionState => CloseError::TransportInternalErrorOther(3),
TransportError::DecodingFrame => CloseError::TransportInternalErrorOther(4), TransportError::DecodingFrame => CloseError::TransportInternalErrorOther(4),
TransportError::DecryptError => CloseError::TransportInternalErrorOther(5), TransportError::DecryptError => CloseError::TransportInternalErrorOther(5),
TransportError::HandshakeFailed => CloseError::TransportInternalErrorOther(6),
TransportError::IntegerOverflow => CloseError::TransportInternalErrorOther(7), TransportError::IntegerOverflow => CloseError::TransportInternalErrorOther(7),
TransportError::InvalidInput => CloseError::TransportInternalErrorOther(8), TransportError::InvalidInput => CloseError::TransportInternalErrorOther(8),
TransportError::InvalidMigration => CloseError::TransportInternalErrorOther(9), TransportError::InvalidMigration => CloseError::TransportInternalErrorOther(9),
@ -1057,7 +1069,6 @@ fn transport_error_to_glean_label(error: &TransportError) -> &'static str {
TransportError::DecodingFrame => "DecodingFrame", TransportError::DecodingFrame => "DecodingFrame",
TransportError::DecryptError => "DecryptError", TransportError::DecryptError => "DecryptError",
TransportError::DisabledVersion => "DisabledVersion", TransportError::DisabledVersion => "DisabledVersion",
TransportError::HandshakeFailed => "HandshakeFailed",
TransportError::IdleTimeout => "IdleTimeout", TransportError::IdleTimeout => "IdleTimeout",
TransportError::IntegerOverflow => "IntegerOverflow", TransportError::IntegerOverflow => "IntegerOverflow",
TransportError::InvalidInput => "InvalidInput", TransportError::InvalidInput => "InvalidInput",

Просмотреть файл

@ -6,11 +6,11 @@ edition = "2018"
license = "MPL-2.0" license = "MPL-2.0"
[dependencies] [dependencies]
neqo-bin = { tag = "v0.9.2", git = "https://github.com/mozilla/neqo" } neqo-bin = { tag = "v0.10.0", git = "https://github.com/mozilla/neqo" }
neqo-transport = { tag = "v0.9.2", git = "https://github.com/mozilla/neqo" } neqo-transport = { tag = "v0.10.0", git = "https://github.com/mozilla/neqo" }
neqo-common = { tag = "v0.9.2", git = "https://github.com/mozilla/neqo" } neqo-common = { tag = "v0.10.0", git = "https://github.com/mozilla/neqo" }
neqo-http3 = { tag = "v0.9.2", git = "https://github.com/mozilla/neqo" } neqo-http3 = { tag = "v0.10.0", git = "https://github.com/mozilla/neqo" }
neqo-qpack = { tag = "v0.9.2", git = "https://github.com/mozilla/neqo" } neqo-qpack = { tag = "v0.10.0", 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.9.2" tag = "v0.10.0"
git = "https://github.com/mozilla/neqo" git = "https://github.com/mozilla/neqo"
default-features = false default-features = false
features = ["gecko"] features = ["gecko"]

Просмотреть файл

@ -179,7 +179,7 @@ impl Http3TestServer {
} }
impl HttpServer for Http3TestServer { impl HttpServer for Http3TestServer {
fn process(&mut self, dgram: Option<&Datagram>, now: Instant) -> Output { fn process(&mut self, dgram: Option<Datagram>, now: Instant) -> Output {
let output = self.server.process(dgram, now); let output = self.server.process(dgram, now);
let output = if self.sessions_to_close.is_empty() { let output = if self.sessions_to_close.is_empty() {
@ -637,7 +637,7 @@ impl ::std::fmt::Display for Server {
} }
impl HttpServer for Server { impl HttpServer for Server {
fn process(&mut self, dgram: Option<&Datagram>, now: Instant) -> Output { fn process(&mut self, dgram: Option<Datagram>, now: Instant) -> Output {
self.0.process(dgram, now) self.0.process(dgram, now)
} }
@ -882,7 +882,7 @@ impl Http3ProxyServer {
} }
impl HttpServer for Http3ProxyServer { impl HttpServer for Http3ProxyServer {
fn process(&mut self, dgram: Option<&Datagram>, now: Instant) -> Output { fn process(&mut self, dgram: Option<Datagram>, now: Instant) -> Output {
let output = self.server.process(dgram, now); let output = self.server.process(dgram, now);
#[cfg(not(target_os = "android"))] #[cfg(not(target_os = "android"))]
@ -1015,7 +1015,7 @@ impl ::std::fmt::Display for NonRespondingServer {
} }
impl HttpServer for NonRespondingServer { impl HttpServer for NonRespondingServer {
fn process(&mut self, _dgram: Option<&Datagram>, _now: Instant) -> Output { fn process(&mut self, _dgram: Option<Datagram>, _now: Instant) -> Output {
Output::None Output::None
} }
@ -1227,7 +1227,7 @@ extern "C" fn __tsan_default_suppressions() -> *const std::os::raw::c_char {
} }
// Work around until we can use raw-dylibs. // Work around until we can use raw-dylibs.
#[cfg_attr(target_os = "windows", link(name="runtimeobject"))] #[cfg_attr(target_os = "windows", link(name = "runtimeobject"))]
extern "C" {} extern "C" {}
#[cfg_attr(target_os = "windows", link(name="propsys"))] #[cfg_attr(target_os = "windows", link(name = "propsys"))]
extern "C" {} extern "C" {}

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"937660e9dcd5400a6b252abc9c7b4c916d475719396d7fd288d260ce39f0e373","benches/main.rs":"aa39bf1f08863e3bace034a991c60a4723f1a7d30b3fc1d1f8c4d7f73bc748c3","src/bin/client.rs":"db77efd75dc0745b6dd983ab8fa3bc8f5f9111967f0d90d23cb19140a940246d","src/bin/server.rs":"2f7ab3c7a98117bd162e6fd07abef1d21791d1bb240db3aae61afa6ff72df83a","src/client/http09.rs":"9d728f068954df99adec622d771e8e734155b3a7aff80d823273a21cab94d6dd","src/client/http3.rs":"77cc2cc6a831a2b3e5719a69798e4f0cafea6f59006caf5990282168c4a30c82","src/client/mod.rs":"931d1b51d71694a56d22af1a6ecb03941ae1283fa04e65a2b83ef08351e71b9d","src/lib.rs":"d2ebba2cb72d1b637baa856c9a5715a31c1f35c3476225ce6ffc9cbe29bc28e9","src/server/http09.rs":"9ffb0f62c6202a2914086b7e1d8ba77e016c1b4f4a9895b268a6312a04ad70e3","src/server/http3.rs":"0bdab101bffda37257360f9a968d32ff8884b40f292878f3dc27b055e0b5864b","src/server/mod.rs":"e1edfc71853f8b5be96287391919dc84d24191e865f7b9b4a38eebfda07ce453","src/udp.rs":"9042b73c20223e1c7b45d862dea9417fc367032db09dd05d48ca06ac33638435"},"package":null} {"files":{"Cargo.toml":"3e509d82762d5e23010e0dc484522c84c08b0c5d596bd0ab7110e2c16ec5afaf","benches/main.rs":"ccfc5f44b2228603ef82a3c22fba57b8beb40a81254bd771b2b26556540d094e","src/bin/client.rs":"db77efd75dc0745b6dd983ab8fa3bc8f5f9111967f0d90d23cb19140a940246d","src/bin/server.rs":"2f7ab3c7a98117bd162e6fd07abef1d21791d1bb240db3aae61afa6ff72df83a","src/client/http09.rs":"c0f30400a4e2822c54051efe6f8a1f096ef21ecfe602737cd71dd5b86b662f4b","src/client/http3.rs":"85a0fc3b1d50f6a108b3d74ee115270b06f2412443134627ade752b9691b5ae5","src/client/mod.rs":"b7f3ca90b886283e999b21288a57db5ed9456062ff12c9bf2570025659c9efdd","src/lib.rs":"d2ebba2cb72d1b637baa856c9a5715a31c1f35c3476225ce6ffc9cbe29bc28e9","src/server/http09.rs":"3d168f28c29cbc7c33aab713afa180dba0f627e55edc60ee7e02ec29e3847e68","src/server/http3.rs":"a15266daec0a3f1ef279f9b1101e49a0537ce0d9f1e34adc2d69fb735634b464","src/server/mod.rs":"d5f7e405edb7cfbe0b898ece754dd62effe71e7db60356411c4ee35e9443beb2","src/udp.rs":"4aadb956e50f961241b2850e6f3bdf715ccbac943e3ab585f4b46e755d03d2de"},"package":null}

2
third_party/rust/neqo-bin/Cargo.toml поставляемый
Просмотреть файл

@ -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.9.2" version = "0.10.0"
authors = ["The Neqo Authors <necko@mozilla.com>"] authors = ["The Neqo Authors <necko@mozilla.com>"]
build = false build = false
autobins = false autobins = false

10
third_party/rust/neqo-bin/benches/main.rs поставляемый
Просмотреть файл

@ -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::{path::PathBuf, str::FromStr}; use std::{env, path::PathBuf, str::FromStr};
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};
@ -20,18 +20,18 @@ fn transfer(c: &mut Criterion) {
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();
let mtu = env::var("MTU").map_or_else(|_| String::new(), |mtu| format!("/mtu-{mtu}"));
for Benchmark { name, requests } in [ for Benchmark { name, requests } in [
Benchmark { Benchmark {
name: "1-conn/1-100mb-resp (aka. Download)".to_string(), name: format!("1-conn/1-100mb-resp{mtu} (aka. Download)"),
requests: vec![100 * 1024 * 1024], requests: vec![100 * 1024 * 1024],
}, },
Benchmark { Benchmark {
name: "1-conn/10_000-parallel-1b-resp (aka. RPS)".to_string(), name: format!("1-conn/10_000-parallel-1b-resp{mtu} (aka. RPS)"),
requests: vec![1; 10_000], requests: vec![1; 10_000],
}, },
Benchmark { Benchmark {
name: "1-conn/1-1b-resp (aka. HPS)".to_string(), name: format!("1-conn/1-1b-resp{mtu} (aka. HPS)"),
requests: vec![1; 1], requests: vec![1; 1],
}, },
] { ] {

Просмотреть файл

@ -26,7 +26,7 @@ use neqo_transport::{
use url::Url; use url::Url;
use super::{get_output_file, qlog_new, Args, CloseState, Res}; use super::{get_output_file, qlog_new, Args, CloseState, Res};
use crate::STREAM_IO_BUFFER_SIZE; use crate::{client::local_addr_for, STREAM_IO_BUFFER_SIZE};
pub struct Handler<'a> { pub struct Handler<'a> {
streams: HashMap<StreamId, Option<BufWriter<File>>>, streams: HashMap<StreamId, Option<BufWriter<File>>>,
@ -37,6 +37,7 @@ pub struct Handler<'a> {
token: Option<ResumptionToken>, token: Option<ResumptionToken>,
needs_key_update: bool, needs_key_update: bool,
read_buffer: Vec<u8>, read_buffer: Vec<u8>,
migration: Option<&'a (u16, SocketAddr)>,
} }
impl Handler<'_> { impl Handler<'_> {
@ -85,6 +86,26 @@ impl super::Handler for Handler<'_> {
self.download_urls(client); self.download_urls(client);
} }
} }
ConnectionEvent::StateChange(State::Confirmed) => {
if let Some((local_port, migration_addr)) = self.migration.take() {
let local_addr = local_addr_for(migration_addr, *local_port);
qdebug!("Migrating path to {:?} -> {:?}", local_addr, migration_addr);
client
.migrate(
Some(local_addr),
Some(*migration_addr),
false,
Instant::now(),
)
.map(|()| {
qinfo!(
"Connection migrated to {:?} -> {:?}",
local_addr,
migration_addr
);
})?;
}
}
ConnectionEvent::StateChange( ConnectionEvent::StateChange(
State::WaitInitial | State::Handshaking | State::Connected, State::WaitInitial | State::Handshaking | State::Connected,
) => { ) => {
@ -181,10 +202,11 @@ impl super::Client for Connection {
self.process_output(now) self.process_output(now)
} }
fn process_multiple_input<'a, I>(&mut self, dgrams: I, now: Instant) fn process_multiple_input<'a>(
where &mut self,
I: IntoIterator<Item = &'a Datagram>, dgrams: impl IntoIterator<Item = Datagram<&'a [u8]>>,
{ now: Instant,
) {
self.process_multiple_input(dgrams, now); self.process_multiple_input(dgrams, now);
} }
@ -211,7 +233,11 @@ impl super::Client for Connection {
} }
impl<'b> Handler<'b> { impl<'b> Handler<'b> {
pub fn new(url_queue: VecDeque<Url>, args: &'b Args) -> Self { pub fn new(
url_queue: VecDeque<Url>,
args: &'b Args,
migration: Option<&'b (u16, SocketAddr)>,
) -> Self {
Self { Self {
streams: HashMap::new(), streams: HashMap::new(),
url_queue, url_queue,
@ -221,6 +247,7 @@ impl<'b> Handler<'b> {
token: None, token: None,
needs_key_update: args.key_update, needs_key_update: args.key_update,
read_buffer: vec![0; STREAM_IO_BUFFER_SIZE], read_buffer: vec![0; STREAM_IO_BUFFER_SIZE],
migration,
} }
} }

Просмотреть файл

@ -132,10 +132,11 @@ impl super::Client for Http3Client {
self.process_output(now) self.process_output(now)
} }
fn process_multiple_input<'a, I>(&mut self, dgrams: I, now: Instant) fn process_multiple_input<'a>(
where &mut self,
I: IntoIterator<Item = &'a Datagram>, dgrams: impl IntoIterator<Item = Datagram<&'a [u8]>>,
{ now: Instant,
) {
self.process_multiple_input(dgrams, now); self.process_multiple_input(dgrams, now);
} }

150
third_party/rust/neqo-bin/src/client/mod.rs поставляемый
Просмотреть файл

@ -31,7 +31,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 tokio::time::Sleep; use tokio::time::Sleep;
use url::{Origin, Url}; use url::{Host, Origin, Url};
use crate::SharedArgs; use crate::SharedArgs;
@ -231,8 +231,11 @@ 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.
self.shared.use_old_http = true;
match testcase.as_str() { match testcase.as_str() {
"http3" => { "http3" => {
self.shared.use_old_http = false;
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}");
@ -242,15 +245,18 @@ impl Args {
self.method = String::from("POST"); self.method = String::from("POST");
} }
} }
"handshake" | "transfer" | "retry" | "ecn" => { "handshake"
self.shared.use_old_http = true; | "transfer"
} | "retry"
| "ecn"
| "rebind-port"
| "rebind-addr"
| "connectionmigration" => {}
"resumption" => { "resumption" => {
if self.urls.len() < 2 { if self.urls.len() < 2 {
qerror!("Warning: resumption test won't work without >1 URL"); qerror!("Warning: resumption test won't work without >1 URL");
exit(127); exit(127);
} }
self.shared.use_old_http = true;
self.resume = true; self.resume = true;
} }
"zerortt" => { "zerortt" => {
@ -258,7 +264,6 @@ 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.use_old_http = true;
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;
@ -267,22 +272,18 @@ impl Args {
self.shared.quic_parameters.no_pacing = true; self.shared.quic_parameters.no_pacing = true;
} }
"multiconnect" => { "multiconnect" => {
self.shared.use_old_http = true;
self.download_in_series = true; self.download_in_series = true;
} }
"chacha20" => { "chacha20" => {
self.shared.use_old_http = true;
self.shared.ciphers.clear(); self.shared.ciphers.clear();
self.shared self.shared
.ciphers .ciphers
.extend_from_slice(&[String::from("TLS_CHACHA20_POLY1305_SHA256")]); .extend_from_slice(&[String::from("TLS_CHACHA20_POLY1305_SHA256")]);
} }
"keyupdate" => { "keyupdate" => {
self.shared.use_old_http = true;
self.key_update = true; self.key_update = true;
} }
"v2" => { "v2" => {
self.shared.use_old_http = true;
// 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();
} }
@ -373,9 +374,11 @@ enum CloseState {
/// Network client, e.g. [`neqo_transport::Connection`] or [`neqo_http3::Http3Client`]. /// Network client, e.g. [`neqo_transport::Connection`] or [`neqo_http3::Http3Client`].
trait Client { trait Client {
fn process_output(&mut self, now: Instant) -> Output; fn process_output(&mut self, now: Instant) -> Output;
fn process_multiple_input<'a, I>(&mut self, dgrams: I, now: Instant) fn process_multiple_input<'a>(
where &mut self,
I: IntoIterator<Item = &'a Datagram>; dgrams: impl IntoIterator<Item = Datagram<&'a [u8]>>,
now: Instant,
);
fn has_events(&self) -> bool; fn has_events(&self) -> bool;
fn close<S>(&mut self, now: Instant, app_error: AppError, msg: S) fn close<S>(&mut self, now: Instant, app_error: AppError, msg: S)
where where
@ -391,9 +394,28 @@ 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>,
} }
impl<'a, H: Handler> Runner<'a, H> { impl<'a, H: Handler> Runner<'a, H> {
fn new(
local_addr: SocketAddr,
socket: &'a mut crate::udp::Socket,
client: H::Client,
handler: H,
args: &'a Args,
) -> Self {
Self {
local_addr,
socket,
client,
handler,
args,
timeout: None,
recv_buf: vec![0; neqo_udp::RECV_BUF_SIZE],
}
}
async fn run(mut self) -> Res<Option<ResumptionToken>> { async fn run(mut self) -> Res<Option<ResumptionToken>> {
loop { loop {
let handler_done = self.handler.handle(&mut self.client)?; let handler_done = self.handler.handle(&mut self.client)?;
@ -456,12 +478,13 @@ impl<'a, H: Handler> Runner<'a, H> {
async fn process_multiple_input(&mut self) -> Res<()> { async fn process_multiple_input(&mut self) -> Res<()> {
loop { loop {
let dgrams = self.socket.recv(&self.local_addr)?; let Some(dgrams) = self.socket.recv(self.local_addr, &mut self.recv_buf)? else {
if dgrams.is_empty() { break;
};
if dgrams.len() == 0 {
break; break;
} }
self.client self.client.process_multiple_input(dgrams, Instant::now());
.process_multiple_input(dgrams.iter(), Instant::now());
self.process_output().await?; self.process_output().await?;
} }
@ -492,6 +515,29 @@ fn qlog_new(args: &Args, hostname: &str, cid: &ConnectionId) -> Res<NeqoQlog> {
.map_err(Error::QlogError) .map_err(Error::QlogError)
} }
const fn local_addr_for(remote_addr: &SocketAddr, local_port: u16) -> SocketAddr {
match remote_addr {
SocketAddr::V4(..) => SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), local_port),
SocketAddr::V6(..) => SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), local_port),
}
}
fn urls_by_origin(urls: &[Url]) -> impl Iterator<Item = ((Host, u16), VecDeque<Url>)> {
urls.iter()
.fold(HashMap::<Origin, VecDeque<Url>>::new(), |mut urls, url| {
urls.entry(url.origin()).or_default().push_back(url.clone());
urls
})
.into_iter()
.filter_map(|(origin, urls)| match origin {
Origin::Tuple(_scheme, h, p) => Some(((h, p), urls)),
Origin::Opaque(x) => {
qwarn!("Opaque origin {x:?}");
None
}
})
}
pub async fn client(mut args: Args) -> Res<()> { pub async fn client(mut args: Args) -> Res<()> {
neqo_common::log::init( neqo_common::log::init(
args.shared args.shared
@ -505,46 +551,24 @@ pub async fn client(mut args: Args) -> Res<()> {
init()?; init()?;
let urls_by_origin = args for ((host, port), mut urls) in urls_by_origin(&args.urls) {
.urls
.clone()
.into_iter()
.fold(HashMap::<Origin, VecDeque<Url>>::new(), |mut urls, url| {
urls.entry(url.origin()).or_default().push_back(url);
urls
})
.into_iter()
.filter_map(|(origin, urls)| match origin {
Origin::Tuple(_scheme, h, p) => Some(((h, p), urls)),
Origin::Opaque(x) => {
qwarn!("Opaque origin {x:?}");
None
}
});
for ((host, port), mut urls) in urls_by_origin {
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);
} }
let remote_addr = format!("{host}:{port}").to_socket_addrs()?.find(|addr| { let mut remote_addrs = format!("{host}:{port}").to_socket_addrs()?.filter(|addr| {
!matches!( !matches!(
(addr, args.ipv4_only, args.ipv6_only), (addr, args.ipv4_only, args.ipv6_only),
(SocketAddr::V4(..), false, true) | (SocketAddr::V6(..), true, false) (SocketAddr::V4(..), false, true) | (SocketAddr::V6(..), true, false)
) )
}); });
let remote_addr = remote_addrs.next();
let Some(remote_addr) = remote_addr else { let Some(remote_addr) = remote_addr else {
qerror!("No compatible address found for: {host}"); qerror!("No compatible address found for: {host}");
exit(1); exit(1);
}; };
let mut socket = crate::udp::Socket::bind(local_addr_for(&remote_addr, 0))?;
let local_addr = match remote_addr {
SocketAddr::V4(..) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from([0; 4])), 0),
SocketAddr::V6(..) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from([0; 16])), 0),
};
let mut socket = crate::udp::Socket::bind(local_addr)?;
let real_local = socket.local_addr().unwrap(); let real_local = socket.local_addr().unwrap();
qinfo!( qinfo!(
"{} Client connecting: {:?} -> {:?}", "{} Client connecting: {:?} -> {:?}",
@ -553,6 +577,18 @@ pub async fn client(mut args: Args) -> Res<()> {
remote_addr, remote_addr,
); );
let migration = if args.shared.qns_test.as_deref() == Some("connectionmigration") {
#[allow(clippy::option_if_let_else)]
if let Some(addr) = remote_addrs.next() {
Some((real_local.port(), addr))
} else {
qerror!("Cannot migrate from {host} when there is no address that follows");
exit(127);
}
} else {
None
};
let hostname = format!("{host}"); let hostname = format!("{host}");
let mut token: Option<ResumptionToken> = None; let mut token: Option<ResumptionToken> = None;
let mut first = true; let mut first = true;
@ -570,34 +606,20 @@ pub async fn client(mut args: Args) -> Res<()> {
http09::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 = http09::Handler::new(to_request, &args, migration.as_ref());
Runner { Runner::new(real_local, &mut socket, client, handler, &args)
args: &args, .run()
client, .await?
handler,
local_addr: real_local,
socket: &mut socket,
timeout: None,
}
.run()
.await?
} else { } else {
let client = http3::create_client(&args, real_local, remote_addr, &hostname, token) let client = http3::create_client(&args, real_local, remote_addr, &hostname, token)
.expect("failed to create client"); .expect("failed to create client");
let handler = http3::Handler::new(to_request, &args); let handler = http3::Handler::new(to_request, &args);
Runner { Runner::new(real_local, &mut socket, client, handler, &args)
args: &args, .run()
client, .await?
handler,
local_addr: real_local,
socket: &mut socket,
timeout: None,
}
.run()
.await?
}; };
} }
} }

Просмотреть файл

@ -185,7 +185,7 @@ impl HttpServer {
} }
impl super::HttpServer for HttpServer { impl super::HttpServer for HttpServer {
fn process(&mut self, dgram: Option<&Datagram>, now: Instant) -> Output { fn process(&mut self, dgram: Option<Datagram>, now: Instant) -> Output {
self.server.process(dgram, now) self.server.process(dgram, now)
} }

Просмотреть файл

@ -79,7 +79,7 @@ impl Display for HttpServer {
} }
impl super::HttpServer for HttpServer { impl super::HttpServer for HttpServer {
fn process(&mut self, dgram: Option<&Datagram>, now: Instant) -> neqo_http3::Output { fn process(&mut self, dgram: Option<Datagram>, now: Instant) -> neqo_http3::Output {
self.server.process(dgram, now) self.server.process(dgram, now)
} }

33
third_party/rust/neqo-bin/src/server/mod.rs поставляемый
Просмотреть файл

@ -194,7 +194,7 @@ fn qns_read_response(filename: &str) -> Result<Vec<u8>, io::Error> {
#[allow(clippy::module_name_repetitions)] #[allow(clippy::module_name_repetitions)]
pub trait HttpServer: Display { pub trait HttpServer: Display {
fn process(&mut self, dgram: Option<&Datagram>, now: Instant) -> Output; fn process(&mut self, dgram: Option<Datagram>, now: Instant) -> Output;
fn process_events(&mut self, now: Instant); fn process_events(&mut self, now: Instant);
fn has_events(&self) -> bool; fn has_events(&self) -> bool;
} }
@ -205,6 +205,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>,
} }
impl ServerRunner { impl ServerRunner {
@ -219,6 +220,7 @@ impl ServerRunner {
server, server,
timeout: None, timeout: None,
sockets, sockets,
recv_buf: vec![0; neqo_udp::RECV_BUF_SIZE],
} }
} }
@ -236,7 +238,7 @@ impl ServerRunner {
.unwrap_or(first_socket) .unwrap_or(first_socket)
} }
async fn process(&mut self, mut dgram: Option<&Datagram>) -> Result<(), io::Error> { async fn process(&mut self, mut dgram: Option<Datagram>) -> Result<(), io::Error> {
loop { loop {
match self.server.process(dgram.take(), (self.now)()) { match self.server.process(dgram.take(), (self.now)()) {
Output::Datagram(dgram) => { Output::Datagram(dgram) => {
@ -289,12 +291,15 @@ impl ServerRunner {
match self.ready().await? { match self.ready().await? {
Ready::Socket(inx) => loop { Ready::Socket(inx) => loop {
let (host, socket) = self.sockets.get_mut(inx).unwrap(); let (host, socket) = self.sockets.get_mut(inx).unwrap();
let dgrams = socket.recv(host)?; let Some(dgrams) = socket.recv(*host, &mut self.recv_buf)? else {
if dgrams.is_empty() { break;
};
if dgrams.len() == 0 {
break; break;
} }
let dgrams: Vec<Datagram> = dgrams.map(|d| d.to_owned()).collect();
for dgram in dgrams { for dgram in dgrams {
self.process(Some(&dgram)).await?; self.process(Some(dgram)).await?;
} }
}, },
Ready::Timeout => { Ready::Timeout => {
@ -336,20 +341,27 @@ pub async fn server(mut args: Args) -> Res<()> {
qwarn!("Both -V and --qns-test were set. Ignoring testcase specific versions."); qwarn!("Both -V and --qns-test were set. Ignoring testcase specific versions.");
} }
// This is the default for all tests except http3.
args.shared.use_old_http = true;
// 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,
"zerortt" => { "zerortt" => {
args.shared.use_old_http = true;
args.shared.alpn = String::from(HQ_INTEROP); args.shared.alpn = String::from(HQ_INTEROP);
args.shared.quic_parameters.max_streams_bidi = 100; args.shared.quic_parameters.max_streams_bidi = 100;
} }
"handshake" | "transfer" | "resumption" | "multiconnect" | "v2" | "ecn" => { "handshake"
args.shared.use_old_http = true; | "transfer"
| "resumption"
| "multiconnect"
| "v2"
| "ecn"
| "rebind-port"
| "rebind-addr"
| "connectionmigration" => {
args.shared.alpn = String::from(HQ_INTEROP); args.shared.alpn = String::from(HQ_INTEROP);
} }
"chacha20" => { "chacha20" => {
args.shared.use_old_http = true;
args.shared.alpn = String::from(HQ_INTEROP); args.shared.alpn = String::from(HQ_INTEROP);
args.shared.ciphers.clear(); args.shared.ciphers.clear();
args.shared args.shared
@ -357,7 +369,6 @@ pub async fn server(mut args: Args) -> Res<()> {
.extend_from_slice(&[String::from("TLS_CHACHA20_POLY1305_SHA256")]); .extend_from_slice(&[String::from("TLS_CHACHA20_POLY1305_SHA256")]);
} }
"retry" => { "retry" => {
args.shared.use_old_http = true;
args.shared.alpn = String::from(HQ_INTEROP); args.shared.alpn = String::from(HQ_INTEROP);
args.retry = true; args.retry = true;
} }

12
third_party/rust/neqo-bin/src/udp.rs поставляемый
Просмотреть файл

@ -7,6 +7,7 @@
use std::{io, net::SocketAddr}; use std::{io, net::SocketAddr};
use neqo_common::Datagram; use neqo_common::Datagram;
use neqo_udp::DatagramIter;
/// 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.
/// ///
@ -55,14 +56,19 @@ impl Socket {
/// Receive a batch of [`Datagram`]s on the given [`Socket`], each set with /// Receive a batch of [`Datagram`]s on the given [`Socket`], each set with
/// the provided local address. /// the provided local address.
pub fn recv(&self, local_address: &SocketAddr) -> Result<Vec<Datagram>, io::Error> { pub fn recv<'a>(
&self,
local_address: SocketAddr,
recv_buf: &'a mut [u8],
) -> Result<Option<DatagramIter<'a>>, io::Error> {
self.inner self.inner
.try_io(tokio::io::Interest::READABLE, || { .try_io(tokio::io::Interest::READABLE, || {
neqo_udp::recv_inner(local_address, &self.state, &self.inner) neqo_udp::recv_inner(local_address, &self.state, &self.inner, recv_buf)
}) })
.map(Some)
.or_else(|e| { .or_else(|e| {
if e.kind() == io::ErrorKind::WouldBlock { if e.kind() == io::ErrorKind::WouldBlock {
Ok(vec![]) Ok(None)
} else { } else {
Err(e) Err(e)
} }

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"eabe319e62a4a42e32f4ec35b2ef74eb513f173d11ba9105efb8e33c5e9e7e28","build.rs":"ee5dc521f3d8e18c2b617192d6b6e678f7f2f9886fdd34c0c1c5ef841419b248","src/codec.rs":"6c12d9db7066497f2566e83efc825ae984d04a6b5176010c93d394904103aeed","src/datagram.rs":"2acecfcbecfbb767ea920e3b22388e67b31fcda776cae5b2d7ecbc67dd9febf7","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":"f53cb2a52dd7725c577d4e42065fb1c498ccc33dff0449b6889d9fbc1fdb96e2","src/tos.rs":"28fd9acfce06f68ac6691efd2609618850182f77ef3717ce2db07bfac19a9396","tests/log.rs":"a11e21fb570258ca93bb40e3923817d381e1e605accbc3aed1df5a0a9918b41d"},"package":null} {"files":{"Cargo.toml":"445c47ac5b982936243339e809670d8aa88e7a059a7adc3b49c32e019653507a","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":"f53cb2a52dd7725c577d4e42065fb1c498ccc33dff0449b6889d9fbc1fdb96e2","src/tos.rs":"28fd9acfce06f68ac6691efd2609618850182f77ef3717ce2db07bfac19a9396","tests/log.rs":"a11e21fb570258ca93bb40e3923817d381e1e605accbc3aed1df5a0a9918b41d"},"package":null}

2
third_party/rust/neqo-common/Cargo.toml поставляемый
Просмотреть файл

@ -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.9.2" version = "0.10.0"
authors = ["The Neqo Authors <necko@mozilla.com>"] authors = ["The Neqo Authors <necko@mozilla.com>"]
build = "build.rs" build = "build.rs"
autobins = false autobins = false

105
third_party/rust/neqo-common/src/datagram.rs поставляемый
Просмотреть файл

@ -9,23 +9,14 @@ use std::{net::SocketAddr, ops::Deref};
use crate::{hex_with_len, IpTos}; use crate::{hex_with_len, IpTos};
#[derive(Clone, PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
pub struct Datagram { pub struct Datagram<D = Vec<u8>> {
src: SocketAddr, src: SocketAddr,
dst: SocketAddr, dst: SocketAddr,
tos: IpTos, tos: IpTos,
d: Vec<u8>, d: D,
} }
impl Datagram { impl<D> Datagram<D> {
pub fn new<V: Into<Vec<u8>>>(src: SocketAddr, dst: SocketAddr, tos: IpTos, d: V) -> Self {
Self {
src,
dst,
tos,
d: d.into(),
}
}
#[must_use] #[must_use]
pub const fn source(&self) -> SocketAddr { pub const fn source(&self) -> SocketAddr {
self.src self.src
@ -46,15 +37,43 @@ impl Datagram {
} }
} }
impl Deref for Datagram { impl<D: AsRef<[u8]>> Datagram<D> {
type Target = Vec<u8>; pub fn len(&self) -> usize {
#[must_use] self.d.as_ref().len()
fn deref(&self) -> &Self::Target { }
&self.d
pub fn is_empty(&self) -> bool {
self.len() == 0
} }
} }
impl std::fmt::Debug for Datagram { #[cfg(test)]
impl<D: AsMut<[u8]> + AsRef<[u8]>> AsMut<[u8]> for Datagram<D> {
fn as_mut(&mut self) -> &mut [u8] {
self.d.as_mut()
}
}
impl Datagram<Vec<u8>> {
pub fn new<V: Into<Vec<u8>>>(src: SocketAddr, dst: SocketAddr, tos: IpTos, d: V) -> Self {
Self {
src,
dst,
tos,
d: d.into(),
}
}
}
impl<D: AsRef<[u8]>> Deref for Datagram<D> {
type Target = [u8];
#[must_use]
fn deref(&self) -> &Self::Target {
AsRef::<[u8]>::as_ref(self)
}
}
impl<D: AsRef<[u8]>> std::fmt::Debug for Datagram<D> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!( write!(
f, f,
@ -67,14 +86,46 @@ impl std::fmt::Debug for Datagram {
} }
} }
#[cfg(test)] impl<'a> Datagram<&'a [u8]> {
use test_fixture::datagram; #[must_use]
pub const fn from_slice(src: SocketAddr, dst: SocketAddr, tos: IpTos, d: &'a [u8]) -> Self {
Self { src, dst, tos, d }
}
#[test] #[must_use]
fn fmt_datagram() { pub fn to_owned(&self) -> Datagram {
let d = datagram([0; 1].to_vec()); Datagram {
assert_eq!( src: self.src,
&format!("{d:?}"), dst: self.dst,
"Datagram IpTos(Cs0, Ect0) [fe80::1]:443->[fe80::1]:443: [1]: 00" tos: self.tos,
); d: self.d.to_vec(),
}
}
}
impl<D: AsRef<[u8]>> AsRef<[u8]> for Datagram<D> {
fn as_ref(&self) -> &[u8] {
self.d.as_ref()
}
}
#[cfg(test)]
mod tests {
use test_fixture::datagram;
#[test]
fn fmt_datagram() {
let d = datagram([0; 1].to_vec());
assert_eq!(
&format!("{d:?}"),
"Datagram IpTos(Cs0, Ect0) [fe80::1]:443->[fe80::1]:443: [1]: 00"
);
}
#[test]
fn is_empty() {
let d = datagram(vec![]);
assert_eq!(d.len(), 0);
assert!(d.is_empty());
}
} }

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"a19a3c6ebbc3eca25aa2b467a1298285cf165df98fbb10c1447b8a5850799cc8","bindings/bindings.toml":"0e06a03035a90ec5f823b30c8b78ec010a332ae0e5ed0c953da2e4c406451793","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":"d24f1a3df8300b93a1b606b2089bd758c9aa41c3a9e333089e6165b3449df94f","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":"59bafcaed7caa66fe448339a1f75ce807ef92fc28247709df4f8058499b0787e","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":"3452a05725c5e72f51dc242fad2523fede8e752bf93f05a5b3b1808b0616cff7","bindings/bindings.toml":"0e06a03035a90ec5f823b30c8b78ec010a332ae0e5ed0c953da2e4c406451793","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":"d24f1a3df8300b93a1b606b2089bd758c9aa41c3a9e333089e6165b3449df94f","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":"59bafcaed7caa66fe448339a1f75ce807ef92fc28247709df4f8058499b0787e","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}

2
third_party/rust/neqo-crypto/Cargo.toml поставляемый
Просмотреть файл

@ -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.9.2" version = "0.10.0"
authors = ["The Neqo Authors <necko@mozilla.com>"] authors = ["The Neqo Authors <necko@mozilla.com>"]
build = "build.rs" build = "build.rs"
autobins = false autobins = false

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"371b4660d42aaef9557a5ce91ad7eac0b78d02d13bd9d3f5dad327a6382e6c8b","src/buffered_send_stream.rs":"dfb248c66ea65418b0c7798c2ecaa3ed70ef1af818ef58d53ef742b3445077b7","src/client_events.rs":"77fedca72ce54956eaba3fb7103085d196a631b764662584ea2629224c5c234e","src/conn_params.rs":"7f0df52bceda1923aef2b7c5c64a532f49ea083ea45e3dcd5bd4b03031b89643","src/connection.rs":"1bf52ac3f3714f5bb2b1237fdb7b026ee4a2183f8f173120661f46213f8c5daa","src/connection_client.rs":"e1ad0e79033735373b5c90971f5ef6269c937f9677ab9ec3a271d6a1b5128370","src/connection_server.rs":"cf4da2cdd823e31d2352e45de84d366c45bd3d8adf38c9151a84d808bda80209","src/control_stream_local.rs":"20917762c7e7c1112c56abf1cbaf0ad7f0eab97d8db9a3b10ff524315a235670","src/control_stream_remote.rs":"3729f67aa0681b1dbd4147063890f8440f27d82454776500ae964a17cda4d6b5","src/features/extended_connect/mod.rs":"cbeb2294eaf34f08a2c0d0fe4d3473aea9c65df6faaec9dc3ed29dcb577b1c3f","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":"3359db4affc034e92b4887a2f564261ce1b3c7f2f7e5ca06d5df7625dbe698ed","src/features/extended_connect/tests/webtransport/negotiation.rs":"a22094dbaf0754d39ac8ac08fce1ae34ace108220b696c7d618567df56cddeec","src/features/extended_connect/tests/webtransport/sessions.rs":"53198069200292a15788eb9de304f670f0044c81df756ce8226d49ea394bc4ec","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":"c6bbf85fbc6cb9adf6115d315f0564317eefd83ff3177c93050844ad77f6e694","src/frames/tests/reader.rs":"9ee0d9cdd87b98da2b94e577bbcc2bfde6d72be5177bf02364188935f79cb36a","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":"53f72e8043505f85cba0f9c16b4a5ce14d6668b030d773067bc88b2a10bdd25b","src/qlog.rs":"db5f2dd6566d44b4f0541f75266b417b558c09e62141f056885cb8c66478a932","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":"8d48376abf36d036f51a84cddcc3d5acd56786b181fba0e24449e1417b030d63","src/server_connection_events.rs":"1396baab265a814045ccfe63d637a4fdc32a667b5eb2925fa4951f5c3078fb20","src/server_events.rs":"02fc8c0711efd758fb1ddee27d257c12ed35e2a989e7bf3de44bd662dc8234e3","src/settings.rs":"d0f8c546e70161422a029a40564b9e9b953fe671c60835196b16f3364779eaf9","src/stream_type_reader.rs":"4e79202e7f1415165fe4eb88b9af67cbb8f85a13d68a577249c397fd5a78dbfb","tests/httpconn.rs":"87c32197258711d916cace23ed850c5bf0198f5e32756c68a32d91206b6e6db8","tests/priority.rs":"364754507873298612ad12e8d1d106d26d993712142d0be4cbf056da5338854c","tests/send_message.rs":"cdf7028eb64f8f3778c3bbb2a10e9482c4e995e9e1813143ccd83ec96b2d4b6a","tests/webtransport.rs":"02b81be0a20252a8bb0796b5287e426c1af5ddaf5a47d68aa9165393cba83c45"},"package":null} {"files":{"Cargo.toml":"8598be82b6e7ce910c20bf0fc518ca50d4cd5698b4f5408f1b33de6dd4169009","src/buffered_send_stream.rs":"dfb248c66ea65418b0c7798c2ecaa3ed70ef1af818ef58d53ef742b3445077b7","src/client_events.rs":"77fedca72ce54956eaba3fb7103085d196a631b764662584ea2629224c5c234e","src/conn_params.rs":"7f0df52bceda1923aef2b7c5c64a532f49ea083ea45e3dcd5bd4b03031b89643","src/connection.rs":"1bf52ac3f3714f5bb2b1237fdb7b026ee4a2183f8f173120661f46213f8c5daa","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":"db5f2dd6566d44b4f0541f75266b417b558c09e62141f056885cb8c66478a932","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}

2
third_party/rust/neqo-http3/Cargo.toml поставляемый
Просмотреть файл

@ -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.9.2" version = "0.10.0"
authors = ["The Neqo Authors <necko@mozilla.com>"] authors = ["The Neqo Authors <necko@mozilla.com>"]
build = false build = false
autobins = false autobins = false

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -68,7 +68,7 @@ pub(crate) enum ExtendedConnectType {
impl ExtendedConnectType { impl ExtendedConnectType {
#[must_use] #[must_use]
#[allow(clippy::unused_self)] // This will change when we have more features using ExtendedConnectType. #[allow(clippy::unused_self)] // This will change when we have more features using ExtendedConnectType.
pub const fn string(&self) -> &str { pub const fn string(self) -> &'static str {
"webtransport" "webtransport"
} }

Просмотреть файл

@ -63,8 +63,8 @@ pub fn default_http3_server(server_params: Http3Parameters) -> Http3Server {
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 {
out = client.process(out.as_ref(), now()).dgram(); out = client.process(out, now()).dgram();
out = server.process(out.as_ref(), now()).dgram(); out = server.process(out, now()).dgram();
if out.is_none() { if out.is_none() {
break; break;
} }
@ -74,31 +74,31 @@ 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(None, now()); let out = client.process_output(now());
assert_eq!(client.state(), Http3State::Initializing); assert_eq!(client.state(), Http3State::Initializing);
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
let out = client.process(out.as_dgram_ref(), now()); let out = client.process(out.dgram(), now());
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_none()); assert!(out.as_dgram_ref().is_none());
let authentication_needed = |e| matches!(e, Http3ClientEvent::AuthenticationNeeded); let authentication_needed = |e| matches!(e, Http3ClientEvent::AuthenticationNeeded);
assert!(client.events().any(authentication_needed)); assert!(client.events().any(authentication_needed));
client.authenticated(AuthenticationStatus::Ok, now()); client.authenticated(AuthenticationStatus::Ok, now());
let out = client.process(out.as_dgram_ref(), now()); let out = client.process(out.dgram(), now());
let connected = |e| matches!(e, Http3ClientEvent::StateChange(Http3State::Connected)); let connected = |e| matches!(e, Http3ClientEvent::StateChange(Http3State::Connected));
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 setttings
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
let out = client.process(out.as_dgram_ref(), now()); let out = client.process(out.dgram(), now());
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
let out = client.process(out.as_dgram_ref(), now()); let out = client.process(out.dgram(), now());
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
std::mem::drop(client.process(out.as_dgram_ref(), now())); std::mem::drop(client.process(out.dgram(), now()));
} }
fn connect( fn connect(
@ -200,10 +200,10 @@ impl WtTest {
let mut now = now(); let mut now = now();
loop { loop {
now += RTT / 2; now += RTT / 2;
out = self.client.process(out.as_ref(), now).dgram(); out = self.client.process(out, now).dgram();
let client_none = out.is_none(); let client_none = out.is_none();
now += RTT / 2; now += RTT / 2;
out = self.server.process(out.as_ref(), now).dgram(); out = self.server.process(out, now).dgram();
if client_none && out.is_none() { if client_none && out.is_none() {
break; break;
} }

Просмотреть файл

@ -86,9 +86,9 @@ fn zero_rtt(
assert_eq!(client.webtransport_enabled(), client_org && server_org); assert_eq!(client.webtransport_enabled(), client_org && server_org);
// exchange token // exchange token
let out = server.process(None, 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.as_dgram_ref(), now() + Duration::from_millis(250))); std::mem::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()
@ -233,8 +233,8 @@ fn zero_rtt_wt_settings() {
fn exchange_packets2(client: &mut Http3Client, server: &mut Connection) { fn exchange_packets2(client: &mut Http3Client, server: &mut Connection) {
let mut out = None; let mut out = None;
loop { loop {
out = client.process(out.as_ref(), now()).dgram(); out = client.process(out, now()).dgram();
out = server.process(out.as_ref(), now()).dgram(); out = server.process(out, now()).dgram();
if out.is_none() { if out.is_none() {
break; break;
} }

Просмотреть файл

@ -425,18 +425,18 @@ fn wt_close_session_cannot_be_sent_at_once() {
Err(Error::InvalidStreamId) Err(Error::InvalidStreamId)
); );
let out = wt.server.process(None, now()); let out = wt.server.process_output(now());
let out = wt.client.process(out.as_dgram_ref(), now()); let out = wt.client.process(out.dgram(), now());
// Client has not received the full CloseSession frame and it can create more streams. // Client has not received the full CloseSession frame and it can create more streams.
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);
let out = wt.server.process(out.as_dgram_ref(), now()); let out = wt.server.process(out.dgram(), now());
let out = wt.client.process(out.as_dgram_ref(), now()); let out = wt.client.process(out.dgram(), now());
let out = wt.server.process(out.as_dgram_ref(), now()); let out = wt.server.process(out.dgram(), now());
let out = wt.client.process(out.as_dgram_ref(), now()); let out = wt.client.process(out.dgram(), now());
let out = wt.server.process(out.as_dgram_ref(), now()); let out = wt.server.process(out.dgram(), now());
let _out = wt.client.process(out.as_dgram_ref(), now()); let _out = wt.client.process(out.dgram(), now());
wt.check_events_after_closing_session_client( wt.check_events_after_closing_session_client(
&[], &[],

Просмотреть файл

@ -22,13 +22,13 @@ pub fn enc_dec<T: FrameDecoder<T>>(d: &Encoder, st: &str, remaining: usize) -> T
let mut conn_c = default_client(); let mut conn_c = default_client();
let mut conn_s = default_server(); let mut conn_s = default_server();
let out = conn_c.process(None, now()); let out = conn_c.process_output(now());
let out = conn_s.process(out.as_dgram_ref(), now()); let out = conn_s.process(out.dgram(), now());
let out = conn_c.process(out.as_dgram_ref(), now()); let out = conn_c.process(out.dgram(), now());
mem::drop(conn_s.process(out.as_dgram_ref(), now())); mem::drop(conn_s.process(out.dgram(), now()));
conn_c.authenticated(AuthenticationStatus::Ok, now()); conn_c.authenticated(AuthenticationStatus::Ok, now());
let out = conn_c.process(None, now()); let out = conn_c.process_output(now());
mem::drop(conn_s.process(out.as_dgram_ref(), now())); mem::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();
@ -38,8 +38,8 @@ pub fn enc_dec<T: FrameDecoder<T>>(d: &Encoder, st: &str, remaining: usize) -> T
// conver string into u8 vector // conver 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(None, now()); let out = conn_s.process_output(now());
mem::drop(conn_c.process(out.as_dgram_ref(), now())); mem::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(

Просмотреть файл

@ -39,8 +39,8 @@ 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(None, now()); let out = self.conn_s.process_output(now());
mem::drop(self.conn_c.process(out.as_dgram_ref(), now())); mem::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(
@ -230,13 +230,13 @@ fn test_reading_frame<T: FrameDecoder<T> + PartialEq + Debug>(
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(None, now()); let out = fr.conn_s.process_output(now());
mem::drop(fr.conn_c.process(out.as_dgram_ref(), now())); mem::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(None, now()); let out = fr.conn_s.process_output(now());
mem::drop(fr.conn_c.process(out.as_dgram_ref(), now())); mem::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(
@ -478,12 +478,12 @@ fn frame_reading_when_stream_is_closed_before_sending_data() {
let mut fr = FrameReaderTest::new(); let mut fr = FrameReaderTest::new();
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(None, now()); let out = fr.conn_s.process_output(now());
mem::drop(fr.conn_c.process(out.as_dgram_ref(), now())); mem::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(None, now()); let out = fr.conn_c.process_output(now());
mem::drop(fr.conn_s.process(out.as_dgram_ref(), now())); mem::drop(fr.conn_s.process(out.dgram(), now()));
assert_eq!( assert_eq!(
Ok((None, true)), Ok((None, true)),
fr.fr fr.fr
@ -501,12 +501,12 @@ fn wt_frame_reading_when_stream_is_closed_before_sending_data() {
let mut fr = FrameReaderTest::new(); let mut fr = FrameReaderTest::new();
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(None, now()); let out = fr.conn_s.process_output(now());
mem::drop(fr.conn_c.process(out.as_dgram_ref(), now())); mem::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(None, now()); let out = fr.conn_c.process_output(now());
mem::drop(fr.conn_s.process(out.as_dgram_ref(), now())); mem::drop(fr.conn_s.process(out.dgram(), now()));
assert_eq!( assert_eq!(
Ok((None, true)), Ok((None, true)),
fr.fr fr.fr

Просмотреть файл

@ -364,7 +364,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 steam 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( mem::drop(base_handler.stream_stop_sending(
conn, conn,
*stream_id, *stream_id,

181
third_party/rust/neqo-http3/src/server.rs поставляемый
Просмотреть файл

@ -113,7 +113,12 @@ impl Http3Server {
self.server.ech_config() self.server.ech_config()
} }
pub fn process(&mut self, dgram: Option<&Datagram>, now: Instant) -> Output { /// Short-hand for [`Http3Server::process`] with no input datagram.
pub fn process_output(&mut self, now: Instant) -> Output {
self.process(None::<Datagram>, now)
}
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);
@ -123,7 +128,7 @@ impl Http3Server {
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),
} }
} }
@ -396,29 +401,29 @@ mod tests {
const SERVER_SIDE_DECODER_STREAM_ID: StreamId = StreamId::new(11); const SERVER_SIDE_DECODER_STREAM_ID: StreamId = StreamId::new(11);
fn connect_transport(server: &mut Http3Server, client: &mut Connection, resume: bool) { fn connect_transport(server: &mut Http3Server, client: &mut Connection, resume: bool) {
let c1 = client.process(None, now()); let c1 = client.process_output(now());
let s1 = server.process(c1.as_dgram_ref(), now()); let s1 = server.process(c1.dgram(), now());
let c2 = client.process(s1.as_dgram_ref(), now()); let c2 = client.process(s1.dgram(), now());
let needs_auth = client let needs_auth = client
.events() .events()
.any(|e| e == ConnectionEvent::AuthenticationNeeded); .any(|e| e == ConnectionEvent::AuthenticationNeeded);
let c2 = if needs_auth { let c2 = if needs_auth {
assert!(!resume); assert!(!resume);
// c2 should just be an ACK, so absorb that. // c2 should just be an ACK, so absorb that.
let s_ack = server.process(c2.as_dgram_ref(), now()); let s_ack = server.process(c2.dgram(), now());
assert!(s_ack.as_dgram_ref().is_none()); assert!(s_ack.dgram().is_none());
client.authenticated(AuthenticationStatus::Ok, now()); client.authenticated(AuthenticationStatus::Ok, now());
client.process(None, now()) client.process_output(now())
} else { } else {
assert!(resume); assert!(resume);
c2 c2
}; };
assert!(client.state().connected()); assert!(client.state().connected());
let s2 = server.process(c2.as_dgram_ref(), now()); let s2 = server.process(c2.dgram(), now());
assert_connected(server); assert_connected(server);
let c3 = client.process(s2.as_dgram_ref(), now()); let c3 = client.process(s2.dgram(), now());
assert!(c3.as_dgram_ref().is_none()); assert!(c3.dgram().is_none());
} }
// Start a client/server and check setting frame. // Start a client/server and check setting frame.
@ -552,9 +557,9 @@ mod tests {
let decoder_stream = neqo_trans_conn.stream_create(StreamType::UniDi).unwrap(); let decoder_stream = neqo_trans_conn.stream_create(StreamType::UniDi).unwrap();
sent = neqo_trans_conn.stream_send(decoder_stream, &[0x3]); sent = neqo_trans_conn.stream_send(decoder_stream, &[0x3]);
assert_eq!(sent, Ok(1)); assert_eq!(sent, Ok(1));
let out1 = neqo_trans_conn.process(None, now()); let out1 = neqo_trans_conn.process_output(now());
let out2 = server.process(out1.as_dgram_ref(), now()); let out2 = server.process(out1.dgram(), now());
mem::drop(neqo_trans_conn.process(out2.as_dgram_ref(), now())); mem::drop(neqo_trans_conn.process(out2.dgram(), now()));
// assert no error occured. // assert no error occured.
assert_not_closed(server); assert_not_closed(server);
@ -584,8 +589,8 @@ mod tests {
let (mut hconn, mut peer_conn) = connect(); let (mut hconn, mut peer_conn) = connect();
let control = peer_conn.control_stream_id; let control = peer_conn.control_stream_id;
peer_conn.stream_close_send(control).unwrap(); peer_conn.stream_close_send(control).unwrap();
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
assert_closed(&hconn, &Error::HttpClosedCriticalStream); assert_closed(&hconn, &Error::HttpClosedCriticalStream);
} }
@ -599,8 +604,8 @@ mod tests {
// Send a MAX_PUSH_ID frame instead. // Send a MAX_PUSH_ID frame instead.
let sent = neqo_trans_conn.stream_send(control_stream, &[0x0, 0xd, 0x1, 0xf]); let sent = neqo_trans_conn.stream_send(control_stream, &[0x0, 0xd, 0x1, 0xf]);
assert_eq!(sent, Ok(4)); assert_eq!(sent, Ok(4));
let out = neqo_trans_conn.process(None, now()); let out = neqo_trans_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
assert_closed(&hconn, &Error::HttpMissingSettings); assert_closed(&hconn, &Error::HttpMissingSettings);
} }
@ -611,8 +616,8 @@ mod tests {
let (mut hconn, mut peer_conn) = connect(); let (mut hconn, mut peer_conn) = connect();
// send the second SETTINGS frame. // send the second SETTINGS frame.
peer_conn.control_send(&[0x4, 0x6, 0x1, 0x40, 0x64, 0x7, 0x40, 0x64]); peer_conn.control_send(&[0x4, 0x6, 0x1, 0x40, 0x64, 0x7, 0x40, 0x64]);
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
assert_closed(&hconn, &Error::HttpFrameUnexpected); assert_closed(&hconn, &Error::HttpFrameUnexpected);
} }
@ -626,8 +631,8 @@ mod tests {
let mut e = Encoder::default(); let mut e = Encoder::default();
frame.encode(&mut e); frame.encode(&mut e);
peer_conn.control_send(e.as_ref()); peer_conn.control_send(e.as_ref());
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
// check if the given connection got closed on invalid stream ids // check if the given connection got closed on invalid stream ids
if valid { if valid {
assert_not_closed(&hconn); assert_not_closed(&hconn);
@ -669,8 +674,8 @@ mod tests {
// receive a frame that is not allowed on the control stream. // receive a frame that is not allowed on the control stream.
peer_conn.control_send(v); peer_conn.control_send(v);
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
assert_closed(&hconn, &Error::HttpFrameUnexpected); assert_closed(&hconn, &Error::HttpFrameUnexpected);
} }
@ -703,11 +708,11 @@ mod tests {
_ = peer_conn _ = peer_conn
.stream_send(new_stream_id, &[0x41, 0x19, 0x4, 0x4, 0x6, 0x0, 0x8, 0x0]) .stream_send(new_stream_id, &[0x41, 0x19, 0x4, 0x4, 0x6, 0x0, 0x8, 0x0])
.unwrap(); .unwrap();
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
let out = hconn.process(out.as_dgram_ref(), now()); let out = hconn.process(out.dgram(), now());
mem::drop(peer_conn.process(out.as_dgram_ref(), now())); mem::drop(peer_conn.process(out.dgram(), now()));
let out = hconn.process(None, now()); let out = hconn.process_output(now());
mem::drop(peer_conn.process(out.as_dgram_ref(), now())); mem::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;
@ -734,9 +739,9 @@ mod tests {
// create a push stream. // create a push stream.
let push_stream_id = peer_conn.stream_create(StreamType::UniDi).unwrap(); let push_stream_id = peer_conn.stream_create(StreamType::UniDi).unwrap();
_ = peer_conn.stream_send(push_stream_id, &[0x1]).unwrap(); _ = peer_conn.stream_send(push_stream_id, &[0x1]).unwrap();
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
let out = hconn.process(out.as_dgram_ref(), now()); let out = hconn.process(out.dgram(), now());
mem::drop(peer_conn.conn.process(out.as_dgram_ref(), now())); mem::drop(peer_conn.conn.process(out.dgram(), now()));
assert_closed(&hconn, &Error::HttpStreamCreation); assert_closed(&hconn, &Error::HttpStreamCreation);
} }
@ -751,77 +756,77 @@ mod tests {
// send the stream type // send the stream type
let mut sent = peer_conn.stream_send(control_stream, &[0x0]); let mut sent = peer_conn.stream_send(control_stream, &[0x0]);
assert_eq!(sent, Ok(1)); assert_eq!(sent, Ok(1));
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
// start sending SETTINGS frame // start sending SETTINGS frame
sent = peer_conn.stream_send(control_stream, &[0x4]); sent = peer_conn.stream_send(control_stream, &[0x4]);
assert_eq!(sent, Ok(1)); assert_eq!(sent, Ok(1));
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
sent = peer_conn.stream_send(control_stream, &[0x4]); sent = peer_conn.stream_send(control_stream, &[0x4]);
assert_eq!(sent, Ok(1)); assert_eq!(sent, Ok(1));
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
sent = peer_conn.stream_send(control_stream, &[0x6]); sent = peer_conn.stream_send(control_stream, &[0x6]);
assert_eq!(sent, Ok(1)); assert_eq!(sent, Ok(1));
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
sent = peer_conn.stream_send(control_stream, &[0x0]); sent = peer_conn.stream_send(control_stream, &[0x0]);
assert_eq!(sent, Ok(1)); assert_eq!(sent, Ok(1));
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
sent = peer_conn.stream_send(control_stream, &[0x8]); sent = peer_conn.stream_send(control_stream, &[0x8]);
assert_eq!(sent, Ok(1)); assert_eq!(sent, Ok(1));
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
sent = peer_conn.stream_send(control_stream, &[0x0]); sent = peer_conn.stream_send(control_stream, &[0x0]);
assert_eq!(sent, Ok(1)); assert_eq!(sent, Ok(1));
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
assert_not_closed(&hconn); assert_not_closed(&hconn);
// Now test PushPromise // Now test PushPromise
sent = peer_conn.stream_send(control_stream, &[0x5]); sent = peer_conn.stream_send(control_stream, &[0x5]);
assert_eq!(sent, Ok(1)); assert_eq!(sent, Ok(1));
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
sent = peer_conn.stream_send(control_stream, &[0x5]); sent = peer_conn.stream_send(control_stream, &[0x5]);
assert_eq!(sent, Ok(1)); assert_eq!(sent, Ok(1));
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
sent = peer_conn.stream_send(control_stream, &[0x4]); sent = peer_conn.stream_send(control_stream, &[0x4]);
assert_eq!(sent, Ok(1)); assert_eq!(sent, Ok(1));
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
sent = peer_conn.stream_send(control_stream, &[0x61]); sent = peer_conn.stream_send(control_stream, &[0x61]);
assert_eq!(sent, Ok(1)); assert_eq!(sent, Ok(1));
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
sent = peer_conn.stream_send(control_stream, &[0x62]); sent = peer_conn.stream_send(control_stream, &[0x62]);
assert_eq!(sent, Ok(1)); assert_eq!(sent, Ok(1));
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
sent = peer_conn.stream_send(control_stream, &[0x63]); sent = peer_conn.stream_send(control_stream, &[0x63]);
assert_eq!(sent, Ok(1)); assert_eq!(sent, Ok(1));
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
sent = peer_conn.stream_send(control_stream, &[0x64]); sent = peer_conn.stream_send(control_stream, &[0x64]);
assert_eq!(sent, Ok(1)); assert_eq!(sent, Ok(1));
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
// PUSH_PROMISE on a control stream will cause an error // PUSH_PROMISE on a control stream will cause an error
assert_closed(&hconn, &Error::HttpFrameUnexpected); assert_closed(&hconn, &Error::HttpFrameUnexpected);
@ -836,8 +841,8 @@ mod tests {
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();
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
assert_closed(&hconn, &Error::HttpFrame); assert_closed(&hconn, &Error::HttpFrame);
} }
@ -888,8 +893,8 @@ mod tests {
peer_conn.stream_send(stream_id, REQUEST_WITH_BODY).unwrap(); peer_conn.stream_send(stream_id, REQUEST_WITH_BODY).unwrap();
peer_conn.stream_close_send(stream_id).unwrap(); peer_conn.stream_close_send(stream_id).unwrap();
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
// Check connection event. There should be 1 Header and 2 data events. // Check connection event. There should be 1 Header and 2 data events.
let mut headers_frames = 0; let mut headers_frames = 0;
@ -935,8 +940,8 @@ mod tests {
.stream_send(stream_id, &REQUEST_WITH_BODY[..20]) .stream_send(stream_id, &REQUEST_WITH_BODY[..20])
.unwrap(); .unwrap();
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
// Check connection event. There should be 1 Header and no data events. // Check connection event. There should be 1 Header and no data events.
let mut headers_frames = 0; let mut headers_frames = 0;
@ -972,7 +977,7 @@ mod tests {
| Http3ServerEvent::WebTransport(_) => {} | Http3ServerEvent::WebTransport(_) => {}
} }
} }
let out = hconn.process(None, now()); let out = hconn.process_output(now());
// Send data. // Send data.
peer_conn peer_conn
@ -980,8 +985,8 @@ mod tests {
.unwrap(); .unwrap();
peer_conn.stream_close_send(stream_id).unwrap(); peer_conn.stream_close_send(stream_id).unwrap();
let out = peer_conn.process(out.as_dgram_ref(), now()); let out = peer_conn.process(out.dgram(), now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
while let Some(event) = hconn.next_event() { while let Some(event) = hconn.next_event() {
match event { match event {
@ -1012,8 +1017,8 @@ mod tests {
.stream_send(request_stream_id, &REQUEST_WITH_BODY[..20]) .stream_send(request_stream_id, &REQUEST_WITH_BODY[..20])
.unwrap(); .unwrap();
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
// Check connection event. There should be 1 Header and no data events. // Check connection event. There should be 1 Header and no data events.
// The server will reset the stream. // The server will reset the stream.
@ -1043,10 +1048,10 @@ mod tests {
| Http3ServerEvent::WebTransport(_) => {} | Http3ServerEvent::WebTransport(_) => {}
} }
} }
let out = hconn.process(None, now()); let out = hconn.process_output(now());
let out = peer_conn.process(out.as_dgram_ref(), now()); let out = peer_conn.process(out.dgram(), now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
// Check that STOP_SENDING and REET has been received. // Check that STOP_SENDING and REET has been received.
let mut reset = 0; let mut reset = 0;
@ -1077,8 +1082,8 @@ mod tests {
peer_conn peer_conn
.stream_reset_send(CLIENT_SIDE_CONTROL_STREAM_ID, Error::HttpNoError.code()) .stream_reset_send(CLIENT_SIDE_CONTROL_STREAM_ID, Error::HttpNoError.code())
.unwrap(); .unwrap();
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
assert_closed(&hconn, &Error::HttpClosedCriticalStream); assert_closed(&hconn, &Error::HttpClosedCriticalStream);
} }
@ -1090,8 +1095,8 @@ mod tests {
peer_conn peer_conn
.stream_reset_send(CLIENT_SIDE_ENCODER_STREAM_ID, Error::HttpNoError.code()) .stream_reset_send(CLIENT_SIDE_ENCODER_STREAM_ID, Error::HttpNoError.code())
.unwrap(); .unwrap();
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
assert_closed(&hconn, &Error::HttpClosedCriticalStream); assert_closed(&hconn, &Error::HttpClosedCriticalStream);
} }
@ -1103,8 +1108,8 @@ mod tests {
peer_conn peer_conn
.stream_reset_send(CLIENT_SIDE_DECODER_STREAM_ID, Error::HttpNoError.code()) .stream_reset_send(CLIENT_SIDE_DECODER_STREAM_ID, Error::HttpNoError.code())
.unwrap(); .unwrap();
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
assert_closed(&hconn, &Error::HttpClosedCriticalStream); assert_closed(&hconn, &Error::HttpClosedCriticalStream);
} }
@ -1117,8 +1122,8 @@ mod tests {
peer_conn peer_conn
.stream_stop_sending(SERVER_SIDE_CONTROL_STREAM_ID, Error::HttpNoError.code()) .stream_stop_sending(SERVER_SIDE_CONTROL_STREAM_ID, Error::HttpNoError.code())
.unwrap(); .unwrap();
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
assert_closed(&hconn, &Error::HttpClosedCriticalStream); assert_closed(&hconn, &Error::HttpClosedCriticalStream);
} }
@ -1130,8 +1135,8 @@ mod tests {
peer_conn peer_conn
.stream_stop_sending(SERVER_SIDE_ENCODER_STREAM_ID, Error::HttpNoError.code()) .stream_stop_sending(SERVER_SIDE_ENCODER_STREAM_ID, Error::HttpNoError.code())
.unwrap(); .unwrap();
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
assert_closed(&hconn, &Error::HttpClosedCriticalStream); assert_closed(&hconn, &Error::HttpClosedCriticalStream);
} }
@ -1143,8 +1148,8 @@ mod tests {
peer_conn peer_conn
.stream_stop_sending(SERVER_SIDE_DECODER_STREAM_ID, Error::HttpNoError.code()) .stream_stop_sending(SERVER_SIDE_DECODER_STREAM_ID, Error::HttpNoError.code())
.unwrap(); .unwrap();
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
assert_closed(&hconn, &Error::HttpClosedCriticalStream); assert_closed(&hconn, &Error::HttpClosedCriticalStream);
} }
@ -1251,8 +1256,8 @@ mod tests {
.stream_send(request_stream_id_2, REQUEST_WITH_BODY) .stream_send(request_stream_id_2, REQUEST_WITH_BODY)
.unwrap(); .unwrap();
let out = peer_conn.process(None, now()); let out = peer_conn.process_output(now());
hconn.process(out.as_dgram_ref(), now()); hconn.process(out.dgram(), now());
let mut requests = HashMap::new(); let mut requests = HashMap::new();
while let Some(event) = hconn.next_event() { while let Some(event) = hconn.next_event() {

Просмотреть файл

@ -268,8 +268,8 @@ mod tests {
let (mut conn_c, mut conn_s) = connect(); let (mut conn_c, mut conn_s) = connect();
// 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(None, now()); let out = conn_s.process_output(now());
mem::drop(conn_c.process(out.as_dgram_ref(), now())); mem::drop(conn_c.process(out.dgram(), now()));
Self { Self {
conn_c, conn_c,
@ -291,8 +291,8 @@ mod tests {
self.conn_s self.conn_s
.stream_send(self.stream_id, &enc[i..=i]) .stream_send(self.stream_id, &enc[i..=i])
.unwrap(); .unwrap();
let out = self.conn_s.process(None, now()); let out = self.conn_s.process_output(now());
mem::drop(self.conn_c.process(out.as_dgram_ref(), now())); mem::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)
@ -305,8 +305,8 @@ mod tests {
if fin { if fin {
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(None, now()); let out = self.conn_s.process_output(now());
mem::drop(self.conn_c.process(out.dgram().as_ref(), now())); mem::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);
} }

74
third_party/rust/neqo-http3/tests/httpconn.rs поставляемый
Просмотреть файл

@ -94,20 +94,20 @@ fn process_client_events(conn: &mut Http3Client) {
fn connect_peers(hconn_c: &mut Http3Client, hconn_s: &mut Http3Server) -> Option<Datagram> { fn connect_peers(hconn_c: &mut Http3Client, hconn_s: &mut Http3Server) -> Option<Datagram> {
assert_eq!(hconn_c.state(), Http3State::Initializing); assert_eq!(hconn_c.state(), Http3State::Initializing);
let out = hconn_c.process(None, now()); // Initial let out = hconn_c.process_output(now()); // Initial
let out = hconn_s.process(out.as_dgram_ref(), now()); // Initial + Handshake let out = hconn_s.process(out.dgram(), now()); // Initial + Handshake
let out = hconn_c.process(out.as_dgram_ref(), now()); // ACK let out = hconn_c.process(out.dgram(), now()); // ACK
mem::drop(hconn_s.process(out.as_dgram_ref(), now())); // consume ACK mem::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());
let out = hconn_c.process(None, now()); // Handshake let out = hconn_c.process_output(now()); // Handshake
assert_eq!(hconn_c.state(), Http3State::Connected); assert_eq!(hconn_c.state(), Http3State::Connected);
let out = hconn_s.process(out.as_dgram_ref(), now()); // Handshake let out = hconn_s.process(out.dgram(), now()); // Handshake
let out = hconn_c.process(out.as_dgram_ref(), now()); let out = hconn_c.process(out.dgram(), now());
let out = hconn_s.process(out.as_dgram_ref(), now()); let out = hconn_s.process(out.dgram(), now());
// assert!(hconn_s.settings_received); // assert!(hconn_s.settings_received);
let out = hconn_c.process(out.as_dgram_ref(), now()); let out = hconn_c.process(out.dgram(), now());
// assert!(hconn_c.settings_received); // assert!(hconn_c.settings_received);
out.dgram() out.dgram()
@ -121,28 +121,28 @@ fn connect_peers_with_network_propagation_delay(
let net_delay = Duration::from_millis(net_delay); let net_delay = Duration::from_millis(net_delay);
assert_eq!(hconn_c.state(), Http3State::Initializing); assert_eq!(hconn_c.state(), Http3State::Initializing);
let mut now = now(); let mut now = now();
let out = hconn_c.process(None, now); // Initial let out = hconn_c.process_output(now); // Initial
now += net_delay; now += net_delay;
let out = hconn_s.process(out.as_dgram_ref(), now); // Initial + Handshake let out = hconn_s.process(out.dgram(), now); // Initial + Handshake
now += net_delay; now += net_delay;
let out = hconn_c.process(out.as_dgram_ref(), now); // ACK let out = hconn_c.process(out.dgram(), now); // ACK
now += net_delay; now += net_delay;
let out = hconn_s.process(out.as_dgram_ref(), now); // consume ACK let out = hconn_s.process(out.dgram(), now); // consume ACK
assert!(out.dgram().is_none()); assert!(out.dgram().is_none());
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));
now += net_delay; now += net_delay;
hconn_c.authenticated(AuthenticationStatus::Ok, now); hconn_c.authenticated(AuthenticationStatus::Ok, now);
let out = hconn_c.process(None, now); // Handshake let out = hconn_c.process_output(now); // Handshake
assert_eq!(hconn_c.state(), Http3State::Connected); assert_eq!(hconn_c.state(), Http3State::Connected);
now += net_delay; now += net_delay;
let out = hconn_s.process(out.as_dgram_ref(), now); // HANDSHAKE_DONE let out = hconn_s.process(out.dgram(), now); // HANDSHAKE_DONE
now += net_delay; now += net_delay;
let out = hconn_c.process(out.as_dgram_ref(), now); // Consume HANDSHAKE_DONE, send control streams. let out = hconn_c.process(out.dgram(), now); // Consume HANDSHAKE_DONE, send control streams.
now += net_delay; now += net_delay;
let out = hconn_s.process(out.as_dgram_ref(), now); // consume and send control streams. let out = hconn_s.process(out.dgram(), now); // consume and send control streams.
now += net_delay; now += net_delay;
let out = hconn_c.process(out.as_dgram_ref(), now); // consume control streams. let out = hconn_c.process(out.dgram(), now); // consume control streams.
(out.dgram(), now) (out.dgram(), now)
} }
@ -157,8 +157,8 @@ fn connect() -> (Http3Client, Http3Server, Option<Datagram>) {
fn exchange_packets(client: &mut Http3Client, server: &mut Http3Server, out_ex: Option<Datagram>) { fn exchange_packets(client: &mut Http3Client, server: &mut Http3Server, out_ex: Option<Datagram>) {
let mut out = out_ex; let mut out = out_ex;
loop { loop {
out = client.process(out.as_ref(), now()).dgram(); out = client.process(out, now()).dgram();
out = server.process(out.as_ref(), now()).dgram(); out = server.process(out, now()).dgram();
if out.is_none() { if out.is_none() {
break; break;
} }
@ -186,17 +186,17 @@ fn fetch() {
.unwrap(); .unwrap();
assert_eq!(req, 0); assert_eq!(req, 0);
hconn_c.stream_close_send(req).unwrap(); hconn_c.stream_close_send(req).unwrap();
let out = hconn_c.process(dgram.as_ref(), now()); let out = hconn_c.process(dgram, now());
qtrace!("-----server"); qtrace!("-----server");
let out = hconn_s.process(out.as_dgram_ref(), now()); let out = hconn_s.process(out.dgram(), now());
mem::drop(hconn_c.process(out.as_dgram_ref(), now())); mem::drop(hconn_c.process(out.dgram(), now()));
process_server_events(&hconn_s); process_server_events(&hconn_s);
let out = hconn_s.process(None, now()); let out = hconn_s.process(None::<Datagram>, now());
qtrace!("-----client"); qtrace!("-----client");
mem::drop(hconn_c.process(out.as_dgram_ref(), now())); mem::drop(hconn_c.process(out.dgram(), now()));
let out = hconn_s.process(None, now()); let out = hconn_s.process(None::<Datagram>, now());
mem::drop(hconn_c.process(out.as_dgram_ref(), now())); mem::drop(hconn_c.process(out.dgram(), now()));
process_client_events(&mut hconn_c); process_client_events(&mut hconn_c);
} }
@ -215,10 +215,10 @@ fn response_103() {
.unwrap(); .unwrap();
assert_eq!(req, 0); assert_eq!(req, 0);
hconn_c.stream_close_send(req).unwrap(); hconn_c.stream_close_send(req).unwrap();
let out = hconn_c.process(dgram.as_ref(), now()); let out = hconn_c.process(dgram, now());
let out = hconn_s.process(out.as_dgram_ref(), now()); let out = hconn_s.process(out.dgram(), now());
mem::drop(hconn_c.process(out.as_dgram_ref(), now())); mem::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"),
@ -226,9 +226,9 @@ fn response_103() {
]; ];
// Send 103 // Send 103
request.send_headers(&info_headers).unwrap(); request.send_headers(&info_headers).unwrap();
let out = hconn_s.process(None, now()); let out = hconn_s.process(None::<Datagram>, now());
mem::drop(hconn_c.process(out.as_dgram_ref(), now())); mem::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,
@ -238,8 +238,8 @@ fn response_103() {
assert!(hconn_c.events().any(info_headers_event)); assert!(hconn_c.events().any(info_headers_event));
set_response(&request); set_response(&request);
let out = hconn_s.process(None, now()); let out = hconn_s.process(None::<Datagram>, now());
mem::drop(hconn_c.process(out.as_dgram_ref(), now())); mem::drop(hconn_c.process(out.dgram(), now()));
process_client_events(&mut hconn_c); process_client_events(&mut hconn_c);
} }
@ -448,8 +448,8 @@ fn zerortt() {
.unwrap(); .unwrap();
hconn_c.stream_close_send(req).unwrap(); hconn_c.stream_close_send(req).unwrap();
let out = hconn_c.process(dgram.as_ref(), now()); let out = hconn_c.process(dgram, now());
let out = hconn_s.process(out.as_dgram_ref(), now()); let out = hconn_s.process(out.dgram(), now());
let mut request_stream = None; let mut request_stream = None;
let mut zerortt_state_change = false; let mut zerortt_state_change = false;
@ -513,7 +513,7 @@ fn fetch_noresponse_will_idletimeout() {
.unwrap(); .unwrap();
assert_eq!(req, 0); assert_eq!(req, 0);
hconn_c.stream_close_send(req).unwrap(); hconn_c.stream_close_send(req).unwrap();
let _out = hconn_c.process(dgram.as_ref(), now); let _out = hconn_c.process(dgram, now);
qtrace!("-----server"); qtrace!("-----server");
let mut done = false; let mut done = false;

24
third_party/rust/neqo-http3/tests/priority.rs поставляемый
Просмотреть файл

@ -16,9 +16,9 @@ use test_fixture::*;
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 {
out = client.process(out.as_ref(), now()).dgram(); out = client.process(out, now()).dgram();
let client_done = out.is_none(); let client_done = out.is_none();
out = server.process(out.as_ref(), now()).dgram(); out = server.process(out, now()).dgram();
if out.is_none() && client_done { if out.is_none() && client_done {
break; break;
} }
@ -28,29 +28,29 @@ 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(None, now()); let out = client.process_output(now());
assert_eq!(client.state(), Http3State::Initializing); assert_eq!(client.state(), Http3State::Initializing);
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
let out = client.process(out.as_dgram_ref(), now()); let out = client.process(out.dgram(), now());
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_none()); assert!(out.as_dgram_ref().is_none());
let authentication_needed = |e| matches!(e, Http3ClientEvent::AuthenticationNeeded); let authentication_needed = |e| matches!(e, Http3ClientEvent::AuthenticationNeeded);
assert!(client.events().any(authentication_needed)); assert!(client.events().any(authentication_needed));
client.authenticated(AuthenticationStatus::Ok, now()); client.authenticated(AuthenticationStatus::Ok, now());
let out = client.process(out.as_dgram_ref(), now()); let out = client.process(out.dgram(), now());
let connected = |e| matches!(e, Http3ClientEvent::StateChange(Http3State::Connected)); let connected = |e| matches!(e, Http3ClientEvent::StateChange(Http3State::Connected));
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 setttings
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
let out = client.process(out.as_dgram_ref(), now()); let out = client.process(out.dgram(), now());
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
let out = client.process(out.as_dgram_ref(), now()); let out = client.process(out.dgram(), now());
_ = server.process(out.as_dgram_ref(), now()); _ = server.process(out.dgram(), now());
} }
fn connect() -> (Http3Client, Http3Server) { fn connect() -> (Http3Client, Http3Server) {

Просмотреть файл

@ -29,8 +29,8 @@ fn response_header_103() -> &'static Vec<Header> {
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 {
out = client.process(out.as_ref(), now()).dgram(); out = client.process(out, now()).dgram();
out = server.process(out.as_ref(), now()).dgram(); out = server.process(out, now()).dgram();
if out.is_none() { if out.is_none() {
break; break;
} }

Просмотреть файл

@ -41,19 +41,19 @@ fn connect() -> (Http3Client, Http3Server) {
) )
.expect("create a server"); .expect("create a server");
assert_eq!(client.state(), Http3State::Initializing); assert_eq!(client.state(), Http3State::Initializing);
let out = client.process(None, now()); let out = client.process_output(now());
assert_eq!(client.state(), Http3State::Initializing); assert_eq!(client.state(), Http3State::Initializing);
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
let out = client.process(out.as_dgram_ref(), now()); let out = client.process(out.dgram(), now());
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_none()); assert!(out.as_dgram_ref().is_none());
let authentication_needed = |e| matches!(e, Http3ClientEvent::AuthenticationNeeded); let authentication_needed = |e| matches!(e, Http3ClientEvent::AuthenticationNeeded);
assert!(client.events().any(authentication_needed)); assert!(client.events().any(authentication_needed));
client.authenticated(AuthenticationStatus::Ok, now()); client.authenticated(AuthenticationStatus::Ok, now());
let mut out = client.process(out.as_dgram_ref(), now()).dgram(); let mut out = client.process(out.dgram(), now()).dgram();
let connected = |e| matches!(e, Http3ClientEvent::StateChange(Http3State::Connected)); let connected = |e| matches!(e, Http3ClientEvent::StateChange(Http3State::Connected));
assert!(client.events().any(connected)); assert!(client.events().any(connected));
@ -61,9 +61,9 @@ fn connect() -> (Http3Client, Http3Server) {
// Exchange H3 setttings // Exchange H3 setttings
loop { loop {
out = server.process(out.as_ref(), now()).dgram(); out = server.process(out, now()).dgram();
let dgram_present = out.is_some(); let dgram_present = out.is_some();
out = client.process(out.as_ref(), now()).dgram(); out = client.process(out, now()).dgram();
if out.is_none() && !dgram_present { if out.is_none() && !dgram_present {
break; break;
} }
@ -74,8 +74,8 @@ fn connect() -> (Http3Client, Http3Server) {
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 {
out = client.process(out.as_ref(), now()).dgram(); out = client.process(out, now()).dgram();
out = server.process(out.as_ref(), now()).dgram(); out = server.process(out, now()).dgram();
if out.is_none() { if out.is_none() {
break; break;
} }

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"6443d8309747dcbcff3f0f8c7f3a5578e6c19fab0128afa6ff6fe9943de4e4d4","src/decoder.rs":"ed2d6fa29e8726429aabb84e65f5d8025b320c0219b442b47c38903728ba3b2d","src/decoder_instructions.rs":"addf304fbd566ca387e5111cbe25784f7f50e0112ce0372b1ad6d18185b45a02","src/encoder.rs":"9a09c2eb6476fb72e3d73937a6e1c98072910fc7f709aca13f41afed38c7dd9f","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":"fbd96ef7d21db2bae19b8e379995544e8cf123e8e5129c1500ace2773acf5649","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":"b47c04269b6b2d0ee8418f407a16f8097b38694eb57b42f5a7d1eabd549a8cc4","src/decoder.rs":"5c76a8407e02999a805ecaeae0ec2743121abe1e35b75126994d52ff7deb6af7","src/decoder_instructions.rs":"addf304fbd566ca387e5111cbe25784f7f50e0112ce0372b1ad6d18185b45a02","src/encoder.rs":"55729ecca0360faa07a2fa0ab11dd2bc26137548e9a499b14d540bcee22b7378","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":"fbd96ef7d21db2bae19b8e379995544e8cf123e8e5129c1500ace2773acf5649","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}

2
third_party/rust/neqo-qpack/Cargo.toml поставляемый
Просмотреть файл

@ -13,7 +13,7 @@
edition = "2021" edition = "2021"
rust-version = "1.76.0" rust-version = "1.76.0"
name = "neqo-qpack" name = "neqo-qpack"
version = "0.9.2" version = "0.10.0"
authors = ["The Neqo Authors <necko@mozilla.com>"] authors = ["The Neqo Authors <necko@mozilla.com>"]
build = false build = false
autobins = false autobins = false

8
third_party/rust/neqo-qpack/src/decoder.rs поставляемый
Просмотреть файл

@ -333,8 +333,8 @@ mod tests {
.peer_conn .peer_conn
.stream_send(decoder.recv_stream_id, encoder_instruction) .stream_send(decoder.recv_stream_id, encoder_instruction)
.unwrap(); .unwrap();
let out = decoder.peer_conn.process(None, now()); let out = decoder.peer_conn.process_output(now());
mem::drop(decoder.conn.process(out.as_dgram_ref(), now())); mem::drop(decoder.conn.process(out.dgram(), now()));
assert_eq!( assert_eq!(
decoder decoder
.decoder .decoder
@ -345,8 +345,8 @@ mod tests {
fn send_instructions_and_check(decoder: &mut TestDecoder, decoder_instruction: &[u8]) { fn send_instructions_and_check(decoder: &mut TestDecoder, decoder_instruction: &[u8]) {
decoder.decoder.send(&mut decoder.conn).unwrap(); decoder.decoder.send(&mut decoder.conn).unwrap();
let out = decoder.conn.process(None, now()); let out = decoder.conn.process_output(now());
mem::drop(decoder.peer_conn.process(out.as_dgram_ref(), now())); mem::drop(decoder.peer_conn.process(out.dgram(), now()));
let mut buf = [0_u8; 100]; let mut buf = [0_u8; 100];
let (amount, fin) = decoder let (amount, fin) = decoder
.peer_conn .peer_conn

18
third_party/rust/neqo-qpack/src/encoder.rs поставляемый
Просмотреть файл

@ -572,9 +572,9 @@ mod tests {
pub fn send_instructions(&mut self, encoder_instruction: &[u8]) { pub fn send_instructions(&mut self, encoder_instruction: &[u8]) {
self.encoder.send_encoder_updates(&mut self.conn).unwrap(); self.encoder.send_encoder_updates(&mut self.conn).unwrap();
let out = self.conn.process(None, now()); let out = self.conn.process_output(now());
let out2 = self.peer_conn.process(out.as_dgram_ref(), now()); let out2 = self.peer_conn.process(out.dgram(), now());
mem::drop(self.conn.process(out2.as_dgram_ref(), now())); mem::drop(self.conn.process(out2.dgram(), now()));
let mut buf = [0_u8; 100]; let mut buf = [0_u8; 100];
let (amount, fin) = self let (amount, fin) = self
.peer_conn .peer_conn
@ -635,8 +635,8 @@ mod tests {
.peer_conn .peer_conn
.stream_send(encoder.recv_stream_id, decoder_instruction) .stream_send(encoder.recv_stream_id, decoder_instruction)
.unwrap(); .unwrap();
let out = encoder.peer_conn.process(None, now()); let out = encoder.peer_conn.process_output(now());
mem::drop(encoder.conn.process(out.as_dgram_ref(), now())); mem::drop(encoder.conn.process(out.dgram(), now()));
assert!(encoder assert!(encoder
.encoder .encoder
.read_instructions(&mut encoder.conn, encoder.recv_stream_id) .read_instructions(&mut encoder.conn, encoder.recv_stream_id)
@ -1563,8 +1563,8 @@ mod tests {
encoder.send_instructions(ONE_INSTRUCTION_1); encoder.send_instructions(ONE_INSTRUCTION_1);
// exchange a flow control update. // exchange a flow control update.
let out = encoder.peer_conn.process(None, now()); let out = encoder.peer_conn.process_output(now());
mem::drop(encoder.conn.process(out.as_dgram_ref(), now())); mem::drop(encoder.conn.process(out.dgram(), now()));
// Try writing a new header block. Now, headers will be added to the dynamic table again, // Try writing a new header block. Now, headers will be added to the dynamic table again,
// because instructions can be sent. // because instructions can be sent.
@ -1610,8 +1610,8 @@ mod tests {
.encoder .encoder
.send_encoder_updates(&mut encoder.conn) .send_encoder_updates(&mut encoder.conn)
.unwrap(); .unwrap();
let out = encoder.conn.process(None, now()); let out = encoder.conn.process_output(now());
mem::drop(encoder.peer_conn.process(out.as_dgram_ref(), now())); mem::drop(encoder.peer_conn.process(out.dgram(), now()));
// receive an insert count increment. // receive an insert count increment.
recv_instruction(&mut encoder, &[0x01]); recv_instruction(&mut encoder, &[0x01]);

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

2
third_party/rust/neqo-transport/Cargo.toml поставляемый
Просмотреть файл

@ -13,7 +13,7 @@
edition = "2021" edition = "2021"
rust-version = "1.76.0" rust-version = "1.76.0"
name = "neqo-transport" name = "neqo-transport"
version = "0.9.2" version = "0.10.0"
authors = ["The Neqo Authors <necko@mozilla.com>"] authors = ["The Neqo Authors <necko@mozilla.com>"]
build = "build.rs" build = "build.rs"
autobins = false autobins = false

Просмотреть файл

@ -13,7 +13,7 @@ use test_fixture::{
sim::{ sim::{
connection::{ConnectionNode, ReachState, ReceiveData, SendData}, connection::{ConnectionNode, ReachState, ReceiveData, SendData},
network::{Delay, TailDrop}, network::{Delay, TailDrop},
Simulator, ReadySimulator, Simulator,
}, },
}; };
@ -21,7 +21,8 @@ const ZERO: Duration = Duration::from_millis(0);
const JITTER: Duration = Duration::from_millis(10); const JITTER: Duration = Duration::from_millis(10);
const TRANSFER_AMOUNT: usize = 1 << 22; // 4Mbyte const TRANSFER_AMOUNT: usize = 1 << 22; // 4Mbyte
fn benchmark_transfer(c: &mut Criterion, label: &str, seed: &Option<impl AsRef<str>>) { #[allow(clippy::needless_pass_by_value)] // Passing String where &str would do is fine here.
fn benchmark_transfer(c: &mut Criterion, label: &str, seed: Option<impl AsRef<str>>) {
for pacing in [false, true] { for pacing in [false, true] {
let mut group = c.benchmark_group(format!("transfer/pacing-{pacing}")); let mut group = c.benchmark_group(format!("transfer/pacing-{pacing}"));
// Don't let criterion calculate throughput, as that's based on wall-clock time, not // Don't let criterion calculate throughput, as that's based on wall-clock time, not
@ -52,9 +53,7 @@ fn benchmark_transfer(c: &mut Criterion, label: &str, seed: &Option<impl AsRef<s
} }
sim.setup() sim.setup()
}, },
|sim| { ReadySimulator::run,
sim.run();
},
SmallInput, SmallInput,
); );
}); });
@ -63,14 +62,14 @@ fn benchmark_transfer(c: &mut Criterion, label: &str, seed: &Option<impl AsRef<s
} }
fn benchmark_transfer_variable(c: &mut Criterion) { fn benchmark_transfer_variable(c: &mut Criterion) {
benchmark_transfer(c, "varying-seeds", &std::env::var("SIMULATION_SEED").ok()); benchmark_transfer(c, "varying-seeds", std::env::var("SIMULATION_SEED").ok());
} }
fn benchmark_transfer_fixed(c: &mut Criterion) { fn benchmark_transfer_fixed(c: &mut Criterion) {
benchmark_transfer( benchmark_transfer(
c, c,
"same-seed", "same-seed",
&Some("62df6933ba1f543cece01db8f27fb2025529b27f93df39e19f006e1db3b8c843"), Some("62df6933ba1f543cece01db8f27fb2025529b27f93df39e19f006e1db3b8c843"),
); );
} }

Просмотреть файл

@ -1022,15 +1022,16 @@ impl Connection {
} }
/// Process new input datagrams on the connection. /// Process new input datagrams on the connection.
pub fn process_input(&mut self, d: &Datagram, now: Instant) { pub fn process_input(&mut self, d: Datagram<impl AsRef<[u8]>>, now: Instant) {
self.process_multiple_input(iter::once(d), now); self.process_multiple_input(iter::once(d), now);
} }
/// Process new input datagrams on the connection. /// Process new input datagrams on the connection.
pub fn process_multiple_input<'a, I>(&mut self, dgrams: I, now: Instant) pub fn process_multiple_input(
where &mut self,
I: IntoIterator<Item = &'a Datagram>, dgrams: impl IntoIterator<Item = Datagram<impl AsRef<[u8]>>>,
{ now: Instant,
) {
let mut dgrams = dgrams.into_iter().peekable(); let mut dgrams = dgrams.into_iter().peekable();
if dgrams.peek().is_none() { if dgrams.peek().is_none() {
return; return;
@ -1161,7 +1162,7 @@ impl Connection {
/// Process input and generate output. /// Process input and generate output.
#[must_use = "Output of the process function must be handled"] #[must_use = "Output of the process function must be handled"]
pub fn process(&mut self, dgram: Option<&Datagram>, now: Instant) -> Output { pub fn process(&mut self, dgram: Option<Datagram<impl AsRef<[u8]>>>, now: Instant) -> Output {
if let Some(d) = dgram { if let Some(d) = dgram {
self.input(d, now, now); self.input(d, now, now);
self.process_saved(now); self.process_saved(now);
@ -1241,20 +1242,20 @@ impl Connection {
} }
} }
fn is_stateless_reset(&self, path: &PathRef, d: &Datagram) -> bool { fn is_stateless_reset(&self, path: &PathRef, d: &Datagram<impl AsRef<[u8]>>) -> bool {
// If the datagram is too small, don't try. // If the datagram is too small, don't try.
// If the connection is connected, then the reset token will be invalid. // If the connection is connected, then the reset token will be invalid.
if d.len() < 16 || !self.state.connected() { if d.len() < 16 || !self.state.connected() {
return false; return false;
} }
<&[u8; 16]>::try_from(&d[d.len() - 16..]) <&[u8; 16]>::try_from(&d.as_ref()[d.len() - 16..])
.map_or(false, |token| path.borrow().is_stateless_reset(token)) .map_or(false, |token| path.borrow().is_stateless_reset(token))
} }
fn check_stateless_reset( fn check_stateless_reset(
&mut self, &mut self,
path: &PathRef, path: &PathRef,
d: &Datagram, d: &Datagram<impl AsRef<[u8]>>,
first: bool, first: bool,
now: Instant, now: Instant,
) -> Res<()> { ) -> Res<()> {
@ -1280,24 +1281,27 @@ impl Connection {
debug_assert!(self.crypto.states.rx_hp(self.version, cspace).is_some()); debug_assert!(self.crypto.states.rx_hp(self.version, cspace).is_some());
for saved in self.saved_datagrams.take_saved() { for saved in self.saved_datagrams.take_saved() {
qtrace!([self], "input saved @{:?}: {:?}", saved.t, saved.d); qtrace!([self], "input saved @{:?}: {:?}", saved.t, saved.d);
self.input(&saved.d, saved.t, now); self.input(saved.d, saved.t, now);
} }
} }
} }
/// In case a datagram arrives that we can only partially process, save any /// In case a datagram arrives that we can only partially process, save any
/// part that we don't have keys for. /// part that we don't have keys for.
fn save_datagram(&mut self, cspace: CryptoSpace, d: &Datagram, remaining: usize, now: Instant) { #[allow(clippy::needless_pass_by_value)] // To consume an owned datagram below.
let d = if remaining < d.len() { fn save_datagram(
Datagram::new( &mut self,
d.source(), cspace: CryptoSpace,
d.destination(), d: Datagram<impl AsRef<[u8]>>,
d.tos(), remaining: usize,
&d[d.len() - remaining..], now: Instant,
) ) {
} else { let d = Datagram::new(
d.clone() d.source(),
}; d.destination(),
d.tos(),
d[d.len() - remaining..].to_vec(),
);
self.saved_datagrams.save(cspace, d, now); self.saved_datagrams.save(cspace, d, now);
self.stats.borrow_mut().saved_datagrams += 1; self.stats.borrow_mut().saved_datagrams += 1;
} }
@ -1498,7 +1502,7 @@ impl Connection {
fn postprocess_packet( fn postprocess_packet(
&mut self, &mut self,
path: &PathRef, path: &PathRef,
d: &Datagram, d: &Datagram<impl AsRef<[u8]>>,
packet: &PublicPacket, packet: &PublicPacket,
migrate: bool, migrate: bool,
now: Instant, now: Instant,
@ -1530,7 +1534,7 @@ impl Connection {
/// Take a datagram as input. This reports an error if the packet was bad. /// Take a datagram as input. This reports an error if the packet was bad.
/// This takes two times: when the datagram was received, and the current time. /// This takes two times: when the datagram was received, and the current time.
fn input(&mut self, d: &Datagram, received: Instant, now: Instant) { fn input(&mut self, d: Datagram<impl AsRef<[u8]>>, received: Instant, now: Instant) {
// First determine the path. // First determine the path.
let path = self.paths.find_path_with_rebinding( let path = self.paths.find_path_with_rebinding(
d.destination(), d.destination(),
@ -1544,11 +1548,16 @@ impl Connection {
self.capture_error(Some(path), now, 0, res).ok(); self.capture_error(Some(path), now, 0, res).ok();
} }
fn input_path(&mut self, path: &PathRef, d: &Datagram, now: Instant) -> Res<()> { fn input_path(
let mut slc = &d[..]; &mut self,
path: &PathRef,
d: Datagram<impl AsRef<[u8]>>,
now: Instant,
) -> Res<()> {
let mut slc = d.as_ref();
let mut dcid = None; let mut dcid = None;
qtrace!([self], "{} input {}", path.borrow(), hex(&**d)); qtrace!([self], "{} input {}", path.borrow(), hex(&d));
let pto = path.borrow().rtt().pto(self.confirmed()); let pto = path.borrow().rtt().pto(self.confirmed());
// Handle each packet in the datagram. // Handle each packet in the datagram.
@ -1606,7 +1615,7 @@ impl Connection {
} else { } else {
match self.process_packet(path, &payload, now) { match self.process_packet(path, &payload, now) {
Ok(migrate) => { Ok(migrate) => {
self.postprocess_packet(path, d, &packet, migrate, now); self.postprocess_packet(path, &d, &packet, migrate, now);
} }
Err(e) => { Err(e) => {
self.ensure_error_path(path, &packet, now); self.ensure_error_path(path, &packet, now);
@ -1648,7 +1657,7 @@ impl Connection {
// Decryption failure, or not having keys is not fatal. // Decryption failure, or not having keys is not fatal.
// If the state isn't available, or we can't decrypt the packet, drop // If the state isn't available, or we can't decrypt the packet, drop
// the rest of the datagram on the floor, but don't generate an error. // the rest of the datagram on the floor, but don't generate an error.
self.check_stateless_reset(path, d, dcid.is_none(), now)?; self.check_stateless_reset(path, &d, dcid.is_none(), now)?;
self.stats.borrow_mut().pkt_dropped("Decryption failure"); self.stats.borrow_mut().pkt_dropped("Decryption failure");
qlog::packet_dropped(&self.qlog, &packet); qlog::packet_dropped(&self.qlog, &packet);
} }
@ -1656,7 +1665,7 @@ impl Connection {
slc = remainder; slc = remainder;
dcid = Some(ConnectionId::from(packet.dcid())); dcid = Some(ConnectionId::from(packet.dcid()));
} }
self.check_stateless_reset(path, d, dcid.is_none(), now)?; self.check_stateless_reset(path, &d, dcid.is_none(), now)?;
Ok(()) Ok(())
} }
@ -1958,7 +1967,13 @@ impl Connection {
Ok(()) Ok(())
} }
fn handle_migration(&mut self, path: &PathRef, d: &Datagram, migrate: bool, now: Instant) { fn handle_migration(
&mut self,
path: &PathRef,
d: &Datagram<impl AsRef<[u8]>>,
migrate: bool,
now: Instant,
) {
if !migrate { if !migrate {
return; return;
} }

Просмотреть файл

@ -13,7 +13,7 @@ use super::{
ack_bytes, connect_rtt_idle, default_client, default_server, fill_cwnd, increase_cwnd, ack_bytes, connect_rtt_idle, default_client, default_server, fill_cwnd, increase_cwnd,
induce_persistent_congestion, new_client, new_server, send_something, DEFAULT_RTT, induce_persistent_congestion, new_client, new_server, send_something, DEFAULT_RTT,
}; };
use crate::stream_id::StreamType; use crate::{connection::tests::assert_path_challenge_min_len, stream_id::StreamType};
/// With the default RTT here (100ms) and default ratio (4), endpoints won't send /// With the default RTT here (100ms) and default ratio (4), endpoints won't send
/// `ACK_FREQUENCY` as the ACK delay isn't different enough from the default. /// `ACK_FREQUENCY` as the ACK delay isn't different enough from the default.
@ -72,7 +72,7 @@ fn ack_rate_exit_slow_start() {
// and to send ACK_FREQUENCY. // and to send ACK_FREQUENCY.
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
assert_eq!(client.stats().frame_tx.ack_frequency, 0); assert_eq!(client.stats().frame_tx.ack_frequency, 0);
let af = client.process(Some(&ack), now).dgram(); let af = client.process(Some(ack), now).dgram();
assert!(af.is_some()); assert!(af.is_some());
assert_eq!(client.stats().frame_tx.ack_frequency, 1); assert_eq!(client.stats().frame_tx.ack_frequency, 1);
} }
@ -121,11 +121,11 @@ fn ack_rate_client_one_rtt() {
// The first packet will elicit an immediate ACK however, so do this twice. // The first packet will elicit an immediate ACK however, so do this twice.
let d = send_something(&mut client, now); let d = send_something(&mut client, now);
now += RTT / 2; now += RTT / 2;
let ack = server.process(Some(&d), now).dgram(); let ack = server.process(Some(d), now).dgram();
assert!(ack.is_some()); assert!(ack.is_some());
let d = send_something(&mut client, now); let d = send_something(&mut client, now);
now += RTT / 2; now += RTT / 2;
let delay = server.process(Some(&d), now).callback(); let delay = server.process(Some(d), now).callback();
assert_eq!(delay, RTT); assert_eq!(delay, RTT);
assert_eq!(client.stats().frame_tx.ack_frequency, 1); assert_eq!(client.stats().frame_tx.ack_frequency, 1);
@ -144,11 +144,11 @@ fn ack_rate_server_half_rtt() {
now += RTT / 2; now += RTT / 2;
// The client now will acknowledge immediately because it has been more than // The client now will acknowledge immediately because it has been more than
// an RTT since it last sent an acknowledgment. // an RTT since it last sent an acknowledgment.
let ack = client.process(Some(&d), now); let ack = client.process(Some(d), now);
assert!(ack.as_dgram_ref().is_some()); assert!(ack.as_dgram_ref().is_some());
let d = send_something(&mut server, now); let d = send_something(&mut server, now);
now += RTT / 2; now += RTT / 2;
let delay = client.process(Some(&d), now).callback(); let delay = client.process(Some(d), now).callback();
assert_eq!(delay, RTT / 2); assert_eq!(delay, RTT / 2);
assert_eq!(server.stats().frame_tx.ack_frequency, 1); assert_eq!(server.stats().frame_tx.ack_frequency, 1);
@ -169,10 +169,11 @@ fn migrate_ack_delay() {
let client1 = send_something(&mut client, now); let client1 = send_something(&mut client, now);
assertions::assert_v4_path(&client1, true); // Contains PATH_CHALLENGE. assertions::assert_v4_path(&client1, true); // Contains PATH_CHALLENGE.
assert_path_challenge_min_len(&client, &client1, now);
let client2 = send_something(&mut client, now); let client2 = send_something(&mut client, now);
assertions::assert_v4_path(&client2, false); // Doesn't. Is dropped. assertions::assert_v4_path(&client2, false); // Doesn't. Is dropped.
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
server.process_input(&client1, now); server.process_input(client1, now);
let stream = client.stream_create(StreamType::UniDi).unwrap(); let stream = client.stream_create(StreamType::UniDi).unwrap();
let now = increase_cwnd(&mut client, &mut server, stream, now); let now = increase_cwnd(&mut client, &mut server, stream, now);
@ -188,7 +189,7 @@ fn migrate_ack_delay() {
// After noticing this new loss, the client sends ACK_FREQUENCY. // After noticing this new loss, the client sends ACK_FREQUENCY.
// It has sent a few before (as we dropped `client2`), so ignore those. // It has sent a few before (as we dropped `client2`), so ignore those.
let ad_before = client.stats().frame_tx.ack_frequency; let ad_before = client.stats().frame_tx.ack_frequency;
let af = client.process(Some(&ack), now).dgram(); let af = client.process(Some(ack), now).dgram();
assert!(af.is_some()); assert!(af.is_some());
assert_eq!(client.stats().frame_tx.ack_frequency, ad_before + 1); assert_eq!(client.stats().frame_tx.ack_frequency, ad_before + 1);
} }

Просмотреть файл

@ -47,7 +47,7 @@ fn cc_slow_start_pmtud() {
let stream_id = client.stream_create(StreamType::UniDi).unwrap(); let stream_id = client.stream_create(StreamType::UniDi).unwrap();
let cwnd = cwnd_avail(&client); let cwnd = cwnd_avail(&client);
let (dgrams, _) = fill_cwnd(&mut client, stream_id, now); let (dgrams, _) = fill_cwnd(&mut client, stream_id, now);
let dgrams_len = dgrams.iter().map(|d| d.len()).sum::<usize>(); let dgrams_len = dgrams.iter().map(Datagram::len).sum::<usize>();
assert_eq!(dgrams_len, cwnd); assert_eq!(dgrams_len, cwnd);
assert!(cwnd_avail(&client) < ACK_ONLY_SIZE_LIMIT); assert!(cwnd_avail(&client) < ACK_ONLY_SIZE_LIMIT);
} }
@ -86,7 +86,7 @@ fn cc_slow_start_to_cong_avoidance_recovery_period(congestion_signal: Congestion
// Client: Process ack // Client: Process ack
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
client.process_input(&s_ack, now); client.process_input(s_ack, now);
assert_eq!( assert_eq!(
client.stats().frame_rx.largest_acknowledged, client.stats().frame_rx.largest_acknowledged,
flight1_largest flight1_largest
@ -117,7 +117,7 @@ fn cc_slow_start_to_cong_avoidance_recovery_period(congestion_signal: Congestion
// Client: Process ack // Client: Process ack
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
client.process_input(&s_ack, now); client.process_input(s_ack, now);
assert_eq!( assert_eq!(
client.stats().frame_rx.largest_acknowledged, client.stats().frame_rx.largest_acknowledged,
flight2_largest flight2_largest
@ -160,7 +160,7 @@ fn cc_cong_avoidance_recovery_period_unchanged() {
// Server: Receive and generate ack // Server: Receive and generate ack
let s_ack = ack_bytes(&mut server, stream_id, c_tx_dgrams, now); let s_ack = ack_bytes(&mut server, stream_id, c_tx_dgrams, now);
client.process_input(&s_ack, now); client.process_input(s_ack, now);
let cwnd1 = cwnd(&client); let cwnd1 = cwnd(&client);
@ -168,7 +168,7 @@ fn cc_cong_avoidance_recovery_period_unchanged() {
let s_ack = ack_bytes(&mut server, stream_id, c_tx_dgrams2, now); let s_ack = ack_bytes(&mut server, stream_id, c_tx_dgrams2, now);
// ACK more packets but they were sent before end of recovery period // ACK more packets but they were sent before end of recovery period
client.process_input(&s_ack, now); client.process_input(s_ack, now);
// cwnd should not have changed since ACKed packets were sent before // cwnd should not have changed since ACKed packets were sent before
// recovery period expired // recovery period expired
@ -198,12 +198,12 @@ fn single_packet_on_recovery() {
// Acknowledge just one packet and cause one packet to be declared lost. // Acknowledge just one packet and cause one packet to be declared lost.
// The length is the amount of credit the client should have. // The length is the amount of credit the client should have.
let ack = server.process(Some(&delivered), now).dgram(); let ack = server.process(Some(delivered), now).dgram();
assert!(ack.is_some()); assert!(ack.is_some());
// The client should see the loss and enter recovery. // The client should see the loss and enter recovery.
// As there are many outstanding packets, there should be no available cwnd. // As there are many outstanding packets, there should be no available cwnd.
client.process_input(&ack.unwrap(), now); client.process_input(ack.unwrap(), now);
assert_eq!(cwnd_avail(&client), 0); assert_eq!(cwnd_avail(&client), 0);
// The client should send one packet, ignoring the cwnd. // The client should send one packet, ignoring the cwnd.
@ -235,7 +235,7 @@ fn cc_cong_avoidance_recovery_period_to_cong_avoidance() {
// Client: Process ack // Client: Process ack
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
client.process_input(&s_ack, now); client.process_input(s_ack, now);
// Should be in CARP now. // Should be in CARP now.
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
@ -251,7 +251,7 @@ fn cc_cong_avoidance_recovery_period_to_cong_avoidance() {
for i in 0..5 { for i in 0..5 {
qinfo!("iteration {}", i); qinfo!("iteration {}", i);
let c_tx_size: usize = c_tx_dgrams.iter().map(|d| d.len()).sum(); let c_tx_size: usize = c_tx_dgrams.iter().map(Datagram::len).sum();
qinfo!( qinfo!(
"client sending {} bytes into cwnd of {}", "client sending {} bytes into cwnd of {}",
c_tx_size, c_tx_size,
@ -269,7 +269,7 @@ fn cc_cong_avoidance_recovery_period_to_cong_avoidance() {
let most = c_tx_dgrams.len() - usize::try_from(DEFAULT_ACK_PACKET_TOLERANCE).unwrap() - 1; let most = c_tx_dgrams.len() - usize::try_from(DEFAULT_ACK_PACKET_TOLERANCE).unwrap() - 1;
let s_ack = ack_bytes(&mut server, stream_id, c_tx_dgrams.drain(..most), now); let s_ack = ack_bytes(&mut server, stream_id, c_tx_dgrams.drain(..most), now);
assert_eq!(cwnd(&client), expected_cwnd); assert_eq!(cwnd(&client), expected_cwnd);
client.process_input(&s_ack, now); client.process_input(s_ack, now);
// make sure to fill cwnd again. // make sure to fill cwnd again.
let (mut new_pkts, next_now) = fill_cwnd(&mut client, stream_id, now); let (mut new_pkts, next_now) = fill_cwnd(&mut client, stream_id, now);
now = next_now; now = next_now;
@ -277,7 +277,7 @@ fn cc_cong_avoidance_recovery_period_to_cong_avoidance() {
let s_ack = ack_bytes(&mut server, stream_id, c_tx_dgrams, now); let s_ack = ack_bytes(&mut server, stream_id, c_tx_dgrams, now);
assert_eq!(cwnd(&client), expected_cwnd); assert_eq!(cwnd(&client), expected_cwnd);
client.process_input(&s_ack, now); client.process_input(s_ack, now);
// make sure to fill cwnd again. // make sure to fill cwnd again.
let (mut new_pkts, next_now) = fill_cwnd(&mut client, stream_id, now); let (mut new_pkts, next_now) = fill_cwnd(&mut client, stream_id, now);
now = next_now; now = next_now;
@ -329,7 +329,7 @@ fn cc_slow_start_to_persistent_congestion_some_acks() {
let s_ack = ack_bytes(&mut server, stream, c_tx_dgrams, now); let s_ack = ack_bytes(&mut server, stream, c_tx_dgrams, now);
now += Duration::from_millis(100); now += Duration::from_millis(100);
client.process_input(&s_ack, now); client.process_input(s_ack, now);
// send bytes that will be lost // send bytes that will be lost
let (_, next_now) = fill_cwnd(&mut client, stream, now); let (_, next_now) = fill_cwnd(&mut client, stream, now);
@ -375,7 +375,7 @@ fn cc_persistent_congestion_to_slow_start() {
// No longer in CARP. (pkts acked from after start of CARP) // No longer in CARP. (pkts acked from after start of CARP)
// Should be in slow start now. // Should be in slow start now.
client.process_input(&s_ack, now); client.process_input(s_ack, now);
// ACKing 2 packets should let client send 4. // ACKing 2 packets should let client send 4.
let (c_tx_dgrams, _) = fill_cwnd(&mut client, stream, now); let (c_tx_dgrams, _) = fill_cwnd(&mut client, stream, now);
@ -402,22 +402,22 @@ fn ack_are_not_cc() {
let other_stream = server.stream_create(StreamType::BiDi).unwrap(); let other_stream = server.stream_create(StreamType::BiDi).unwrap();
assert_eq!(other_stream, 1); assert_eq!(other_stream, 1);
server.stream_send(other_stream, b"dropped").unwrap(); server.stream_send(other_stream, b"dropped").unwrap();
let dropped_packet = server.process(None, now).dgram(); let dropped_packet = server.process_output(now).dgram();
assert!(dropped_packet.is_some()); // Now drop this one. assert!(dropped_packet.is_some()); // Now drop this one.
// Now the server sends a packet that will force an ACK, // Now the server sends a packet that will force an ACK,
// because the client will detect a gap. // because the client will detect a gap.
server.stream_send(other_stream, b"sent").unwrap(); server.stream_send(other_stream, b"sent").unwrap();
let ack_eliciting_packet = server.process(None, now).dgram(); let ack_eliciting_packet = server.process_output(now).dgram();
assert!(ack_eliciting_packet.is_some()); assert!(ack_eliciting_packet.is_some());
// The client can ack the server packet even if cc windows is full. // The client can ack the server packet even if cc windows is full.
qdebug!([client], "Process ack-eliciting"); qdebug!([client], "Process ack-eliciting");
let ack_pkt = client.process(ack_eliciting_packet.as_ref(), now).dgram(); let ack_pkt = client.process(ack_eliciting_packet, now).dgram();
assert!(ack_pkt.is_some()); assert!(ack_pkt.is_some());
qdebug!([server], "Handle ACK"); qdebug!([server], "Handle ACK");
let prev_ack_count = server.stats().frame_rx.ack; let prev_ack_count = server.stats().frame_rx.ack;
server.process_input(&ack_pkt.unwrap(), now); server.process_input(ack_pkt.unwrap(), now);
assert_eq!(server.stats().frame_rx.ack, prev_ack_count + 1); assert_eq!(server.stats().frame_rx.ack, prev_ack_count + 1);
} }

Просмотреть файл

@ -41,7 +41,7 @@ fn connection_close() {
client.close(now, 42, ""); client.close(now, 42, "");
let stats_before = client.stats().frame_tx; let stats_before = client.stats().frame_tx;
let out = client.process(None, now); let out = client.process_output(now);
let stats_after = client.stats().frame_tx; let stats_after = client.stats().frame_tx;
assert_eq!( assert_eq!(
stats_after.connection_close, stats_after.connection_close,
@ -49,7 +49,7 @@ fn connection_close() {
); );
assert_eq!(stats_after.ack, stats_before.ack + 1); assert_eq!(stats_after.ack, stats_before.ack + 1);
server.process_input(&out.dgram().unwrap(), now); server.process_input(out.dgram().unwrap(), now);
assert_draining(&server, &Error::PeerApplicationError(42)); assert_draining(&server, &Error::PeerApplicationError(42));
} }
@ -65,7 +65,7 @@ fn connection_close_with_long_reason_string() {
client.close(now, 42, long_reason); client.close(now, 42, long_reason);
let stats_before = client.stats().frame_tx; let stats_before = client.stats().frame_tx;
let out = client.process(None, now); let out = client.process_output(now);
let stats_after = client.stats().frame_tx; let stats_after = client.stats().frame_tx;
assert_eq!( assert_eq!(
stats_after.connection_close, stats_after.connection_close,
@ -73,7 +73,7 @@ fn connection_close_with_long_reason_string() {
); );
assert_eq!(stats_after.ack, stats_before.ack + 1); assert_eq!(stats_after.ack, stats_before.ack + 1);
server.process_input(&out.dgram().unwrap(), now); server.process_input(out.dgram().unwrap(), now);
assert_draining(&server, &Error::PeerApplicationError(42)); assert_draining(&server, &Error::PeerApplicationError(42));
} }
@ -84,17 +84,17 @@ fn early_application_close() {
let mut server = default_server(); let mut server = default_server();
// One flight each. // One flight each.
let dgram = client.process(None, now()).dgram(); let dgram = client.process_output(now()).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
let dgram = server.process(dgram.as_ref(), now()).dgram(); let dgram = server.process(dgram, now()).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
server.close(now(), 77, String::new()); server.close(now(), 77, String::new());
assert!(server.state().closed()); assert!(server.state().closed());
let dgram = server.process(None, now()).dgram(); let dgram = server.process_output(now()).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
assert_draining(&client, &Error::PeerError(ERROR_APPLICATION_CLOSE)); assert_draining(&client, &Error::PeerError(ERROR_APPLICATION_CLOSE));
} }
@ -109,15 +109,15 @@ fn bad_tls_version() {
.unwrap(); .unwrap();
let mut server = default_server(); let mut server = default_server();
let dgram = client.process(None, now()).dgram(); let dgram = client.process_output(now()).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
let dgram = server.process(dgram.as_ref(), now()).dgram(); let dgram = server.process(dgram, now()).dgram();
assert_eq!( assert_eq!(
*server.state(), *server.state(),
State::Closed(CloseReason::Transport(Error::ProtocolViolation)) State::Closed(CloseReason::Transport(Error::ProtocolViolation))
); );
assert!(dgram.is_some()); assert!(dgram.is_some());
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
assert_draining(&client, &Error::PeerError(Error::ProtocolViolation.code())); assert_draining(&client, &Error::PeerError(Error::ProtocolViolation.code()));
} }
@ -134,21 +134,21 @@ fn closing_timers_interation() {
// We're going to induce time-based loss recovery so that timer is set. // We're going to induce time-based loss recovery so that timer is set.
let _p1 = send_something(&mut client, now); let _p1 = send_something(&mut client, now);
let p2 = send_something(&mut client, now); let p2 = send_something(&mut client, now);
let ack = server.process(Some(&p2), now).dgram(); let ack = server.process(Some(p2), now).dgram();
assert!(ack.is_some()); // This is an ACK. assert!(ack.is_some()); // This is an ACK.
// After processing the ACK, we should be on the loss recovery timer. // After processing the ACK, we should be on the loss recovery timer.
let cb = client.process(ack.as_ref(), now).callback(); let cb = client.process(ack, now).callback();
assert_ne!(cb, Duration::from_secs(0)); assert_ne!(cb, Duration::from_secs(0));
now += cb; now += cb;
// Rather than let the timer pop, close the connection. // Rather than let the timer pop, close the connection.
client.close(now, 0, ""); client.close(now, 0, "");
let client_close = client.process(None, now).dgram(); let client_close = client.process_output(now).dgram();
assert!(client_close.is_some()); assert!(client_close.is_some());
// This should now report the end of the closing period, not a // This should now report the end of the closing period, not a
// zero-duration wait driven by the (now defunct) loss recovery timer. // zero-duration wait driven by the (now defunct) loss recovery timer.
let client_close_timer = client.process(None, now).callback(); let client_close_timer = client.process_output(now).callback();
assert_ne!(client_close_timer, Duration::from_secs(0)); assert_ne!(client_close_timer, Duration::from_secs(0));
} }
@ -164,20 +164,20 @@ fn closing_and_draining() {
// Close the connection. // Close the connection.
client.close(now(), APP_ERROR, ""); client.close(now(), APP_ERROR, "");
let client_close = client.process(None, now()).dgram(); let client_close = client.process_output(now()).dgram();
assert!(client_close.is_some()); assert!(client_close.is_some());
let client_close_timer = client.process(None, now()).callback(); let client_close_timer = client.process_output(now()).callback();
assert_ne!(client_close_timer, Duration::from_secs(0)); assert_ne!(client_close_timer, Duration::from_secs(0));
// The client will spit out the same packet in response to anything it receives. // The client will spit out the same packet in response to anything it receives.
let p3 = send_something(&mut server, now()); let p3 = send_something(&mut server, now());
let client_close2 = client.process(Some(&p3), now()).dgram(); let client_close2 = client.process(Some(p3), now()).dgram();
assert_eq!( assert_eq!(
client_close.as_ref().unwrap().len(), client_close.as_ref().unwrap().len(),
client_close2.as_ref().unwrap().len() client_close2.as_ref().unwrap().len()
); );
// After this time, the client should transition to closed. // After this time, the client should transition to closed.
let end = client.process(None, now() + client_close_timer); let end = client.process_output(now() + client_close_timer);
assert_eq!(end, Output::None); assert_eq!(end, Output::None);
assert_eq!( assert_eq!(
*client.state(), *client.state(),
@ -185,17 +185,17 @@ fn closing_and_draining() {
); );
// When the server receives the close, it too should generate CONNECTION_CLOSE. // When the server receives the close, it too should generate CONNECTION_CLOSE.
let server_close = server.process(client_close.as_ref(), now()).dgram(); let server_close = server.process(client_close, now()).dgram();
assert!(server.state().closed()); assert!(server.state().closed());
assert!(server_close.is_some()); assert!(server_close.is_some());
// .. but it ignores any further close packets. // .. but it ignores any further close packets.
let server_close_timer = server.process(client_close2.as_ref(), now()).callback(); let server_close_timer = server.process(client_close2, now()).callback();
assert_ne!(server_close_timer, Duration::from_secs(0)); assert_ne!(server_close_timer, Duration::from_secs(0));
// Even a legitimate packet without a close in it. // Even a legitimate packet without a close in it.
let server_close_timer2 = server.process(Some(&p1), now()).callback(); let server_close_timer2 = server.process(Some(p1), now()).callback();
assert_eq!(server_close_timer, server_close_timer2); assert_eq!(server_close_timer, server_close_timer2);
let end = server.process(None, now() + server_close_timer); let end = server.process_output(now() + server_close_timer);
assert_eq!(end, Output::None); assert_eq!(end, Output::None);
assert_eq!( assert_eq!(
*server.state(), *server.state(),
@ -218,6 +218,6 @@ fn stateless_reset_client() {
.unwrap(); .unwrap();
connect_force_idle(&mut client, &mut server); connect_force_idle(&mut client, &mut server);
client.process_input(&datagram(vec![77; 21]), now()); client.process_input(datagram(vec![77; 21]), now());
assert_draining(&client, &Error::StatelessReset); assert_draining(&client, &Error::StatelessReset);
} }

Просмотреть файл

@ -93,7 +93,7 @@ fn datagram_enabled_on_client() {
let out = server.process_output(now()).dgram().unwrap(); let out = server.process_output(now()).dgram().unwrap();
assert_eq!(server.stats().frame_tx.datagram, dgram_sent + 1); assert_eq!(server.stats().frame_tx.datagram, dgram_sent + 1);
client.process_input(&out, now()); client.process_input(out, now());
assert!(matches!( assert!(matches!(
client.next_event().unwrap(), client.next_event().unwrap(),
ConnectionEvent::Datagram(data) if data == DATA_SMALLER_THAN_MTU ConnectionEvent::Datagram(data) if data == DATA_SMALLER_THAN_MTU
@ -124,7 +124,7 @@ fn datagram_enabled_on_server() {
let out = client.process_output(now()).dgram().unwrap(); let out = client.process_output(now()).dgram().unwrap();
assert_eq!(client.stats().frame_tx.datagram, dgram_sent + 1); assert_eq!(client.stats().frame_tx.datagram, dgram_sent + 1);
server.process_input(&out, now()); server.process_input(out, now());
assert!(matches!( assert!(matches!(
server.next_event().unwrap(), server.next_event().unwrap(),
ConnectionEvent::Datagram(data) if data == DATA_SMALLER_THAN_MTU ConnectionEvent::Datagram(data) if data == DATA_SMALLER_THAN_MTU
@ -240,7 +240,7 @@ fn datagram_acked() {
assert_eq!(client.stats().frame_tx.datagram, dgram_sent + 1); assert_eq!(client.stats().frame_tx.datagram, dgram_sent + 1);
let dgram_received = server.stats().frame_rx.datagram; let dgram_received = server.stats().frame_rx.datagram;
server.process_input(&out.unwrap(), now()); server.process_input(out.unwrap(), now());
assert_eq!(server.stats().frame_rx.datagram, dgram_received + 1); assert_eq!(server.stats().frame_rx.datagram, dgram_received + 1);
let now = now() + AT_LEAST_PTO; let now = now() + AT_LEAST_PTO;
// Ack should be sent // Ack should be sent
@ -253,7 +253,7 @@ fn datagram_acked() {
ConnectionEvent::Datagram(data) if data == DATA_SMALLER_THAN_MTU ConnectionEvent::Datagram(data) if data == DATA_SMALLER_THAN_MTU
)); ));
client.process_input(&out.unwrap(), now); client.process_input(out.unwrap(), now);
assert!(matches!( assert!(matches!(
client.next_event().unwrap(), client.next_event().unwrap(),
ConnectionEvent::OutgoingDatagramOutcome { id, outcome } if id == 1 && outcome == OutgoingDatagramOutcome::Acked ConnectionEvent::OutgoingDatagramOutcome { id, outcome } if id == 1 && outcome == OutgoingDatagramOutcome::Acked
@ -265,7 +265,7 @@ fn send_packet_and_get_server_event(
server: &mut Connection, server: &mut Connection,
) -> ConnectionEvent { ) -> ConnectionEvent {
let out = client.process_output(now()).dgram(); let out = client.process_output(now()).dgram();
server.process_input(&out.unwrap(), now()); server.process_input(out.unwrap(), now());
let mut events: Vec<_> = server let mut events: Vec<_> = server
.events() .events()
.filter_map(|evt| match evt { .filter_map(|evt| match evt {
@ -404,7 +404,7 @@ fn dgram_no_allowed() {
.test_write_frames(InsertDatagram { data: DATA_MTU }, now()) .test_write_frames(InsertDatagram { data: DATA_MTU }, now())
.dgram() .dgram()
.unwrap(); .unwrap();
client.process_input(&out, now()); client.process_input(out, now());
assert_error(&client, &CloseReason::Transport(Error::ProtocolViolation)); assert_error(&client, &CloseReason::Transport(Error::ProtocolViolation));
} }
@ -420,7 +420,7 @@ fn dgram_too_big() {
.test_write_frames(InsertDatagram { data: DATA_MTU }, now()) .test_write_frames(InsertDatagram { data: DATA_MTU }, now())
.dgram() .dgram()
.unwrap(); .unwrap();
client.process_input(&out, now()); client.process_input(out, now());
assert_error(&client, &CloseReason::Transport(Error::ProtocolViolation)); assert_error(&client, &CloseReason::Transport(Error::ProtocolViolation));
} }
@ -455,7 +455,7 @@ fn outgoing_datagram_queue_full() {
// Send DATA_SMALLER_THAN_MTU_2 datagram // Send DATA_SMALLER_THAN_MTU_2 datagram
let out = client.process_output(now()).dgram(); let out = client.process_output(now()).dgram();
assert_eq!(client.stats().frame_tx.datagram, dgram_sent + 1); assert_eq!(client.stats().frame_tx.datagram, dgram_sent + 1);
server.process_input(&out.unwrap(), now()); server.process_input(out.unwrap(), now());
assert!(matches!( assert!(matches!(
server.next_event().unwrap(), server.next_event().unwrap(),
ConnectionEvent::Datagram(data) if data == DATA_SMALLER_THAN_MTU_2 ConnectionEvent::Datagram(data) if data == DATA_SMALLER_THAN_MTU_2
@ -465,7 +465,7 @@ fn outgoing_datagram_queue_full() {
let dgram_sent2 = client.stats().frame_tx.datagram; let dgram_sent2 = client.stats().frame_tx.datagram;
let out = client.process_output(now()).dgram(); let out = client.process_output(now()).dgram();
assert_eq!(client.stats().frame_tx.datagram, dgram_sent2 + 1); assert_eq!(client.stats().frame_tx.datagram, dgram_sent2 + 1);
server.process_input(&out.unwrap(), now()); server.process_input(out.unwrap(), now());
assert!(matches!( assert!(matches!(
server.next_event().unwrap(), server.next_event().unwrap(),
ConnectionEvent::Datagram(data) if data == DATA_MTU ConnectionEvent::Datagram(data) if data == DATA_MTU
@ -479,7 +479,7 @@ fn send_datagram(sender: &mut Connection, receiver: &mut Connection, data: Vec<u
assert_eq!(sender.stats().frame_tx.datagram, dgram_sent + 1); assert_eq!(sender.stats().frame_tx.datagram, dgram_sent + 1);
let dgram_received = receiver.stats().frame_rx.datagram; let dgram_received = receiver.stats().frame_rx.datagram;
receiver.process_input(&out, now()); receiver.process_input(out, now());
assert_eq!(receiver.stats().frame_rx.datagram, dgram_received + 1); assert_eq!(receiver.stats().frame_rx.datagram, dgram_received + 1);
} }
@ -593,7 +593,7 @@ fn multiple_quic_datagrams_in_one_packet() {
let out = client.process_output(now()).dgram(); let out = client.process_output(now()).dgram();
assert_eq!(client.stats().frame_tx.datagram, dgram_sent + 2); assert_eq!(client.stats().frame_tx.datagram, dgram_sent + 2);
server.process_input(&out.unwrap(), now()); server.process_input(out.unwrap(), now());
let datagram = |e: &_| matches!(e, ConnectionEvent::Datagram(..)); let datagram = |e: &_| matches!(e, ConnectionEvent::Datagram(..));
assert_eq!(server.events().filter(datagram).count(), 2); assert_eq!(server.events().filter(datagram).count(), 2);
} }

Просмотреть файл

@ -14,9 +14,10 @@ use test_fixture::{
use crate::{ use crate::{
connection::tests::{ connection::tests::{
connect_force_idle, connect_force_idle_with_modifier, default_client, default_server, assert_path_challenge_min_len, connect_force_idle, connect_force_idle_with_modifier,
handshake_with_modifier, migration::get_cid, new_client, new_server, send_and_receive, default_client, default_server, handshake_with_modifier, migration::get_cid, new_client,
send_something, send_something_with_modifier, send_with_modifier_and_receive, DEFAULT_RTT, new_server, send_and_receive, send_something, send_something_with_modifier,
send_with_modifier_and_receive, DEFAULT_RTT,
}, },
ecn::ECN_TEST_COUNT, ecn::ECN_TEST_COUNT,
path::MAX_PATH_PROBES, path::MAX_PATH_PROBES,
@ -120,6 +121,7 @@ fn migration_delay_to_ecn_blackhole() {
// This should be a PATH_CHALLENGE. // This should be a PATH_CHALLENGE.
probes += 1; probes += 1;
assert_eq!(client.stats().frame_tx.path_challenge, probes); assert_eq!(client.stats().frame_tx.path_challenge, probes);
assert_path_challenge_min_len(&client, &d, now);
if probes <= MAX_PATH_PROBES { if probes <= MAX_PATH_PROBES {
// The first probes should be sent with ECN. // The first probes should be sent with ECN.
assert_ecn_enabled(d.tos()); assert_ecn_enabled(d.tos());
@ -143,12 +145,12 @@ fn stats() {
for _ in 0..ECN_TEST_COUNT { for _ in 0..ECN_TEST_COUNT {
let ack = send_and_receive(&mut client, &mut server, now); let ack = send_and_receive(&mut client, &mut server, now);
client.process_input(&ack.unwrap(), now); client.process_input(ack.unwrap(), now);
} }
for _ in 0..ECN_TEST_COUNT { for _ in 0..ECN_TEST_COUNT {
let ack = send_and_receive(&mut server, &mut client, now); let ack = send_and_receive(&mut server, &mut client, now);
server.process_input(&ack.unwrap(), now); server.process_input(ack.unwrap(), now);
} }
for stats in [client.stats(), server.stats()] { for stats in [client.stats(), server.stats()] {
@ -194,7 +196,7 @@ fn disables_on_remark() {
for _ in 0..ECN_TEST_COUNT { for _ in 0..ECN_TEST_COUNT {
if let Some(ack) = send_with_modifier_and_receive(&mut client, &mut server, now, remark()) { if let Some(ack) = send_with_modifier_and_receive(&mut client, &mut server, now, remark()) {
client.process_input(&ack, now); client.process_input(ack, now);
} }
} }
@ -223,21 +225,21 @@ pub fn migration_with_modifiers(
// Right after the handshake, the ECN validation should still be in progress. // Right after the handshake, the ECN validation should still be in progress.
let client_pkt = send_something(&mut client, now); let client_pkt = send_something(&mut client, now);
assert_ecn_enabled(client_pkt.tos()); assert_ecn_enabled(client_pkt.tos());
server.process_input(&orig_path_modifier(client_pkt).unwrap(), now); server.process_input(orig_path_modifier(client_pkt).unwrap(), now);
// Send some data on the current path. // Send some data on the current path.
for _ in 0..burst { for _ in 0..burst {
let client_pkt = send_something_with_modifier(&mut client, now, orig_path_modifier); let client_pkt = send_something_with_modifier(&mut client, now, orig_path_modifier);
server.process_input(&client_pkt, now); server.process_input(client_pkt, now);
} }
if let Some(ack) = server.process_output(now).dgram() { if let Some(ack) = server.process_output(now).dgram() {
client.process_input(&ack, now); client.process_input(ack, now);
} }
let client_pkt = send_something(&mut client, now); let client_pkt = send_something(&mut client, now);
let tos_before_migration = client_pkt.tos(); let tos_before_migration = client_pkt.tos();
server.process_input(&orig_path_modifier(client_pkt).unwrap(), now); server.process_input(orig_path_modifier(client_pkt).unwrap(), now);
client client
.migrate(Some(DEFAULT_ADDR_V4), Some(DEFAULT_ADDR_V4), false, now) .migrate(Some(DEFAULT_ADDR_V4), Some(DEFAULT_ADDR_V4), false, now)
@ -247,25 +249,27 @@ pub fn migration_with_modifiers(
let probe = new_path_modifier(client.process_output(now).dgram().unwrap()); let probe = new_path_modifier(client.process_output(now).dgram().unwrap());
if let Some(probe) = probe { if let Some(probe) = probe {
assert_v4_path(&probe, true); // Contains PATH_CHALLENGE. assert_v4_path(&probe, true); // Contains PATH_CHALLENGE.
assert_path_challenge_min_len(&client, &probe, now);
assert_eq!(client.stats().frame_tx.path_challenge, 1); assert_eq!(client.stats().frame_tx.path_challenge, 1);
let probe_cid = ConnectionId::from(get_cid(&probe)); let probe_cid = ConnectionId::from(get_cid(&probe));
let resp = new_path_modifier(server.process(Some(&probe), now).dgram().unwrap()).unwrap(); let resp = new_path_modifier(server.process(Some(probe), now).dgram().unwrap()).unwrap();
assert_v4_path(&resp, true); assert_v4_path(&resp, true);
assert_eq!(server.stats().frame_tx.path_response, 1); assert_eq!(server.stats().frame_tx.path_response, 1);
assert_eq!(server.stats().frame_tx.path_challenge, 1); assert_eq!(server.stats().frame_tx.path_challenge, 1);
assert_path_challenge_min_len(&server, &resp, now);
// Data continues to be exchanged on the old path. // Data continues to be exchanged on the old path.
let client_data = send_something_with_modifier(&mut client, now, orig_path_modifier); let client_data = send_something_with_modifier(&mut client, now, orig_path_modifier);
assert_ne!(get_cid(&client_data), probe_cid); assert_ne!(get_cid(&client_data), probe_cid);
assert_v6_path(&client_data, false); assert_v6_path(&client_data, false);
server.process_input(&client_data, now); server.process_input(client_data, now);
let server_data = send_something_with_modifier(&mut server, now, orig_path_modifier); let server_data = send_something_with_modifier(&mut server, now, orig_path_modifier);
assert_v6_path(&server_data, false); assert_v6_path(&server_data, false);
client.process_input(&server_data, now); client.process_input(server_data, now);
// Once the client receives the probe response, it migrates to the new path. // Once the client receives the probe response, it migrates to the new path.
client.process_input(&resp, now); client.process_input(resp, now);
assert_eq!(client.stats().frame_rx.path_challenge, 1); assert_eq!(client.stats().frame_rx.path_challenge, 1);
migrated = true; migrated = true;
@ -276,7 +280,7 @@ pub fn migration_with_modifiers(
// However, it will probe the old path again, even though it has just // However, it will probe the old path again, even though it has just
// received a response to its last probe, because it needs to verify // received a response to its last probe, because it needs to verify
// that the migration is genuine. // that the migration is genuine.
server.process_input(&migrate_client, now); server.process_input(migrate_client, now);
} }
let stream_before = server.stats().frame_tx.stream; let stream_before = server.stats().frame_tx.stream;
@ -287,6 +291,10 @@ pub fn migration_with_modifiers(
server.stats().frame_tx.path_challenge, server.stats().frame_tx.path_challenge,
if migrated { 2 } else { 0 } if migrated { 2 } else { 0 }
); );
if migrated {
assert_path_challenge_min_len(&server, &probe_old_server, now);
}
assert_eq!( assert_eq!(
server.stats().frame_tx.stream, server.stats().frame_tx.stream,
if migrated { stream_before } else { 1 } if migrated { stream_before } else { 1 }
@ -301,8 +309,8 @@ pub fn migration_with_modifiers(
assert_eq!(server.stats().frame_tx.stream, stream_before + 1); assert_eq!(server.stats().frame_tx.stream, stream_before + 1);
// The client receives these checks and responds to the probe, but uses the new path. // The client receives these checks and responds to the probe, but uses the new path.
client.process_input(&migrate_server, now); client.process_input(migrate_server, now);
client.process_input(&probe_old_server, now); client.process_input(probe_old_server, now);
let old_probe_resp = send_something_with_modifier(&mut client, now, new_path_modifier); let old_probe_resp = send_something_with_modifier(&mut client, now, new_path_modifier);
assert_v6_path(&old_probe_resp, true); assert_v6_path(&old_probe_resp, true);
let client_confirmation = client.process_output(now).dgram().unwrap(); let client_confirmation = client.process_output(now).dgram().unwrap();
@ -315,17 +323,17 @@ pub fn migration_with_modifiers(
let server_confirmation = let server_confirmation =
send_something_with_modifier(&mut server, now + server_pacing, new_path_modifier); send_something_with_modifier(&mut server, now + server_pacing, new_path_modifier);
assert_v4_path(&server_confirmation, false); assert_v4_path(&server_confirmation, false);
client.process_input(&server_confirmation, now); client.process_input(server_confirmation, now);
// Send some data on the new path. // Send some data on the new path.
for _ in 0..burst { for _ in 0..burst {
now += client.process_output(now).callback(); now += client.process_output(now).callback();
let client_pkt = send_something_with_modifier(&mut client, now, new_path_modifier); let client_pkt = send_something_with_modifier(&mut client, now, new_path_modifier);
server.process_input(&client_pkt, now); server.process_input(client_pkt, now);
} }
if let Some(ack) = server.process_output(now).dgram() { if let Some(ack) = server.process_output(now).dgram() {
client.process_input(&ack, now); client.process_input(ack, now);
} }
} }

Просмотреть файл

@ -48,37 +48,37 @@ const ECH_PUBLIC_NAME: &str = "public.example";
fn full_handshake(pmtud: bool) { fn full_handshake(pmtud: bool) {
qdebug!("---- client: generate CH"); qdebug!("---- client: generate CH");
let mut client = new_client(ConnectionParameters::default().pmtud(pmtud)); let mut client = new_client(ConnectionParameters::default().pmtud(pmtud));
let out = client.process(None, now()); let out = client.process_output(now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
assert_eq!(out.as_dgram_ref().unwrap().len(), client.plpmtu()); assert_eq!(out.as_dgram_ref().unwrap().len(), client.plpmtu());
qdebug!("---- server: CH -> SH, EE, CERT, CV, FIN"); qdebug!("---- server: CH -> SH, EE, CERT, CV, FIN");
let mut server = new_server(ConnectionParameters::default().pmtud(pmtud)); let mut server = new_server(ConnectionParameters::default().pmtud(pmtud));
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
assert_eq!(out.as_dgram_ref().unwrap().len(), server.plpmtu()); assert_eq!(out.as_dgram_ref().unwrap().len(), server.plpmtu());
qdebug!("---- client: cert verification"); qdebug!("---- client: cert verification");
let out = client.process(out.as_dgram_ref(), now()); let out = client.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_none()); assert!(out.as_dgram_ref().is_none());
assert!(maybe_authenticate(&mut client)); assert!(maybe_authenticate(&mut client));
qdebug!("---- client: SH..FIN -> FIN"); qdebug!("---- client: SH..FIN -> FIN");
let out = client.process(out.as_dgram_ref(), now()); let out = client.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
assert_eq!(*client.state(), State::Connected); assert_eq!(*client.state(), State::Connected);
qdebug!("---- server: FIN -> ACKS"); qdebug!("---- server: FIN -> ACKS");
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
assert_eq!(*server.state(), State::Confirmed); assert_eq!(*server.state(), State::Confirmed);
qdebug!("---- client: ACKS -> 0"); qdebug!("---- client: ACKS -> 0");
let out = client.process(out.as_dgram_ref(), now()); let out = client.process(out.dgram(), now());
if pmtud { if pmtud {
// PMTUD causes a PING probe to be sent here // PMTUD causes a PING probe to be sent here
let pkt = out.dgram().unwrap(); let pkt = out.dgram().unwrap();
@ -103,19 +103,19 @@ fn handshake_pmtud() {
fn handshake_failed_authentication() { fn handshake_failed_authentication() {
qdebug!("---- client: generate CH"); qdebug!("---- client: generate CH");
let mut client = default_client(); let mut client = default_client();
let out = client.process(None, now()); let out = client.process_output(now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
qdebug!("---- server: CH -> SH, EE, CERT, CV, FIN"); qdebug!("---- server: CH -> SH, EE, CERT, CV, FIN");
let mut server = default_server(); let mut server = default_server();
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
qdebug!("---- client: cert verification"); qdebug!("---- client: cert verification");
let out = client.process(out.as_dgram_ref(), now()); let out = client.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_none()); assert!(out.as_dgram_ref().is_none());
let authentication_needed = |e| matches!(e, ConnectionEvent::AuthenticationNeeded); let authentication_needed = |e| matches!(e, ConnectionEvent::AuthenticationNeeded);
@ -124,11 +124,11 @@ fn handshake_failed_authentication() {
client.authenticated(AuthenticationStatus::CertRevoked, now()); client.authenticated(AuthenticationStatus::CertRevoked, now());
qdebug!("---- client: -> Alert(certificate_revoked)"); qdebug!("---- client: -> Alert(certificate_revoked)");
let out = client.process(None, now()); let out = client.process_output(now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
qdebug!("---- server: Alert(certificate_revoked)"); qdebug!("---- server: Alert(certificate_revoked)");
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
assert_error(&client, &CloseReason::Transport(Error::CryptoAlert(44))); assert_error(&client, &CloseReason::Transport(Error::CryptoAlert(44)));
assert_error(&server, &CloseReason::Transport(Error::PeerError(300))); assert_error(&server, &CloseReason::Transport(Error::PeerError(300)));
@ -160,29 +160,29 @@ fn no_alpn() {
fn dup_server_flight1() { fn dup_server_flight1() {
qdebug!("---- client: generate CH"); qdebug!("---- client: generate CH");
let mut client = default_client(); let mut client = default_client();
let out = client.process(None, now()); let out = client.process_output(now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
assert_eq!(out.as_dgram_ref().unwrap().len(), client.plpmtu()); assert_eq!(out.as_dgram_ref().unwrap().len(), client.plpmtu());
qdebug!("Output={:0x?}", out.as_dgram_ref()); qdebug!("Output={:0x?}", out.as_dgram_ref());
qdebug!("---- server: CH -> SH, EE, CERT, CV, FIN"); qdebug!("---- server: CH -> SH, EE, CERT, CV, FIN");
let mut server = default_server(); let mut server = default_server();
let out_to_rep = server.process(out.as_dgram_ref(), now()); let out_to_rep = server.process(out.dgram(), now());
assert!(out_to_rep.as_dgram_ref().is_some()); assert!(out_to_rep.as_dgram_ref().is_some());
qdebug!("Output={:0x?}", out_to_rep.as_dgram_ref()); qdebug!("Output={:0x?}", out_to_rep.as_dgram_ref());
qdebug!("---- client: cert verification"); qdebug!("---- client: cert verification");
let out = client.process(Some(out_to_rep.as_dgram_ref().unwrap()), now()); let out = client.process(Some(out_to_rep.as_dgram_ref().cloned().unwrap()), now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
qdebug!("Output={:0x?}", out.as_dgram_ref()); qdebug!("Output={:0x?}", out.as_dgram_ref());
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_none()); assert!(out.as_dgram_ref().is_none());
assert!(maybe_authenticate(&mut client)); assert!(maybe_authenticate(&mut client));
qdebug!("---- client: SH..FIN -> FIN"); qdebug!("---- client: SH..FIN -> FIN");
let out = client.process(None, now()); let out = client.process_output(now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
qdebug!("Output={:0x?}", out.as_dgram_ref()); qdebug!("Output={:0x?}", out.as_dgram_ref());
@ -191,7 +191,7 @@ fn dup_server_flight1() {
assert_eq!(1, client.stats().dropped_rx); assert_eq!(1, client.stats().dropped_rx);
qdebug!("---- Dup, ignored"); qdebug!("---- Dup, ignored");
let out = client.process(out_to_rep.as_dgram_ref(), now()); let out = client.process(out_to_rep.dgram(), now());
assert!(out.as_dgram_ref().is_none()); assert!(out.as_dgram_ref().is_none());
qdebug!("Output={:0x?}", out.as_dgram_ref()); qdebug!("Output={:0x?}", out.as_dgram_ref());
@ -216,17 +216,17 @@ fn crypto_frame_split() {
) )
.expect("create a server"); .expect("create a server");
let client1 = client.process(None, now()); let client1 = client.process_output(now());
assert!(client1.as_dgram_ref().is_some()); assert!(client1.as_dgram_ref().is_some());
// The entire server flight doesn't fit in a single packet because the // The entire server flight doesn't fit in a single packet because the
// certificate is large, therefore the server will produce 2 packets. // certificate is large, therefore the server will produce 2 packets.
let server1 = server.process(client1.as_dgram_ref(), now()); let server1 = server.process(client1.dgram(), now());
assert!(server1.as_dgram_ref().is_some()); assert!(server1.as_dgram_ref().is_some());
let server2 = server.process(None, now()); let server2 = server.process_output(now());
assert!(server2.as_dgram_ref().is_some()); assert!(server2.as_dgram_ref().is_some());
let client2 = client.process(server1.as_dgram_ref(), now()); let client2 = client.process(server1.dgram(), now());
// This is an ack. // This is an ack.
assert!(client2.as_dgram_ref().is_some()); assert!(client2.as_dgram_ref().is_some());
// The client might have the certificate now, so we can't guarantee that // The client might have the certificate now, so we can't guarantee that
@ -235,11 +235,11 @@ fn crypto_frame_split() {
assert_eq!(*client.state(), State::Handshaking); assert_eq!(*client.state(), State::Handshaking);
// let server process the ack for the first packet. // let server process the ack for the first packet.
let server3 = server.process(client2.as_dgram_ref(), now()); let server3 = server.process(client2.dgram(), now());
assert!(server3.as_dgram_ref().is_none()); assert!(server3.as_dgram_ref().is_none());
// Consume the second packet from the server. // Consume the second packet from the server.
let client3 = client.process(server2.as_dgram_ref(), now()); let client3 = client.process(server2.dgram(), now());
// Check authentication. // Check authentication.
let auth2 = maybe_authenticate(&mut client); let auth2 = maybe_authenticate(&mut client);
@ -247,13 +247,13 @@ fn crypto_frame_split() {
// Now client has all data to finish handshake. // Now client has all data to finish handshake.
assert_eq!(*client.state(), State::Connected); assert_eq!(*client.state(), State::Connected);
let client4 = client.process(server3.as_dgram_ref(), now()); let client4 = client.process(server3.dgram(), now());
// One of these will contain data depending on whether Authentication was completed // One of these will contain data depending on whether Authentication was completed
// after the first or second server packet. // after the first or second server packet.
assert!(client3.as_dgram_ref().is_some() ^ client4.as_dgram_ref().is_some()); assert!(client3.as_dgram_ref().is_some() ^ client4.as_dgram_ref().is_some());
mem::drop(server.process(client3.as_dgram_ref(), now())); mem::drop(server.process(client3.dgram(), now()));
mem::drop(server.process(client4.as_dgram_ref(), now())); mem::drop(server.process(client4.dgram(), now()));
assert_eq!(*client.state(), State::Connected); assert_eq!(*client.state(), State::Connected);
assert_eq!(*server.state(), State::Confirmed); assert_eq!(*server.state(), State::Confirmed);
@ -283,21 +283,21 @@ fn send_05rtt() {
let mut client = default_client(); let mut client = default_client();
let mut server = default_server(); let mut server = default_server();
let c1 = client.process(None, now()).dgram(); let c1 = client.process_output(now()).dgram();
assert!(c1.is_some()); assert!(c1.is_some());
let s1 = server.process(c1.as_ref(), now()).dgram().unwrap(); let s1 = server.process(c1, now()).dgram().unwrap();
assert_eq!(s1.len(), server.plpmtu()); assert_eq!(s1.len(), server.plpmtu());
// The server should accept writes at this point. // The server should accept writes at this point.
let s2 = send_something(&mut server, now()); let s2 = send_something(&mut server, now());
// Complete the handshake at the client. // Complete the handshake at the client.
client.process_input(&s1, now()); client.process_input(s1, now());
maybe_authenticate(&mut client); maybe_authenticate(&mut client);
assert_eq!(*client.state(), State::Connected); assert_eq!(*client.state(), State::Connected);
// The client should receive the 0.5-RTT data now. // The client should receive the 0.5-RTT data now.
client.process_input(&s2, now()); client.process_input(s2, now());
let mut buf = vec![0; DEFAULT_STREAM_DATA.len() + 1]; let mut buf = vec![0; DEFAULT_STREAM_DATA.len() + 1];
let stream_id = client let stream_id = client
.events() .events()
@ -320,21 +320,21 @@ fn reorder_05rtt() {
let mut client = default_client(); let mut client = default_client();
let mut server = default_server(); let mut server = default_server();
let c1 = client.process(None, now()).dgram(); let c1 = client.process_output(now()).dgram();
assert!(c1.is_some()); assert!(c1.is_some());
let s1 = server.process(c1.as_ref(), now()).dgram().unwrap(); let s1 = server.process(c1, now()).dgram().unwrap();
// The server should accept writes at this point. // The server should accept writes at this point.
let s2 = send_something(&mut server, now()); let s2 = send_something(&mut server, now());
// We can't use the standard facility to complete the handshake, so // We can't use the standard facility to complete the handshake, so
// drive it as aggressively as possible. // drive it as aggressively as possible.
client.process_input(&s2, now()); client.process_input(s2, now());
assert_eq!(client.stats().saved_datagrams, 1); assert_eq!(client.stats().saved_datagrams, 1);
// After processing the first packet, the client should go back and // After processing the first packet, the client should go back and
// process the 0.5-RTT packet data, which should make data available. // process the 0.5-RTT packet data, which should make data available.
client.process_input(&s1, now()); client.process_input(s1, now());
// We can't use `maybe_authenticate` here as that consumes events. // We can't use `maybe_authenticate` here as that consumes events.
client.authenticated(AuthenticationStatus::Ok, now()); client.authenticated(AuthenticationStatus::Ok, now());
assert_eq!(*client.state(), State::Connected); assert_eq!(*client.state(), State::Connected);
@ -372,7 +372,7 @@ fn reorder_05rtt_with_0rtt() {
server.send_ticket(now, &[]).unwrap(); server.send_ticket(now, &[]).unwrap();
let ticket = server.process_output(now).dgram().unwrap(); let ticket = server.process_output(now).dgram().unwrap();
now += RTT / 2; now += RTT / 2;
client.process_input(&ticket, now); client.process_input(ticket, now);
let token = get_tokens(&mut client).pop().unwrap(); let token = get_tokens(&mut client).pop().unwrap();
let mut client = default_client(); let mut client = default_client();
@ -389,35 +389,35 @@ fn reorder_05rtt_with_0rtt() {
// Handle the first packet and send 0.5-RTT in response. Drop the response. // Handle the first packet and send 0.5-RTT in response. Drop the response.
now += RTT / 2; now += RTT / 2;
mem::drop(server.process(Some(&c1), now).dgram().unwrap()); mem::drop(server.process(Some(c1), now).dgram().unwrap());
// The gap in 0-RTT will result in this 0.5 RTT containing an ACK. // The gap in 0-RTT will result in this 0.5 RTT containing an ACK.
server.process_input(&c2, now); server.process_input(c2, now);
let s2 = send_something(&mut server, now); let s2 = send_something(&mut server, now);
// Save the 0.5 RTT. // Save the 0.5 RTT.
now += RTT / 2; now += RTT / 2;
client.process_input(&s2, now); client.process_input(s2, now);
assert_eq!(client.stats().saved_datagrams, 1); assert_eq!(client.stats().saved_datagrams, 1);
// Now PTO at the client and cause the server to re-send handshake packets. // Now PTO at the client and cause the server to re-send handshake packets.
now += AT_LEAST_PTO; now += AT_LEAST_PTO;
let c3 = client.process(None, now).dgram(); let c3 = client.process_output(now).dgram();
assert_coalesced_0rtt(c3.as_ref().unwrap()); assert_coalesced_0rtt(c3.as_ref().unwrap());
now += RTT / 2; now += RTT / 2;
let s3 = server.process(c3.as_ref(), now).dgram().unwrap(); let s3 = server.process(c3, now).dgram().unwrap();
// The client should be able to process the 0.5 RTT now. // The client should be able to process the 0.5 RTT now.
// This should contain an ACK, so we are processing an ACK from the past. // This should contain an ACK, so we are processing an ACK from the past.
now += RTT / 2; now += RTT / 2;
client.process_input(&s3, now); client.process_input(s3, now);
maybe_authenticate(&mut client); maybe_authenticate(&mut client);
let c4 = client.process(None, now).dgram(); let c4 = client.process_output(now).dgram();
assert_eq!(*client.state(), State::Connected); assert_eq!(*client.state(), State::Connected);
assert_eq!(client.paths.rtt(), RTT); assert_eq!(client.paths.rtt(), RTT);
now += RTT / 2; now += RTT / 2;
server.process_input(&c4.unwrap(), now); server.process_input(c4.unwrap(), now);
assert_eq!(*server.state(), State::Confirmed); assert_eq!(*server.state(), State::Confirmed);
// Don't check server RTT as it will be massively inflated by a // Don't check server RTT as it will be massively inflated by a
// poor initial estimate received when the server dropped the // poor initial estimate received when the server dropped the
@ -435,10 +435,10 @@ fn coalesce_05rtt() {
// The first exchange doesn't offer a chance for the server to send. // The first exchange doesn't offer a chance for the server to send.
// So drop the server flight and wait for the PTO. // So drop the server flight and wait for the PTO.
let c1 = client.process(None, now).dgram(); let c1 = client.process_output(now).dgram();
assert!(c1.is_some()); assert!(c1.is_some());
now += RTT / 2; now += RTT / 2;
let s1 = server.process(c1.as_ref(), now).dgram(); let s1 = server.process(c1, now).dgram();
assert!(s1.is_some()); assert!(s1.is_some());
// Drop the server flight. Then send some data. // Drop the server flight. Then send some data.
@ -450,10 +450,10 @@ fn coalesce_05rtt() {
// The server should then send its entire flight again, // The server should then send its entire flight again,
// including the application data, which it sends in a 1-RTT packet. // including the application data, which it sends in a 1-RTT packet.
now += AT_LEAST_PTO; now += AT_LEAST_PTO;
let c2 = client.process(None, now).dgram(); let c2 = client.process_output(now).dgram();
assert!(c2.is_some()); assert!(c2.is_some());
now += RTT / 2; now += RTT / 2;
let s2 = server.process(c2.as_ref(), now).dgram(); let s2 = server.process(c2, now).dgram();
// Even though there is a 1-RTT packet at the end of the datagram, the // Even though there is a 1-RTT packet at the end of the datagram, the
// flight should be padded to full size. // flight should be padded to full size.
assert_eq!(s2.as_ref().unwrap().len(), server.plpmtu()); assert_eq!(s2.as_ref().unwrap().len(), server.plpmtu());
@ -462,7 +462,7 @@ fn coalesce_05rtt() {
// packet until authentication completes though. So it saves it. // packet until authentication completes though. So it saves it.
now += RTT / 2; now += RTT / 2;
assert_eq!(client.stats().dropped_rx, 0); assert_eq!(client.stats().dropped_rx, 0);
mem::drop(client.process(s2.as_ref(), now).dgram()); mem::drop(client.process(s2, now).dgram());
// This packet will contain an ACK, but we can ignore it. // This packet will contain an ACK, but we can ignore it.
assert_eq!(client.stats().dropped_rx, 0); assert_eq!(client.stats().dropped_rx, 0);
assert_eq!(client.stats().packets_rx, 3); assert_eq!(client.stats().packets_rx, 3);
@ -470,7 +470,7 @@ fn coalesce_05rtt() {
// After (successful) authentication, the packet is processed. // After (successful) authentication, the packet is processed.
maybe_authenticate(&mut client); maybe_authenticate(&mut client);
let c3 = client.process(None, now).dgram(); let c3 = client.process_output(now).dgram();
assert!(c3.is_some()); assert!(c3.is_some());
assert_eq!(client.stats().dropped_rx, 0); // No Initial padding. assert_eq!(client.stats().dropped_rx, 0); // No Initial padding.
assert_eq!(client.stats().packets_rx, 4); assert_eq!(client.stats().packets_rx, 4);
@ -479,11 +479,11 @@ fn coalesce_05rtt() {
// Allow the handshake to complete. // Allow the handshake to complete.
now += RTT / 2; now += RTT / 2;
let s3 = server.process(c3.as_ref(), now).dgram(); let s3 = server.process(c3, now).dgram();
assert!(s3.is_some()); assert!(s3.is_some());
assert_eq!(*server.state(), State::Confirmed); assert_eq!(*server.state(), State::Confirmed);
now += RTT / 2; now += RTT / 2;
mem::drop(client.process(s3.as_ref(), now).dgram()); mem::drop(client.process(s3, now).dgram());
assert_eq!(*client.state(), State::Confirmed); assert_eq!(*client.state(), State::Confirmed);
assert_eq!(client.stats().dropped_rx, 0); // No dropped packets. assert_eq!(client.stats().dropped_rx, 0); // No dropped packets.
@ -496,11 +496,11 @@ fn reorder_handshake() {
let mut server = default_server(); let mut server = default_server();
let mut now = now(); let mut now = now();
let c1 = client.process(None, now).dgram(); let c1 = client.process_output(now).dgram();
assert!(c1.is_some()); assert!(c1.is_some());
now += RTT / 2; now += RTT / 2;
let s1 = server.process(c1.as_ref(), now).dgram(); let s1 = server.process(c1, now).dgram();
assert!(s1.is_some()); assert!(s1.is_some());
// Drop the Initial packet from this. // Drop the Initial packet from this.
@ -510,7 +510,7 @@ fn reorder_handshake() {
// Pass just the handshake packet in and the client can't handle it yet. // Pass just the handshake packet in and the client can't handle it yet.
// It can only send another Initial packet. // It can only send another Initial packet.
now += RTT / 2; now += RTT / 2;
let dgram = client.process(s_hs.as_ref(), now).dgram(); let dgram = client.process(s_hs, now).dgram();
assertions::assert_initial(dgram.as_ref().unwrap(), false); assertions::assert_initial(dgram.as_ref().unwrap(), false);
assert_eq!(client.stats().saved_datagrams, 1); assert_eq!(client.stats().saved_datagrams, 1);
assert_eq!(client.stats().packets_rx, 1); assert_eq!(client.stats().packets_rx, 1);
@ -519,9 +519,9 @@ fn reorder_handshake() {
// Though we currently allow the server to arm its PTO timer, use // Though we currently allow the server to arm its PTO timer, use
// a second client Initial packet to cause it to send again. // a second client Initial packet to cause it to send again.
now += AT_LEAST_PTO; now += AT_LEAST_PTO;
let c2 = client.process(None, now).dgram(); let c2 = client.process_output(now).dgram();
now += RTT / 2; now += RTT / 2;
let s2 = server.process(c2.as_ref(), now).dgram(); let s2 = server.process(c2, now).dgram();
assert!(s2.is_some()); assert!(s2.is_some());
let (s_init, s_hs) = split_datagram(&s2.unwrap()); let (s_init, s_hs) = split_datagram(&s2.unwrap());
@ -529,28 +529,28 @@ fn reorder_handshake() {
// Processing the Handshake packet first should save it. // Processing the Handshake packet first should save it.
now += RTT / 2; now += RTT / 2;
client.process_input(&s_hs.unwrap(), now); client.process_input(s_hs.unwrap(), now);
assert_eq!(client.stats().saved_datagrams, 2); assert_eq!(client.stats().saved_datagrams, 2);
assert_eq!(client.stats().packets_rx, 2); assert_eq!(client.stats().packets_rx, 2);
client.process_input(&s_init, now); client.process_input(s_init, now);
// Each saved packet should now be "received" again. // Each saved packet should now be "received" again.
assert_eq!(client.stats().packets_rx, 7); assert_eq!(client.stats().packets_rx, 7);
maybe_authenticate(&mut client); maybe_authenticate(&mut client);
let c3 = client.process(None, now).dgram(); let c3 = client.process_output(now).dgram();
assert!(c3.is_some()); assert!(c3.is_some());
// Note that though packets were saved and processed very late, // Note that though packets were saved and processed very late,
// they don't cause the RTT to change. // they don't cause the RTT to change.
now += RTT / 2; now += RTT / 2;
let s3 = server.process(c3.as_ref(), now).dgram(); let s3 = server.process(c3, now).dgram();
assert_eq!(*server.state(), State::Confirmed); assert_eq!(*server.state(), State::Confirmed);
// Don't check server RTT estimate as it will be inflated due to // Don't check server RTT estimate as it will be inflated due to
// it making a guess based on retransmissions when it dropped // it making a guess based on retransmissions when it dropped
// the Initial packet number space. // the Initial packet number space.
now += RTT / 2; now += RTT / 2;
client.process_input(&s3.unwrap(), now); client.process_input(s3.unwrap(), now);
assert_eq!(*client.state(), State::Confirmed); assert_eq!(*client.state(), State::Confirmed);
assert_eq!(client.paths.rtt(), RTT); assert_eq!(client.paths.rtt(), RTT);
} }
@ -563,24 +563,24 @@ fn reorder_1rtt() {
let mut server = default_server(); let mut server = default_server();
let mut now = now(); let mut now = now();
let c1 = client.process(None, now).dgram(); let c1 = client.process_output(now).dgram();
assert!(c1.is_some()); assert!(c1.is_some());
now += RTT / 2; now += RTT / 2;
let s1 = server.process(c1.as_ref(), now).dgram(); let s1 = server.process(c1, now).dgram();
assert!(s1.is_some()); assert!(s1.is_some());
now += RTT / 2; now += RTT / 2;
client.process_input(&s1.unwrap(), now); client.process_input(s1.unwrap(), now);
maybe_authenticate(&mut client); maybe_authenticate(&mut client);
let c2 = client.process(None, now).dgram(); let c2 = client.process_output(now).dgram();
assert!(c2.is_some()); assert!(c2.is_some());
// Now get a bunch of packets from the client. // Now get a bunch of packets from the client.
// Give them to the server before giving it `c2`. // Give them to the server before giving it `c2`.
for _ in 0..PACKETS { for _ in 0..PACKETS {
let d = send_something(&mut client, now); let d = send_something(&mut client, now);
server.process_input(&d, now + RTT / 2); server.process_input(d, now + RTT / 2);
} }
// The server has now received those packets, and saved them. // The server has now received those packets, and saved them.
// The two extra received are Initial + the junk we use for padding. // The two extra received are Initial + the junk we use for padding.
@ -589,7 +589,7 @@ fn reorder_1rtt() {
assert_eq!(server.stats().dropped_rx, 1); assert_eq!(server.stats().dropped_rx, 1);
now += RTT / 2; now += RTT / 2;
let s2 = server.process(c2.as_ref(), now).dgram(); let s2 = server.process(c2, now).dgram();
// The server has now received those packets, and saved them. // The server has now received those packets, and saved them.
// The two additional are a Handshake and a 1-RTT (w/ NEW_CONNECTION_ID). // The two additional are a Handshake and a 1-RTT (w/ NEW_CONNECTION_ID).
assert_eq!(server.stats().packets_rx, PACKETS * 2 + 4); assert_eq!(server.stats().packets_rx, PACKETS * 2 + 4);
@ -599,7 +599,7 @@ fn reorder_1rtt() {
assert_eq!(server.paths.rtt(), RTT); assert_eq!(server.paths.rtt(), RTT);
now += RTT / 2; now += RTT / 2;
client.process_input(&s2.unwrap(), now); client.process_input(s2.unwrap(), now);
assert_eq!(client.paths.rtt(), RTT); assert_eq!(client.paths.rtt(), RTT);
// All the stream data that was sent should now be available. // All the stream data that was sent should now be available.
@ -627,7 +627,7 @@ fn reorder_1rtt() {
fn corrupted_initial() { fn corrupted_initial() {
let mut client = default_client(); let mut client = default_client();
let mut server = default_server(); let mut server = default_server();
let d = client.process(None, now()).dgram().unwrap(); let d = client.process_output(now()).dgram().unwrap();
let mut corrupted = Vec::from(&d[..]); let mut corrupted = Vec::from(&d[..]);
// Find the last non-zero value and corrupt that. // Find the last non-zero value and corrupt that.
let (idx, _) = corrupted let (idx, _) = corrupted
@ -638,7 +638,7 @@ fn corrupted_initial() {
.unwrap(); .unwrap();
corrupted[idx] ^= 0x76; corrupted[idx] ^= 0x76;
let dgram = Datagram::new(d.source(), d.destination(), d.tos(), corrupted); let dgram = Datagram::new(d.source(), d.destination(), d.tos(), corrupted);
server.process_input(&dgram, now()); server.process_input(dgram, now());
// The server should have received two packets, // The server should have received two packets,
// the first should be dropped, the second saved. // the first should be dropped, the second saved.
assert_eq!(server.stats().packets_rx, 2); assert_eq!(server.stats().packets_rx, 2);
@ -655,14 +655,14 @@ fn verify_pkt_honors_mtu() {
let now = now(); let now = now();
let res = client.process(None, now); let res = client.process_output(now);
let idle_timeout = ConnectionParameters::default().get_idle_timeout(); let idle_timeout = ConnectionParameters::default().get_idle_timeout();
assert_eq!(res, Output::Callback(idle_timeout)); assert_eq!(res, Output::Callback(idle_timeout));
// Try to send a large stream and verify first packet is correctly sized // Try to send a large stream and verify first packet is correctly sized
let stream_id = client.stream_create(StreamType::UniDi).unwrap(); let stream_id = client.stream_create(StreamType::UniDi).unwrap();
assert_eq!(client.stream_send(stream_id, &[0xbb; 2000]).unwrap(), 2000); assert_eq!(client.stream_send(stream_id, &[0xbb; 2000]).unwrap(), 2000);
let pkt0 = client.process(None, now); let pkt0 = client.process_output(now);
assert!(matches!(pkt0, Output::Datagram(_))); assert!(matches!(pkt0, Output::Datagram(_)));
assert_eq!(pkt0.as_dgram_ref().unwrap().len(), client.plpmtu()); assert_eq!(pkt0.as_dgram_ref().unwrap().len(), client.plpmtu());
} }
@ -673,10 +673,10 @@ fn extra_initial_hs() {
let mut server = default_server(); let mut server = default_server();
let mut now = now(); let mut now = now();
let c_init = client.process(None, now).dgram(); let c_init = client.process_output(now).dgram();
assert!(c_init.is_some()); assert!(c_init.is_some());
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
let s_init = server.process(c_init.as_ref(), now).dgram(); let s_init = server.process(c_init, now).dgram();
assert!(s_init.is_some()); assert!(s_init.is_some());
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
@ -688,28 +688,28 @@ fn extra_initial_hs() {
// Do that EXTRA_INITIALS times and each time the client will emit // Do that EXTRA_INITIALS times and each time the client will emit
// another Initial packet. // another Initial packet.
for _ in 0..=super::super::EXTRA_INITIALS { for _ in 0..=super::super::EXTRA_INITIALS {
let c_init = client.process(undecryptable.as_ref(), now).dgram(); let c_init = client.process(undecryptable.clone(), now).dgram();
assertions::assert_initial(c_init.as_ref().unwrap(), false); assertions::assert_initial(c_init.as_ref().unwrap(), false);
now += DEFAULT_RTT / 10; now += DEFAULT_RTT / 10;
} }
// After EXTRA_INITIALS, the client stops sending Initial packets. // After EXTRA_INITIALS, the client stops sending Initial packets.
let nothing = client.process(undecryptable.as_ref(), now).dgram(); let nothing = client.process(undecryptable, now).dgram();
assert!(nothing.is_none()); assert!(nothing.is_none());
// Until PTO, where another Initial can be used to complete the handshake. // Until PTO, where another Initial can be used to complete the handshake.
now += AT_LEAST_PTO; now += AT_LEAST_PTO;
let c_init = client.process(None, now).dgram(); let c_init = client.process_output(now).dgram();
assertions::assert_initial(c_init.as_ref().unwrap(), false); assertions::assert_initial(c_init.as_ref().unwrap(), false);
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
let s_init = server.process(c_init.as_ref(), now).dgram(); let s_init = server.process(c_init, now).dgram();
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
client.process_input(&s_init.unwrap(), now); client.process_input(s_init.unwrap(), now);
maybe_authenticate(&mut client); maybe_authenticate(&mut client);
let c_fin = client.process_output(now).dgram(); let c_fin = client.process_output(now).dgram();
assert_eq!(*client.state(), State::Connected); assert_eq!(*client.state(), State::Connected);
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
server.process_input(&c_fin.unwrap(), now); server.process_input(c_fin.unwrap(), now);
assert_eq!(*server.state(), State::Confirmed); assert_eq!(*server.state(), State::Confirmed);
} }
@ -719,10 +719,10 @@ fn extra_initial_invalid_cid() {
let mut server = default_server(); let mut server = default_server();
let mut now = now(); let mut now = now();
let c_init = client.process(None, now).dgram(); let c_init = client.process_output(now).dgram();
assert!(c_init.is_some()); assert!(c_init.is_some());
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
let s_init = server.process(c_init.as_ref(), now).dgram(); let s_init = server.process(c_init, now).dgram();
assert!(s_init.is_some()); assert!(s_init.is_some());
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
@ -734,7 +734,7 @@ fn extra_initial_invalid_cid() {
assert_ne!(copy[5], 0); // The DCID should be non-zero length. assert_ne!(copy[5], 0); // The DCID should be non-zero length.
copy[6] ^= 0xc4; copy[6] ^= 0xc4;
let dgram_copy = Datagram::new(hs.destination(), hs.source(), hs.tos(), copy); let dgram_copy = Datagram::new(hs.destination(), hs.source(), hs.tos(), copy);
let nothing = client.process(Some(&dgram_copy), now).dgram(); let nothing = client.process(Some(dgram_copy), now).dgram();
assert!(nothing.is_none()); assert!(nothing.is_none());
} }
@ -783,7 +783,7 @@ fn anti_amplification() {
let c_init = client.process_output(now).dgram(); let c_init = client.process_output(now).dgram();
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
let s_init1 = server.process(c_init.as_ref(), now).dgram().unwrap(); let s_init1 = server.process(c_init, now).dgram().unwrap();
assert_eq!(s_init1.len(), server.plpmtu()); assert_eq!(s_init1.len(), server.plpmtu());
let s_init2 = server.process_output(now).dgram().unwrap(); let s_init2 = server.process_output(now).dgram().unwrap();
assert_eq!(s_init2.len(), server.plpmtu()); assert_eq!(s_init2.len(), server.plpmtu());
@ -795,11 +795,11 @@ fn anti_amplification() {
assert_eq!(cb, server.conn_params.get_idle_timeout()); assert_eq!(cb, server.conn_params.get_idle_timeout());
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
client.process_input(&s_init1, now); client.process_input(s_init1, now);
client.process_input(&s_init2, now); client.process_input(s_init2, now);
let ack_count = client.stats().frame_tx.ack; let ack_count = client.stats().frame_tx.ack;
let frame_count = client.stats().frame_tx.all(); let frame_count = client.stats().frame_tx.all();
let ack = client.process(Some(&s_init3), now).dgram().unwrap(); let ack = client.process(Some(s_init3), now).dgram().unwrap();
assert!(!maybe_authenticate(&mut client)); // No need yet. assert!(!maybe_authenticate(&mut client)); // No need yet.
// The client sends a padded datagram, with just ACK for Handshake. // The client sends a padded datagram, with just ACK for Handshake.
@ -808,16 +808,16 @@ fn anti_amplification() {
assert_ne!(ack.len(), client.plpmtu()); // Not padded (it includes Handshake). assert_ne!(ack.len(), client.plpmtu()); // Not padded (it includes Handshake).
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
let remainder = server.process(Some(&ack), now).dgram(); let remainder = server.process(Some(ack), now).dgram();
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
client.process_input(&remainder.unwrap(), now); client.process_input(remainder.unwrap(), now);
assert!(maybe_authenticate(&mut client)); // OK, we have all of it. assert!(maybe_authenticate(&mut client)); // OK, we have all of it.
let fin = client.process_output(now).dgram(); let fin = client.process_output(now).dgram();
assert_eq!(*client.state(), State::Connected); assert_eq!(*client.state(), State::Connected);
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
server.process_input(&fin.unwrap(), now); server.process_input(fin.unwrap(), now);
assert_eq!(*server.state(), State::Confirmed); assert_eq!(*server.state(), State::Confirmed);
} }
@ -833,17 +833,17 @@ fn garbage_initial() {
corrupted.push(initial[initial.len() - 1] ^ 0xb7); corrupted.push(initial[initial.len() - 1] ^ 0xb7);
corrupted.extend_from_slice(rest.as_ref().map_or(&[], |r| &r[..])); corrupted.extend_from_slice(rest.as_ref().map_or(&[], |r| &r[..]));
let garbage = datagram(corrupted); let garbage = datagram(corrupted);
assert_eq!(Output::None, server.process(Some(&garbage), now())); assert_eq!(Output::None, server.process(Some(garbage), now()));
} }
#[test] #[test]
fn drop_initial_packet_from_wrong_address() { fn drop_initial_packet_from_wrong_address() {
let mut client = default_client(); let mut client = default_client();
let out = client.process(None, now()); let out = client.process_output(now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
let mut server = default_server(); let mut server = default_server();
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
let p = out.dgram().unwrap(); let p = out.dgram().unwrap();
@ -854,24 +854,24 @@ fn drop_initial_packet_from_wrong_address() {
&p[..], &p[..],
); );
let out = client.process(Some(&dgram), now()); let out = client.process(Some(dgram), now());
assert!(out.as_dgram_ref().is_none()); assert!(out.as_dgram_ref().is_none());
} }
#[test] #[test]
fn drop_handshake_packet_from_wrong_address() { fn drop_handshake_packet_from_wrong_address() {
let mut client = default_client(); let mut client = default_client();
let out = client.process(None, now()); let out = client.process_output(now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
let mut server = default_server(); let mut server = default_server();
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
let (s_in, s_hs) = split_datagram(&out.dgram().unwrap()); let (s_in, s_hs) = split_datagram(&out.dgram().unwrap());
// Pass the initial packet. // Pass the initial packet.
mem::drop(client.process(Some(&s_in), now()).dgram()); mem::drop(client.process(Some(s_in), now()).dgram());
let p = s_hs.unwrap(); let p = s_hs.unwrap();
let dgram = Datagram::new( let dgram = Datagram::new(
@ -881,7 +881,7 @@ fn drop_handshake_packet_from_wrong_address() {
&p[..], &p[..],
); );
let out = client.process(Some(&dgram), now()); let out = client.process(Some(dgram), now());
assert!(out.as_dgram_ref().is_none()); assert!(out.as_dgram_ref().is_none());
} }
@ -930,8 +930,8 @@ fn ech_retry() {
.unwrap(); .unwrap();
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
let dgram = server.process(dgram.as_ref(), now()).dgram(); let dgram = server.process(dgram, now()).dgram();
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
let auth_event = ConnectionEvent::EchFallbackAuthenticationNeeded { let auth_event = ConnectionEvent::EchFallbackAuthenticationNeeded {
public_name: String::from(ECH_PUBLIC_NAME), public_name: String::from(ECH_PUBLIC_NAME),
}; };
@ -941,7 +941,7 @@ fn ech_retry() {
// Tell the server about the error. // Tell the server about the error.
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
server.process_input(&dgram.unwrap(), now()); server.process_input(dgram.unwrap(), now());
assert_eq!( assert_eq!(
server.state().error(), server.state().error(),
Some(&CloseReason::Transport(Error::PeerError(0x100 + 121))) Some(&CloseReason::Transport(Error::PeerError(0x100 + 121)))
@ -985,8 +985,8 @@ fn ech_retry_fallback_rejected() {
.unwrap(); .unwrap();
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
let dgram = server.process(dgram.as_ref(), now()).dgram(); let dgram = server.process(dgram, now()).dgram();
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
let auth_event = ConnectionEvent::EchFallbackAuthenticationNeeded { let auth_event = ConnectionEvent::EchFallbackAuthenticationNeeded {
public_name: String::from(ECH_PUBLIC_NAME), public_name: String::from(ECH_PUBLIC_NAME),
}; };
@ -1000,7 +1000,7 @@ fn ech_retry_fallback_rejected() {
// Pass the error on. // Pass the error on.
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
server.process_input(&dgram.unwrap(), now()); server.process_input(dgram.unwrap(), now());
assert_eq!( assert_eq!(
server.state().error(), server.state().error(),
Some(&CloseReason::Transport(Error::PeerError(298))) Some(&CloseReason::Transport(Error::PeerError(298)))
@ -1018,13 +1018,13 @@ fn bad_min_ack_delay() {
let mut client = default_client(); let mut client = default_client();
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
let dgram = server.process(dgram.as_ref(), now()).dgram(); let dgram = server.process(dgram, now()).dgram();
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
client.authenticated(AuthenticationStatus::Ok, now()); client.authenticated(AuthenticationStatus::Ok, now());
assert_eq!(client.state().error(), Some(&EXPECTED_ERROR)); assert_eq!(client.state().error(), Some(&EXPECTED_ERROR));
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
server.process_input(&dgram.unwrap(), now()); server.process_input(dgram.unwrap(), now());
assert_eq!( assert_eq!(
server.state().error(), server.state().error(),
Some(&CloseReason::Transport(Error::PeerError( Some(&CloseReason::Transport(Error::PeerError(
@ -1044,7 +1044,7 @@ fn only_server_initial() {
let client_dgram = client.process_output(now).dgram(); let client_dgram = client.process_output(now).dgram();
// Now fetch two flights of messages from the server. // Now fetch two flights of messages from the server.
let server_dgram1 = server.process(client_dgram.as_ref(), now).dgram(); let server_dgram1 = server.process(client_dgram, now).dgram();
let server_dgram2 = server.process_output(now + AT_LEAST_PTO).dgram(); let server_dgram2 = server.process_output(now + AT_LEAST_PTO).dgram();
// Only pass on the Initial from the first. We should get a Handshake in return. // Only pass on the Initial from the first. We should get a Handshake in return.
@ -1054,7 +1054,7 @@ fn only_server_initial() {
// The client will not acknowledge the Initial as it discards keys. // The client will not acknowledge the Initial as it discards keys.
// It sends a Handshake probe instead, containing just a PING frame. // It sends a Handshake probe instead, containing just a PING frame.
assert_eq!(client.stats().frame_tx.ping, 0); assert_eq!(client.stats().frame_tx.ping, 0);
let probe = client.process(Some(&initial), now).dgram(); let probe = client.process(Some(initial), now).dgram();
assertions::assert_handshake(&probe.unwrap()); assertions::assert_handshake(&probe.unwrap());
assert_eq!(client.stats().dropped_rx, 0); assert_eq!(client.stats().dropped_rx, 0);
assert_eq!(client.stats().frame_tx.ping, 1); assert_eq!(client.stats().frame_tx.ping, 1);
@ -1066,17 +1066,17 @@ fn only_server_initial() {
now += AT_LEAST_PTO; now += AT_LEAST_PTO;
assert_eq!(client.stats().frame_tx.ping, 1); assert_eq!(client.stats().frame_tx.ping, 1);
let discarded = client.stats().dropped_rx; let discarded = client.stats().dropped_rx;
let probe = client.process(Some(&initial), now).dgram(); let probe = client.process(Some(initial), now).dgram();
assertions::assert_handshake(&probe.unwrap()); assertions::assert_handshake(&probe.unwrap());
assert_eq!(client.stats().frame_tx.ping, 2); assert_eq!(client.stats().frame_tx.ping, 2);
assert_eq!(client.stats().dropped_rx, discarded + 1); assert_eq!(client.stats().dropped_rx, discarded + 1);
// Pass the Handshake packet and complete the handshake. // Pass the Handshake packet and complete the handshake.
client.process_input(&handshake.unwrap(), now); client.process_input(handshake.unwrap(), now);
maybe_authenticate(&mut client); maybe_authenticate(&mut client);
let dgram = client.process_output(now).dgram(); let dgram = client.process_output(now).dgram();
let dgram = server.process(dgram.as_ref(), now).dgram(); let dgram = server.process(dgram, now).dgram();
client.process_input(&dgram.unwrap(), now); client.process_input(dgram.unwrap(), now);
assert_eq!(*client.state(), State::Confirmed); assert_eq!(*client.state(), State::Confirmed);
assert_eq!(*server.state(), State::Confirmed); assert_eq!(*server.state(), State::Confirmed);
@ -1102,25 +1102,25 @@ fn no_extra_probes_after_confirmed() {
// Finally, run the handshake. // Finally, run the handshake.
now += AT_LEAST_PTO * 2; now += AT_LEAST_PTO * 2;
let dgram = client.process_output(now).dgram(); let dgram = client.process_output(now).dgram();
let dgram = server.process(dgram.as_ref(), now).dgram(); let dgram = server.process(dgram, now).dgram();
// The server should have dropped the Initial keys now, so passing in the Initial // The server should have dropped the Initial keys now, so passing in the Initial
// should elicit a retransmit rather than having it completely ignored. // should elicit a retransmit rather than having it completely ignored.
let spare_handshake = server.process(Some(&replay_initial), now).dgram(); let spare_handshake = server.process(Some(replay_initial), now).dgram();
assert!(spare_handshake.is_some()); assert!(spare_handshake.is_some());
client.process_input(&dgram.unwrap(), now); client.process_input(dgram.unwrap(), now);
maybe_authenticate(&mut client); maybe_authenticate(&mut client);
let dgram = client.process_output(now).dgram(); let dgram = client.process_output(now).dgram();
let dgram = server.process(dgram.as_ref(), now).dgram(); let dgram = server.process(dgram, now).dgram();
client.process_input(&dgram.unwrap(), now); client.process_input(dgram.unwrap(), now);
assert_eq!(*client.state(), State::Confirmed); assert_eq!(*client.state(), State::Confirmed);
assert_eq!(*server.state(), State::Confirmed); assert_eq!(*server.state(), State::Confirmed);
let probe = server.process(spare_initial.as_ref(), now).dgram(); let probe = server.process(spare_initial, now).dgram();
assert!(probe.is_none()); assert!(probe.is_none());
let probe = client.process(spare_handshake.as_ref(), now).dgram(); let probe = client.process(spare_handshake, now).dgram();
assert!(probe.is_none()); assert!(probe.is_none());
} }
@ -1133,12 +1133,12 @@ fn implicit_rtt_server() {
let dgram = client.process_output(now).dgram(); let dgram = client.process_output(now).dgram();
now += RTT / 2; now += RTT / 2;
let dgram = server.process(dgram.as_ref(), now).dgram(); let dgram = server.process(dgram, now).dgram();
now += RTT / 2; now += RTT / 2;
let dgram = client.process(dgram.as_ref(), now).dgram(); let dgram = client.process(dgram, now).dgram();
assertions::assert_handshake(dgram.as_ref().unwrap()); assertions::assert_handshake(dgram.as_ref().unwrap());
now += RTT / 2; now += RTT / 2;
server.process_input(&dgram.unwrap(), now); server.process_input(dgram.unwrap(), now);
// The server doesn't receive any acknowledgments, but it can infer // The server doesn't receive any acknowledgments, but it can infer
// an RTT estimate from having discarded the Initial packet number space. // an RTT estimate from having discarded the Initial packet number space.
@ -1157,14 +1157,14 @@ fn emit_authentication_needed_once() {
) )
.expect("create a server"); .expect("create a server");
let client1 = client.process(None, now()); let client1 = client.process_output(now());
assert!(client1.as_dgram_ref().is_some()); assert!(client1.as_dgram_ref().is_some());
// The entire server flight doesn't fit in a single packet because the // The entire server flight doesn't fit in a single packet because the
// certificate is large, therefore the server will produce 2 packets. // certificate is large, therefore the server will produce 2 packets.
let server1 = server.process(client1.as_dgram_ref(), now()); let server1 = server.process(client1.dgram(), now());
assert!(server1.as_dgram_ref().is_some()); assert!(server1.as_dgram_ref().is_some());
let server2 = server.process(None, now()); let server2 = server.process_output(now());
assert!(server2.as_dgram_ref().is_some()); assert!(server2.as_dgram_ref().is_some());
let authentication_needed_count = |client: &mut Connection| { let authentication_needed_count = |client: &mut Connection| {
@ -1184,7 +1184,7 @@ fn emit_authentication_needed_once() {
// packet, but be large enough that the CertificateVerify message does not // packet, but be large enough that the CertificateVerify message does not
// also fit in the same packet. Our default test setup achieves this, but // also fit in the same packet. Our default test setup achieves this, but
// changes to the setup might invalidate this test. // changes to the setup might invalidate this test.
_ = client.process(server1.as_dgram_ref(), now()); _ = client.process(server1.dgram(), now());
assert_eq!(1, authentication_needed_count(&mut client)); assert_eq!(1, authentication_needed_count(&mut client));
assert!(client.peer_certificate().is_some()); assert!(client.peer_certificate().is_some());
@ -1192,7 +1192,7 @@ fn emit_authentication_needed_once() {
// `Connection::authenticated`. On receiving the second packet from the // `Connection::authenticated`. On receiving the second packet from the
// server, the client must not emit a another // server, the client must not emit a another
// `ConnectionEvent::AuthenticationNeeded`. // `ConnectionEvent::AuthenticationNeeded`.
_ = client.process(server2.as_dgram_ref(), now()); _ = client.process(server2.dgram(), now());
assert_eq!(0, authentication_needed_count(&mut client)); assert_eq!(0, authentication_needed_count(&mut client));
} }
@ -1204,7 +1204,7 @@ fn client_initial_retransmits_identical() {
// Force the client to retransmit its Initial packet a number of times and make sure the // Force the client to retransmit its Initial packet a number of times and make sure the
// retranmissions are identical to the original. Also, verify the PTO durations. // retranmissions are identical to the original. Also, verify the PTO durations.
for i in 1..=5 { for i in 1..=5 {
let ci = client.process(None, now).dgram().unwrap(); let ci = client.process_output(now).dgram().unwrap();
assert_eq!(ci.len(), client.plpmtu()); assert_eq!(ci.len(), client.plpmtu());
assert_eq!( assert_eq!(
client.stats().frame_tx, client.stats().frame_tx,
@ -1213,7 +1213,7 @@ fn client_initial_retransmits_identical() {
..Default::default() ..Default::default()
} }
); );
let pto = client.process(None, now).callback(); let pto = client.process_output(now).callback();
assert_eq!(pto, DEFAULT_RTT * 3 * (1 << (i - 1))); assert_eq!(pto, DEFAULT_RTT * 3 * (1 << (i - 1)));
now += pto; now += pto;
} }
@ -1223,14 +1223,14 @@ fn client_initial_retransmits_identical() {
fn server_initial_retransmits_identical() { fn server_initial_retransmits_identical() {
let mut now = now(); let mut now = now();
let mut client = default_client(); let mut client = default_client();
let mut ci = client.process(None, now).dgram(); let mut ci = client.process_output(now).dgram();
// Force the server to retransmit its Initial packet a number of times and make sure the // Force the server to retransmit its Initial packet a number of times and make sure the
// retranmissions are identical to the original. Also, verify the PTO durations. // retranmissions are identical to the original. Also, verify the PTO durations.
let mut server = default_server(); let mut server = default_server();
let mut total_ptos: Duration = Duration::from_secs(0); let mut total_ptos: Duration = Duration::from_secs(0);
for i in 1..=3 { for i in 1..=3 {
let si = server.process(ci.take().as_ref(), now).dgram().unwrap(); let si = server.process(ci.take(), now).dgram().unwrap();
assert_eq!(si.len(), server.plpmtu()); assert_eq!(si.len(), server.plpmtu());
assert_eq!( assert_eq!(
server.stats().frame_tx, server.stats().frame_tx,
@ -1241,7 +1241,7 @@ fn server_initial_retransmits_identical() {
} }
); );
let pto = server.process(None, now).callback(); let pto = server.process_output(now).callback();
if i < 3 { if i < 3 {
assert_eq!(pto, DEFAULT_RTT * 3 * (1 << (i - 1))); assert_eq!(pto, DEFAULT_RTT * 3 * (1 << (i - 1)));
} else { } else {

Просмотреть файл

@ -40,17 +40,14 @@ fn test_idle_timeout(client: &mut Connection, server: &mut Connection, timeout:
let now = now(); let now = now();
let res = client.process(None, now); let res = client.process_output(now);
assert_eq!(res, Output::Callback(timeout)); assert_eq!(res, Output::Callback(timeout));
// Still connected after timeout-1 seconds. Idle timer not reset // Still connected after timeout-1 seconds. Idle timer not reset
mem::drop(client.process( mem::drop(client.process_output(now + timeout.checked_sub(Duration::from_secs(1)).unwrap()));
None,
now + timeout.checked_sub(Duration::from_secs(1)).unwrap(),
));
assert!(matches!(client.state(), State::Confirmed)); assert!(matches!(client.state(), State::Confirmed));
mem::drop(client.process(None, now + timeout)); mem::drop(client.process_output(now + timeout));
// Not connected after timeout. // Not connected after timeout.
assert!(matches!(client.state(), State::Closed(_))); assert!(matches!(client.state(), State::Closed(_)));
@ -112,19 +109,19 @@ fn asymmetric_idle_timeout() {
connect(&mut client, &mut server); connect(&mut client, &mut server);
let c1 = send_something(&mut client, now()); let c1 = send_something(&mut client, now());
let c2 = send_something(&mut client, now()); let c2 = send_something(&mut client, now());
server.process_input(&c2, now()); server.process_input(c2, now());
server.process_input(&c1, now()); server.process_input(c1, now());
let s1 = send_something(&mut server, now()); let s1 = send_something(&mut server, now());
let s2 = send_something(&mut server, now()); let s2 = send_something(&mut server, now());
client.process_input(&s2, now()); client.process_input(s2, now());
let ack = client.process(Some(&s1), now()).dgram(); let ack = client.process(Some(s1), now()).dgram();
assert!(ack.is_some()); assert!(ack.is_some());
// Now both should have received ACK frames so should be idle. // Now both should have received ACK frames so should be idle.
assert_eq!(server.process(ack, now()), Output::Callback(LOWER_TIMEOUT));
assert_eq!( assert_eq!(
server.process(ack.as_ref(), now()), client.process_output(now()),
Output::Callback(LOWER_TIMEOUT) Output::Callback(LOWER_TIMEOUT)
); );
assert_eq!(client.process(None, now()), Output::Callback(LOWER_TIMEOUT));
} }
#[test] #[test]
@ -152,17 +149,17 @@ fn tiny_idle_timeout() {
let c1 = send_something(&mut client, now); let c1 = send_something(&mut client, now);
let c2 = send_something(&mut client, now); let c2 = send_something(&mut client, now);
now += RTT / 2; now += RTT / 2;
server.process_input(&c2, now); server.process_input(c2, now);
server.process_input(&c1, now); server.process_input(c1, now);
let s1 = send_something(&mut server, now); let s1 = send_something(&mut server, now);
let s2 = send_something(&mut server, now); let s2 = send_something(&mut server, now);
now += RTT / 2; now += RTT / 2;
client.process_input(&s2, now); client.process_input(s2, now);
let ack = client.process(Some(&s1), now).dgram(); let ack = client.process(Some(s1), now).dgram();
assert!(ack.is_some()); assert!(ack.is_some());
// The client should be idle now, but with a different timer. // The client should be idle now, but with a different timer.
if let Output::Callback(t) = client.process(None, now) { if let Output::Callback(t) = client.process_output(now) {
assert!(t > LOWER_TIMEOUT); assert!(t > LOWER_TIMEOUT);
} else { } else {
panic!("Client not idle"); panic!("Client not idle");
@ -170,7 +167,7 @@ fn tiny_idle_timeout() {
// The server should go idle after the ACK, but again with a larger timeout. // The server should go idle after the ACK, but again with a larger timeout.
now += RTT / 2; now += RTT / 2;
if let Output::Callback(t) = client.process(ack.as_ref(), now) { if let Output::Callback(t) = client.process(ack, now) {
assert!(t > LOWER_TIMEOUT); assert!(t > LOWER_TIMEOUT);
} else { } else {
panic!("Client not idle"); panic!("Client not idle");
@ -186,7 +183,7 @@ fn idle_send_packet1() {
let mut now = now(); let mut now = now();
connect_force_idle(&mut client, &mut server); connect_force_idle(&mut client, &mut server);
let timeout = client.process(None, now).callback(); let timeout = client.process_output(now).callback();
assert_eq!(timeout, default_timeout()); assert_eq!(timeout, default_timeout());
now += Duration::from_secs(10); now += Duration::from_secs(10);
@ -196,13 +193,13 @@ fn idle_send_packet1() {
// Still connected after 39 seconds because idle timer reset by the // Still connected after 39 seconds because idle timer reset by the
// outgoing packet. // outgoing packet.
now += default_timeout() - DELTA; now += default_timeout() - DELTA;
let dgram = client.process(None, now).dgram(); let dgram = client.process_output(now).dgram();
assert!(dgram.is_some()); // PTO assert!(dgram.is_some()); // PTO
assert!(client.state().connected()); assert!(client.state().connected());
// Not connected after 40 seconds. // Not connected after 40 seconds.
now += DELTA; now += DELTA;
let out = client.process(None, now); let out = client.process_output(now);
assert!(matches!(out, Output::None)); assert!(matches!(out, Output::None));
assert!(client.state().closed()); assert!(client.state().closed());
} }
@ -218,7 +215,7 @@ fn idle_send_packet2() {
let mut now = now(); let mut now = now();
let timeout = client.process(None, now).callback(); let timeout = client.process_output(now).callback();
assert_eq!(timeout, default_timeout()); assert_eq!(timeout, default_timeout());
// First transmission at t=GAP. // First transmission at t=GAP.
@ -231,14 +228,14 @@ fn idle_send_packet2() {
// Still connected just before GAP + default_timeout(). // Still connected just before GAP + default_timeout().
now += default_timeout() - DELTA; now += default_timeout() - DELTA;
let dgram = client.process(None, now).dgram(); let dgram = client.process_output(now).dgram();
assert!(dgram.is_some()); // PTO assert!(dgram.is_some()); // PTO
assert!(matches!(client.state(), State::Confirmed)); assert!(matches!(client.state(), State::Confirmed));
// Not connected after 40 seconds because timer not reset by second // Not connected after 40 seconds because timer not reset by second
// outgoing packet // outgoing packet
now += DELTA; now += DELTA;
let out = client.process(None, now); let out = client.process_output(now);
assert!(matches!(out, Output::None)); assert!(matches!(out, Output::None));
assert!(matches!(client.state(), State::Closed(_))); assert!(matches!(client.state(), State::Closed(_)));
} }
@ -253,7 +250,7 @@ fn idle_recv_packet() {
let mut now = now(); let mut now = now();
let res = client.process(None, now); let res = client.process_output(now);
assert_eq!(res, Output::Callback(default_timeout())); assert_eq!(res, Output::Callback(default_timeout()));
let stream = client.stream_create(StreamType::BiDi).unwrap(); let stream = client.stream_create(StreamType::BiDi).unwrap();
@ -264,21 +261,21 @@ fn idle_recv_packet() {
// Note that it is important that this not result in the RTT increasing above 0. // Note that it is important that this not result in the RTT increasing above 0.
// Otherwise, the eventual timeout will be extended (and we're not testing that). // Otherwise, the eventual timeout will be extended (and we're not testing that).
now += Duration::from_secs(10); now += Duration::from_secs(10);
let out = client.process(None, now); let out = client.process_output(now);
server.process_input(&out.dgram().unwrap(), now); server.process_input(out.dgram().unwrap(), now);
assert_eq!(server.stream_send(stream, b"world").unwrap(), 5); assert_eq!(server.stream_send(stream, b"world").unwrap(), 5);
let out = server.process_output(now); let out = server.process_output(now);
assert_ne!(out.as_dgram_ref(), None); assert_ne!(out.as_dgram_ref(), None);
mem::drop(client.process(out.as_dgram_ref(), now)); mem::drop(client.process(out.dgram(), now));
assert!(matches!(client.state(), State::Confirmed)); assert!(matches!(client.state(), State::Confirmed));
// Add a little less than the idle timeout and we're still connected. // Add a little less than the idle timeout and we're still connected.
now += default_timeout() - FUDGE; now += default_timeout() - FUDGE;
mem::drop(client.process(None, now)); mem::drop(client.process_output(now));
assert!(matches!(client.state(), State::Confirmed)); assert!(matches!(client.state(), State::Confirmed));
now += FUDGE; now += FUDGE;
mem::drop(client.process(None, now)); mem::drop(client.process_output(now));
assert!(matches!(client.state(), State::Closed(_))); assert!(matches!(client.state(), State::Closed(_)));
} }
@ -296,9 +293,9 @@ fn idle_caching() {
// Perform the first round trip, but drop the Initial from the server. // Perform the first round trip, but drop the Initial from the server.
// The client then caches the Handshake packet. // The client then caches the Handshake packet.
let dgram = client.process_output(start).dgram(); let dgram = client.process_output(start).dgram();
let dgram = server.process(dgram.as_ref(), start).dgram(); let dgram = server.process(dgram, start).dgram();
let (_, handshake) = split_datagram(&dgram.unwrap()); let (_, handshake) = split_datagram(&dgram.unwrap());
client.process_input(&handshake.unwrap(), start); client.process_input(handshake.unwrap(), start);
// Perform an exchange and keep the connection alive. // Perform an exchange and keep the connection alive.
let middle = start + AT_LEAST_PTO; let middle = start + AT_LEAST_PTO;
@ -309,7 +306,7 @@ fn idle_caching() {
mem::drop(server.process_output(middle).dgram()); mem::drop(server.process_output(middle).dgram());
// Now let the server process the RTX'ed client Initial. This causes the server // Now let the server process the RTX'ed client Initial. This causes the server
// to send CRYPTO frames again, so manually extract and discard those. // to send CRYPTO frames again, so manually extract and discard those.
server.process_input(&dgram.unwrap(), middle); server.process_input(dgram.unwrap(), middle);
let mut tokens = Vec::new(); let mut tokens = Vec::new();
server.crypto.streams.write_frame( server.crypto.streams.write_frame(
PacketNumberSpace::Initial, PacketNumberSpace::Initial,
@ -333,7 +330,7 @@ fn idle_caching() {
let (initial, _) = split_datagram(&dgram.unwrap()); let (initial, _) = split_datagram(&dgram.unwrap());
let crypto_before_c = client.stats().frame_rx.crypto; let crypto_before_c = client.stats().frame_rx.crypto;
let ack_before = client.stats().frame_rx.ack; let ack_before = client.stats().frame_rx.ack;
client.process_input(&initial, middle); client.process_input(initial, middle);
assert_eq!(client.stats().frame_rx.crypto, crypto_before_c); assert_eq!(client.stats().frame_rx.crypto, crypto_before_c);
assert_eq!(client.stats().frame_rx.ack, ack_before + 1); assert_eq!(client.stats().frame_rx.ack, ack_before + 1);
@ -342,11 +339,11 @@ fn idle_caching() {
let dgram = server.process_output(end).dgram(); let dgram = server.process_output(end).dgram();
let (initial, _) = split_datagram(&dgram.unwrap()); let (initial, _) = split_datagram(&dgram.unwrap());
neqo_common::qwarn!("client ingests initial, finally"); neqo_common::qwarn!("client ingests initial, finally");
mem::drop(client.process(Some(&initial), end)); mem::drop(client.process(Some(initial), end));
maybe_authenticate(&mut client); maybe_authenticate(&mut client);
let dgram = client.process_output(end).dgram(); let dgram = client.process_output(end).dgram();
let dgram = server.process(dgram.as_ref(), end).dgram(); let dgram = server.process(dgram, end).dgram();
client.process_input(&dgram.unwrap(), end); client.process_input(dgram.unwrap(), end);
assert_eq!(*client.state(), State::Confirmed); assert_eq!(*client.state(), State::Confirmed);
assert_eq!(*server.state(), State::Confirmed); assert_eq!(*server.state(), State::Confirmed);
} }
@ -375,7 +372,7 @@ fn create_stream_idle_rtt(
_ = initiator.stream_send(stream, DEFAULT_STREAM_DATA).unwrap(); _ = initiator.stream_send(stream, DEFAULT_STREAM_DATA).unwrap();
let req = initiator.process_output(now).dgram(); let req = initiator.process_output(now).dgram();
now += rtt / 2; now += rtt / 2;
responder.process_input(&req.unwrap(), now); responder.process_input(req.unwrap(), now);
// Reordering two packets from the responder forces the initiator to be idle. // Reordering two packets from the responder forces the initiator to be idle.
_ = responder.stream_send(stream, DEFAULT_STREAM_DATA).unwrap(); _ = responder.stream_send(stream, DEFAULT_STREAM_DATA).unwrap();
@ -384,15 +381,15 @@ fn create_stream_idle_rtt(
let resp2 = responder.process_output(now).dgram(); let resp2 = responder.process_output(now).dgram();
now += rtt / 2; now += rtt / 2;
initiator.process_input(&resp2.unwrap(), now); initiator.process_input(resp2.unwrap(), now);
initiator.process_input(&resp1.unwrap(), now); initiator.process_input(resp1.unwrap(), now);
let ack = initiator.process_output(now).dgram(); let ack = initiator.process_output(now).dgram();
assert!(ack.is_some()); assert!(ack.is_some());
check_idle(initiator, now); check_idle(initiator, now);
// Receiving the ACK should return the responder to idle too. // Receiving the ACK should return the responder to idle too.
now += rtt / 2; now += rtt / 2;
responder.process_input(&ack.unwrap(), now); responder.process_input(ack.unwrap(), now);
check_idle(responder, now); check_idle(responder, now);
(now, stream) (now, stream)
@ -428,9 +425,9 @@ fn keep_alive_initiator() {
assert_eq!(server.stats().frame_tx.ping, pings_before + 1); assert_eq!(server.stats().frame_tx.ping, pings_before + 1);
// Exchange ack for the PING. // Exchange ack for the PING.
let out = client.process(ping.as_ref(), now).dgram(); let out = client.process(ping, now).dgram();
let out = server.process(out.as_ref(), now).dgram(); let out = server.process(out, now).dgram();
assert!(client.process(out.as_ref(), now).dgram().is_none()); assert!(client.process(out, now).dgram().is_none());
// Check that there will be next keep-alive ping after keep_alive_timeout(). // Check that there will be next keep-alive ping after keep_alive_timeout().
assert_idle(&mut server, now, keep_alive_timeout()); assert_idle(&mut server, now, keep_alive_timeout());
@ -469,12 +466,12 @@ fn keep_alive_lost() {
assert_eq!(server.stats().frame_tx.ping, pings_before2 + 1); assert_eq!(server.stats().frame_tx.ping, pings_before2 + 1);
// Exchange ack for the PING. // Exchange ack for the PING.
let out = client.process(ping.as_ref(), now).dgram(); let out = client.process(ping, now).dgram();
now += Duration::from_millis(20); now += Duration::from_millis(20);
let out = server.process(out.as_ref(), now).dgram(); let out = server.process(out, now).dgram();
assert!(client.process(out.as_ref(), now).dgram().is_none()); assert!(client.process(out, now).dgram().is_none());
// TODO: if we run server.process with current value of now, the server will // TODO: if we run server.process with current value of now, the server will
// return some small timeout for the recovry although it does not have // return some small timeout for the recovry although it does not have
@ -527,10 +524,10 @@ fn keep_alive_unmark() {
fn transfer_force_idle(sender: &mut Connection, receiver: &mut Connection) { fn transfer_force_idle(sender: &mut Connection, receiver: &mut Connection) {
let dgram = sender.process_output(now()).dgram(); let dgram = sender.process_output(now()).dgram();
let chaff = send_something(sender, now()); let chaff = send_something(sender, now());
receiver.process_input(&chaff, now()); receiver.process_input(chaff, now());
receiver.process_input(&dgram.unwrap(), now()); receiver.process_input(dgram.unwrap(), now());
let ack = receiver.process_output(now()).dgram(); let ack = receiver.process_output(now()).dgram();
sender.process_input(&ack.unwrap(), now()); sender.process_input(ack.unwrap(), now());
} }
/// Receiving the end of the stream stops keep-alives for that stream. /// Receiving the end of the stream stops keep-alives for that stream.
@ -598,7 +595,7 @@ fn keep_alive_stop_sending() {
// The server will have sent RESET_STREAM, which the client will // The server will have sent RESET_STREAM, which the client will
// want to acknowledge, so force that out. // want to acknowledge, so force that out.
let junk = send_something(&mut server, now()); let junk = send_something(&mut server, now());
let ack = client.process(Some(&junk), now()).dgram(); let ack = client.process(Some(junk), now()).dgram();
assert!(ack.is_some()); assert!(ack.is_some());
// Now the client should be idle. // Now the client should be idle.
@ -661,7 +658,7 @@ fn keep_alive_uni() {
_ = client.stream_send(stream, DEFAULT_STREAM_DATA).unwrap(); _ = client.stream_send(stream, DEFAULT_STREAM_DATA).unwrap();
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
server.process_input(&dgram.unwrap(), now()); server.process_input(dgram.unwrap(), now());
server.stream_keep_alive(stream, true).unwrap(); server.stream_keep_alive(stream, true).unwrap();
} }

Просмотреть файл

@ -33,7 +33,7 @@ fn check_discarded(
mem::drop(peer.process_output(now())); mem::drop(peer.process_output(now()));
let before = peer.stats(); let before = peer.stats();
let out = peer.process(Some(pkt), now()); let out = peer.process(Some(pkt.clone()), now());
assert_eq!(out.as_dgram_ref().is_some(), response); assert_eq!(out.as_dgram_ref().is_some(), response);
let after = peer.stats(); let after = peer.stats();
assert_eq!(dropped, after.dropped_rx - before.dropped_rx); assert_eq!(dropped, after.dropped_rx - before.dropped_rx);
@ -57,17 +57,17 @@ fn overwrite_invocations(n: PacketNumber) {
fn discarded_initial_keys() { fn discarded_initial_keys() {
qdebug!("---- client: generate CH"); qdebug!("---- client: generate CH");
let mut client = default_client(); let mut client = default_client();
let init_pkt_c = client.process(None, now()).dgram(); let init_pkt_c = client.process_output(now()).dgram();
assert!(init_pkt_c.is_some()); assert!(init_pkt_c.is_some());
assert_eq!(init_pkt_c.as_ref().unwrap().len(), client.plpmtu()); assert_eq!(init_pkt_c.as_ref().unwrap().len(), client.plpmtu());
qdebug!("---- server: CH -> SH, EE, CERT, CV, FIN"); qdebug!("---- server: CH -> SH, EE, CERT, CV, FIN");
let mut server = default_server(); let mut server = default_server();
let init_pkt_s = server.process(init_pkt_c.as_ref(), now()).dgram(); let init_pkt_s = server.process(init_pkt_c.clone(), now()).dgram();
assert!(init_pkt_s.is_some()); assert!(init_pkt_s.is_some());
qdebug!("---- client: cert verification"); qdebug!("---- client: cert verification");
let out = client.process(init_pkt_s.as_ref(), now()).dgram(); let out = client.process(init_pkt_s.clone(), now()).dgram();
assert!(out.is_some()); assert!(out.is_some());
// The client has received a handshake packet. It will remove the Initial keys. // The client has received a handshake packet. It will remove the Initial keys.
@ -86,12 +86,12 @@ fn discarded_initial_keys() {
check_discarded(&mut server, &init_pkt_c.clone().unwrap(), false, 1, 1); check_discarded(&mut server, &init_pkt_c.clone().unwrap(), false, 1, 1);
qdebug!("---- client: SH..FIN -> FIN"); qdebug!("---- client: SH..FIN -> FIN");
let out = client.process(None, now()).dgram(); let out = client.process_output(now()).dgram();
assert!(out.is_some()); assert!(out.is_some());
// The server will process the first Handshake packet. // The server will process the first Handshake packet.
// After this the Initial keys will be dropped. // After this the Initial keys will be dropped.
let out = server.process(out.as_ref(), now()).dgram(); let out = server.process(out, now()).dgram();
assert!(out.is_some()); assert!(out.is_some());
// Check that the Initial keys are dropped at the server // Check that the Initial keys are dropped at the server
@ -116,7 +116,7 @@ fn key_update_client() {
// Initiating an update should only increase the write epoch. // Initiating an update should only increase the write epoch.
let idle_timeout = ConnectionParameters::default().get_idle_timeout(); let idle_timeout = ConnectionParameters::default().get_idle_timeout();
assert_eq!(Output::Callback(idle_timeout), client.process(None, now)); assert_eq!(Output::Callback(idle_timeout), client.process_output(now));
assert_eq!(client.get_epochs(), (Some(4), Some(3))); assert_eq!(client.get_epochs(), (Some(4), Some(3)));
// Send something to propagate the update. // Send something to propagate the update.
@ -125,7 +125,7 @@ fn key_update_client() {
// The server should now be waiting to discharge read keys. // The server should now be waiting to discharge read keys.
assert_eq!(server.get_epochs(), (Some(4), Some(3))); assert_eq!(server.get_epochs(), (Some(4), Some(3)));
let res = server.process(None, now); let res = server.process_output(now);
if let Output::Callback(t) = res { if let Output::Callback(t) = res {
assert!(t < idle_timeout); assert!(t < idle_timeout);
} else { } else {
@ -142,10 +142,10 @@ fn key_update_client() {
// But at this point the client hasn't received a key update from the server. // But at this point the client hasn't received a key update from the server.
// It will be stuck with old keys. // It will be stuck with old keys.
now += AT_LEAST_PTO; now += AT_LEAST_PTO;
let dgram = client.process(None, now).dgram(); let dgram = client.process_output(now).dgram();
assert!(dgram.is_some()); // Drop this packet. assert!(dgram.is_some()); // Drop this packet.
assert_eq!(client.get_epochs(), (Some(4), Some(3))); assert_eq!(client.get_epochs(), (Some(4), Some(3)));
mem::drop(server.process(None, now)); mem::drop(server.process_output(now));
assert_eq!(server.get_epochs(), (Some(4), Some(4))); assert_eq!(server.get_epochs(), (Some(4), Some(4)));
// Even though the server has updated, it hasn't received an ACK yet. // Even though the server has updated, it hasn't received an ACK yet.
@ -155,7 +155,7 @@ fn key_update_client() {
// The previous PTO packet (see above) was dropped, so we should get an ACK here. // The previous PTO packet (see above) was dropped, so we should get an ACK here.
let dgram = send_and_receive(&mut client, &mut server, now); let dgram = send_and_receive(&mut client, &mut server, now);
assert!(dgram.is_some()); assert!(dgram.is_some());
let res = client.process(dgram.as_ref(), now); let res = client.process(dgram, now);
// This is the first packet that the client has received from the server // This is the first packet that the client has received from the server
// with new keys, so its read timer just started. // with new keys, so its read timer just started.
if let Output::Callback(t) = res { if let Output::Callback(t) = res {
@ -170,7 +170,7 @@ fn key_update_client() {
assert_update_blocked(&mut server); assert_update_blocked(&mut server);
now += AT_LEAST_PTO; now += AT_LEAST_PTO;
mem::drop(client.process(None, now)); mem::drop(client.process_output(now));
assert_eq!(client.get_epochs(), (Some(4), Some(4))); assert_eq!(client.get_epochs(), (Some(4), Some(4)));
} }
@ -194,11 +194,11 @@ fn key_update_consecutive() {
assert_eq!(client.get_epochs(), (Some(4), Some(3))); assert_eq!(client.get_epochs(), (Some(4), Some(3)));
// Have the server process the ACK. // Have the server process the ACK.
if let Output::Callback(_) = server.process(dgram.as_ref(), now) { if let Output::Callback(_) = server.process(dgram, now) {
assert_eq!(server.get_epochs(), (Some(4), Some(3))); assert_eq!(server.get_epochs(), (Some(4), Some(3)));
// Now move the server temporarily into the future so that it // Now move the server temporarily into the future so that it
// rotates the keys. The client stays in the present. // rotates the keys. The client stays in the present.
mem::drop(server.process(None, now + AT_LEAST_PTO)); mem::drop(server.process_output(now + AT_LEAST_PTO));
assert_eq!(server.get_epochs(), (Some(4), Some(4))); assert_eq!(server.get_epochs(), (Some(4), Some(4)));
} else { } else {
panic!("server should have a timer set"); panic!("server should have a timer set");
@ -224,33 +224,33 @@ fn key_update_before_confirmed() {
assert_update_blocked(&mut server); assert_update_blocked(&mut server);
// Client Initial // Client Initial
let dgram = client.process(None, now()).dgram(); let dgram = client.process_output(now()).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
assert_update_blocked(&mut client); assert_update_blocked(&mut client);
// Server Initial + Handshake // Server Initial + Handshake
let dgram = server.process(dgram.as_ref(), now()).dgram(); let dgram = server.process(dgram, now()).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
assert_update_blocked(&mut server); assert_update_blocked(&mut server);
// Client Handshake // Client Handshake
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
assert_update_blocked(&mut client); assert_update_blocked(&mut client);
assert!(maybe_authenticate(&mut client)); assert!(maybe_authenticate(&mut client));
assert_update_blocked(&mut client); assert_update_blocked(&mut client);
let dgram = client.process(None, now()).dgram(); let dgram = client.process_output(now()).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
assert_update_blocked(&mut client); assert_update_blocked(&mut client);
// Server HANDSHAKE_DONE // Server HANDSHAKE_DONE
let dgram = server.process(dgram.as_ref(), now()).dgram(); let dgram = server.process(dgram, now()).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
assert!(server.initiate_key_update().is_ok()); assert!(server.initiate_key_update().is_ok());
// Client receives HANDSHAKE_DONE // Client receives HANDSHAKE_DONE
let dgram = client.process(dgram.as_ref(), now()).dgram(); let dgram = client.process(dgram, now()).dgram();
assert!(dgram.is_none()); assert!(dgram.is_none());
assert!(client.initiate_key_update().is_ok()); assert!(client.initiate_key_update().is_ok());
} }
@ -281,13 +281,13 @@ fn exhaust_read_keys() {
let dgram = send_something(&mut client, now()); let dgram = send_something(&mut client, now());
overwrite_invocations(0); overwrite_invocations(0);
let dgram = server.process(Some(&dgram), now()).dgram(); let dgram = server.process(Some(dgram), now()).dgram();
assert!(matches!( assert!(matches!(
server.state(), server.state(),
State::Closed(CloseReason::Transport(Error::KeysExhausted)) State::Closed(CloseReason::Transport(Error::KeysExhausted))
)); ));
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
assert!(matches!( assert!(matches!(
client.state(), client.state(),
State::Draining { State::Draining {

Просмотреть файл

@ -25,7 +25,7 @@ use super::{
}; };
use crate::{ use crate::{
cid::LOCAL_ACTIVE_CID_LIMIT, cid::LOCAL_ACTIVE_CID_LIMIT,
connection::tests::{send_something_paced, send_with_extra}, connection::tests::{assert_path_challenge_min_len, send_something_paced, send_with_extra},
frame::FRAME_TYPE_NEW_CONNECTION_ID, frame::FRAME_TYPE_NEW_CONNECTION_ID,
packet::PacketBuilder, packet::PacketBuilder,
path::MAX_PATH_PROBES, path::MAX_PATH_PROBES,
@ -75,7 +75,7 @@ fn rebinding_port() {
let dgram = send_something(&mut client, now()); let dgram = send_something(&mut client, now());
let dgram = change_source_port(&dgram); let dgram = change_source_port(&dgram);
server.process_input(&dgram, now()); server.process_input(dgram, now());
// Have the server send something so that it generates a packet. // Have the server send something so that it generates a packet.
let stream_id = server.stream_create(StreamType::UniDi).unwrap(); let stream_id = server.stream_create(StreamType::UniDi).unwrap();
server.stream_close_send(stream_id).unwrap(); server.stream_close_send(stream_id).unwrap();
@ -97,15 +97,17 @@ fn path_forwarding_attack() {
let dgram = send_something(&mut client, now); let dgram = send_something(&mut client, now);
let dgram = change_path(&dgram, DEFAULT_ADDR_V4); let dgram = change_path(&dgram, DEFAULT_ADDR_V4);
server.process_input(&dgram, now); server.process_input(dgram, now);
// The server now probes the new (primary) path. // The server now probes the new (primary) path.
let new_probe = server.process_output(now).dgram().unwrap(); let new_probe = server.process_output(now).dgram().unwrap();
assert_eq!(server.stats().frame_tx.path_challenge, 1); assert_eq!(server.stats().frame_tx.path_challenge, 1);
assert_path_challenge_min_len(&server, &new_probe, now);
assert_v4_path(&new_probe, false); // Can't be padded. assert_v4_path(&new_probe, false); // Can't be padded.
// The server also probes the old path. // The server also probes the old path.
let old_probe = server.process_output(now).dgram().unwrap(); let old_probe = server.process_output(now).dgram().unwrap();
assert_path_challenge_min_len(&server, &old_probe, now);
assert_eq!(server.stats().frame_tx.path_challenge, 2); assert_eq!(server.stats().frame_tx.path_challenge, 2);
assert_v6_path(&old_probe, true); assert_v6_path(&old_probe, true);
@ -117,14 +119,14 @@ fn path_forwarding_attack() {
// The client should respond to the challenge on the new path. // The client should respond to the challenge on the new path.
// The server couldn't pad, so the client is also amplification limited. // The server couldn't pad, so the client is also amplification limited.
let new_resp = client.process(Some(&new_probe), now).dgram().unwrap(); let new_resp = client.process(Some(new_probe), now).dgram().unwrap();
assert_eq!(client.stats().frame_rx.path_challenge, 1); assert_eq!(client.stats().frame_rx.path_challenge, 1);
assert_eq!(client.stats().frame_tx.path_challenge, 1); assert_eq!(client.stats().frame_tx.path_challenge, 1);
assert_eq!(client.stats().frame_tx.path_response, 1); assert_eq!(client.stats().frame_tx.path_response, 1);
assert_v4_path(&new_resp, false); assert_v4_path(&new_resp, false);
// The client also responds to probes on the old path. // The client also responds to probes on the old path.
let old_resp = client.process(Some(&old_probe), now).dgram().unwrap(); let old_resp = client.process(Some(old_probe), now).dgram().unwrap();
assert_eq!(client.stats().frame_rx.path_challenge, 2); assert_eq!(client.stats().frame_rx.path_challenge, 2);
assert_eq!(client.stats().frame_tx.path_challenge, 1); assert_eq!(client.stats().frame_tx.path_challenge, 1);
assert_eq!(client.stats().frame_tx.path_response, 2); assert_eq!(client.stats().frame_tx.path_response, 2);
@ -137,12 +139,13 @@ fn path_forwarding_attack() {
// Receiving the PATH_RESPONSE from the client opens the amplification // Receiving the PATH_RESPONSE from the client opens the amplification
// limit enough for the server to respond. // limit enough for the server to respond.
// This is padded because it includes PATH_CHALLENGE. // This is padded because it includes PATH_CHALLENGE.
let server_data1 = server.process(Some(&new_resp), now).dgram().unwrap(); let server_data1 = server.process(Some(new_resp), now).dgram().unwrap();
assert_v4_path(&server_data1, true); assert_v4_path(&server_data1, true);
assert_eq!(server.stats().frame_tx.path_challenge, 3); assert_eq!(server.stats().frame_tx.path_challenge, 3);
assert_path_challenge_min_len(&server, &server_data1, now);
// The client responds to this probe on the new path. // The client responds to this probe on the new path.
client.process_input(&server_data1, now); client.process_input(server_data1, now);
let stream_before = client.stats().frame_tx.stream; let stream_before = client.stats().frame_tx.stream;
let padded_resp = send_something(&mut client, now); let padded_resp = send_something(&mut client, now);
assert_eq!(stream_before, client.stats().frame_tx.stream); assert_eq!(stream_before, client.stats().frame_tx.stream);
@ -157,7 +160,7 @@ fn path_forwarding_attack() {
assert_v4_path(&server_data2, false); assert_v4_path(&server_data2, false);
// Until new data is received from the client on the old path. // Until new data is received from the client on the old path.
server.process_input(&client_data2, now); server.process_input(client_data2, now);
// The server sends a probe on the new path. // The server sends a probe on the new path.
let server_data3 = send_something(&mut server, now); let server_data3 = send_something(&mut server, now);
assert_v4_path(&server_data3, true); assert_v4_path(&server_data3, true);
@ -179,13 +182,15 @@ fn migrate_immediate() {
let client1 = send_something(&mut client, now); let client1 = send_something(&mut client, now);
assert_v4_path(&client1, true); // Contains PATH_CHALLENGE. assert_v4_path(&client1, true); // Contains PATH_CHALLENGE.
assert_path_challenge_min_len(&client, &client1, now);
let client2 = send_something(&mut client, now); let client2 = send_something(&mut client, now);
assert_v4_path(&client2, false); // Doesn't. assert_v4_path(&client2, false); // Doesn't.
let server_delayed = send_something(&mut server, now); let server_delayed = send_something(&mut server, now);
// The server accepts the first packet and migrates (but probes). // The server accepts the first packet and migrates (but probes).
let server1 = server.process(Some(&client1), now).dgram().unwrap(); let server1 = server.process(Some(client1), now).dgram().unwrap();
assert_v4_path(&server1, true); assert_v4_path(&server1, true);
let server2 = server.process_output(now).dgram().unwrap(); let server2 = server.process_output(now).dgram().unwrap();
assert_v6_path(&server2, true); assert_v6_path(&server2, true);
@ -193,13 +198,13 @@ fn migrate_immediate() {
// The second packet has no real effect, it just elicits an ACK. // The second packet has no real effect, it just elicits an ACK.
let all_before = server.stats().frame_tx.all(); let all_before = server.stats().frame_tx.all();
let ack_before = server.stats().frame_tx.ack; let ack_before = server.stats().frame_tx.ack;
let server3 = server.process(Some(&client2), now).dgram(); let server3 = server.process(Some(client2), now).dgram();
assert!(server3.is_some()); assert!(server3.is_some());
assert_eq!(server.stats().frame_tx.all(), all_before + 1); assert_eq!(server.stats().frame_tx.all(), all_before + 1);
assert_eq!(server.stats().frame_tx.ack, ack_before + 1); assert_eq!(server.stats().frame_tx.ack, ack_before + 1);
// Receiving a packet sent by the server before migration doesn't change path. // Receiving a packet sent by the server before migration doesn't change path.
client.process_input(&server_delayed, now); client.process_input(server_delayed, now);
// The client has sent two unpaced packets and this new path has no RTT estimate // The client has sent two unpaced packets and this new path has no RTT estimate
// so this might be paced. // so this might be paced.
let (client3, _t) = send_something_paced(&mut client, now, true); let (client3, _t) = send_something_paced(&mut client, now, true);
@ -236,6 +241,7 @@ fn migrate_immediate_fail() {
let probe = client.process_output(now).dgram().unwrap(); let probe = client.process_output(now).dgram().unwrap();
assert_v4_path(&probe, true); // Contains PATH_CHALLENGE. assert_v4_path(&probe, true); // Contains PATH_CHALLENGE.
assert_path_challenge_min_len(&client, &probe, now);
// -1 because first PATH_CHALLENGE already sent above // -1 because first PATH_CHALLENGE already sent above
for _ in 0..MAX_PATH_PROBES * 2 - 1 { for _ in 0..MAX_PATH_PROBES * 2 - 1 {
@ -246,6 +252,7 @@ fn migrate_immediate_fail() {
let before = client.stats().frame_tx; let before = client.stats().frame_tx;
let probe = client.process_output(now).dgram().unwrap(); let probe = client.process_output(now).dgram().unwrap();
assert_v4_path(&probe, true); // Contains PATH_CHALLENGE. assert_v4_path(&probe, true); // Contains PATH_CHALLENGE.
assert_path_challenge_min_len(&client, &probe, now);
let after = client.stats().frame_tx; let after = client.stats().frame_tx;
assert_eq!(after.path_challenge, before.path_challenge + 1); assert_eq!(after.path_challenge, before.path_challenge + 1);
assert_eq!(after.padding, before.padding + 1); assert_eq!(after.padding, before.padding + 1);
@ -253,8 +260,9 @@ fn migrate_immediate_fail() {
// This might be a PTO, which will result in sending a probe. // This might be a PTO, which will result in sending a probe.
if let Some(probe) = client.process_output(now).dgram() { if let Some(probe) = client.process_output(now).dgram() {
assert_v4_path(&probe, false); // Contains PATH_CHALLENGE. assert_v4_path(&probe, false); // Contains PING.
let after = client.stats().frame_tx; let after = client.stats().frame_tx;
assert_eq!(after.path_challenge, before.path_challenge + 1);
assert_eq!(after.ping, before.ping + 1); assert_eq!(after.ping, before.ping + 1);
assert_eq!(after.all(), before.all() + 3); assert_eq!(after.all(), before.all() + 3);
} }
@ -286,14 +294,15 @@ fn migrate_same() {
let probe = client.process_output(now).dgram().unwrap(); let probe = client.process_output(now).dgram().unwrap();
assert_v6_path(&probe, true); // Contains PATH_CHALLENGE. assert_v6_path(&probe, true); // Contains PATH_CHALLENGE.
assert_eq!(client.stats().frame_tx.path_challenge, 1); assert_eq!(client.stats().frame_tx.path_challenge, 1);
assert_path_challenge_min_len(&client, &probe, now);
let resp = server.process(Some(&probe), now).dgram().unwrap(); let resp = server.process(Some(probe), now).dgram().unwrap();
assert_v6_path(&resp, true); assert_v6_path(&resp, true);
assert_eq!(server.stats().frame_tx.path_response, 1); assert_eq!(server.stats().frame_tx.path_response, 1);
assert_eq!(server.stats().frame_tx.path_challenge, 0); assert_eq!(server.stats().frame_tx.path_challenge, 0);
// Everything continues happily. // Everything continues happily.
client.process_input(&resp, now); client.process_input(resp, now);
let contd = send_something(&mut client, now); let contd = send_something(&mut client, now);
assert_v6_path(&contd, false); assert_v6_path(&contd, false);
} }
@ -312,6 +321,7 @@ fn migrate_same_fail() {
let probe = client.process_output(now).dgram().unwrap(); let probe = client.process_output(now).dgram().unwrap();
assert_v6_path(&probe, true); // Contains PATH_CHALLENGE. assert_v6_path(&probe, true); // Contains PATH_CHALLENGE.
assert_path_challenge_min_len(&client, &probe, now);
// -1 because first PATH_CHALLENGE already sent above // -1 because first PATH_CHALLENGE already sent above
for _ in 0..MAX_PATH_PROBES * 2 - 1 { for _ in 0..MAX_PATH_PROBES * 2 - 1 {
@ -322,6 +332,7 @@ fn migrate_same_fail() {
let before = client.stats().frame_tx; let before = client.stats().frame_tx;
let probe = client.process_output(now).dgram().unwrap(); let probe = client.process_output(now).dgram().unwrap();
assert_v6_path(&probe, true); // Contains PATH_CHALLENGE. assert_v6_path(&probe, true); // Contains PATH_CHALLENGE.
assert_path_challenge_min_len(&client, &probe, now);
let after = client.stats().frame_tx; let after = client.stats().frame_tx;
assert_eq!(after.path_challenge, before.path_challenge + 1); assert_eq!(after.path_challenge, before.path_challenge + 1);
assert_eq!(after.padding, before.padding + 1); assert_eq!(after.padding, before.padding + 1);
@ -329,8 +340,9 @@ fn migrate_same_fail() {
// This might be a PTO, which will result in sending a probe. // This might be a PTO, which will result in sending a probe.
if let Some(probe) = client.process_output(now).dgram() { if let Some(probe) = client.process_output(now).dgram() {
assert_v6_path(&probe, false); // Contains PATH_CHALLENGE. assert_v6_path(&probe, false); // Contains PING.
let after = client.stats().frame_tx; let after = client.stats().frame_tx;
assert_eq!(after.path_challenge, before.path_challenge + 1);
assert_eq!(after.ping, before.ping + 1); assert_eq!(after.ping, before.ping + 1);
assert_eq!(after.all(), before.all() + 3); assert_eq!(after.all(), before.all() + 3);
} }
@ -368,11 +380,13 @@ fn migration(mut client: Connection) {
let probe = client.process_output(now).dgram().unwrap(); let probe = client.process_output(now).dgram().unwrap();
assert_v4_path(&probe, true); // Contains PATH_CHALLENGE. assert_v4_path(&probe, true); // Contains PATH_CHALLENGE.
assert_path_challenge_min_len(&client, &probe, now);
assert_eq!(client.stats().frame_tx.path_challenge, 1); assert_eq!(client.stats().frame_tx.path_challenge, 1);
let probe_cid = ConnectionId::from(get_cid(&probe)); let probe_cid = ConnectionId::from(get_cid(&probe));
let resp = server.process(Some(&probe), now).dgram().unwrap(); let resp = server.process(Some(probe), now).dgram().unwrap();
assert_v4_path(&resp, true); assert_v4_path(&resp, true);
assert_path_challenge_min_len(&server, &resp, now);
assert_eq!(server.stats().frame_tx.path_response, 1); assert_eq!(server.stats().frame_tx.path_response, 1);
assert_eq!(server.stats().frame_tx.path_challenge, 1); assert_eq!(server.stats().frame_tx.path_challenge, 1);
@ -380,12 +394,12 @@ fn migration(mut client: Connection) {
let client_data = send_something(&mut client, now); let client_data = send_something(&mut client, now);
assert_ne!(get_cid(&client_data), probe_cid); assert_ne!(get_cid(&client_data), probe_cid);
assert_v6_path(&client_data, false); assert_v6_path(&client_data, false);
server.process_input(&client_data, now); server.process_input(client_data, now);
let server_data = send_something(&mut server, now); let server_data = send_something(&mut server, now);
assert_v6_path(&server_data, false); assert_v6_path(&server_data, false);
// Once the client receives the probe response, it migrates to the new path. // Once the client receives the probe response, it migrates to the new path.
client.process_input(&resp, now); client.process_input(resp, now);
assert_eq!(client.stats().frame_rx.path_challenge, 1); assert_eq!(client.stats().frame_rx.path_challenge, 1);
let migrate_client = send_something(&mut client, now); let migrate_client = send_something(&mut client, now);
assert_v4_path(&migrate_client, true); // Responds to server probe. assert_v4_path(&migrate_client, true); // Responds to server probe.
@ -394,11 +408,12 @@ fn migration(mut client: Connection) {
// However, it will probe the old path again, even though it has just // However, it will probe the old path again, even though it has just
// received a response to its last probe, because it needs to verify // received a response to its last probe, because it needs to verify
// that the migration is genuine. // that the migration is genuine.
server.process_input(&migrate_client, now); server.process_input(migrate_client, now);
let stream_before = server.stats().frame_tx.stream; let stream_before = server.stats().frame_tx.stream;
let probe_old_server = send_something(&mut server, now); let probe_old_server = send_something(&mut server, now);
// This is just the double-check probe; no STREAM frames. // This is just the double-check probe; no STREAM frames.
assert_v6_path(&probe_old_server, true); assert_v6_path(&probe_old_server, true);
assert_path_challenge_min_len(&server, &probe_old_server, now);
assert_eq!(server.stats().frame_tx.path_challenge, 2); assert_eq!(server.stats().frame_tx.path_challenge, 2);
assert_eq!(server.stats().frame_tx.stream, stream_before); assert_eq!(server.stats().frame_tx.stream, stream_before);
@ -409,8 +424,8 @@ fn migration(mut client: Connection) {
assert_eq!(server.stats().frame_tx.stream, stream_before + 1); assert_eq!(server.stats().frame_tx.stream, stream_before + 1);
// The client receives these checks and responds to the probe, but uses the new path. // The client receives these checks and responds to the probe, but uses the new path.
client.process_input(&migrate_server, now); client.process_input(migrate_server, now);
client.process_input(&probe_old_server, now); client.process_input(probe_old_server, now);
let old_probe_resp = send_something(&mut client, now); let old_probe_resp = send_something(&mut client, now);
assert_v6_path(&old_probe_resp, true); assert_v6_path(&old_probe_resp, true);
let client_confirmation = client.process_output(now).dgram().unwrap(); let client_confirmation = client.process_output(now).dgram().unwrap();
@ -450,11 +465,11 @@ fn migration_client_empty_cid() {
/// Returns the packet containing `HANDSHAKE_DONE` from the server. /// Returns the packet containing `HANDSHAKE_DONE` from the server.
fn fast_handshake(client: &mut Connection, server: &mut Connection) -> Option<Datagram> { fn fast_handshake(client: &mut Connection, server: &mut Connection) -> Option<Datagram> {
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
let dgram = server.process(dgram.as_ref(), now()).dgram(); let dgram = server.process(dgram, now()).dgram();
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
assert!(maybe_authenticate(client)); assert!(maybe_authenticate(client));
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
server.process(dgram.as_ref(), now()).dgram() server.process(dgram, now()).dgram()
} }
fn preferred_address(hs_client: SocketAddr, hs_server: SocketAddr, preferred: SocketAddr) { fn preferred_address(hs_client: SocketAddr, hs_server: SocketAddr, preferred: SocketAddr) {
@ -512,9 +527,10 @@ fn preferred_address(hs_client: SocketAddr, hs_server: SocketAddr, preferred: So
// The client is about to process HANDSHAKE_DONE. // The client is about to process HANDSHAKE_DONE.
// It should start probing toward the server's preferred address. // It should start probing toward the server's preferred address.
let probe = client.process(dgram.as_ref(), now()).dgram().unwrap(); let probe = client.process(dgram, now()).dgram().unwrap();
assert_toward_spa(&probe, true); assert_toward_spa(&probe, true);
assert_eq!(client.stats().frame_tx.path_challenge, 1); assert_eq!(client.stats().frame_tx.path_challenge, 1);
assert_path_challenge_min_len(&client, &probe, now());
assert_ne!(client.process_output(now()).callback(), Duration::new(0, 0)); assert_ne!(client.process_output(now()).callback(), Duration::new(0, 0));
// Data continues on the main path for the client. // Data continues on the main path for the client.
@ -522,28 +538,30 @@ fn preferred_address(hs_client: SocketAddr, hs_server: SocketAddr, preferred: So
assert_orig_path(&data, false); assert_orig_path(&data, false);
// The server responds to the probe. // The server responds to the probe.
let resp = server.process(Some(&probe), now()).dgram().unwrap(); let resp = server.process(Some(probe), now()).dgram().unwrap();
assert_from_spa(&resp, true); assert_from_spa(&resp, true);
assert_eq!(server.stats().frame_tx.path_challenge, 1); assert_eq!(server.stats().frame_tx.path_challenge, 1);
assert_path_challenge_min_len(&server, &resp, now());
assert_eq!(server.stats().frame_tx.path_response, 1); assert_eq!(server.stats().frame_tx.path_response, 1);
// Data continues on the main path for the server. // Data continues on the main path for the server.
server.process_input(&data, now()); server.process_input(data, now());
let data = send_something(&mut server, now()); let data = send_something(&mut server, now());
assert_orig_path(&data, false); assert_orig_path(&data, false);
// Client gets the probe response back and it migrates. // Client gets the probe response back and it migrates.
client.process_input(&resp, now()); client.process_input(resp, now());
client.process_input(&data, now()); client.process_input(data, now());
let data = send_something(&mut client, now()); let data = send_something(&mut client, now());
assert_toward_spa(&data, true); assert_toward_spa(&data, true);
assert_eq!(client.stats().frame_tx.stream, 2); assert_eq!(client.stats().frame_tx.stream, 2);
assert_eq!(client.stats().frame_tx.path_response, 1); assert_eq!(client.stats().frame_tx.path_response, 1);
// The server sees the migration and probes the old path. // The server sees the migration and probes the old path.
let probe = server.process(Some(&data), now()).dgram().unwrap(); let probe = server.process(Some(data), now()).dgram().unwrap();
assert_orig_path(&probe, true); assert_orig_path(&probe, true);
assert_eq!(server.stats().frame_tx.path_challenge, 2); assert_eq!(server.stats().frame_tx.path_challenge, 2);
assert_path_challenge_min_len(&server, &probe, now());
// But data now goes on the new path. // But data now goes on the new path.
let data = send_something(&mut server, now()); let data = send_something(&mut server, now());
@ -583,7 +601,7 @@ fn expect_no_migration(client: &mut Connection, server: &mut Connection) {
let dgram = fast_handshake(client, server); let dgram = fast_handshake(client, server);
// The client won't probe now, though it could; it remains idle. // The client won't probe now, though it could; it remains idle.
let out = client.process(dgram.as_ref(), now()); let out = client.process(dgram, now());
assert_ne!(out.callback(), Duration::new(0, 0)); assert_ne!(out.callback(), Duration::new(0, 0));
// Data continues on the main path for the client. // Data continues on the main path for the client.
@ -708,14 +726,14 @@ fn migration_invalid_state() {
assert!(client assert!(client
.migrate(Some(DEFAULT_ADDR), Some(DEFAULT_ADDR), false, now()) .migrate(Some(DEFAULT_ADDR), Some(DEFAULT_ADDR), false, now())
.is_err()); .is_err());
let close = client.process(None, now()).dgram(); let close = client.process_output(now()).dgram();
let dgram = server.process(close.as_ref(), now()).dgram(); let dgram = server.process(close, now()).dgram();
assert!(server assert!(server
.migrate(Some(DEFAULT_ADDR), Some(DEFAULT_ADDR), false, now()) .migrate(Some(DEFAULT_ADDR), Some(DEFAULT_ADDR), false, now())
.is_err()); .is_err());
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
assert!(client assert!(client
.migrate(Some(DEFAULT_ADDR), Some(DEFAULT_ADDR), false, now()) .migrate(Some(DEFAULT_ADDR), Some(DEFAULT_ADDR), false, now())
.is_err()); .is_err());
@ -814,7 +832,7 @@ fn retire_all() {
let new_cid_before = client.stats().frame_rx.new_connection_id; let new_cid_before = client.stats().frame_rx.new_connection_id;
let retire_cid_before = client.stats().frame_tx.retire_connection_id; let retire_cid_before = client.stats().frame_tx.retire_connection_id;
client.process_input(&ncid, now()); client.process_input(ncid, now());
let retire = send_something(&mut client, now()); let retire = send_something(&mut client, now());
assert_eq!( assert_eq!(
client.stats().frame_rx.new_connection_id, client.stats().frame_rx.new_connection_id,
@ -854,6 +872,7 @@ fn retire_prior_to_migration_failure() {
let probe = client.process_output(now()).dgram().unwrap(); let probe = client.process_output(now()).dgram().unwrap();
assert_v4_path(&probe, true); assert_v4_path(&probe, true);
assert_eq!(client.stats().frame_tx.path_challenge, 1); assert_eq!(client.stats().frame_tx.path_challenge, 1);
assert_path_challenge_min_len(&client, &probe, now());
let probe_cid = ConnectionId::from(get_cid(&probe)); let probe_cid = ConnectionId::from(get_cid(&probe));
assert_ne!(original_cid, probe_cid); assert_ne!(original_cid, probe_cid);
@ -861,17 +880,18 @@ fn retire_prior_to_migration_failure() {
// retire all of the available connection IDs. // retire all of the available connection IDs.
let retire_all = send_with_extra(&mut server, RetireAll { cid_gen }, now()); let retire_all = send_with_extra(&mut server, RetireAll { cid_gen }, now());
let resp = server.process(Some(&probe), now()).dgram().unwrap(); let resp = server.process(Some(probe), now()).dgram().unwrap();
assert_v4_path(&resp, true); assert_v4_path(&resp, true);
assert_eq!(server.stats().frame_tx.path_response, 1); assert_eq!(server.stats().frame_tx.path_response, 1);
assert_eq!(server.stats().frame_tx.path_challenge, 1); assert_eq!(server.stats().frame_tx.path_challenge, 1);
assert_path_challenge_min_len(&server, &resp, now());
// Have the client receive the NEW_CONNECTION_ID with Retire Prior To. // Have the client receive the NEW_CONNECTION_ID with Retire Prior To.
client.process_input(&retire_all, now()); client.process_input(retire_all, now());
// This packet contains the probe response, which should be fine, but it // This packet contains the probe response, which should be fine, but it
// also includes PATH_CHALLENGE for the new path, and the client can't // also includes PATH_CHALLENGE for the new path, and the client can't
// respond without a connection ID. We treat this as a connection error. // respond without a connection ID. We treat this as a connection error.
client.process_input(&resp, now()); client.process_input(resp, now());
assert!(matches!( assert!(matches!(
client.state(), client.state(),
State::Closing { State::Closing {
@ -907,6 +927,7 @@ fn retire_prior_to_migration_success() {
let probe = client.process_output(now()).dgram().unwrap(); let probe = client.process_output(now()).dgram().unwrap();
assert_v4_path(&probe, true); assert_v4_path(&probe, true);
assert_eq!(client.stats().frame_tx.path_challenge, 1); assert_eq!(client.stats().frame_tx.path_challenge, 1);
assert_path_challenge_min_len(&client, &probe, now());
let probe_cid = ConnectionId::from(get_cid(&probe)); let probe_cid = ConnectionId::from(get_cid(&probe));
assert_ne!(original_cid, probe_cid); assert_ne!(original_cid, probe_cid);
@ -914,15 +935,16 @@ fn retire_prior_to_migration_success() {
// retire all of the available connection IDs. // retire all of the available connection IDs.
let retire_all = send_with_extra(&mut server, RetireAll { cid_gen }, now()); let retire_all = send_with_extra(&mut server, RetireAll { cid_gen }, now());
let resp = server.process(Some(&probe), now()).dgram().unwrap(); let resp = server.process(Some(probe), now()).dgram().unwrap();
assert_v4_path(&resp, true); assert_v4_path(&resp, true);
assert_eq!(server.stats().frame_tx.path_response, 1); assert_eq!(server.stats().frame_tx.path_response, 1);
assert_eq!(server.stats().frame_tx.path_challenge, 1); assert_eq!(server.stats().frame_tx.path_challenge, 1);
assert_path_challenge_min_len(&server, &resp, now());
// Have the client receive the NEW_CONNECTION_ID with Retire Prior To second. // Have the client receive the NEW_CONNECTION_ID with Retire Prior To second.
// As this occurs in a very specific order, migration succeeds. // As this occurs in a very specific order, migration succeeds.
client.process_input(&resp, now()); client.process_input(resp, now());
client.process_input(&retire_all, now()); client.process_input(retire_all, now());
// Migration succeeds and the new path gets the last connection ID. // Migration succeeds and the new path gets the last connection ID.
let dgram = send_something(&mut client, now()); let dgram = send_something(&mut client, now());
@ -952,12 +974,12 @@ fn error_on_new_path_with_no_connection_id() {
Rc::new(RefCell::new(CountingConnectionIdGenerator::default())); Rc::new(RefCell::new(CountingConnectionIdGenerator::default()));
let retire_all = send_with_extra(&mut server, RetireAll { cid_gen }, now()); let retire_all = send_with_extra(&mut server, RetireAll { cid_gen }, now());
client.process_input(&retire_all, now()); client.process_input(retire_all, now());
let garbage = send_with_extra(&mut server, GarbageWriter {}, now()); let garbage = send_with_extra(&mut server, GarbageWriter {}, now());
let dgram = change_path(&garbage, DEFAULT_ADDR_V4); let dgram = change_path(&garbage, DEFAULT_ADDR_V4);
client.process_input(&dgram, now()); client.process_input(dgram, now());
// See issue #1697. We had a crash when the client had a temporary path and // See issue #1697. We had a crash when the client had a temporary path and
// process_output is called. // process_output is called.
@ -972,7 +994,7 @@ fn error_on_new_path_with_no_connection_id() {
)); ));
// Wait until the connection is closed. // Wait until the connection is closed.
let mut now = now(); let mut now = now();
now += client.process(None, now).callback(); now += client.process_output(now).callback();
_ = client.process_output(now); _ = client.process_output(now);
// No closing frames should be sent, and the connection should be closed. // No closing frames should be sent, and the connection should be closed.
assert_eq!(client.stats().frame_tx.connection_close, closing_frames); assert_eq!(client.stats().frame_tx.connection_close, closing_frames);

Просмотреть файл

@ -30,7 +30,7 @@ use crate::{
stats::{FrameStats, Stats, MAX_PTO_COUNTS}, stats::{FrameStats, Stats, MAX_PTO_COUNTS},
tparams::{DISABLE_MIGRATION, GREASE_QUIC_BIT}, tparams::{DISABLE_MIGRATION, GREASE_QUIC_BIT},
ConnectionIdDecoder, ConnectionIdGenerator, ConnectionParameters, Error, StreamId, StreamType, ConnectionIdDecoder, ConnectionIdGenerator, ConnectionParameters, Error, StreamId, StreamType,
Version, Version, MIN_INITIAL_PACKET_SIZE,
}; };
// All the tests. // All the tests.
@ -208,7 +208,7 @@ fn handshake_with_modifier(
if should_ping { if should_ping {
a.test_frame_writer = Some(Box::new(PingWriter {})); a.test_frame_writer = Some(Box::new(PingWriter {}));
} }
let output = a.process(input.as_ref(), now).dgram(); let output = a.process(input, now).dgram();
if should_ping { if should_ping {
a.test_frame_writer = None; a.test_frame_writer = None;
did_ping[a.role()] = true; did_ping[a.role()] = true;
@ -219,7 +219,7 @@ fn handshake_with_modifier(
mem::swap(&mut a, &mut b); mem::swap(&mut a, &mut b);
} }
if let Some(d) = input { if let Some(d) = input {
a.process_input(&d, now); a.process_input(d, now);
} }
now now
} }
@ -299,7 +299,7 @@ fn exchange_ticket(
server.send_ticket(now, &[]).expect("can send ticket"); server.send_ticket(now, &[]).expect("can send ticket");
let ticket = server.process_output(now).dgram(); let ticket = server.process_output(now).dgram();
assert!(ticket.is_some()); assert!(ticket.is_some());
client.process_input(&ticket.unwrap(), now); client.process_input(ticket.unwrap(), now);
assert_eq!(*client.state(), State::Confirmed); assert_eq!(*client.state(), State::Confirmed);
get_tokens(client).pop().expect("should have token") get_tokens(client).pop().expect("should have token")
} }
@ -397,7 +397,7 @@ fn fill_cwnd(c: &mut Connection, stream: StreamId, mut now: Instant) -> (Vec<Dat
qtrace!( qtrace!(
"fill_cwnd sent {} bytes", "fill_cwnd sent {} bytes",
total_dgrams.iter().map(|d| d.len()).sum::<usize>() total_dgrams.iter().map(Datagram::len).sum::<usize>()
); );
(total_dgrams, now) (total_dgrams, now)
} }
@ -415,7 +415,7 @@ fn increase_cwnd(
let pkt = sender.process_output(now); let pkt = sender.process_output(now);
match pkt { match pkt {
Output::Datagram(dgram) => { Output::Datagram(dgram) => {
receiver.process_input(&dgram, now + DEFAULT_RTT / 2); receiver.process_input(dgram, now + DEFAULT_RTT / 2);
} }
Output::Callback(t) => { Output::Callback(t) => {
if t < DEFAULT_RTT { if t < DEFAULT_RTT {
@ -432,7 +432,7 @@ fn increase_cwnd(
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
let ack = receiver.process_output(now).dgram(); let ack = receiver.process_output(now).dgram();
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
sender.process_input(&ack.unwrap(), now); sender.process_input(ack.unwrap(), now);
now now
} }
@ -453,7 +453,7 @@ where
let in_dgrams = in_dgrams.into_iter(); let in_dgrams = in_dgrams.into_iter();
qdebug!([dest], "ack_bytes {} datagrams", in_dgrams.len()); qdebug!([dest], "ack_bytes {} datagrams", in_dgrams.len());
for dgram in in_dgrams { for dgram in in_dgrams {
dest.process_input(&dgram, now); dest.process_input(dgram, now);
} }
loop { loop {
@ -524,7 +524,7 @@ fn induce_persistent_congestion(
// An ACK for the third PTO causes persistent congestion. // An ACK for the third PTO causes persistent congestion.
let s_ack = ack_bytes(server, stream, c_tx_dgrams, now); let s_ack = ack_bytes(server, stream, c_tx_dgrams, now);
client.process_input(&s_ack, now); client.process_input(s_ack, now);
assert_eq!(cwnd(client), cwnd_min(client)); assert_eq!(cwnd(client), cwnd_min(client));
now now
} }
@ -635,7 +635,7 @@ fn send_with_modifier_and_receive(
modifier: fn(Datagram) -> Option<Datagram>, modifier: fn(Datagram) -> Option<Datagram>,
) -> Option<Datagram> { ) -> Option<Datagram> {
let dgram = send_something_with_modifier(sender, now, modifier); let dgram = send_something_with_modifier(sender, now, modifier);
receiver.process(Some(&dgram), now).dgram() receiver.process(Some(dgram), now).dgram()
} }
/// Send something on a stream from `sender` to `receiver`. /// Send something on a stream from `sender` to `receiver`.
@ -669,6 +669,27 @@ fn assert_default_stats(stats: &Stats) {
assert_eq!(stats.frame_tx, dflt_frames); assert_eq!(stats.frame_tx, dflt_frames);
} }
fn assert_path_challenge_min_len(c: &Connection, d: &Datagram, now: Instant) {
let path = c.paths.find_path(
d.source(),
d.destination(),
c.conn_params.get_cc_algorithm(),
c.conn_params.pacing_enabled(),
now,
);
if path.borrow().amplification_limit() < path.borrow().plpmtu() {
// If the amplification limit is less than the PLPMTU, then the path
// challenge will not have been padded.
return;
}
assert!(
d.len() >= MIN_INITIAL_PACKET_SIZE,
"{} < {}",
d.len(),
MIN_INITIAL_PACKET_SIZE
);
}
#[test] #[test]
fn create_client() { fn create_client() {
let client = default_client(); let client = default_client();

Просмотреть файл

@ -26,7 +26,7 @@ fn no_encryption() {
let client_pkt = client.process_output(now()).dgram().unwrap(); let client_pkt = client.process_output(now()).dgram().unwrap();
assert!(client_pkt[..client_pkt.len() - AEAD_NULL_TAG.len()].ends_with(DATA_CLIENT)); assert!(client_pkt[..client_pkt.len() - AEAD_NULL_TAG.len()].ends_with(DATA_CLIENT));
server.process_input(&client_pkt, now()); server.process_input(client_pkt, now());
let mut buf = vec![0; 100]; let mut buf = vec![0; 100];
let (len, _) = server.stream_recv(stream_id, &mut buf).unwrap(); let (len, _) = server.stream_recv(stream_id, &mut buf).unwrap();
assert_eq!(len, DATA_CLIENT.len()); assert_eq!(len, DATA_CLIENT.len());
@ -35,7 +35,7 @@ fn no_encryption() {
let server_pkt = server.process_output(now()).dgram().unwrap(); let server_pkt = server.process_output(now()).dgram().unwrap();
assert!(server_pkt[..server_pkt.len() - AEAD_NULL_TAG.len()].ends_with(DATA_SERVER)); assert!(server_pkt[..server_pkt.len() - AEAD_NULL_TAG.len()].ends_with(DATA_SERVER));
client.process_input(&server_pkt, now()); client.process_input(server_pkt, now());
let (len, _) = client.stream_recv(stream_id, &mut buf).unwrap(); let (len, _) = client.stream_recv(stream_id, &mut buf).unwrap();
assert_eq!(len, DATA_SERVER.len()); assert_eq!(len, DATA_SERVER.len());
assert_eq!(&buf[..len], DATA_SERVER); assert_eq!(&buf[..len], DATA_SERVER);

Просмотреть файл

@ -41,7 +41,7 @@ fn receive_stream() {
assert_eq!(MESSAGE.len(), client.stream_send(id, MESSAGE).unwrap()); assert_eq!(MESSAGE.len(), client.stream_send(id, MESSAGE).unwrap());
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
server.process_input(&dgram.unwrap(), now()); server.process_input(dgram.unwrap(), now());
assert_eq!( assert_eq!(
server server
.stream_priority( .stream_priority(
@ -83,7 +83,7 @@ fn relative() {
.unwrap(); .unwrap();
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
server.process_input(&dgram.unwrap(), now()); server.process_input(dgram.unwrap(), now());
// The "id_normal" stream will get a `NewStream` event, but no data. // The "id_normal" stream will get a `NewStream` event, but no data.
for e in server.events() { for e in server.events() {
@ -114,7 +114,7 @@ fn reprioritize() {
.unwrap(); .unwrap();
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
server.process_input(&dgram.unwrap(), now()); server.process_input(dgram.unwrap(), now());
// The "id_normal" stream will get a `NewStream` event, but no data. // The "id_normal" stream will get a `NewStream` event, but no data.
for e in server.events() { for e in server.events() {
@ -133,7 +133,7 @@ fn reprioritize() {
) )
.unwrap(); .unwrap();
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
server.process_input(&dgram.unwrap(), now()); server.process_input(dgram.unwrap(), now());
for e in server.events() { for e in server.events() {
if let ConnectionEvent::RecvStreamReadable { stream_id } = e { if let ConnectionEvent::RecvStreamReadable { stream_id } = e {
@ -164,7 +164,7 @@ fn repairing_loss() {
let _lost = client.process_output(now).dgram(); let _lost = client.process_output(now).dgram();
for _ in 0..5 { for _ in 0..5 {
match client.process_output(now) { match client.process_output(now) {
Output::Datagram(d) => server.process_input(&d, now), Output::Datagram(d) => server.process_input(d, now),
Output::Callback(delay) => now += delay, Output::Callback(delay) => now += delay,
Output::None => unreachable!(), Output::None => unreachable!(),
} }
@ -177,9 +177,9 @@ fn repairing_loss() {
let id_normal = client.stream_create(StreamType::UniDi).unwrap(); let id_normal = client.stream_create(StreamType::UniDi).unwrap();
fill_stream(&mut client, id_normal); fill_stream(&mut client, id_normal);
let dgram = client.process(ack.as_ref(), now).dgram(); let dgram = client.process(ack, now).dgram();
assert_eq!(client.stats().lost, 1); // Client should have noticed the loss. assert_eq!(client.stats().lost, 1); // Client should have noticed the loss.
server.process_input(&dgram.unwrap(), now); server.process_input(dgram.unwrap(), now);
// Only the low priority stream has data as the retransmission of the data from // Only the low priority stream has data as the retransmission of the data from
// the lost packet is now more important than new data from the high priority stream. // the lost packet is now more important than new data from the high priority stream.
@ -195,7 +195,7 @@ fn repairing_loss() {
// the retransmitted data into a second packet, it will also contain data from the // the retransmitted data into a second packet, it will also contain data from the
// normal priority stream. // normal priority stream.
let dgram = client.process_output(now).dgram(); let dgram = client.process_output(now).dgram();
server.process_input(&dgram.unwrap(), now); server.process_input(dgram.unwrap(), now);
assert!(server.events().any( assert!(server.events().any(
|e| matches!(e, ConnectionEvent::RecvStreamReadable { stream_id } if stream_id == id_normal), |e| matches!(e, ConnectionEvent::RecvStreamReadable { stream_id } if stream_id == id_normal),
)); ));
@ -210,8 +210,8 @@ fn critical() {
// Rather than connect, send stream data in 0.5-RTT. // Rather than connect, send stream data in 0.5-RTT.
// That allows this to test that critical streams pre-empt most frame types. // That allows this to test that critical streams pre-empt most frame types.
let dgram = client.process_output(now).dgram(); let dgram = client.process_output(now).dgram();
let dgram = server.process(dgram.as_ref(), now).dgram(); let dgram = server.process(dgram, now).dgram();
client.process_input(&dgram.unwrap(), now); client.process_input(dgram.unwrap(), now);
maybe_authenticate(&mut client); maybe_authenticate(&mut client);
let id = server.stream_create(StreamType::UniDi).unwrap(); let id = server.stream_create(StreamType::UniDi).unwrap();
@ -238,8 +238,8 @@ fn critical() {
assert_eq!(stats_after.handshake_done, 0); assert_eq!(stats_after.handshake_done, 0);
// Complete the handshake. // Complete the handshake.
let dgram = client.process(dgram.as_ref(), now).dgram(); let dgram = client.process(dgram, now).dgram();
server.process_input(&dgram.unwrap(), now); server.process_input(dgram.unwrap(), now);
// Critical beats everything but HANDSHAKE_DONE. // Critical beats everything but HANDSHAKE_DONE.
let stats_before = server.stats().frame_tx; let stats_before = server.stats().frame_tx;
@ -261,8 +261,8 @@ fn important() {
// Rather than connect, send stream data in 0.5-RTT. // Rather than connect, send stream data in 0.5-RTT.
// That allows this to test that important streams pre-empt most frame types. // That allows this to test that important streams pre-empt most frame types.
let dgram = client.process_output(now).dgram(); let dgram = client.process_output(now).dgram();
let dgram = server.process(dgram.as_ref(), now).dgram(); let dgram = server.process(dgram, now).dgram();
client.process_input(&dgram.unwrap(), now); client.process_input(dgram.unwrap(), now);
maybe_authenticate(&mut client); maybe_authenticate(&mut client);
let id = server.stream_create(StreamType::UniDi).unwrap(); let id = server.stream_create(StreamType::UniDi).unwrap();
@ -290,8 +290,8 @@ fn important() {
assert_eq!(stats_after.stream, stats_before.stream + 1); assert_eq!(stats_after.stream, stats_before.stream + 1);
// Complete the handshake. // Complete the handshake.
let dgram = client.process(dgram.as_ref(), now).dgram(); let dgram = client.process(dgram, now).dgram();
server.process_input(&dgram.unwrap(), now); server.process_input(dgram.unwrap(), now);
// Important beats everything but flow control. // Important beats everything but flow control.
let stats_before = server.stats().frame_tx; let stats_before = server.stats().frame_tx;
@ -314,8 +314,8 @@ fn high_normal() {
// Rather than connect, send stream data in 0.5-RTT. // Rather than connect, send stream data in 0.5-RTT.
// That allows this to test that important streams pre-empt most frame types. // That allows this to test that important streams pre-empt most frame types.
let dgram = client.process_output(now).dgram(); let dgram = client.process_output(now).dgram();
let dgram = server.process(dgram.as_ref(), now).dgram(); let dgram = server.process(dgram, now).dgram();
client.process_input(&dgram.unwrap(), now); client.process_input(dgram.unwrap(), now);
maybe_authenticate(&mut client); maybe_authenticate(&mut client);
let id = server.stream_create(StreamType::UniDi).unwrap(); let id = server.stream_create(StreamType::UniDi).unwrap();
@ -343,8 +343,8 @@ fn high_normal() {
assert_eq!(stats_after.stream, stats_before.stream + 1); assert_eq!(stats_after.stream, stats_before.stream + 1);
// Complete the handshake. // Complete the handshake.
let dgram = client.process(dgram.as_ref(), now).dgram(); let dgram = client.process(dgram, now).dgram();
server.process_input(&dgram.unwrap(), now); server.process_input(dgram.unwrap(), now);
// High or Normal doesn't beat NEW_CONNECTION_ID, // High or Normal doesn't beat NEW_CONNECTION_ID,
// but they beat CRYPTO/NEW_TOKEN. // but they beat CRYPTO/NEW_TOKEN.

Просмотреть файл

@ -45,7 +45,7 @@ fn pto_works_basic() {
let mut now = now(); let mut now = now();
let res = client.process(None, now); let res = client.process_output(now);
let idle_timeout = ConnectionParameters::default().get_idle_timeout(); let idle_timeout = ConnectionParameters::default().get_idle_timeout();
assert_eq!(res, Output::Callback(idle_timeout)); assert_eq!(res, Output::Callback(idle_timeout));
@ -59,19 +59,19 @@ fn pto_works_basic() {
// Send a packet after some time. // Send a packet after some time.
now += Duration::from_secs(10); now += Duration::from_secs(10);
let out = client.process(None, now); let out = client.process_output(now);
assert!(out.dgram().is_some()); assert!(out.dgram().is_some());
// Nothing to do, should return callback // Nothing to do, should return callback
let out = client.process(None, now); let out = client.process_output(now);
assert!(matches!(out, Output::Callback(_))); assert!(matches!(out, Output::Callback(_)));
// One second later, it should want to send PTO packet // One second later, it should want to send PTO packet
now += AT_LEAST_PTO; now += AT_LEAST_PTO;
let out = client.process(None, now); let out = client.process_output(now);
let stream_before = server.stats().frame_rx.stream; let stream_before = server.stats().frame_rx.stream;
server.process_input(&out.dgram().unwrap(), now); server.process_input(out.dgram().unwrap(), now);
assert_eq!(server.stats().frame_rx.stream, stream_before + 2); assert_eq!(server.stats().frame_rx.stream, stream_before + 2);
} }
@ -96,7 +96,7 @@ fn pto_works_full_cwnd() {
// Both datagrams contain one or more STREAM frames. // Both datagrams contain one or more STREAM frames.
for d in dgrams { for d in dgrams {
let stream_before = server.stats().frame_rx.stream; let stream_before = server.stats().frame_rx.stream;
server.process_input(&d, now); server.process_input(d, now);
assert!(server.stats().frame_rx.stream > stream_before); assert!(server.stats().frame_rx.stream > stream_before);
} }
} }
@ -115,49 +115,49 @@ fn pto_works_ping() {
let pkt3 = send_something(&mut client, now); let pkt3 = send_something(&mut client, now);
// Nothing to do, should return callback // Nothing to do, should return callback
let cb = client.process(None, now).callback(); let cb = client.process_output(now).callback();
// The PTO timer is calculated with: // The PTO timer is calculated with:
// RTT + max(rttvar * 4, GRANULARITY) + max_ack_delay // RTT + max(rttvar * 4, GRANULARITY) + max_ack_delay
// With zero RTT and rttvar, max_ack_delay is minimum too (GRANULARITY) // With zero RTT and rttvar, max_ack_delay is minimum too (GRANULARITY)
assert_eq!(cb, GRANULARITY * 2); assert_eq!(cb, GRANULARITY * 2);
// Process these by server, skipping pkt0 // Process these by server, skipping pkt0
let srv0 = server.process(Some(&pkt1), now).dgram(); let srv0 = server.process(Some(pkt1), now).dgram();
assert!(srv0.is_some()); // ooo, ack client pkt1 assert!(srv0.is_some()); // ooo, ack client pkt1
now += Duration::from_millis(20); now += Duration::from_millis(20);
// process pkt2 (immediate ack because last ack was more than an RTT ago; RTT=0) // process pkt2 (immediate ack because last ack was more than an RTT ago; RTT=0)
let srv1 = server.process(Some(&pkt2), now).dgram(); let srv1 = server.process(Some(pkt2), now).dgram();
assert!(srv1.is_some()); // this is now dropped assert!(srv1.is_some()); // this is now dropped
now += Duration::from_millis(20); now += Duration::from_millis(20);
// process pkt3 (acked for same reason) // process pkt3 (acked for same reason)
let srv2 = server.process(Some(&pkt3), now).dgram(); let srv2 = server.process(Some(pkt3), now).dgram();
// ack client pkt 2 & 3 // ack client pkt 2 & 3
assert!(srv2.is_some()); assert!(srv2.is_some());
// client processes ack // client processes ack
let pkt4 = client.process(srv2.as_ref(), now).dgram(); let pkt4 = client.process(srv2, now).dgram();
// client resends data from pkt0 // client resends data from pkt0
assert!(pkt4.is_some()); assert!(pkt4.is_some());
// server sees ooo pkt0 and generates immediate ack // server sees ooo pkt0 and generates immediate ack
let srv3 = server.process(Some(&pkt0), now).dgram(); let srv3 = server.process(Some(pkt0), now).dgram();
assert!(srv3.is_some()); assert!(srv3.is_some());
// Accept the acknowledgment. // Accept the acknowledgment.
let pkt5 = client.process(srv3.as_ref(), now).dgram(); let pkt5 = client.process(srv3, now).dgram();
assert!(pkt5.is_none()); assert!(pkt5.is_none());
now += Duration::from_millis(70); now += Duration::from_millis(70);
// PTO expires. No unacked data. Only send PING. // PTO expires. No unacked data. Only send PING.
let client_pings = client.stats().frame_tx.ping; let client_pings = client.stats().frame_tx.ping;
let pkt6 = client.process(None, now).dgram(); let pkt6 = client.process_output(now).dgram();
assert_eq!(client.stats().frame_tx.ping, client_pings + 1); assert_eq!(client.stats().frame_tx.ping, client_pings + 1);
let server_pings = server.stats().frame_rx.ping; let server_pings = server.stats().frame_rx.ping;
server.process_input(&pkt6.unwrap(), now); server.process_input(pkt6.unwrap(), now);
assert_eq!(server.stats().frame_rx.ping, server_pings + 1); assert_eq!(server.stats().frame_rx.ping, server_pings + 1);
} }
@ -168,40 +168,40 @@ fn pto_initial() {
qdebug!("---- client: generate CH"); qdebug!("---- client: generate CH");
let mut client = default_client(); let mut client = default_client();
let pkt1 = client.process(None, now).dgram(); let pkt1 = client.process_output(now).dgram();
assert!(pkt1.is_some()); assert!(pkt1.is_some());
assert_eq!(pkt1.clone().unwrap().len(), client.plpmtu()); assert_eq!(pkt1.clone().unwrap().len(), client.plpmtu());
let delay = client.process(None, now).callback(); let delay = client.process_output(now).callback();
assert_eq!(delay, INITIAL_PTO); assert_eq!(delay, INITIAL_PTO);
// Resend initial after PTO. // Resend initial after PTO.
now += delay; now += delay;
let pkt2 = client.process(None, now).dgram(); let pkt2 = client.process_output(now).dgram();
assert!(pkt2.is_some()); assert!(pkt2.is_some());
assert_eq!(pkt2.unwrap().len(), client.plpmtu()); assert_eq!(pkt2.unwrap().len(), client.plpmtu());
let delay = client.process(None, now).callback(); let delay = client.process_output(now).callback();
// PTO has doubled. // PTO has doubled.
assert_eq!(delay, INITIAL_PTO * 2); assert_eq!(delay, INITIAL_PTO * 2);
// Server process the first initial pkt. // Server process the first initial pkt.
let mut server = default_server(); let mut server = default_server();
let out = server.process(pkt1.as_ref(), now).dgram(); let out = server.process(pkt1, now).dgram();
assert!(out.is_some()); assert!(out.is_some());
// Client receives ack for the first initial packet as well a Handshake packet. // Client receives ack for the first initial packet as well a Handshake packet.
// After the handshake packet the initial keys and the crypto stream for the initial // After the handshake packet the initial keys and the crypto stream for the initial
// packet number space will be discarded. // packet number space will be discarded.
// Here only an ack for the Handshake packet will be sent. // Here only an ack for the Handshake packet will be sent.
let out = client.process(out.as_ref(), now).dgram(); let out = client.process(out, now).dgram();
assert!(out.is_some()); assert!(out.is_some());
// We do not have PTO for the resent initial packet any more, but // We do not have PTO for the resent initial packet any more, but
// the Handshake PTO timer should be armed. As the RTT is apparently // the Handshake PTO timer should be armed. As the RTT is apparently
// the same as the initial PTO value, and there is only one sample, // the same as the initial PTO value, and there is only one sample,
// the PTO will be 3x the INITIAL PTO. // the PTO will be 3x the INITIAL PTO.
let delay = client.process(None, now).callback(); let delay = client.process_output(now).callback();
assert_eq!(delay, INITIAL_PTO * 3); assert_eq!(delay, INITIAL_PTO * 3);
} }
@ -215,37 +215,37 @@ fn pto_handshake_complete() {
let mut client = default_client(); let mut client = default_client();
let mut server = default_server(); let mut server = default_server();
let pkt = client.process(None, now).dgram(); let pkt = client.process_output(now).dgram();
assert_initial(pkt.as_ref().unwrap(), false); assert_initial(pkt.as_ref().unwrap(), false);
let cb = client.process(None, now).callback(); let cb = client.process_output(now).callback();
assert_eq!(cb, Duration::from_millis(300)); assert_eq!(cb, Duration::from_millis(300));
now += HALF_RTT; now += HALF_RTT;
let pkt = server.process(pkt.as_ref(), now).dgram(); let pkt = server.process(pkt, now).dgram();
assert_initial(pkt.as_ref().unwrap(), false); assert_initial(pkt.as_ref().unwrap(), false);
now += HALF_RTT; now += HALF_RTT;
let pkt = client.process(pkt.as_ref(), now).dgram(); let pkt = client.process(pkt, now).dgram();
assert_handshake(pkt.as_ref().unwrap()); assert_handshake(pkt.as_ref().unwrap());
let cb = client.process(None, now).callback(); let cb = client.process_output(now).callback();
// The client now has a single RTT estimate (20ms), so // The client now has a single RTT estimate (20ms), so
// the handshake PTO is set based on that. // the handshake PTO is set based on that.
assert_eq!(cb, HALF_RTT * 6); assert_eq!(cb, HALF_RTT * 6);
now += HALF_RTT; now += HALF_RTT;
let pkt = server.process(pkt.as_ref(), now).dgram(); let pkt = server.process(pkt, now).dgram();
assert!(pkt.is_none()); assert!(pkt.is_none());
now += HALF_RTT; now += HALF_RTT;
client.authenticated(AuthenticationStatus::Ok, now); client.authenticated(AuthenticationStatus::Ok, now);
qdebug!("---- client: SH..FIN -> FIN"); qdebug!("---- client: SH..FIN -> FIN");
let pkt1 = client.process(None, now).dgram(); let pkt1 = client.process_output(now).dgram();
assert_handshake(pkt1.as_ref().unwrap()); assert_handshake(pkt1.as_ref().unwrap());
assert_eq!(*client.state(), State::Connected); assert_eq!(*client.state(), State::Connected);
let cb = client.process(None, now).callback(); let cb = client.process_output(now).callback();
assert_eq!(cb, HALF_RTT * 6); assert_eq!(cb, HALF_RTT * 6);
let mut pto_counts = [0; MAX_PTO_COUNTS]; let mut pto_counts = [0; MAX_PTO_COUNTS];
@ -255,7 +255,7 @@ fn pto_handshake_complete() {
// Wait long enough that the 1-RTT PTO also fires. // Wait long enough that the 1-RTT PTO also fires.
qdebug!("---- client: PTO"); qdebug!("---- client: PTO");
now += HALF_RTT * 6; now += HALF_RTT * 6;
let pkt2 = client.process(None, now).dgram(); let pkt2 = client.process_output(now).dgram();
assert_handshake(pkt2.as_ref().unwrap()); assert_handshake(pkt2.as_ref().unwrap());
pto_counts[0] = 1; pto_counts[0] = 1;
@ -267,14 +267,14 @@ fn pto_handshake_complete() {
let stream_id = client.stream_create(StreamType::UniDi).unwrap(); let stream_id = client.stream_create(StreamType::UniDi).unwrap();
client.stream_close_send(stream_id).unwrap(); client.stream_close_send(stream_id).unwrap();
now += HALF_RTT * 6; now += HALF_RTT * 6;
let pkt3 = client.process(None, now).dgram(); let pkt3 = client.process_output(now).dgram();
assert_handshake(pkt3.as_ref().unwrap()); assert_handshake(pkt3.as_ref().unwrap());
let (pkt3_hs, pkt3_1rtt) = split_datagram(&pkt3.unwrap()); let (pkt3_hs, pkt3_1rtt) = split_datagram(&pkt3.unwrap());
assert_handshake(&pkt3_hs); assert_handshake(&pkt3_hs);
assert!(pkt3_1rtt.is_some()); assert!(pkt3_1rtt.is_some());
// PTO has been doubled. // PTO has been doubled.
let cb = client.process(None, now).callback(); let cb = client.process_output(now).callback();
assert_eq!(cb, HALF_RTT * 12); assert_eq!(cb, HALF_RTT * 12);
// We still have only a single PTO // We still have only a single PTO
@ -288,8 +288,8 @@ fn pto_handshake_complete() {
// This should remove the 1-RTT PTO from messing this test up. // This should remove the 1-RTT PTO from messing this test up.
let server_acks = server.stats().frame_tx.ack; let server_acks = server.stats().frame_tx.ack;
let server_done = server.stats().frame_tx.handshake_done; let server_done = server.stats().frame_tx.handshake_done;
server.process_input(&pkt3_1rtt.unwrap(), now); server.process_input(pkt3_1rtt.unwrap(), now);
let ack = server.process(pkt1.as_ref(), now).dgram(); let ack = server.process(pkt1, now).dgram();
assert!(ack.is_some()); assert!(ack.is_some());
assert_eq!(server.stats().frame_tx.ack, server_acks + 2); assert_eq!(server.stats().frame_tx.ack, server_acks + 2);
assert_eq!(server.stats().frame_tx.handshake_done, server_done + 1); assert_eq!(server.stats().frame_tx.handshake_done, server_done + 1);
@ -302,14 +302,14 @@ fn pto_handshake_complete() {
assert!(pkt2_1rtt.is_some()); assert!(pkt2_1rtt.is_some());
let dropped_before1 = server.stats().dropped_rx; let dropped_before1 = server.stats().dropped_rx;
let server_frames = server.stats().frame_rx.all(); let server_frames = server.stats().frame_rx.all();
server.process_input(&pkt2_hs, now); server.process_input(pkt2_hs, now);
assert_eq!(1, server.stats().dropped_rx - dropped_before1); assert_eq!(1, server.stats().dropped_rx - dropped_before1);
assert_eq!(server.stats().frame_rx.all(), server_frames); assert_eq!(server.stats().frame_rx.all(), server_frames);
server.process_input(&pkt2_1rtt.unwrap(), now); server.process_input(pkt2_1rtt.unwrap(), now);
let server_frames2 = server.stats().frame_rx.all(); let server_frames2 = server.stats().frame_rx.all();
let dropped_before2 = server.stats().dropped_rx; let dropped_before2 = server.stats().dropped_rx;
server.process_input(&pkt3_hs, now); server.process_input(pkt3_hs, now);
assert_eq!(1, server.stats().dropped_rx - dropped_before2); assert_eq!(1, server.stats().dropped_rx - dropped_before2);
assert_eq!(server.stats().frame_rx.all(), server_frames2); assert_eq!(server.stats().frame_rx.all(), server_frames2);
@ -317,14 +317,14 @@ fn pto_handshake_complete() {
// Let the client receive the ACK. // Let the client receive the ACK.
// It should now be wait to acknowledge the HANDSHAKE_DONE. // It should now be wait to acknowledge the HANDSHAKE_DONE.
let cb = client.process(ack.as_ref(), now).callback(); let cb = client.process(ack, now).callback();
// The default ack delay is the RTT divided by the default ACK ratio of 4. // The default ack delay is the RTT divided by the default ACK ratio of 4.
let expected_ack_delay = HALF_RTT * 2 / 4; let expected_ack_delay = HALF_RTT * 2 / 4;
assert_eq!(cb, expected_ack_delay); assert_eq!(cb, expected_ack_delay);
// Let the ACK delay timer expire. // Let the ACK delay timer expire.
now += cb; now += cb;
let out = client.process(None, now).dgram(); let out = client.process_output(now).dgram();
assert!(out.is_some()); assert!(out.is_some());
} }
@ -334,19 +334,19 @@ fn pto_handshake_frames() {
let mut now = now(); let mut now = now();
qdebug!("---- client: generate CH"); qdebug!("---- client: generate CH");
let mut client = default_client(); let mut client = default_client();
let pkt = client.process(None, now); let pkt = client.process_output(now);
now += Duration::from_millis(10); now += Duration::from_millis(10);
qdebug!("---- server: CH -> SH, EE, CERT, CV, FIN"); qdebug!("---- server: CH -> SH, EE, CERT, CV, FIN");
let mut server = default_server(); let mut server = default_server();
let pkt = server.process(pkt.as_dgram_ref(), now); let pkt = server.process(pkt.dgram(), now);
now += Duration::from_millis(10); now += Duration::from_millis(10);
qdebug!("---- client: cert verification"); qdebug!("---- client: cert verification");
let pkt = client.process(pkt.as_dgram_ref(), now); let pkt = client.process(pkt.dgram(), now);
now += Duration::from_millis(10); now += Duration::from_millis(10);
mem::drop(server.process(pkt.as_dgram_ref(), now)); mem::drop(server.process(pkt.dgram(), now));
now += Duration::from_millis(10); now += Duration::from_millis(10);
client.authenticated(AuthenticationStatus::Ok, now); client.authenticated(AuthenticationStatus::Ok, now);
@ -355,21 +355,21 @@ fn pto_handshake_frames() {
assert_eq!(stream, 2); assert_eq!(stream, 2);
assert_eq!(client.stream_send(stream, b"zero").unwrap(), 4); assert_eq!(client.stream_send(stream, b"zero").unwrap(), 4);
qdebug!("---- client: SH..FIN -> FIN and 1RTT packet"); qdebug!("---- client: SH..FIN -> FIN and 1RTT packet");
let pkt1 = client.process(None, now).dgram(); let pkt1 = client.process_output(now).dgram();
assert!(pkt1.is_some()); assert!(pkt1.is_some());
// Get PTO timer. // Get PTO timer.
let out = client.process(None, now); let out = client.process_output(now);
assert_eq!(out, Output::Callback(Duration::from_millis(60))); assert_eq!(out, Output::Callback(Duration::from_millis(60)));
// Wait for PTO to expire and resend a handshake packet. // Wait for PTO to expire and resend a handshake packet.
now += Duration::from_millis(60); now += Duration::from_millis(60);
let pkt2 = client.process(None, now).dgram(); let pkt2 = client.process_output(now).dgram();
assert!(pkt2.is_some()); assert!(pkt2.is_some());
now += Duration::from_millis(10); now += Duration::from_millis(10);
let crypto_before = server.stats().frame_rx.crypto; let crypto_before = server.stats().frame_rx.crypto;
server.process_input(&pkt2.unwrap(), now); server.process_input(pkt2.unwrap(), now);
assert_eq!(server.stats().frame_rx.crypto, crypto_before + 1); assert_eq!(server.stats().frame_rx.crypto, crypto_before + 1);
} }
@ -388,21 +388,21 @@ fn handshake_ack_pto() {
let big = TransportParameter::Bytes(vec![0; Pmtud::default_plpmtu(DEFAULT_ADDR.ip())]); let big = TransportParameter::Bytes(vec![0; Pmtud::default_plpmtu(DEFAULT_ADDR.ip())]);
server.set_local_tparam(0xce16, big).unwrap(); server.set_local_tparam(0xce16, big).unwrap();
let c1 = client.process(None, now).dgram(); let c1 = client.process_output(now).dgram();
now += RTT / 2; now += RTT / 2;
let s1 = server.process(c1.as_ref(), now).dgram(); let s1 = server.process(c1, now).dgram();
assert!(s1.is_some()); assert!(s1.is_some());
let s2 = server.process(None, now).dgram(); let s2 = server.process_output(now).dgram();
assert!(s1.is_some()); assert!(s1.is_some());
// Now let the client have the Initial, but drop the first coalesced Handshake packet. // Now let the client have the Initial, but drop the first coalesced Handshake packet.
now += RTT / 2; now += RTT / 2;
let (initial, _) = split_datagram(&s1.unwrap()); let (initial, _) = split_datagram(&s1.unwrap());
client.process_input(&initial, now); client.process_input(initial, now);
let c2 = client.process(s2.as_ref(), now).dgram(); let c2 = client.process(s2, now).dgram();
assert!(c2.is_some()); // This is an ACK. Drop it. assert!(c2.is_some()); // This is an ACK. Drop it.
let delay = client.process(None, now).callback(); let delay = client.process_output(now).callback();
assert_eq!(delay, RTT * 3); assert_eq!(delay, RTT * 3);
let mut pto_counts = [0; MAX_PTO_COUNTS]; let mut pto_counts = [0; MAX_PTO_COUNTS];
@ -410,26 +410,26 @@ fn handshake_ack_pto() {
// Wait for the PTO and ensure that the client generates a packet. // Wait for the PTO and ensure that the client generates a packet.
now += delay; now += delay;
let c3 = client.process(None, now).dgram(); let c3 = client.process_output(now).dgram();
assert!(c3.is_some()); assert!(c3.is_some());
now += RTT / 2; now += RTT / 2;
let ping_before = server.stats().frame_rx.ping; let ping_before = server.stats().frame_rx.ping;
server.process_input(&c3.unwrap(), now); server.process_input(c3.unwrap(), now);
assert_eq!(server.stats().frame_rx.ping, ping_before + 1); assert_eq!(server.stats().frame_rx.ping, ping_before + 1);
pto_counts[0] = 1; pto_counts[0] = 1;
assert_eq!(client.stats.borrow().pto_counts, pto_counts); assert_eq!(client.stats.borrow().pto_counts, pto_counts);
// Now complete the handshake as cheaply as possible. // Now complete the handshake as cheaply as possible.
let dgram = server.process(None, now).dgram(); let dgram = server.process_output(now).dgram();
client.process_input(&dgram.unwrap(), now); client.process_input(dgram.unwrap(), now);
maybe_authenticate(&mut client); maybe_authenticate(&mut client);
let dgram = client.process(None, now).dgram(); let dgram = client.process_output(now).dgram();
assert_eq!(*client.state(), State::Connected); assert_eq!(*client.state(), State::Connected);
let dgram = server.process(dgram.as_ref(), now).dgram(); let dgram = server.process(dgram, now).dgram();
assert_eq!(*server.state(), State::Confirmed); assert_eq!(*server.state(), State::Confirmed);
client.process_input(&dgram.unwrap(), now); client.process_input(dgram.unwrap(), now);
assert_eq!(*client.state(), State::Confirmed); assert_eq!(*client.state(), State::Confirmed);
assert_eq!(client.stats.borrow().pto_counts, pto_counts); assert_eq!(client.stats.borrow().pto_counts, pto_counts);
@ -450,12 +450,12 @@ fn loss_recovery_crash() {
assert!(ack.is_some()); assert!(ack.is_some());
// Have the server process the ACK. // Have the server process the ACK.
let cb = server.process(ack.as_ref(), now).callback(); let cb = server.process(ack, now).callback();
assert!(cb > Duration::from_secs(0)); assert!(cb > Duration::from_secs(0));
// Now we leap into the future. The server should regard the first // Now we leap into the future. The server should regard the first
// packet as lost based on time alone. // packet as lost based on time alone.
let dgram = server.process(None, now + AT_LEAST_PTO).dgram(); let dgram = server.process_output(now + AT_LEAST_PTO).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
// This crashes. // This crashes.
@ -480,10 +480,10 @@ fn ack_after_pto() {
now += AT_LEAST_PTO; now += AT_LEAST_PTO;
// We can use MAX_PTO_PACKET_COUNT, because we know the handshake is over. // We can use MAX_PTO_PACKET_COUNT, because we know the handshake is over.
for _ in 0..MAX_PTO_PACKET_COUNT { for _ in 0..MAX_PTO_PACKET_COUNT {
let dgram = client.process(None, now).dgram(); let dgram = client.process_output(now).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
} }
assert!(client.process(None, now).dgram().is_none()); assert!(client.process_output(now).dgram().is_none());
// The server now needs to send something that will cause the // The server now needs to send something that will cause the
// client to want to acknowledge it. A little out of order // client to want to acknowledge it. A little out of order
@ -495,13 +495,13 @@ fn ack_after_pto() {
// The client is now after a PTO, but if it receives something // The client is now after a PTO, but if it receives something
// that demands acknowledgment, it will send just the ACK. // that demands acknowledgment, it will send just the ACK.
let ack = client.process(Some(&dgram), now).dgram(); let ack = client.process(Some(dgram), now).dgram();
assert!(ack.is_some()); assert!(ack.is_some());
// Make sure that the packet only contained an ACK frame. // Make sure that the packet only contained an ACK frame.
let all_frames_before = server.stats().frame_rx.all(); let all_frames_before = server.stats().frame_rx.all();
let ack_before = server.stats().frame_rx.ack; let ack_before = server.stats().frame_rx.ack;
server.process_input(&ack.unwrap(), now); server.process_input(ack.unwrap(), now);
assert_eq!(server.stats().frame_rx.all(), all_frames_before + 1); assert_eq!(server.stats().frame_rx.all(), all_frames_before + 1);
assert_eq!(server.stats().frame_rx.ack, ack_before + 1); assert_eq!(server.stats().frame_rx.ack, ack_before + 1);
} }
@ -522,7 +522,7 @@ fn lost_but_kept_and_lr_timer() {
// At t=RTT/2 the server receives the packet and ACKs it. // At t=RTT/2 the server receives the packet and ACKs it.
now += RTT / 2; now += RTT / 2;
let ack = server.process(Some(&p2), now).dgram(); let ack = server.process(Some(p2), now).dgram();
assert!(ack.is_some()); assert!(ack.is_some());
// The client also sends another two packets (p3, p4), again losing the first. // The client also sends another two packets (p3, p4), again losing the first.
let _p3 = send_something(&mut client, now); let _p3 = send_something(&mut client, now);
@ -531,24 +531,24 @@ fn lost_but_kept_and_lr_timer() {
// At t=RTT the client receives the ACK and goes into timed loss recovery. // At t=RTT the client receives the ACK and goes into timed loss recovery.
// The client doesn't call p1 lost at this stage, but it will soon. // The client doesn't call p1 lost at this stage, but it will soon.
now += RTT / 2; now += RTT / 2;
let res = client.process(ack.as_ref(), now); let res = client.process(ack, now);
// The client should be on a loss recovery timer as p1 is missing. // The client should be on a loss recovery timer as p1 is missing.
let lr_timer = res.callback(); let lr_timer = res.callback();
// Loss recovery timer should be RTT/8, but only check for 0 or >=RTT/2. // Loss recovery timer should be RTT/8, but only check for 0 or >=RTT/2.
assert_ne!(lr_timer, Duration::from_secs(0)); assert_ne!(lr_timer, Duration::from_secs(0));
assert!(lr_timer < (RTT / 2)); assert!(lr_timer < (RTT / 2));
// The server also receives and acknowledges p4, again sending an ACK. // The server also receives and acknowledges p4, again sending an ACK.
let ack = server.process(Some(&p4), now).dgram(); let ack = server.process(Some(p4), now).dgram();
assert!(ack.is_some()); assert!(ack.is_some());
// At t=RTT*3/2 the client should declare p1 to be lost. // At t=RTT*3/2 the client should declare p1 to be lost.
now += RTT / 2; now += RTT / 2;
// So the client will send the data from p1 again. // So the client will send the data from p1 again.
let res = client.process(None, now); let res = client.process_output(now);
assert!(res.dgram().is_some()); assert!(res.dgram().is_some());
// When the client processes the ACK, it should engage the // When the client processes the ACK, it should engage the
// loss recovery timer for p3, not p1 (even though it still tracks p1). // loss recovery timer for p3, not p1 (even though it still tracks p1).
let res = client.process(ack.as_ref(), now); let res = client.process(ack, now);
let lr_timer2 = res.callback(); let lr_timer2 = res.callback();
assert_eq!(lr_timer, lr_timer2); assert_eq!(lr_timer, lr_timer2);
} }
@ -569,9 +569,9 @@ fn loss_time_past_largest_acked() {
let mut now = now(); let mut now = now();
// Start the handshake. // Start the handshake.
let c_in = client.process(None, now).dgram(); let c_in = client.process_output(now).dgram();
now += RTT / 2; now += RTT / 2;
let s_hs1 = server.process(c_in.as_ref(), now).dgram(); let s_hs1 = server.process(c_in, now).dgram();
// Get some spare server handshake packets for the client to ACK. // Get some spare server handshake packets for the client to ACK.
// This involves a time machine, so be a little cautious. // This involves a time machine, so be a little cautious.
@ -579,15 +579,15 @@ fn loss_time_past_largest_acked() {
// with a much lower RTT estimate, so the PTO at this point should // with a much lower RTT estimate, so the PTO at this point should
// be much smaller than an RTT and so the server shouldn't see // be much smaller than an RTT and so the server shouldn't see
// time go backwards. // time go backwards.
let s_pto = server.process(None, now).callback(); let s_pto = server.process_output(now).callback();
assert_ne!(s_pto, Duration::from_secs(0)); assert_ne!(s_pto, Duration::from_secs(0));
assert!(s_pto < RTT); assert!(s_pto < RTT);
let s_hs2 = server.process(None, now + s_pto).dgram(); let s_hs2 = server.process_output(now + s_pto).dgram();
assert!(s_hs2.is_some()); assert!(s_hs2.is_some());
let s_pto = server.process(None, now).callback(); let s_pto = server.process_output(now).callback();
assert_ne!(s_pto, Duration::from_secs(0)); assert_ne!(s_pto, Duration::from_secs(0));
assert!(s_pto < RTT); assert!(s_pto < RTT);
let s_hs3 = server.process(None, now + s_pto).dgram(); let s_hs3 = server.process_output(now + s_pto).dgram();
assert!(s_hs3.is_some()); assert!(s_hs3.is_some());
// We are blocked by the amplification limit now. // We are blocked by the amplification limit now.
@ -601,26 +601,26 @@ fn loss_time_past_largest_acked() {
// to generate an ack-eliciting packet. For that, we use the Finished message. // to generate an ack-eliciting packet. For that, we use the Finished message.
// Reordering delivery ensures that the later packet is also acknowledged. // Reordering delivery ensures that the later packet is also acknowledged.
now += RTT / 2; now += RTT / 2;
let c_hs1 = client.process(s_hs1.as_ref(), now).dgram(); let c_hs1 = client.process(s_hs1, now).dgram();
assert!(c_hs1.is_some()); // This comes first, so it's useless. assert!(c_hs1.is_some()); // This comes first, so it's useless.
maybe_authenticate(&mut client); maybe_authenticate(&mut client);
let c_hs2 = client.process(None, now).dgram(); let c_hs2 = client.process_output(now).dgram();
assert!(c_hs2.is_some()); // This one will elicit an ACK. assert!(c_hs2.is_some()); // This one will elicit an ACK.
// The we need the outstanding packet to be sent after the // The we need the outstanding packet to be sent after the
// application data packet, so space these out a tiny bit. // application data packet, so space these out a tiny bit.
let _p1 = send_something(&mut client, now + INCR); let _p1 = send_something(&mut client, now + INCR);
let c_hs3 = client.process(s_hs2.as_ref(), now + (INCR * 2)).dgram(); let c_hs3 = client.process(s_hs2, now + (INCR * 2)).dgram();
assert!(c_hs3.is_some()); // This will be left outstanding. assert!(c_hs3.is_some()); // This will be left outstanding.
let c_hs4 = client.process(s_hs3.as_ref(), now + (INCR * 3)).dgram(); let c_hs4 = client.process(s_hs3, now + (INCR * 3)).dgram();
assert!(c_hs4.is_some()); // This will be acknowledged. assert!(c_hs4.is_some()); // This will be acknowledged.
// Process c_hs2 and c_hs4, but skip c_hs3. // Process c_hs2 and c_hs4, but skip c_hs3.
// Then get an ACK for the client. // Then get an ACK for the client.
now += RTT / 2; now += RTT / 2;
// Deliver c_hs4 first, but don't generate a packet. // Deliver c_hs4 first, but don't generate a packet.
server.process_input(&c_hs4.unwrap(), now); server.process_input(c_hs4.unwrap(), now);
let s_ack = server.process(c_hs2.as_ref(), now).dgram(); let s_ack = server.process(c_hs2, now).dgram();
assert!(s_ack.is_some()); assert!(s_ack.is_some());
// This includes an ACK, but it also includes HANDSHAKE_DONE, // This includes an ACK, but it also includes HANDSHAKE_DONE,
// which we need to remove because that will cause the Handshake loss // which we need to remove because that will cause the Handshake loss
@ -629,12 +629,12 @@ fn loss_time_past_largest_acked() {
// Now the client should start its loss recovery timer based on the ACK. // Now the client should start its loss recovery timer based on the ACK.
now += RTT / 2; now += RTT / 2;
let _c_ack = client.process(Some(&s_hs_ack), now).dgram(); let _c_ack = client.process(Some(s_hs_ack), now).dgram();
// This ACK triggers an immediate ACK, due to an ACK loss during handshake. // This ACK triggers an immediate ACK, due to an ACK loss during handshake.
let c_ack = client.process(None, now).dgram(); let c_ack = client.process_output(now).dgram();
assert!(c_ack.is_none()); assert!(c_ack.is_none());
// The client should now have the loss recovery timer active. // The client should now have the loss recovery timer active.
let lr_time = client.process(None, now).callback(); let lr_time = client.process_output(now).callback();
assert_ne!(lr_time, Duration::from_secs(0)); assert_ne!(lr_time, Duration::from_secs(0));
assert!(lr_time < (RTT / 2)); assert!(lr_time < (RTT / 2));
} }
@ -648,12 +648,12 @@ fn trickle(sender: &mut Connection, receiver: &mut Connection, mut count: usize,
while count > 0 { while count > 0 {
qdebug!("trickle: remaining={}", count); qdebug!("trickle: remaining={}", count);
assert_eq!(sender.stream_send(id, &[9]).unwrap(), 1); assert_eq!(sender.stream_send(id, &[9]).unwrap(), 1);
let dgram = sender.process(maybe_ack.as_ref(), now).dgram(); let dgram = sender.process(maybe_ack, now).dgram();
maybe_ack = receiver.process(dgram.as_ref(), now).dgram(); maybe_ack = receiver.process(dgram, now).dgram();
count -= usize::from(maybe_ack.is_some()); count -= usize::from(maybe_ack.is_some());
} }
sender.process_input(&maybe_ack.unwrap(), now); sender.process_input(maybe_ack.unwrap(), now);
} }
/// Ensure that a PING frame is sent with ACK sometimes. /// Ensure that a PING frame is sent with ACK sometimes.
@ -744,7 +744,7 @@ fn fast_pto() {
let mut server = default_server(); let mut server = default_server();
let mut now = connect_rtt_idle(&mut client, &mut server, DEFAULT_RTT); let mut now = connect_rtt_idle(&mut client, &mut server, DEFAULT_RTT);
let res = client.process(None, now); let res = client.process_output(now);
let idle_timeout = ConnectionParameters::default().get_idle_timeout() - (DEFAULT_RTT / 2); let idle_timeout = ConnectionParameters::default().get_idle_timeout() - (DEFAULT_RTT / 2);
assert_eq!(res, Output::Callback(idle_timeout)); assert_eq!(res, Output::Callback(idle_timeout));
@ -766,10 +766,10 @@ fn fast_pto() {
// Once the PTO timer expires, a PTO packet should be sent should want to send PTO packet. // Once the PTO timer expires, a PTO packet should be sent should want to send PTO packet.
now += cb; now += cb;
let dgram = client.process(None, now).dgram(); let dgram = client.process_output(now).dgram();
let stream_before = server.stats().frame_rx.stream; let stream_before = server.stats().frame_rx.stream;
server.process_input(&dgram.unwrap(), now); server.process_input(dgram.unwrap(), now);
assert_eq!(server.stats().frame_rx.stream, stream_before + 1); assert_eq!(server.stats().frame_rx.stream, stream_before + 1);
} }
@ -781,7 +781,7 @@ fn fast_pto_persistent_congestion() {
let mut server = default_server(); let mut server = default_server();
let mut now = connect_rtt_idle(&mut client, &mut server, DEFAULT_RTT); let mut now = connect_rtt_idle(&mut client, &mut server, DEFAULT_RTT);
let res = client.process(None, now); let res = client.process_output(now);
let idle_timeout = ConnectionParameters::default().get_idle_timeout() - (DEFAULT_RTT / 2); let idle_timeout = ConnectionParameters::default().get_idle_timeout() - (DEFAULT_RTT / 2);
assert_eq!(res, Output::Callback(idle_timeout)); assert_eq!(res, Output::Callback(idle_timeout));
@ -809,9 +809,9 @@ fn fast_pto_persistent_congestion() {
// Now acknowledge the tail packet and enter persistent congestion. // Now acknowledge the tail packet and enter persistent congestion.
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
let ack = server.process(Some(&dgram), now).dgram(); let ack = server.process(Some(dgram), now).dgram();
now += DEFAULT_RTT / 2; now += DEFAULT_RTT / 2;
client.process_input(&ack.unwrap(), now); client.process_input(ack.unwrap(), now);
assert_eq!(cwnd(&client), cwnd_min(&client)); assert_eq!(cwnd(&client), cwnd_min(&client));
} }
@ -841,7 +841,7 @@ fn ack_for_unsent() {
.unwrap(); .unwrap();
// Now deliver the packet with the spoofed ACK frame // Now deliver the packet with the spoofed ACK frame
client.process_input(&spoofed, now()); client.process_input(spoofed, now());
assert!(matches!( assert!(matches!(
client.state(), client.state(),
State::Closing { State::Closing {

Просмотреть файл

@ -66,7 +66,7 @@ fn remember_smoothed_rtt() {
let ticket = server.process_output(now).dgram(); let ticket = server.process_output(now).dgram();
assert!(ticket.is_some()); assert!(ticket.is_some());
now += RTT1 / 2; now += RTT1 / 2;
client.process_input(&ticket.unwrap(), now); client.process_input(ticket.unwrap(), now);
let token = get_tokens(&mut client).pop().unwrap(); let token = get_tokens(&mut client).pop().unwrap();
let mut client = default_client(); let mut client = default_client();
@ -102,7 +102,7 @@ fn ticket_rtt(rtt: Duration) -> Duration {
let client_dcid = client_dcid.to_owned(); let client_dcid = client_dcid.to_owned();
now += rtt / 2; now += rtt / 2;
let server_packet = server.process(client_initial.as_dgram_ref(), now).dgram(); let server_packet = server.process(client_initial.dgram(), now).dgram();
let (server_initial, server_hs) = split_datagram(server_packet.as_ref().unwrap()); let (server_initial, server_hs) = split_datagram(server_packet.as_ref().unwrap());
let (protected_header, _, _, payload) = let (protected_header, _, _, payload) =
decode_initial_header(&server_initial, Role::Server).unwrap(); decode_initial_header(&server_initial, Role::Server).unwrap();
@ -143,15 +143,15 @@ fn ticket_rtt(rtt: Duration) -> Duration {
// Now a connection can be made successfully. // Now a connection can be made successfully.
now += rtt / 2; now += rtt / 2;
client.process_input(&si, now); client.process_input(si, now);
client.process_input(&server_hs.unwrap(), now); client.process_input(server_hs.unwrap(), now);
client.authenticated(AuthenticationStatus::Ok, now); client.authenticated(AuthenticationStatus::Ok, now);
let finished = client.process_output(now); let finished = client.process_output(now);
assert_eq!(*client.state(), State::Connected); assert_eq!(*client.state(), State::Connected);
now += rtt / 2; now += rtt / 2;
_ = server.process(finished.as_dgram_ref(), now); _ = server.process(finished.dgram(), now);
assert_eq!(*server.state(), State::Confirmed); assert_eq!(*server.state(), State::Confirmed);
// Don't deliver the server's handshake finished, it has ACKs. // Don't deliver the server's handshake finished, it has ACKs.
@ -164,7 +164,7 @@ fn ticket_rtt(rtt: Duration) -> Duration {
let ticket = server.process_output(now).dgram(); let ticket = server.process_output(now).dgram();
assert!(ticket.is_some()); assert!(ticket.is_some());
now += rtt / 2; now += rtt / 2;
client.process_input(&ticket.unwrap(), now); client.process_input(ticket.unwrap(), now);
let token = get_tokens(&mut client).pop().unwrap(); let token = get_tokens(&mut client).pop().unwrap();
// And connect again. // And connect again.
@ -213,7 +213,7 @@ fn address_validation_token_resume() {
let mut server = resumed_server(&client); let mut server = resumed_server(&client);
// Grab an Initial packet from the client. // Grab an Initial packet from the client.
let dgram = client.process(None, now).dgram(); let dgram = client.process_output(now).dgram();
assertions::assert_initial(dgram.as_ref().unwrap(), true); assertions::assert_initial(dgram.as_ref().unwrap(), true);
// Now try to complete the handshake after giving time for a client PTO. // Now try to complete the handshake after giving time for a client PTO.
@ -242,26 +242,26 @@ fn two_tickets_on_timer() {
let pkt = send_something(&mut server, now()); let pkt = send_something(&mut server, now());
// process() will return an ack first // process() will return an ack first
assert!(client.process(Some(&pkt), now()).dgram().is_some()); assert!(client.process(Some(pkt), now()).dgram().is_some());
// We do not have a ResumptionToken event yet, because NEW_TOKEN was not sent. // We do not have a ResumptionToken event yet, because NEW_TOKEN was not sent.
assert_eq!(get_tokens(&mut client).len(), 0); assert_eq!(get_tokens(&mut client).len(), 0);
// We need to wait for release_resumption_token_timer to expire. The timer will be // We need to wait for release_resumption_token_timer to expire. The timer will be
// set to 3 * PTO // set to 3 * PTO
let mut now = now() + 3 * client.pto(); let mut now = now() + 3 * client.pto();
mem::drop(client.process(None, now)); mem::drop(client.process_output(now));
let mut recv_tokens = get_tokens(&mut client); let mut recv_tokens = get_tokens(&mut client);
assert_eq!(recv_tokens.len(), 1); assert_eq!(recv_tokens.len(), 1);
let token1 = recv_tokens.pop().unwrap(); let token1 = recv_tokens.pop().unwrap();
// Wai for anottheer 3 * PTO to get the nex okeen. // Wai for anottheer 3 * PTO to get the nex okeen.
now += 3 * client.pto(); now += 3 * client.pto();
mem::drop(client.process(None, now)); mem::drop(client.process_output(now));
let mut recv_tokens = get_tokens(&mut client); let mut recv_tokens = get_tokens(&mut client);
assert_eq!(recv_tokens.len(), 1); assert_eq!(recv_tokens.len(), 1);
let token2 = recv_tokens.pop().unwrap(); let token2 = recv_tokens.pop().unwrap();
// Wait for 3 * PTO, but now there are no more tokens. // Wait for 3 * PTO, but now there are no more tokens.
now += 3 * client.pto(); now += 3 * client.pto();
mem::drop(client.process(None, now)); mem::drop(client.process_output(now));
assert_eq!(get_tokens(&mut client).len(), 0); assert_eq!(get_tokens(&mut client).len(), 0);
assert_ne!(token1.as_ref(), token2.as_ref()); assert_ne!(token1.as_ref(), token2.as_ref());
@ -283,7 +283,7 @@ fn two_tickets_with_new_token() {
server.send_ticket(now(), &[]).expect("send ticket2"); server.send_ticket(now(), &[]).expect("send ticket2");
let pkt = send_something(&mut server, now()); let pkt = send_something(&mut server, now());
client.process_input(&pkt, now()); client.process_input(pkt, now());
let mut all_tokens = get_tokens(&mut client); let mut all_tokens = get_tokens(&mut client);
assert_eq!(all_tokens.len(), 2); assert_eq!(all_tokens.len(), 2);
let token1 = all_tokens.pop().unwrap(); let token1 = all_tokens.pop().unwrap();
@ -303,8 +303,8 @@ fn take_token() {
connect(&mut client, &mut server); connect(&mut client, &mut server);
server.send_ticket(now(), &[]).unwrap(); server.send_ticket(now(), &[]).unwrap();
let dgram = server.process(None, now()).dgram(); let dgram = server.process_output(now()).dgram();
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
// There should be no ResumptionToken event here. // There should be no ResumptionToken event here.
let tokens = get_tokens(&mut client); let tokens = get_tokens(&mut client);

Просмотреть файл

@ -32,14 +32,14 @@ use crate::{
fn stream_create() { fn stream_create() {
let mut client = default_client(); let mut client = default_client();
let out = client.process(None, now()); let out = client.process_output(now());
let mut server = default_server(); let mut server = default_server();
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
let out = client.process(out.as_dgram_ref(), now()); let out = client.process(out.dgram(), now());
mem::drop(server.process(out.as_dgram_ref(), now())); mem::drop(server.process(out.dgram(), now()));
assert!(maybe_authenticate(&mut client)); assert!(maybe_authenticate(&mut client));
let out = client.process(None, now()); let out = client.process_output(now());
// client now in State::Connected // client now in State::Connected
assert_eq!(client.stream_create(StreamType::UniDi).unwrap(), 2); assert_eq!(client.stream_create(StreamType::UniDi).unwrap(), 2);
@ -47,7 +47,7 @@ fn stream_create() {
assert_eq!(client.stream_create(StreamType::BiDi).unwrap(), 0); assert_eq!(client.stream_create(StreamType::BiDi).unwrap(), 0);
assert_eq!(client.stream_create(StreamType::BiDi).unwrap(), 4); assert_eq!(client.stream_create(StreamType::BiDi).unwrap(), 4);
mem::drop(server.process(out.as_dgram_ref(), now())); mem::drop(server.process(out.dgram(), now()));
// server now in State::Connected // server now in State::Connected
assert_eq!(server.stream_create(StreamType::UniDi).unwrap(), 3); assert_eq!(server.stream_create(StreamType::UniDi).unwrap(), 3);
assert_eq!(server.stream_create(StreamType::UniDi).unwrap(), 7); assert_eq!(server.stream_create(StreamType::UniDi).unwrap(), 7);
@ -86,7 +86,7 @@ fn transfer() {
qdebug!("---- server receives"); qdebug!("---- server receives");
for d in datagrams { for d in datagrams {
let out = server.process(Some(&d), now()); let out = server.process(Some(d), now());
// With an RTT of zero, the server will acknowledge every packet immediately. // With an RTT of zero, the server will acknowledge every packet immediately.
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
qdebug!("Output={:0x?}", out.as_dgram_ref()); qdebug!("Output={:0x?}", out.as_dgram_ref());
@ -151,7 +151,7 @@ fn sendorder_test(order_of_sendorder: &[Option<SendOrder>]) {
qdebug!("---- server receives"); qdebug!("---- server receives");
for d in datagrams { for d in datagrams {
let out = server.process(Some(&d), now()); let out = server.process(Some(d), now());
qdebug!("Output={:0x?}", out.as_dgram_ref()); qdebug!("Output={:0x?}", out.as_dgram_ref());
} }
assert_eq!(*server.state(), State::Confirmed); assert_eq!(*server.state(), State::Confirmed);
@ -317,12 +317,12 @@ fn report_fin_when_stream_closed_wo_data() {
// create a stream // create a stream
let stream_id = client.stream_create(StreamType::BiDi).unwrap(); let stream_id = client.stream_create(StreamType::BiDi).unwrap();
client.stream_send(stream_id, &[0x00]).unwrap(); client.stream_send(stream_id, &[0x00]).unwrap();
let out = client.process(None, now()); let out = client.process_output(now());
mem::drop(server.process(out.as_dgram_ref(), now())); mem::drop(server.process(out.dgram(), now()));
server.stream_close_send(stream_id).unwrap(); server.stream_close_send(stream_id).unwrap();
let out = server.process(None, now()); let out = server.process_output(now());
mem::drop(client.process(out.as_dgram_ref(), now())); mem::drop(client.process(out.dgram(), now()));
let stream_readable = |e| matches!(e, ConnectionEvent::RecvStreamReadable { .. }); let stream_readable = |e| matches!(e, ConnectionEvent::RecvStreamReadable { .. });
assert!(client.events().any(stream_readable)); assert!(client.events().any(stream_readable));
} }
@ -330,9 +330,9 @@ fn report_fin_when_stream_closed_wo_data() {
fn exchange_data(client: &mut Connection, server: &mut Connection) { fn exchange_data(client: &mut Connection, server: &mut Connection) {
let mut input = None; let mut input = None;
loop { loop {
let out = client.process(input.as_ref(), now()).dgram(); let out = client.process(input, now()).dgram();
let c_done = out.is_none(); let c_done = out.is_none();
let out = server.process(out.as_ref(), now()).dgram(); let out = server.process(out, now()).dgram();
if out.is_none() && c_done { if out.is_none() && c_done {
break; break;
} }
@ -373,8 +373,8 @@ fn sending_max_data() {
assert_eq!(received, SMALL_MAX_DATA); assert_eq!(received, SMALL_MAX_DATA);
assert!(!fin); assert!(!fin);
let out = server.process(None, now()).dgram(); let out = server.process_output(now()).dgram();
client.process_input(&out.unwrap(), now()); client.process_input(out.unwrap(), now());
assert_eq!( assert_eq!(
client client
@ -511,8 +511,8 @@ fn do_not_accept_data_after_stop_sending() {
// create a stream // create a stream
let stream_id = client.stream_create(StreamType::BiDi).unwrap(); let stream_id = client.stream_create(StreamType::BiDi).unwrap();
client.stream_send(stream_id, &[0x00]).unwrap(); client.stream_send(stream_id, &[0x00]).unwrap();
let out = client.process(None, now()); let out = client.process_output(now());
mem::drop(server.process(out.as_dgram_ref(), now())); mem::drop(server.process(out.dgram(), now()));
let stream_readable = |e| matches!(e, ConnectionEvent::RecvStreamReadable { .. }); let stream_readable = |e| matches!(e, ConnectionEvent::RecvStreamReadable { .. });
assert!(server.events().any(stream_readable)); assert!(server.events().any(stream_readable));
@ -520,7 +520,7 @@ fn do_not_accept_data_after_stop_sending() {
// Send one more packet from client. The packet should arrive after the server // Send one more packet from client. The packet should arrive after the server
// has already requested stop_sending. // has already requested stop_sending.
client.stream_send(stream_id, &[0x00]).unwrap(); client.stream_send(stream_id, &[0x00]).unwrap();
let out_second_data_frame = client.process(None, now()); let out_second_data_frame = client.process_output(now());
// Call stop sending. // Call stop sending.
assert_eq!( assert_eq!(
Ok(()), Ok(()),
@ -529,10 +529,10 @@ fn do_not_accept_data_after_stop_sending() {
// Receive the second data frame. The frame should be ignored and // Receive the second data frame. The frame should be ignored and
// DataReadable events shouldn't be posted. // DataReadable events shouldn't be posted.
let out = server.process(out_second_data_frame.as_dgram_ref(), now()); let out = server.process(out_second_data_frame.dgram(), now());
assert!(!server.events().any(stream_readable)); assert!(!server.events().any(stream_readable));
mem::drop(client.process(out.as_dgram_ref(), now())); mem::drop(client.process(out.dgram(), now()));
assert_eq!( assert_eq!(
Err(Error::FinalSizeError), Err(Error::FinalSizeError),
client.stream_send(stream_id, &[0x00]) client.stream_send(stream_id, &[0x00])
@ -549,8 +549,8 @@ fn simultaneous_stop_sending_and_reset() {
// create a stream // create a stream
let stream_id = client.stream_create(StreamType::BiDi).unwrap(); let stream_id = client.stream_create(StreamType::BiDi).unwrap();
client.stream_send(stream_id, &[0x00]).unwrap(); client.stream_send(stream_id, &[0x00]).unwrap();
let out = client.process(None, now()); let out = client.process_output(now());
let ack = server.process(out.as_dgram_ref(), now()).dgram(); let ack = server.process(out.dgram(), now()).dgram();
let stream_readable = let stream_readable =
|e| matches!(e, ConnectionEvent::RecvStreamReadable { stream_id: id } if id == stream_id); |e| matches!(e, ConnectionEvent::RecvStreamReadable { stream_id: id } if id == stream_id);
@ -559,23 +559,23 @@ fn simultaneous_stop_sending_and_reset() {
// The client resets the stream. The packet with reset should arrive after the server // The client resets the stream. The packet with reset should arrive after the server
// has already requested stop_sending. // has already requested stop_sending.
client.stream_reset_send(stream_id, 0).unwrap(); client.stream_reset_send(stream_id, 0).unwrap();
let out_reset_frame = client.process(ack.as_ref(), now()).dgram(); let out_reset_frame = client.process(ack, now()).dgram();
// Send something out of order to force the server to generate an // Send something out of order to force the server to generate an
// acknowledgment at the next opportunity. // acknowledgment at the next opportunity.
let force_ack = send_something(&mut client, now()); let force_ack = send_something(&mut client, now());
server.process_input(&force_ack, now()); server.process_input(force_ack, now());
// Call stop sending. // Call stop sending.
server.stream_stop_sending(stream_id, 0).unwrap(); server.stream_stop_sending(stream_id, 0).unwrap();
// Receive the second data frame. The frame should be ignored and // Receive the second data frame. The frame should be ignored and
// DataReadable events shouldn't be posted. // DataReadable events shouldn't be posted.
let ack = server.process(out_reset_frame.as_ref(), now()).dgram(); let ack = server.process(out_reset_frame, now()).dgram();
assert!(ack.is_some()); assert!(ack.is_some());
assert!(!server.events().any(stream_readable)); assert!(!server.events().any(stream_readable));
// The client gets the STOP_SENDING frame. // The client gets the STOP_SENDING frame.
client.process_input(&ack.unwrap(), now()); client.process_input(ack.unwrap(), now());
assert_eq!( assert_eq!(
Err(Error::InvalidStreamId), Err(Error::InvalidStreamId),
client.stream_send(stream_id, &[0x00]) client.stream_send(stream_id, &[0x00])
@ -588,35 +588,35 @@ fn client_fin_reorder() {
let mut server = default_server(); let mut server = default_server();
// Send ClientHello. // Send ClientHello.
let client_hs = client.process(None, now()); let client_hs = client.process_output(now());
assert!(client_hs.as_dgram_ref().is_some()); assert!(client_hs.as_dgram_ref().is_some());
let server_hs = server.process(client_hs.as_dgram_ref(), now()); let server_hs = server.process(client_hs.dgram(), now());
assert!(server_hs.as_dgram_ref().is_some()); // ServerHello, etc... assert!(server_hs.as_dgram_ref().is_some()); // ServerHello, etc...
let client_ack = client.process(server_hs.as_dgram_ref(), now()); let client_ack = client.process(server_hs.dgram(), now());
assert!(client_ack.as_dgram_ref().is_some()); assert!(client_ack.as_dgram_ref().is_some());
let server_out = server.process(client_ack.as_dgram_ref(), now()); let server_out = server.process(client_ack.dgram(), now());
assert!(server_out.as_dgram_ref().is_none()); assert!(server_out.as_dgram_ref().is_none());
assert!(maybe_authenticate(&mut client)); assert!(maybe_authenticate(&mut client));
assert_eq!(*client.state(), State::Connected); assert_eq!(*client.state(), State::Connected);
let client_fin = client.process(None, now()); let client_fin = client.process_output(now());
assert!(client_fin.as_dgram_ref().is_some()); assert!(client_fin.as_dgram_ref().is_some());
let client_stream_id = client.stream_create(StreamType::UniDi).unwrap(); let client_stream_id = client.stream_create(StreamType::UniDi).unwrap();
client.stream_send(client_stream_id, &[1, 2, 3]).unwrap(); client.stream_send(client_stream_id, &[1, 2, 3]).unwrap();
let client_stream_data = client.process(None, now()); let client_stream_data = client.process_output(now());
assert!(client_stream_data.as_dgram_ref().is_some()); assert!(client_stream_data.as_dgram_ref().is_some());
// Now stream data gets before client_fin // Now stream data gets before client_fin
let server_out = server.process(client_stream_data.as_dgram_ref(), now()); let server_out = server.process(client_stream_data.dgram(), now());
assert!(server_out.as_dgram_ref().is_none()); // the packet will be discarded assert!(server_out.as_dgram_ref().is_none()); // the packet will be discarded
assert_eq!(*server.state(), State::Handshaking); assert_eq!(*server.state(), State::Handshaking);
let server_out = server.process(client_fin.as_dgram_ref(), now()); let server_out = server.process(client_fin.dgram(), now());
assert!(server_out.as_dgram_ref().is_some()); assert!(server_out.as_dgram_ref().is_some());
} }
@ -629,10 +629,10 @@ fn after_fin_is_read_conn_events_for_stream_should_be_removed() {
let id = server.stream_create(StreamType::BiDi).unwrap(); let id = server.stream_create(StreamType::BiDi).unwrap();
server.stream_send(id, &[6; 10]).unwrap(); server.stream_send(id, &[6; 10]).unwrap();
server.stream_close_send(id).unwrap(); server.stream_close_send(id).unwrap();
let out = server.process(None, now()).dgram(); let out = server.process_output(now()).dgram();
assert!(out.is_some()); assert!(out.is_some());
mem::drop(client.process(out.as_ref(), now())); mem::drop(client.process(out, now()));
// read from the stream before checking connection events. // read from the stream before checking connection events.
let mut buf = vec![0; 4000]; let mut buf = vec![0; 4000];
@ -654,10 +654,10 @@ fn after_stream_stop_sending_is_called_conn_events_for_stream_should_be_removed(
let id = server.stream_create(StreamType::BiDi).unwrap(); let id = server.stream_create(StreamType::BiDi).unwrap();
server.stream_send(id, &[6; 10]).unwrap(); server.stream_send(id, &[6; 10]).unwrap();
server.stream_close_send(id).unwrap(); server.stream_close_send(id).unwrap();
let out = server.process(None, now()).dgram(); let out = server.process_output(now()).dgram();
assert!(out.is_some()); assert!(out.is_some());
mem::drop(client.process(out.as_ref(), now())); mem::drop(client.process(out, now()));
// send stop seending. // send stop seending.
client client
@ -682,11 +682,11 @@ fn stream_data_blocked_generates_max_stream_data() {
// Send some data and consume some flow control. // Send some data and consume some flow control.
let stream_id = server.stream_create(StreamType::UniDi).unwrap(); let stream_id = server.stream_create(StreamType::UniDi).unwrap();
_ = server.stream_send(stream_id, DEFAULT_STREAM_DATA).unwrap(); _ = server.stream_send(stream_id, DEFAULT_STREAM_DATA).unwrap();
let dgram = server.process(None, now).dgram(); let dgram = server.process_output(now).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
// Consume the data. // Consume the data.
client.process_input(&dgram.unwrap(), now); client.process_input(dgram.unwrap(), now);
let mut buf = [0; 10]; let mut buf = [0; 10];
let (count, end) = client.stream_recv(stream_id, &mut buf[..]).unwrap(); let (count, end) = client.stream_recv(stream_id, &mut buf[..]).unwrap();
assert_eq!(count, DEFAULT_STREAM_DATA.len()); assert_eq!(count, DEFAULT_STREAM_DATA.len());
@ -703,14 +703,14 @@ fn stream_data_blocked_generates_max_stream_data() {
assert!(dgram.is_some()); assert!(dgram.is_some());
let sdb_before = client.stats().frame_rx.stream_data_blocked; let sdb_before = client.stats().frame_rx.stream_data_blocked;
let dgram = client.process(dgram.as_ref(), now).dgram(); let dgram = client.process(dgram, now).dgram();
assert_eq!(client.stats().frame_rx.stream_data_blocked, sdb_before + 1); assert_eq!(client.stats().frame_rx.stream_data_blocked, sdb_before + 1);
assert!(dgram.is_some()); assert!(dgram.is_some());
// Client should have sent a MAX_STREAM_DATA frame with just a small increase // Client should have sent a MAX_STREAM_DATA frame with just a small increase
// on the default window size. // on the default window size.
let msd_before = server.stats().frame_rx.max_stream_data; let msd_before = server.stats().frame_rx.max_stream_data;
server.process_input(&dgram.unwrap(), now); server.process_input(dgram.unwrap(), now);
assert_eq!(server.stats().frame_rx.max_stream_data, msd_before + 1); assert_eq!(server.stats().frame_rx.max_stream_data, msd_before + 1);
// Test that the entirety of the receive buffer is available now. // Test that the entirety of the receive buffer is available now.
@ -742,22 +742,22 @@ fn max_streams_after_bidi_closed() {
// Write on the one stream and send that out. // Write on the one stream and send that out.
_ = client.stream_send(stream_id, REQUEST).unwrap(); _ = client.stream_send(stream_id, REQUEST).unwrap();
client.stream_close_send(stream_id).unwrap(); client.stream_close_send(stream_id).unwrap();
let dgram = client.process(None, now()).dgram(); let dgram = client.process_output(now()).dgram();
// Now handle the stream and send an incomplete response. // Now handle the stream and send an incomplete response.
server.process_input(&dgram.unwrap(), now()); server.process_input(dgram.unwrap(), now());
server.stream_send(stream_id, RESPONSE).unwrap(); server.stream_send(stream_id, RESPONSE).unwrap();
let dgram = server.process_output(now()).dgram(); let dgram = server.process_output(now()).dgram();
// The server shouldn't have released more stream credit. // The server shouldn't have released more stream credit.
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
let e = client.stream_create(StreamType::BiDi).unwrap_err(); let e = client.stream_create(StreamType::BiDi).unwrap_err();
assert!(matches!(e, Error::StreamLimitError)); assert!(matches!(e, Error::StreamLimitError));
// Closing the stream isn't enough. // Closing the stream isn't enough.
server.stream_close_send(stream_id).unwrap(); server.stream_close_send(stream_id).unwrap();
let dgram = server.process_output(now()).dgram(); let dgram = server.process_output(now()).dgram();
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
assert!(client.stream_create(StreamType::BiDi).is_err()); assert!(client.stream_create(StreamType::BiDi).is_err());
// The server needs to see an acknowledgment from the client for its // The server needs to see an acknowledgment from the client for its
@ -771,12 +771,12 @@ fn max_streams_after_bidi_closed() {
// We need an ACK from the client now, but that isn't guaranteed, // We need an ACK from the client now, but that isn't guaranteed,
// so give the client one more packet just in case. // so give the client one more packet just in case.
let dgram = send_something(&mut server, now()); let dgram = send_something(&mut server, now());
client.process_input(&dgram, now()); client.process_input(dgram, now());
// Now get the client to send the ACK and have the server handle that. // Now get the client to send the ACK and have the server handle that.
let dgram = send_something(&mut client, now()); let dgram = send_something(&mut client, now());
let dgram = server.process(Some(&dgram), now()).dgram(); let dgram = server.process(Some(dgram), now()).dgram();
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
assert!(client.stream_create(StreamType::BiDi).is_ok()); assert!(client.stream_create(StreamType::BiDi).is_ok());
assert!(client.stream_create(StreamType::BiDi).is_err()); assert!(client.stream_create(StreamType::BiDi).is_err());
} }
@ -790,8 +790,8 @@ fn no_dupdata_readable_events() {
// create a stream // create a stream
let stream_id = client.stream_create(StreamType::BiDi).unwrap(); let stream_id = client.stream_create(StreamType::BiDi).unwrap();
client.stream_send(stream_id, &[0x00]).unwrap(); client.stream_send(stream_id, &[0x00]).unwrap();
let out = client.process(None, now()); let out = client.process_output(now());
mem::drop(server.process(out.as_dgram_ref(), now())); mem::drop(server.process(out.dgram(), now()));
// We have a data_readable event. // We have a data_readable event.
let stream_readable = |e| matches!(e, ConnectionEvent::RecvStreamReadable { .. }); let stream_readable = |e| matches!(e, ConnectionEvent::RecvStreamReadable { .. });
@ -800,16 +800,16 @@ fn no_dupdata_readable_events() {
// Send one more data frame from client. The previous stream data has not been read yet, // Send one more data frame from client. The previous stream data has not been read yet,
// therefore there should not be a new DataReadable event. // therefore there should not be a new DataReadable event.
client.stream_send(stream_id, &[0x00]).unwrap(); client.stream_send(stream_id, &[0x00]).unwrap();
let out_second_data_frame = client.process(None, now()); let out_second_data_frame = client.process_output(now());
mem::drop(server.process(out_second_data_frame.as_dgram_ref(), now())); mem::drop(server.process(out_second_data_frame.dgram(), now()));
assert!(!server.events().any(stream_readable)); assert!(!server.events().any(stream_readable));
// One more frame with a fin will not produce a new DataReadable event, because the // One more frame with a fin will not produce a new DataReadable event, because the
// previous stream data has not been read yet. // previous stream data has not been read yet.
client.stream_send(stream_id, &[0x00]).unwrap(); client.stream_send(stream_id, &[0x00]).unwrap();
client.stream_close_send(stream_id).unwrap(); client.stream_close_send(stream_id).unwrap();
let out_third_data_frame = client.process(None, now()); let out_third_data_frame = client.process_output(now());
mem::drop(server.process(out_third_data_frame.as_dgram_ref(), now())); mem::drop(server.process(out_third_data_frame.dgram(), now()));
assert!(!server.events().any(stream_readable)); assert!(!server.events().any(stream_readable));
} }
@ -822,8 +822,8 @@ fn no_dupdata_readable_events_empty_last_frame() {
// create a stream // create a stream
let stream_id = client.stream_create(StreamType::BiDi).unwrap(); let stream_id = client.stream_create(StreamType::BiDi).unwrap();
client.stream_send(stream_id, &[0x00]).unwrap(); client.stream_send(stream_id, &[0x00]).unwrap();
let out = client.process(None, now()); let out = client.process_output(now());
mem::drop(server.process(out.as_dgram_ref(), now())); mem::drop(server.process(out.dgram(), now()));
// We have a data_readable event. // We have a data_readable event.
let stream_readable = |e| matches!(e, ConnectionEvent::RecvStreamReadable { .. }); let stream_readable = |e| matches!(e, ConnectionEvent::RecvStreamReadable { .. });
@ -832,8 +832,8 @@ fn no_dupdata_readable_events_empty_last_frame() {
// An empty frame with a fin will not produce a new DataReadable event, because // An empty frame with a fin will not produce a new DataReadable event, because
// the previous stream data has not been read yet. // the previous stream data has not been read yet.
client.stream_close_send(stream_id).unwrap(); client.stream_close_send(stream_id).unwrap();
let out_second_data_frame = client.process(None, now()); let out_second_data_frame = client.process_output(now());
mem::drop(server.process(out_second_data_frame.as_dgram_ref(), now())); mem::drop(server.process(out_second_data_frame.dgram(), now()));
assert!(!server.events().any(stream_readable)); assert!(!server.events().any(stream_readable));
} }
@ -854,15 +854,15 @@ fn change_flow_control(stream_type: StreamType, new_fc: u64) {
assert_eq!(u64::try_from(written1).unwrap(), RECV_BUFFER_START); assert_eq!(u64::try_from(written1).unwrap(), RECV_BUFFER_START);
// Send the stream to the client. // Send the stream to the client.
let out = server.process(None, now()); let out = server.process_output(now());
mem::drop(client.process(out.as_dgram_ref(), now())); mem::drop(client.process(out.dgram(), now()));
// change max_stream_data for stream_id. // change max_stream_data for stream_id.
client.set_stream_max_data(stream_id, new_fc).unwrap(); client.set_stream_max_data(stream_id, new_fc).unwrap();
// server should receive a MAX_SREAM_DATA frame if the flow control window is updated. // server should receive a MAX_SREAM_DATA frame if the flow control window is updated.
let out2 = client.process(None, now()); let out2 = client.process_output(now());
let out3 = server.process(out2.as_dgram_ref(), now()); let out3 = server.process(out2.dgram(), now());
let expected = usize::from(RECV_BUFFER_START < new_fc); let expected = usize::from(RECV_BUFFER_START < new_fc);
assert_eq!(server.stats().frame_rx.max_stream_data, expected); assert_eq!(server.stats().frame_rx.max_stream_data, expected);
@ -875,17 +875,17 @@ fn change_flow_control(stream_type: StreamType, new_fc: u64) {
} }
// Exchange packets so that client gets all data. // Exchange packets so that client gets all data.
let out4 = client.process(out3.as_dgram_ref(), now()); let out4 = client.process(out3.dgram(), now());
let out5 = server.process(out4.as_dgram_ref(), now()); let out5 = server.process(out4.dgram(), now());
mem::drop(client.process(out5.as_dgram_ref(), now())); mem::drop(client.process(out5.dgram(), now()));
// read all data by client // read all data by client
let mut buf = [0x0; 10000]; let mut buf = [0x0; 10000];
let (read, _) = client.stream_recv(stream_id, &mut buf).unwrap(); let (read, _) = client.stream_recv(stream_id, &mut buf).unwrap();
assert_eq!(u64::try_from(read).unwrap(), max(RECV_BUFFER_START, new_fc)); assert_eq!(u64::try_from(read).unwrap(), max(RECV_BUFFER_START, new_fc));
let out4 = client.process(None, now()); let out4 = client.process_output(now());
mem::drop(server.process(out4.as_dgram_ref(), now())); mem::drop(server.process(out4.dgram(), now()));
let written3 = server.stream_send(stream_id, &[0x0; 10000]).unwrap(); let written3 = server.stream_send(stream_id, &[0x0; 10000]).unwrap();
assert_eq!(u64::try_from(written3).unwrap(), new_fc); assert_eq!(u64::try_from(written3).unwrap(), new_fc);
@ -939,13 +939,13 @@ fn session_flow_control_stop_sending_state_recv() {
// In this case the final size is only known after RESET frame is received. // In this case the final size is only known after RESET frame is received.
// The server sends STOP_SENDING -> the client sends RESET -> the server // The server sends STOP_SENDING -> the client sends RESET -> the server
// sends MAX_DATA. // sends MAX_DATA.
let out = server.process(None, now()).dgram(); let out = server.process_output(now()).dgram();
let out = client.process(out.as_ref(), now()).dgram(); let out = client.process(out, now()).dgram();
// the client is still limited. // the client is still limited.
let stream_id2 = client.stream_create(StreamType::UniDi).unwrap(); let stream_id2 = client.stream_create(StreamType::UniDi).unwrap();
assert_eq!(client.stream_avail_send_space(stream_id2).unwrap(), 0); assert_eq!(client.stream_avail_send_space(stream_id2).unwrap(), 0);
let out = server.process(out.as_ref(), now()).dgram(); let out = server.process(out, now()).dgram();
client.process_input(&out.unwrap(), now()); client.process_input(out.unwrap(), now());
assert_eq!( assert_eq!(
client.stream_avail_send_space(stream_id2).unwrap(), client.stream_avail_send_space(stream_id2).unwrap(),
SMALL_MAX_DATA SMALL_MAX_DATA
@ -977,12 +977,12 @@ fn session_flow_control_stop_sending_state_size_known() {
SMALL_MAX_DATA SMALL_MAX_DATA
); );
let out1 = client.process(None, now()).dgram(); let out1 = client.process_output(now()).dgram();
// Delay this packet and let the server receive fin first (it will enter SizeKnown state). // Delay this packet and let the server receive fin first (it will enter SizeKnown state).
client.stream_close_send(stream_id).unwrap(); client.stream_close_send(stream_id).unwrap();
let out2 = client.process(None, now()).dgram(); let out2 = client.process_output(now()).dgram();
server.process_input(&out2.unwrap(), now()); server.process_input(out2.unwrap(), now());
server server
.stream_stop_sending(stream_id, Error::NoError.code()) .stream_stop_sending(stream_id, Error::NoError.code())
@ -991,8 +991,8 @@ fn session_flow_control_stop_sending_state_size_known() {
// In this case the final size is known when stream_stop_sending is called // In this case the final size is known when stream_stop_sending is called
// and the server releases flow control immediately and sends STOP_SENDING and // and the server releases flow control immediately and sends STOP_SENDING and
// MAX_DATA in the same packet. // MAX_DATA in the same packet.
let out = server.process(out1.as_ref(), now()).dgram(); let out = server.process(out1, now()).dgram();
client.process_input(&out.unwrap(), now()); client.process_input(out.unwrap(), now());
// The flow control should have been updated and the client can again send // The flow control should have been updated and the client can again send
// SMALL_MAX_DATA. // SMALL_MAX_DATA.
@ -1108,16 +1108,16 @@ fn session_flow_control_affects_all_streams() {
fn connect_w_different_limit(bidi_limit: u64, unidi_limit: u64) { fn connect_w_different_limit(bidi_limit: u64, unidi_limit: u64) {
let mut client = default_client(); let mut client = default_client();
let out = client.process(None, now()); let out = client.process_output(now());
let mut server = new_server( let mut server = new_server(
ConnectionParameters::default() ConnectionParameters::default()
.max_streams(StreamType::BiDi, bidi_limit) .max_streams(StreamType::BiDi, bidi_limit)
.max_streams(StreamType::UniDi, unidi_limit), .max_streams(StreamType::UniDi, unidi_limit),
); );
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
let out = client.process(out.as_dgram_ref(), now()); let out = client.process(out.dgram(), now());
mem::drop(server.process(out.as_dgram_ref(), now())); mem::drop(server.process(out.dgram(), now()));
assert!(maybe_authenticate(&mut client)); assert!(maybe_authenticate(&mut client));

Просмотреть файл

@ -27,11 +27,11 @@ const INITIAL_PTO: Duration = Duration::from_millis(300);
fn unknown_version() { fn unknown_version() {
let mut client = default_client(); let mut client = default_client();
// Start the handshake. // Start the handshake.
mem::drop(client.process(None, now()).dgram()); mem::drop(client.process_output(now()).dgram());
let mut unknown_version_packet = vec![0x80, 0x1a, 0x1a, 0x1a, 0x1a]; let mut unknown_version_packet = vec![0x80, 0x1a, 0x1a, 0x1a, 0x1a];
unknown_version_packet.resize(MIN_INITIAL_PACKET_SIZE, 0x0); unknown_version_packet.resize(MIN_INITIAL_PACKET_SIZE, 0x0);
mem::drop(client.process(Some(&datagram(unknown_version_packet)), now())); mem::drop(client.process(Some(datagram(unknown_version_packet)), now()));
assert_eq!(1, client.stats().dropped_rx); assert_eq!(1, client.stats().dropped_rx);
} }
@ -43,7 +43,7 @@ fn server_receive_unknown_first_packet() {
unknown_version_packet.resize(MIN_INITIAL_PACKET_SIZE, 0x0); unknown_version_packet.resize(MIN_INITIAL_PACKET_SIZE, 0x0);
assert_eq!( assert_eq!(
server.process(Some(&datagram(unknown_version_packet)), now()), server.process(Some(datagram(unknown_version_packet)), now()),
Output::None Output::None
); );
@ -72,7 +72,7 @@ fn version_negotiation_current_version() {
let mut client = default_client(); let mut client = default_client();
// Start the handshake. // Start the handshake.
let initial_pkt = client let initial_pkt = client
.process(None, now()) .process_output(now())
.dgram() .dgram()
.expect("a datagram") .expect("a datagram")
.to_vec(); .to_vec();
@ -83,7 +83,7 @@ fn version_negotiation_current_version() {
); );
let dgram = datagram(vn); let dgram = datagram(vn);
let delay = client.process(Some(&dgram), now()).callback(); let delay = client.process(Some(dgram), now()).callback();
assert_eq!(delay, INITIAL_PTO); assert_eq!(delay, INITIAL_PTO);
assert_eq!(*client.state(), State::WaitInitial); assert_eq!(*client.state(), State::WaitInitial);
assert_eq!(1, client.stats().dropped_rx); assert_eq!(1, client.stats().dropped_rx);
@ -94,7 +94,7 @@ fn version_negotiation_version0() {
let mut client = default_client(); let mut client = default_client();
// Start the handshake. // Start the handshake.
let initial_pkt = client let initial_pkt = client
.process(None, now()) .process_output(now())
.dgram() .dgram()
.expect("a datagram") .expect("a datagram")
.to_vec(); .to_vec();
@ -102,7 +102,7 @@ fn version_negotiation_version0() {
let vn = create_vn(&initial_pkt, &[0, 0x1a1a_1a1a]); let vn = create_vn(&initial_pkt, &[0, 0x1a1a_1a1a]);
let dgram = datagram(vn); let dgram = datagram(vn);
let delay = client.process(Some(&dgram), now()).callback(); let delay = client.process(Some(dgram), now()).callback();
assert_eq!(delay, INITIAL_PTO); assert_eq!(delay, INITIAL_PTO);
assert_eq!(*client.state(), State::WaitInitial); assert_eq!(*client.state(), State::WaitInitial);
assert_eq!(1, client.stats().dropped_rx); assert_eq!(1, client.stats().dropped_rx);
@ -113,7 +113,7 @@ fn version_negotiation_only_reserved() {
let mut client = default_client(); let mut client = default_client();
// Start the handshake. // Start the handshake.
let initial_pkt = client let initial_pkt = client
.process(None, now()) .process_output(now())
.dgram() .dgram()
.expect("a datagram") .expect("a datagram")
.to_vec(); .to_vec();
@ -121,7 +121,7 @@ fn version_negotiation_only_reserved() {
let vn = create_vn(&initial_pkt, &[0x1a1a_1a1a, 0x2a2a_2a2a]); let vn = create_vn(&initial_pkt, &[0x1a1a_1a1a, 0x2a2a_2a2a]);
let dgram = datagram(vn); let dgram = datagram(vn);
assert_eq!(client.process(Some(&dgram), now()), Output::None); assert_eq!(client.process(Some(dgram), now()), Output::None);
match client.state() { match client.state() {
State::Closed(err) => { State::Closed(err) => {
assert_eq!(*err, CloseReason::Transport(Error::VersionNegotiation)); assert_eq!(*err, CloseReason::Transport(Error::VersionNegotiation));
@ -135,7 +135,7 @@ fn version_negotiation_corrupted() {
let mut client = default_client(); let mut client = default_client();
// Start the handshake. // Start the handshake.
let initial_pkt = client let initial_pkt = client
.process(None, now()) .process_output(now())
.dgram() .dgram()
.expect("a datagram") .expect("a datagram")
.to_vec(); .to_vec();
@ -143,7 +143,7 @@ fn version_negotiation_corrupted() {
let vn = create_vn(&initial_pkt, &[0x1a1a_1a1a, 0x2a2a_2a2a]); let vn = create_vn(&initial_pkt, &[0x1a1a_1a1a, 0x2a2a_2a2a]);
let dgram = datagram(vn[..vn.len() - 1].to_vec()); let dgram = datagram(vn[..vn.len() - 1].to_vec());
let delay = client.process(Some(&dgram), now()).callback(); let delay = client.process(Some(dgram), now()).callback();
assert_eq!(delay, INITIAL_PTO); assert_eq!(delay, INITIAL_PTO);
assert_eq!(*client.state(), State::WaitInitial); assert_eq!(*client.state(), State::WaitInitial);
assert_eq!(1, client.stats().dropped_rx); assert_eq!(1, client.stats().dropped_rx);
@ -154,7 +154,7 @@ fn version_negotiation_empty() {
let mut client = default_client(); let mut client = default_client();
// Start the handshake. // Start the handshake.
let initial_pkt = client let initial_pkt = client
.process(None, now()) .process_output(now())
.dgram() .dgram()
.expect("a datagram") .expect("a datagram")
.to_vec(); .to_vec();
@ -162,7 +162,7 @@ fn version_negotiation_empty() {
let vn = create_vn(&initial_pkt, &[]); let vn = create_vn(&initial_pkt, &[]);
let dgram = datagram(vn); let dgram = datagram(vn);
let delay = client.process(Some(&dgram), now()).callback(); let delay = client.process(Some(dgram), now()).callback();
assert_eq!(delay, INITIAL_PTO); assert_eq!(delay, INITIAL_PTO);
assert_eq!(*client.state(), State::WaitInitial); assert_eq!(*client.state(), State::WaitInitial);
assert_eq!(1, client.stats().dropped_rx); assert_eq!(1, client.stats().dropped_rx);
@ -173,14 +173,14 @@ fn version_negotiation_not_supported() {
let mut client = default_client(); let mut client = default_client();
// Start the handshake. // Start the handshake.
let initial_pkt = client let initial_pkt = client
.process(None, now()) .process_output(now())
.dgram() .dgram()
.expect("a datagram") .expect("a datagram")
.to_vec(); .to_vec();
let vn = create_vn(&initial_pkt, &[0x1a1a_1a1a, 0x2a2a_2a2a, 0xff00_0001]); let vn = create_vn(&initial_pkt, &[0x1a1a_1a1a, 0x2a2a_2a2a, 0xff00_0001]);
let dgram = datagram(vn); let dgram = datagram(vn);
assert_eq!(client.process(Some(&dgram), now()), Output::None); assert_eq!(client.process(Some(dgram), now()), Output::None);
match client.state() { match client.state() {
State::Closed(err) => { State::Closed(err) => {
assert_eq!(*err, CloseReason::Transport(Error::VersionNegotiation)); assert_eq!(*err, CloseReason::Transport(Error::VersionNegotiation));
@ -194,7 +194,7 @@ fn version_negotiation_bad_cid() {
let mut client = default_client(); let mut client = default_client();
// Start the handshake. // Start the handshake.
let mut initial_pkt = client let mut initial_pkt = client
.process(None, now()) .process_output(now())
.dgram() .dgram()
.expect("a datagram") .expect("a datagram")
.to_vec(); .to_vec();
@ -203,7 +203,7 @@ fn version_negotiation_bad_cid() {
let vn = create_vn(&initial_pkt, &[0x1a1a_1a1a, 0x2a2a_2a2a, 0xff00_0001]); let vn = create_vn(&initial_pkt, &[0x1a1a_1a1a, 0x2a2a_2a2a, 0xff00_0001]);
let dgram = datagram(vn); let dgram = datagram(vn);
let delay = client.process(Some(&dgram), now()).callback(); let delay = client.process(Some(dgram), now()).callback();
assert_eq!(delay, INITIAL_PTO); assert_eq!(delay, INITIAL_PTO);
assert_eq!(*client.state(), State::WaitInitial); assert_eq!(*client.state(), State::WaitInitial);
assert_eq!(1, client.stats().dropped_rx); assert_eq!(1, client.stats().dropped_rx);
@ -240,11 +240,11 @@ fn compatible_upgrade_large_initial() {
// Each should elicit a Version 1 ACK from the server. // Each should elicit a Version 1 ACK from the server.
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
let dgram = server.process(dgram.as_ref(), now()).dgram(); let dgram = server.process(dgram, now()).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
// The following uses the Version from *outside* this crate. // The following uses the Version from *outside* this crate.
assertions::assert_version(dgram.as_ref().unwrap(), Version::Version1.wire_version()); assertions::assert_version(dgram.as_ref().unwrap(), Version::Version1.wire_version());
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
connect(&mut client, &mut server); connect(&mut client, &mut server);
assert_eq!(client.version(), Version::Version2); assert_eq!(client.version(), Version::Version2);
@ -308,7 +308,7 @@ fn version_negotiation_downgrade() {
let initial = client.process_output(now()).dgram().unwrap(); let initial = client.process_output(now()).dgram().unwrap();
let vn = create_vn(&initial, &[DOWNGRADE.wire_version()]); let vn = create_vn(&initial, &[DOWNGRADE.wire_version()]);
let dgram = datagram(vn); let dgram = datagram(vn);
client.process_input(&dgram, now()); client.process_input(dgram, now());
connect_fail( connect_fail(
&mut client, &mut client,
@ -328,7 +328,7 @@ fn invalid_server_version() {
new_server(ConnectionParameters::default().versions(Version::Version2, Version::all())); new_server(ConnectionParameters::default().versions(Version::Version2, Version::all()));
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
server.process_input(&dgram.unwrap(), now()); server.process_input(dgram.unwrap(), now());
// One packet received. // One packet received.
assert_eq!(server.stats().packets_rx, 1); assert_eq!(server.stats().packets_rx, 1);
@ -459,7 +459,7 @@ fn compatible_upgrade_0rtt_rejected() {
let initial = send_something(&mut client, now()); let initial = send_something(&mut client, now());
assertions::assert_version(&initial, Version::Version1.wire_version()); assertions::assert_version(&initial, Version::Version1.wire_version());
assertions::assert_coalesced_0rtt(&initial); assertions::assert_coalesced_0rtt(&initial);
server.process_input(&initial, now()); server.process_input(initial, now());
assert!(!server assert!(!server
.events() .events()
.any(|e| matches!(e, ConnectionEvent::NewStream { .. }))); .any(|e| matches!(e, ConnectionEvent::NewStream { .. })));
@ -467,9 +467,9 @@ fn compatible_upgrade_0rtt_rejected() {
// Finalize the connection. Don't use connect() because it uses // Finalize the connection. Don't use connect() because it uses
// maybe_authenticate() too liberally and that eats the events we want to check. // maybe_authenticate() too liberally and that eats the events we want to check.
let dgram = server.process_output(now()).dgram(); // ServerHello flight let dgram = server.process_output(now()).dgram(); // ServerHello flight
let dgram = client.process(dgram.as_ref(), now()).dgram(); // Client Finished (note: no authentication) let dgram = client.process(dgram, now()).dgram(); // Client Finished (note: no authentication)
let dgram = server.process(dgram.as_ref(), now()).dgram(); // HANDSHAKE_DONE let dgram = server.process(dgram, now()).dgram(); // HANDSHAKE_DONE
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
assert!(matches!(client.state(), State::Confirmed)); assert!(matches!(client.state(), State::Confirmed));
assert!(matches!(server.state(), State::Confirmed)); assert!(matches!(server.state(), State::Confirmed));

Просмотреть файл

@ -52,24 +52,24 @@ fn zero_rtt_send_recv() {
let mut server = resumed_server(&client); let mut server = resumed_server(&client);
// Send ClientHello. // Send ClientHello.
let client_hs = client.process(None, now()); let client_hs = client.process_output(now());
assert!(client_hs.as_dgram_ref().is_some()); assert!(client_hs.as_dgram_ref().is_some());
// Now send a 0-RTT packet. // Now send a 0-RTT packet.
let client_stream_id = client.stream_create(StreamType::UniDi).unwrap(); let client_stream_id = client.stream_create(StreamType::UniDi).unwrap();
client.stream_send(client_stream_id, &[1, 2, 3]).unwrap(); client.stream_send(client_stream_id, &[1, 2, 3]).unwrap();
let client_0rtt = client.process(None, now()); let client_0rtt = client.process_output(now());
assert!(client_0rtt.as_dgram_ref().is_some()); assert!(client_0rtt.as_dgram_ref().is_some());
// 0-RTT packets on their own shouldn't be padded to MIN_INITIAL_PACKET_SIZE. // 0-RTT packets on their own shouldn't be padded to MIN_INITIAL_PACKET_SIZE.
assert!(client_0rtt.as_dgram_ref().unwrap().len() < MIN_INITIAL_PACKET_SIZE); assert!(client_0rtt.as_dgram_ref().unwrap().len() < MIN_INITIAL_PACKET_SIZE);
let server_hs = server.process(client_hs.as_dgram_ref(), now()); let server_hs = server.process(client_hs.dgram(), now());
assert!(server_hs.as_dgram_ref().is_some()); // ServerHello, etc... assert!(server_hs.as_dgram_ref().is_some()); // ServerHello, etc...
let all_frames = server.stats().frame_tx.all(); let all_frames = server.stats().frame_tx.all();
let ack_frames = server.stats().frame_tx.ack; let ack_frames = server.stats().frame_tx.ack;
let server_process_0rtt = server.process(client_0rtt.as_dgram_ref(), now()); let server_process_0rtt = server.process(client_0rtt.dgram(), now());
assert!(server_process_0rtt.as_dgram_ref().is_some()); assert!(server_process_0rtt.dgram().is_some());
assert_eq!(server.stats().frame_tx.all(), all_frames + 1); assert_eq!(server.stats().frame_tx.all(), all_frames + 1);
assert_eq!(server.stats().frame_tx.ack, ack_frames + 1); assert_eq!(server.stats().frame_tx.ack, ack_frames + 1);
@ -100,12 +100,12 @@ fn zero_rtt_send_coalesce() {
// This should result in a datagram that coalesces Initial and 0-RTT. // This should result in a datagram that coalesces Initial and 0-RTT.
let client_stream_id = client.stream_create(StreamType::UniDi).unwrap(); let client_stream_id = client.stream_create(StreamType::UniDi).unwrap();
client.stream_send(client_stream_id, &[1, 2, 3]).unwrap(); client.stream_send(client_stream_id, &[1, 2, 3]).unwrap();
let client_0rtt = client.process(None, now()); let client_0rtt = client.process_output(now());
assert!(client_0rtt.as_dgram_ref().is_some()); assert!(client_0rtt.as_dgram_ref().is_some());
assertions::assert_coalesced_0rtt(&client_0rtt.as_dgram_ref().unwrap()[..]); assertions::assert_coalesced_0rtt(&client_0rtt.as_dgram_ref().unwrap()[..]);
let server_hs = server.process(client_0rtt.as_dgram_ref(), now()); let server_hs = server.process(client_0rtt.dgram(), now());
assert!(server_hs.as_dgram_ref().is_some()); // Should produce ServerHello etc... assert!(server_hs.as_dgram_ref().is_some()); // Should produce ServerHello etc...
let server_stream_id = server let server_stream_id = server
@ -153,18 +153,18 @@ fn zero_rtt_send_reject() {
.expect("enable 0-RTT"); .expect("enable 0-RTT");
// Send ClientHello. // Send ClientHello.
let client_hs = client.process(None, now()); let client_hs = client.process_output(now());
assert!(client_hs.as_dgram_ref().is_some()); assert!(client_hs.as_dgram_ref().is_some());
// Write some data on the client. // Write some data on the client.
let stream_id = client.stream_create(StreamType::UniDi).unwrap(); let stream_id = client.stream_create(StreamType::UniDi).unwrap();
client.stream_send(stream_id, MESSAGE).unwrap(); client.stream_send(stream_id, MESSAGE).unwrap();
let client_0rtt = client.process(None, now()); let client_0rtt = client.process_output(now());
assert!(client_0rtt.as_dgram_ref().is_some()); assert!(client_0rtt.as_dgram_ref().is_some());
let server_hs = server.process(client_hs.as_dgram_ref(), now()); let server_hs = server.process(client_hs.dgram(), now());
assert!(server_hs.as_dgram_ref().is_some()); // Should produce ServerHello etc... assert!(server_hs.as_dgram_ref().is_some()); // Should produce ServerHello etc...
let server_ignored = server.process(client_0rtt.as_dgram_ref(), now()); let server_ignored = server.process(client_0rtt.dgram(), now());
assert!(server_ignored.as_dgram_ref().is_none()); assert!(server_ignored.as_dgram_ref().is_none());
// The server shouldn't receive that 0-RTT data. // The server shouldn't receive that 0-RTT data.
@ -172,14 +172,14 @@ fn zero_rtt_send_reject() {
assert!(!server.events().any(recvd_stream_evt)); assert!(!server.events().any(recvd_stream_evt));
// Client should get a rejection. // Client should get a rejection.
let client_fin = client.process(server_hs.as_dgram_ref(), now()); let client_fin = client.process(server_hs.dgram(), now());
let recvd_0rtt_reject = |e| e == ConnectionEvent::ZeroRttRejected; let recvd_0rtt_reject = |e| e == ConnectionEvent::ZeroRttRejected;
assert!(client.events().any(recvd_0rtt_reject)); assert!(client.events().any(recvd_0rtt_reject));
// Server consume client_fin // Server consume client_fin
let server_ack = server.process(client_fin.as_dgram_ref(), now()); let server_ack = server.process(client_fin.dgram(), now());
assert!(server_ack.as_dgram_ref().is_some()); assert!(server_ack.as_dgram_ref().is_some());
let client_out = client.process(server_ack.as_dgram_ref(), now()); let client_out = client.process(server_ack.dgram(), now());
assert!(client_out.as_dgram_ref().is_none()); assert!(client_out.as_dgram_ref().is_none());
// ...and the client stream should be gone. // ...and the client stream should be gone.
@ -191,11 +191,11 @@ fn zero_rtt_send_reject() {
let stream_id_after_reject = client.stream_create(StreamType::UniDi).unwrap(); let stream_id_after_reject = client.stream_create(StreamType::UniDi).unwrap();
assert_eq!(stream_id, stream_id_after_reject); assert_eq!(stream_id, stream_id_after_reject);
client.stream_send(stream_id_after_reject, MESSAGE).unwrap(); client.stream_send(stream_id_after_reject, MESSAGE).unwrap();
let client_after_reject = client.process(None, now()).dgram(); let client_after_reject = client.process_output(now()).dgram();
assert!(client_after_reject.is_some()); assert!(client_after_reject.is_some());
// The server should receive new stream // The server should receive new stream
server.process_input(&client_after_reject.unwrap(), now()); server.process_input(client_after_reject.unwrap(), now());
assert!(server.events().any(recvd_stream_evt)); assert!(server.events().any(recvd_stream_evt));
} }
@ -227,15 +227,15 @@ fn zero_rtt_update_flow_control() {
); );
// Stream limits should be low for 0-RTT. // Stream limits should be low for 0-RTT.
let client_hs = client.process(None, now()).dgram(); let client_hs = client.process_output(now()).dgram();
let uni_stream = client.stream_create(StreamType::UniDi).unwrap(); let uni_stream = client.stream_create(StreamType::UniDi).unwrap();
assert!(!client.stream_send_atomic(uni_stream, MESSAGE).unwrap()); assert!(!client.stream_send_atomic(uni_stream, MESSAGE).unwrap());
let bidi_stream = client.stream_create(StreamType::BiDi).unwrap(); let bidi_stream = client.stream_create(StreamType::BiDi).unwrap();
assert!(!client.stream_send_atomic(bidi_stream, MESSAGE).unwrap()); assert!(!client.stream_send_atomic(bidi_stream, MESSAGE).unwrap());
// Now get the server transport parameters. // Now get the server transport parameters.
let server_hs = server.process(client_hs.as_ref(), now()).dgram(); let server_hs = server.process(client_hs, now()).dgram();
client.process_input(&server_hs.unwrap(), now()); client.process_input(server_hs.unwrap(), now());
// The streams should report a writeable event. // The streams should report a writeable event.
let mut uni_stream_event = false; let mut uni_stream_event = false;
@ -299,7 +299,7 @@ fn zero_rtt_loss_accepted() {
} }
// Process CI/0-RTT // Process CI/0-RTT
let si = server.process(ci.as_dgram_ref(), now); let si = server.process(ci.dgram(), now);
assert!(si.as_dgram_ref().is_some()); assert!(si.as_dgram_ref().is_some());
let server_stream_id = server let server_stream_id = server
@ -312,7 +312,7 @@ fn zero_rtt_loss_accepted() {
assert_eq!(client_stream_id, server_stream_id.as_u64()); assert_eq!(client_stream_id, server_stream_id.as_u64());
// 0-RTT should be accepted // 0-RTT should be accepted
client.process_input(si.as_dgram_ref().unwrap(), now); client.process_input(si.dgram().unwrap(), now);
let recvd_0rtt_reject = |e| e == ConnectionEvent::ZeroRttRejected; let recvd_0rtt_reject = |e| e == ConnectionEvent::ZeroRttRejected;
assert!( assert!(
!client.events().any(recvd_0rtt_reject), !client.events().any(recvd_0rtt_reject),

1
third_party/rust/neqo-transport/src/lib.rs поставляемый
Просмотреть файл

@ -107,7 +107,6 @@ pub enum Error {
DecodingFrame, DecodingFrame,
DecryptError, DecryptError,
DisabledVersion, DisabledVersion,
HandshakeFailed,
IdleTimeout, IdleTimeout,
IntegerOverflow, IntegerOverflow,
InvalidInput, InvalidInput,

2
third_party/rust/neqo-transport/src/path.rs поставляемый
Просмотреть файл

@ -718,7 +718,7 @@ impl Path {
// with the current value. // with the current value.
let tos = self.tos(); let tos = self.tos();
self.ecn_info.on_packet_sent(stats); self.ecn_info.on_packet_sent(stats);
Datagram::new(self.local, self.remote, tos, payload) Datagram::new(self.local, self.remote, tos, payload.into())
} }
/// Get local address as `SocketAddr` /// Get local address as `SocketAddr`

16
third_party/rust/neqo-transport/src/server.rs поставляемый
Просмотреть файл

@ -195,7 +195,7 @@ impl Server {
fn handle_initial( fn handle_initial(
&mut self, &mut self,
initial: InitialDetails, initial: InitialDetails,
dgram: &Datagram, dgram: Datagram<impl AsRef<[u8]>>,
now: Instant, now: Instant,
) -> Output { ) -> Output {
qdebug!([self], "Handle initial"); qdebug!([self], "Handle initial");
@ -297,7 +297,7 @@ impl Server {
fn accept_connection( fn accept_connection(
&mut self, &mut self,
initial: InitialDetails, initial: InitialDetails,
dgram: &Datagram, dgram: Datagram<impl AsRef<[u8]>>,
orig_dcid: Option<ConnectionId>, orig_dcid: Option<ConnectionId>,
now: Instant, now: Instant,
) -> Output { ) -> Output {
@ -339,7 +339,7 @@ impl Server {
} }
} }
fn process_input(&mut self, dgram: &Datagram, now: Instant) -> Output { fn process_input(&mut self, dgram: Datagram<impl AsRef<[u8]>>, now: Instant) -> Output {
qtrace!("Process datagram: {}", hex(&dgram[..])); qtrace!("Process datagram: {}", hex(&dgram[..]));
// This is only looking at the first packet header in the datagram. // This is only looking at the first packet header in the datagram.
@ -430,7 +430,7 @@ impl Server {
let mut callback = None; let mut callback = None;
for connection in &mut self.connections { for connection in &mut self.connections {
match connection.borrow_mut().process(None, now) { match connection.borrow_mut().process_output(now) {
Output::None => {} Output::None => {}
d @ Output::Datagram(_) => return d, d @ Output::Datagram(_) => return d,
Output::Callback(next) => match callback { Output::Callback(next) => match callback {
@ -443,8 +443,14 @@ impl Server {
callback.map_or(Output::None, Output::Callback) callback.map_or(Output::None, Output::Callback)
} }
/// Short-hand for [`Server::process`] without an input datagram.
#[must_use] #[must_use]
pub fn process(&mut self, dgram: Option<&Datagram>, now: Instant) -> Output { pub fn process_output(&mut self, now: Instant) -> Output {
self.process(None::<Datagram>, now)
}
#[must_use]
pub fn process(&mut self, dgram: Option<Datagram<impl AsRef<[u8]>>>, now: Instant) -> Output {
let out = dgram let out = dgram
.map_or(Output::None, |d| self.process_input(d, now)) .map_or(Output::None, |d| self.process_input(d, now))
.or_else(|| self.process_next_output(now)); .or_else(|| self.process_next_output(now));

Просмотреть файл

@ -58,27 +58,27 @@ pub fn connect(client: &mut Connection, server: &mut Server) -> ConnectionRef {
server.set_validation(ValidateAddress::Never); server.set_validation(ValidateAddress::Never);
assert_eq!(*client.state(), State::Init); assert_eq!(*client.state(), State::Init);
let out = client.process(None, now()); // ClientHello let out = client.process_output(now()); // ClientHello
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
let out = server.process(out.as_dgram_ref(), now()); // ServerHello... let out = server.process(out.dgram(), now()); // ServerHello...
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
// Ingest the server Certificate. // Ingest the server Certificate.
let out = client.process(out.as_dgram_ref(), now()); let out = client.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_some()); // This should just be an ACK. assert!(out.as_dgram_ref().is_some()); // This should just be an ACK.
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_none()); // So the server should have nothing to say. assert!(out.as_dgram_ref().is_none()); // So the server should have nothing to say.
// Now mark the server as authenticated. // Now mark the server as authenticated.
client.authenticated(AuthenticationStatus::Ok, now()); client.authenticated(AuthenticationStatus::Ok, now());
let out = client.process(None, now()); let out = client.process_output(now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
assert_eq!(*client.state(), State::Connected); assert_eq!(*client.state(), State::Connected);
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_some()); // ACK + HANDSHAKE_DONE + NST assert!(out.as_dgram_ref().is_some()); // ACK + HANDSHAKE_DONE + NST
// Have the client process the HANDSHAKE_DONE. // Have the client process the HANDSHAKE_DONE.
let out = client.process(out.as_dgram_ref(), now()); let out = client.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_none()); assert!(out.as_dgram_ref().is_none());
assert_eq!(*client.state(), State::Confirmed); assert_eq!(*client.state(), State::Confirmed);
@ -105,14 +105,14 @@ pub fn generate_ticket(server: &mut Server) -> ResumptionToken {
let mut server_conn = connect(&mut client, server); let mut server_conn = connect(&mut client, server);
server_conn.borrow_mut().send_ticket(now(), &[]).unwrap(); server_conn.borrow_mut().send_ticket(now(), &[]).unwrap();
let out = server.process(None, now()); let out = server.process_output(now());
client.process_input(out.as_dgram_ref().unwrap(), now()); // Consume ticket, ignore output. client.process_input(out.dgram().unwrap(), now()); // Consume ticket, ignore output.
let ticket = find_ticket(&mut client); let ticket = find_ticket(&mut client);
// Have the client close the connection and then let the server clean up. // Have the client close the connection and then let the server clean up.
client.close(now(), 0, "got a ticket"); client.close(now(), 0, "got a ticket");
let out = client.process_output(now()); let out = client.process_output(now());
mem::drop(server.process(out.as_dgram_ref(), now())); mem::drop(server.process(out.dgram(), now()));
// Calling active_connections clears the set of active connections. // Calling active_connections clears the set of active connections.
assert_eq!(server.active_connections().len(), 1); assert_eq!(server.active_connections().len(), 1);
ticket ticket

Просмотреть файл

@ -265,7 +265,7 @@ fn process_client_initial(v: Version, packet: &[u8]) {
let dgram = datagram(packet.to_vec()); let dgram = datagram(packet.to_vec());
assert_eq!(*server.state(), State::Init); assert_eq!(*server.state(), State::Init);
let out = server.process(Some(&dgram), now()); let out = server.process(Some(dgram), now());
assert_eq!(*server.state(), State::Handshaking); assert_eq!(*server.state(), State::Handshaking);
assert!(out.dgram().is_some()); assert!(out.dgram().is_some());
} }

Просмотреть файл

@ -29,9 +29,9 @@ fn truncate_long_packet() {
let mut client = default_client(); let mut client = default_client();
let mut server = default_server(); let mut server = default_server();
let out = client.process(None, now()); let out = client.process_output(now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
// This will truncate the Handshake packet from the server. // This will truncate the Handshake packet from the server.
@ -44,18 +44,18 @@ fn truncate_long_packet() {
dupe.tos(), dupe.tos(),
&dupe[..(dupe.len() - tail)], &dupe[..(dupe.len() - tail)],
); );
let hs_probe = client.process(Some(&truncated), now()).dgram(); let hs_probe = client.process(Some(truncated), now()).dgram();
assert!(hs_probe.is_some()); assert!(hs_probe.is_some());
// Now feed in the untruncated packet. // Now feed in the untruncated packet.
let out = client.process(out.as_dgram_ref(), now()); let out = client.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_some()); // Throw this ACK away. assert!(out.as_dgram_ref().is_some()); // Throw this ACK away.
assert!(test_fixture::maybe_authenticate(&mut client)); assert!(test_fixture::maybe_authenticate(&mut client));
let out = client.process(None, now()); let out = client.process_output(now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
assert!(client.state().connected()); assert!(client.state().connected());
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
assert!(server.state().connected()); assert!(server.state().connected());
} }
@ -76,7 +76,7 @@ fn reorder_server_initial() {
decode_initial_header(client_initial.as_dgram_ref().unwrap(), Role::Client).unwrap(); decode_initial_header(client_initial.as_dgram_ref().unwrap(), Role::Client).unwrap();
let client_dcid = client_dcid.to_owned(); let client_dcid = client_dcid.to_owned();
let server_packet = server.process(client_initial.as_dgram_ref(), now()).dgram(); let server_packet = server.process(client_initial.dgram(), now()).dgram();
let (server_initial, server_hs) = split_datagram(server_packet.as_ref().unwrap()); let (server_initial, server_hs) = split_datagram(server_packet.as_ref().unwrap());
let (protected_header, _, _, payload) = let (protected_header, _, _, payload) =
decode_initial_header(&server_initial, Role::Server).unwrap(); decode_initial_header(&server_initial, Role::Server).unwrap();
@ -119,16 +119,16 @@ fn reorder_server_initial() {
// Now a connection can be made successfully. // Now a connection can be made successfully.
// Though we modified the server's Initial packet, we get away with it. // Though we modified the server's Initial packet, we get away with it.
// TLS only authenticates the content of the CRYPTO frame, which was untouched. // TLS only authenticates the content of the CRYPTO frame, which was untouched.
client.process_input(&reordered, now()); client.process_input(reordered, now());
client.process_input(&server_hs.unwrap(), now()); client.process_input(server_hs.unwrap(), now());
assert!(test_fixture::maybe_authenticate(&mut client)); assert!(test_fixture::maybe_authenticate(&mut client));
let finished = client.process_output(now()); let finished = client.process_output(now());
assert_eq!(*client.state(), State::Connected); assert_eq!(*client.state(), State::Connected);
let done = server.process(finished.as_dgram_ref(), now()); let done = server.process(finished.dgram(), now());
assert_eq!(*server.state(), State::Confirmed); assert_eq!(*server.state(), State::Confirmed);
client.process_input(done.as_dgram_ref().unwrap(), now()); client.process_input(done.dgram().unwrap(), now());
assert_eq!(*client.state(), State::Confirmed); assert_eq!(*client.state(), State::Confirmed);
} }
@ -171,12 +171,13 @@ fn packet_without_frames() {
let mut server = default_server(); let mut server = default_server();
let client_initial = client.process_output(now()); let client_initial = client.process_output(now());
let client_initial_clone = client_initial.as_dgram_ref().unwrap().clone();
let (_, client_dcid, _, _) = let (_, client_dcid, _, _) =
decode_initial_header(client_initial.as_dgram_ref().unwrap(), Role::Client).unwrap(); decode_initial_header(&client_initial_clone, Role::Client).unwrap();
let server_packet = server.process(client_initial.as_dgram_ref(), now()).dgram(); let server_packet = server.process(client_initial.dgram(), now()).dgram();
let modified = set_payload(server_packet.as_ref(), client_dcid, &[]); let modified = set_payload(server_packet.as_ref(), client_dcid, &[]);
client.process_input(&modified, now()); client.process_input(modified, now());
assert_eq!( assert_eq!(
client.state(), client.state(),
&State::Closed(CloseReason::Transport(Error::ProtocolViolation)) &State::Closed(CloseReason::Transport(Error::ProtocolViolation))
@ -192,12 +193,13 @@ fn packet_with_only_padding() {
let mut server = default_server(); let mut server = default_server();
let client_initial = client.process_output(now()); let client_initial = client.process_output(now());
let client_initial_clone = client_initial.as_dgram_ref().unwrap().clone();
let (_, client_dcid, _, _) = let (_, client_dcid, _, _) =
decode_initial_header(client_initial.as_dgram_ref().unwrap(), Role::Client).unwrap(); decode_initial_header(&client_initial_clone, Role::Client).unwrap();
let server_packet = server.process(client_initial.as_dgram_ref(), now()).dgram(); let server_packet = server.process(client_initial.dgram(), now()).dgram();
let modified = set_payload(server_packet.as_ref(), client_dcid, &[0]); let modified = set_payload(server_packet.as_ref(), client_dcid, &[0]);
client.process_input(&modified, now()); client.process_input(modified, now());
assert_eq!(client.state(), &State::WaitInitial); assert_eq!(client.state(), &State::WaitInitial);
} }
@ -215,7 +217,7 @@ fn overflow_crypto() {
decode_initial_header(client_initial.as_ref().unwrap(), Role::Client).unwrap(); decode_initial_header(client_initial.as_ref().unwrap(), Role::Client).unwrap();
let client_dcid = client_dcid.to_owned(); let client_dcid = client_dcid.to_owned();
let server_packet = server.process(client_initial.as_ref(), now()).dgram(); let server_packet = server.process(client_initial, now()).dgram();
let (server_initial, _) = split_datagram(server_packet.as_ref().unwrap()); let (server_initial, _) = split_datagram(server_packet.as_ref().unwrap());
// Now decrypt the server packet to get AEAD and HP instances. // Now decrypt the server packet to get AEAD and HP instances.
@ -261,7 +263,7 @@ fn overflow_crypto() {
server_initial.tos(), server_initial.tos(),
packet, packet,
); );
client.process_input(&dgram, now()); client.process_input(dgram, now());
if let State::Closing { error, .. } = client.state() { if let State::Closing { error, .. } = client.state() {
assert!( assert!(
matches!(error, CloseReason::Transport(Error::CryptoBufferExceeded)), matches!(error, CloseReason::Transport(Error::CryptoBufferExceeded)),

122
third_party/rust/neqo-transport/tests/retry.rs поставляемый
Просмотреть файл

@ -35,23 +35,23 @@ fn retry_basic() {
server.set_validation(ValidateAddress::Always); server.set_validation(ValidateAddress::Always);
let mut client = default_client(); let mut client = default_client();
let dgram = client.process(None, now()).dgram(); // Initial let dgram = client.process_output(now()).dgram(); // Initial
assert!(dgram.is_some()); assert!(dgram.is_some());
let dgram = server.process(dgram.as_ref(), now()).dgram(); // Retry let dgram = server.process(dgram, now()).dgram(); // Retry
assert!(dgram.is_some()); assert!(dgram.is_some());
assertions::assert_retry(dgram.as_ref().unwrap()); assertions::assert_retry(dgram.as_ref().unwrap());
let dgram = client.process(dgram.as_ref(), now()).dgram(); // Initial w/token let dgram = client.process(dgram, now()).dgram(); // Initial w/token
assert!(dgram.is_some()); assert!(dgram.is_some());
let dgram = server.process(dgram.as_ref(), now()).dgram(); // Initial, HS let dgram = server.process(dgram, now()).dgram(); // Initial, HS
assert!(dgram.is_some()); assert!(dgram.is_some());
mem::drop(client.process(dgram.as_ref(), now()).dgram()); // Ingest, drop any ACK. mem::drop(client.process(dgram, now()).dgram()); // Ingest, drop any ACK.
client.authenticated(AuthenticationStatus::Ok, now()); client.authenticated(AuthenticationStatus::Ok, now());
let dgram = client.process(None, now()).dgram(); // Send Finished let dgram = client.process_output(now()).dgram(); // Send Finished
assert!(dgram.is_some()); assert!(dgram.is_some());
assert_eq!(*client.state(), State::Connected); assert_eq!(*client.state(), State::Connected);
let dgram = server.process(dgram.as_ref(), now()).dgram(); // (done) let dgram = server.process(dgram, now()).dgram(); // (done)
assert!(dgram.is_some()); // Note that this packet will be dropped... assert!(dgram.is_some()); // Note that this packet will be dropped...
connected_server(&server); connected_server(&server);
} }
@ -66,12 +66,12 @@ fn implicit_rtt_retry() {
let mut client = default_client(); let mut client = default_client();
let mut now = now(); let mut now = now();
let dgram = client.process(None, now).dgram(); let dgram = client.process_output(now).dgram();
now += RTT / 2; now += RTT / 2;
let dgram = server.process(dgram.as_ref(), now).dgram(); let dgram = server.process(dgram, now).dgram();
assertions::assert_retry(dgram.as_ref().unwrap()); assertions::assert_retry(dgram.as_ref().unwrap());
now += RTT / 2; now += RTT / 2;
client.process_input(&dgram.unwrap(), now); client.process_input(dgram.unwrap(), now);
assert_eq!(client.stats().rtt, RTT); assert_eq!(client.stats().rtt, RTT);
} }
@ -83,18 +83,18 @@ fn retry_expired() {
let mut client = default_client(); let mut client = default_client();
let mut now = now(); let mut now = now();
let dgram = client.process(None, now).dgram(); // Initial let dgram = client.process_output(now).dgram(); // Initial
assert!(dgram.is_some()); assert!(dgram.is_some());
let dgram = server.process(dgram.as_ref(), now).dgram(); // Retry let dgram = server.process(dgram, now).dgram(); // Retry
assert!(dgram.is_some()); assert!(dgram.is_some());
assertions::assert_retry(dgram.as_ref().unwrap()); assertions::assert_retry(dgram.as_ref().unwrap());
let dgram = client.process(dgram.as_ref(), now).dgram(); // Initial w/token let dgram = client.process(dgram, now).dgram(); // Initial w/token
assert!(dgram.is_some()); assert!(dgram.is_some());
now += Duration::from_secs(60); // Too long for Retry. now += Duration::from_secs(60); // Too long for Retry.
let dgram = server.process(dgram.as_ref(), now).dgram(); // Initial, HS let dgram = server.process(dgram, now).dgram(); // Initial, HS
assert!(dgram.is_none()); assert!(dgram.is_none());
} }
@ -111,26 +111,26 @@ fn retry_0rtt() {
let client_stream = client.stream_create(StreamType::UniDi).unwrap(); let client_stream = client.stream_create(StreamType::UniDi).unwrap();
client.stream_send(client_stream, &[1, 2, 3]).unwrap(); client.stream_send(client_stream, &[1, 2, 3]).unwrap();
let dgram = client.process(None, now()).dgram(); // Initial w/0-RTT let dgram = client.process_output(now()).dgram(); // Initial w/0-RTT
assert!(dgram.is_some()); assert!(dgram.is_some());
assertions::assert_coalesced_0rtt(dgram.as_ref().unwrap()); assertions::assert_coalesced_0rtt(dgram.as_ref().unwrap());
let dgram = server.process(dgram.as_ref(), now()).dgram(); // Retry let dgram = server.process(dgram, now()).dgram(); // Retry
assert!(dgram.is_some()); assert!(dgram.is_some());
assertions::assert_retry(dgram.as_ref().unwrap()); assertions::assert_retry(dgram.as_ref().unwrap());
// After retry, there should be a token and still coalesced 0-RTT. // After retry, there should be a token and still coalesced 0-RTT.
let dgram = client.process(dgram.as_ref(), now()).dgram(); let dgram = client.process(dgram, now()).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
assertions::assert_coalesced_0rtt(dgram.as_ref().unwrap()); assertions::assert_coalesced_0rtt(dgram.as_ref().unwrap());
let dgram = server.process(dgram.as_ref(), now()).dgram(); // Initial, HS let dgram = server.process(dgram, now()).dgram(); // Initial, HS
assert!(dgram.is_some()); assert!(dgram.is_some());
let dgram = client.process(dgram.as_ref(), now()).dgram(); let dgram = client.process(dgram, now()).dgram();
// Note: the client doesn't need to authenticate the server here // Note: the client doesn't need to authenticate the server here
// as there is no certificate; authentication is based on the ticket. // as there is no certificate; authentication is based on the ticket.
assert!(dgram.is_some()); assert!(dgram.is_some());
assert_eq!(*client.state(), State::Connected); assert_eq!(*client.state(), State::Connected);
let dgram = server.process(dgram.as_ref(), now()).dgram(); // (done) let dgram = server.process(dgram, now()).dgram(); // (done)
assert!(dgram.is_some()); assert!(dgram.is_some());
connected_server(&server); connected_server(&server);
assert!(client.tls_info().unwrap().resumed()); assert!(client.tls_info().unwrap().resumed());
@ -142,14 +142,14 @@ fn retry_different_ip() {
server.set_validation(ValidateAddress::Always); server.set_validation(ValidateAddress::Always);
let mut client = default_client(); let mut client = default_client();
let dgram = client.process(None.as_ref(), now()).dgram(); // Initial let dgram = client.process_output(now()).dgram(); // Initial
assert!(dgram.is_some()); assert!(dgram.is_some());
let dgram = server.process(dgram.as_ref(), now()).dgram(); // Retry let dgram = server.process(dgram, now()).dgram(); // Retry
assert!(dgram.is_some()); assert!(dgram.is_some());
assertions::assert_retry(dgram.as_ref().unwrap()); assertions::assert_retry(dgram.as_ref().unwrap());
let dgram = client.process(dgram.as_ref(), now()).dgram(); // Initial w/token let dgram = client.process(dgram, now()).dgram(); // Initial w/token
assert!(dgram.is_some()); assert!(dgram.is_some());
// Change the source IP on the address from the client. // Change the source IP on the address from the client.
@ -157,7 +157,7 @@ fn retry_different_ip() {
let other_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 2)); let other_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 2));
let other_addr = SocketAddr::new(other_v4, 443); let other_addr = SocketAddr::new(other_v4, 443);
let from_other = Datagram::new(other_addr, dgram.destination(), dgram.tos(), &dgram[..]); let from_other = Datagram::new(other_addr, dgram.destination(), dgram.tos(), &dgram[..]);
let dgram = server.process(Some(&from_other), now()).dgram(); let dgram = server.process(Some(from_other), now()).dgram();
assert!(dgram.is_none()); assert!(dgram.is_none());
} }
@ -170,7 +170,7 @@ fn new_token_different_ip() {
let mut client = default_client(); let mut client = default_client();
client.enable_resumption(now(), &token).unwrap(); client.enable_resumption(now(), &token).unwrap();
let dgram = client.process(None, now()).dgram(); // Initial let dgram = client.process_output(now()).dgram(); // Initial
assert!(dgram.is_some()); assert!(dgram.is_some());
assertions::assert_initial(dgram.as_ref().unwrap(), true); assertions::assert_initial(dgram.as_ref().unwrap(), true);
@ -178,7 +178,7 @@ fn new_token_different_ip() {
let d = dgram.unwrap(); let d = dgram.unwrap();
let src = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 2)), d.source().port()); let src = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 2)), d.source().port());
let dgram = Some(Datagram::new(src, d.destination(), d.tos(), &d[..])); let dgram = Some(Datagram::new(src, d.destination(), d.tos(), &d[..]));
let dgram = server.process(dgram.as_ref(), now()).dgram(); // Retry let dgram = server.process(dgram, now()).dgram(); // Retry
assert!(dgram.is_some()); assert!(dgram.is_some());
assertions::assert_retry(dgram.as_ref().unwrap()); assertions::assert_retry(dgram.as_ref().unwrap());
} }
@ -192,7 +192,7 @@ fn new_token_expired() {
let mut client = default_client(); let mut client = default_client();
client.enable_resumption(now(), &token).unwrap(); client.enable_resumption(now(), &token).unwrap();
let dgram = client.process(None, now()).dgram(); // Initial let dgram = client.process_output(now()).dgram(); // Initial
assert!(dgram.is_some()); assert!(dgram.is_some());
assertions::assert_initial(dgram.as_ref().unwrap(), true); assertions::assert_initial(dgram.as_ref().unwrap(), true);
@ -203,7 +203,7 @@ fn new_token_expired() {
let d = dgram.unwrap(); let d = dgram.unwrap();
let src = SocketAddr::new(d.source().ip(), d.source().port() + 1); let src = SocketAddr::new(d.source().ip(), d.source().port() + 1);
let dgram = Some(Datagram::new(src, d.destination(), d.tos(), &d[..])); let dgram = Some(Datagram::new(src, d.destination(), d.tos(), &d[..]));
let dgram = server.process(dgram.as_ref(), the_future).dgram(); // Retry let dgram = server.process(dgram, the_future).dgram(); // Retry
assert!(dgram.is_some()); assert!(dgram.is_some());
assertions::assert_retry(dgram.as_ref().unwrap()); assertions::assert_retry(dgram.as_ref().unwrap());
} }
@ -215,34 +215,34 @@ fn retry_after_initial() {
retry_server.set_validation(ValidateAddress::Always); retry_server.set_validation(ValidateAddress::Always);
let mut client = default_client(); let mut client = default_client();
let cinit = client.process(None, now()).dgram(); // Initial let cinit = client.process_output(now()).dgram(); // Initial
assert!(cinit.is_some()); assert!(cinit.is_some());
let server_flight = server.process(cinit.as_ref(), now()).dgram(); // Initial let server_flight = server.process(cinit.clone(), now()).dgram(); // Initial
assert!(server_flight.is_some()); assert!(server_flight.is_some());
// We need to have the client just process the Initial. // We need to have the client just process the Initial.
let (server_initial, _other) = split_datagram(server_flight.as_ref().unwrap()); let (server_initial, _other) = split_datagram(server_flight.as_ref().unwrap());
let dgram = client.process(Some(&server_initial), now()).dgram(); let dgram = client.process(Some(server_initial), now()).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
assert!(*client.state() != State::Connected); assert!(*client.state() != State::Connected);
let retry = retry_server.process(cinit.as_ref(), now()).dgram(); // Retry! let retry = retry_server.process(cinit, now()).dgram(); // Retry!
assert!(retry.is_some()); assert!(retry.is_some());
assertions::assert_retry(retry.as_ref().unwrap()); assertions::assert_retry(retry.as_ref().unwrap());
// The client should ignore the retry. // The client should ignore the retry.
let junk = client.process(retry.as_ref(), now()).dgram(); let junk = client.process(retry, now()).dgram();
assert!(junk.is_none()); assert!(junk.is_none());
// Either way, the client should still be able to process the server flight and connect. // Either way, the client should still be able to process the server flight and connect.
let dgram = client.process(server_flight.as_ref(), now()).dgram(); let dgram = client.process(server_flight, now()).dgram();
assert!(dgram.is_some()); // Drop this one. assert!(dgram.is_some()); // Drop this one.
assert!(test_fixture::maybe_authenticate(&mut client)); assert!(test_fixture::maybe_authenticate(&mut client));
let dgram = client.process(None, now()).dgram(); let dgram = client.process_output(now()).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
assert_eq!(*client.state(), State::Connected); assert_eq!(*client.state(), State::Connected);
let dgram = server.process(dgram.as_ref(), now()).dgram(); // (done) let dgram = server.process(dgram, now()).dgram(); // (done)
assert!(dgram.is_some()); assert!(dgram.is_some());
connected_server(&server); connected_server(&server);
} }
@ -253,9 +253,9 @@ fn retry_bad_integrity() {
server.set_validation(ValidateAddress::Always); server.set_validation(ValidateAddress::Always);
let mut client = default_client(); let mut client = default_client();
let dgram = client.process(None, now()).dgram(); // Initial let dgram = client.process_output(now()).dgram(); // Initial
assert!(dgram.is_some()); assert!(dgram.is_some());
let dgram = server.process(dgram.as_ref(), now()).dgram(); // Retry let dgram = server.process(dgram, now()).dgram(); // Retry
assert!(dgram.is_some()); assert!(dgram.is_some());
let retry = &dgram.as_ref().unwrap(); let retry = &dgram.as_ref().unwrap();
@ -266,7 +266,7 @@ fn retry_bad_integrity() {
let tweaked_packet = Datagram::new(retry.source(), retry.destination(), retry.tos(), tweaked); let tweaked_packet = Datagram::new(retry.source(), retry.destination(), retry.tos(), tweaked);
// The client should ignore this packet. // The client should ignore this packet.
let dgram = client.process(Some(&tweaked_packet), now()).dgram(); let dgram = client.process(Some(tweaked_packet), now()).dgram();
assert!(dgram.is_none()); assert!(dgram.is_none());
} }
@ -278,16 +278,14 @@ fn retry_bad_token() {
let mut server = default_server(); let mut server = default_server();
// Send a retry to one server, then replay it to the other. // Send a retry to one server, then replay it to the other.
let client_initial1 = client.process(None, now()).dgram(); let client_initial1 = client.process_output(now()).dgram();
assert!(client_initial1.is_some()); assert!(client_initial1.is_some());
let retry = retry_server let retry = retry_server.process(client_initial1, now()).dgram();
.process(client_initial1.as_ref(), now())
.dgram();
assert!(retry.is_some()); assert!(retry.is_some());
let client_initial2 = client.process(retry.as_ref(), now()).dgram(); let client_initial2 = client.process(retry, now()).dgram();
assert!(client_initial2.is_some()); assert!(client_initial2.is_some());
let dgram = server.process(client_initial2.as_ref(), now()).dgram(); let dgram = server.process(client_initial2, now()).dgram();
assert!(dgram.is_none()); assert!(dgram.is_none());
} }
@ -303,20 +301,20 @@ fn retry_after_pto() {
server.set_validation(ValidateAddress::Always); server.set_validation(ValidateAddress::Always);
let mut now = now(); let mut now = now();
let ci = client.process(None, now).dgram(); let ci = client.process_output(now).dgram();
assert!(ci.is_some()); // sit on this for a bit.RefCell assert!(ci.is_some()); // sit on this for a bit.RefCell
// Let PTO fire on the client and then let it exhaust its PTO packets. // Let PTO fire on the client and then let it exhaust its PTO packets.
now += Duration::from_secs(1); now += Duration::from_secs(1);
let pto = client.process(None, now).dgram(); let pto = client.process_output(now).dgram();
assert!(pto.unwrap().len() >= MIN_INITIAL_PACKET_SIZE); assert!(pto.unwrap().len() >= MIN_INITIAL_PACKET_SIZE);
let cb = client.process(None, now).callback(); let cb = client.process_output(now).callback();
assert_ne!(cb, Duration::new(0, 0)); assert_ne!(cb, Duration::new(0, 0));
let retry = server.process(ci.as_ref(), now).dgram(); let retry = server.process(ci, now).dgram();
assertions::assert_retry(retry.as_ref().unwrap()); assertions::assert_retry(retry.as_ref().unwrap());
let ci2 = client.process(retry.as_ref(), now).dgram(); let ci2 = client.process(retry, now).dgram();
assert!(ci2.unwrap().len() >= MIN_INITIAL_PACKET_SIZE); assert!(ci2.unwrap().len() >= MIN_INITIAL_PACKET_SIZE);
} }
@ -326,14 +324,14 @@ fn vn_after_retry() {
server.set_validation(ValidateAddress::Always); server.set_validation(ValidateAddress::Always);
let mut client = default_client(); let mut client = default_client();
let dgram = client.process(None, now()).dgram(); // Initial let dgram = client.process_output(now()).dgram(); // Initial
assert!(dgram.is_some()); assert!(dgram.is_some());
let dgram = server.process(dgram.as_ref(), now()).dgram(); // Retry let dgram = server.process(dgram, now()).dgram(); // Retry
assert!(dgram.is_some()); assert!(dgram.is_some());
assertions::assert_retry(dgram.as_ref().unwrap()); assertions::assert_retry(dgram.as_ref().unwrap());
let dgram = client.process(dgram.as_ref(), now()).dgram(); // Initial w/token let dgram = client.process(dgram, now()).dgram(); // Initial w/token
assert!(dgram.is_some()); assert!(dgram.is_some());
let mut encoder = Encoder::default(); let mut encoder = Encoder::default();
@ -345,7 +343,7 @@ fn vn_after_retry() {
let vn = datagram(encoder.into()); let vn = datagram(encoder.into());
assert_ne!( assert_ne!(
client.process(Some(&vn), now()).callback(), client.process(Some(vn), now()).callback(),
Duration::from_secs(0) Duration::from_secs(0)
); );
} }
@ -368,13 +366,11 @@ fn mitm_retry() {
let mut server = default_server(); let mut server = default_server();
// Trigger initial and a second client Initial. // Trigger initial and a second client Initial.
let client_initial1 = client.process(None, now()).dgram(); let client_initial1 = client.process_output(now()).dgram();
assert!(client_initial1.is_some()); assert!(client_initial1.is_some());
let retry = retry_server let retry = retry_server.process(client_initial1, now()).dgram();
.process(client_initial1.as_ref(), now())
.dgram();
assert!(retry.is_some()); assert!(retry.is_some());
let client_initial2 = client.process(retry.as_ref(), now()).dgram(); let client_initial2 = client.process(retry, now()).dgram();
assert!(client_initial2.is_some()); assert!(client_initial2.is_some());
// Now to start the epic process of decrypting the packet, // Now to start the epic process of decrypting the packet,
@ -432,15 +428,15 @@ fn mitm_retry() {
notoken_packet, notoken_packet,
); );
qdebug!("passing modified Initial to the main server"); qdebug!("passing modified Initial to the main server");
let dgram = server.process(Some(&new_datagram), now()).dgram(); let dgram = server.process(Some(new_datagram), now()).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
let dgram = client.process(dgram.as_ref(), now()).dgram(); // Generate an ACK. let dgram = client.process(dgram, now()).dgram(); // Generate an ACK.
assert!(dgram.is_some()); assert!(dgram.is_some());
let dgram = server.process(dgram.as_ref(), now()).dgram(); let dgram = server.process(dgram, now()).dgram();
assert!(dgram.is_none()); assert!(dgram.is_none());
assert!(test_fixture::maybe_authenticate(&mut client)); assert!(test_fixture::maybe_authenticate(&mut client));
let dgram = client.process(dgram.as_ref(), now()).dgram(); let dgram = client.process(dgram, now()).dgram();
assert!(dgram.is_some()); // Client sending CLOSE_CONNECTIONs assert!(dgram.is_some()); // Client sending CLOSE_CONNECTIONs
assert!(matches!( assert!(matches!(
*client.state(), *client.state(),

Просмотреть файл

@ -47,8 +47,8 @@ pub fn complete_connection(
}; };
while !is_done(client) { while !is_done(client) {
_ = test_fixture::maybe_authenticate(client); _ = test_fixture::maybe_authenticate(client);
let out = client.process(datagram.as_ref(), now()); let out = client.process(datagram, now());
let out = server.process(out.as_dgram_ref(), now()); let out = server.process(out.dgram(), now());
datagram = out.dgram(); datagram = out.dgram();
} }
@ -111,9 +111,9 @@ fn connect_single_version_server() {
// Run the version negotiation exchange if necessary. // Run the version negotiation exchange if necessary.
let out = client.process_output(now()); let out = client.process_output(now());
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
let dgram = server.process(out.as_dgram_ref(), now()).dgram(); let dgram = server.process(out.dgram(), now()).dgram();
assertions::assert_vn(dgram.as_ref().unwrap()); assertions::assert_vn(dgram.as_ref().unwrap());
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
} }
let server_conn = connect(&mut client, &mut server); let server_conn = connect(&mut client, &mut server);
@ -133,14 +133,16 @@ fn duplicate_initial() {
let mut client = default_client(); let mut client = default_client();
assert_eq!(*client.state(), State::Init); assert_eq!(*client.state(), State::Init);
let initial = client.process(None, now()); let initial = client.process_output(now());
assert!(initial.as_dgram_ref().is_some()); assert!(initial.as_dgram_ref().is_some());
// The server should ignore a packets with the same remote address and // The server should ignore a packets with the same remote address and
// destination connection ID as an existing connection attempt. // destination connection ID as an existing connection attempt.
let server_initial = server.process(initial.as_dgram_ref(), now()).dgram(); let server_initial = server
.process(initial.as_dgram_ref().cloned(), now())
.dgram();
assert!(server_initial.is_some()); assert!(server_initial.is_some());
let dgram = server.process(initial.as_dgram_ref(), now()).dgram(); let dgram = server.process(initial.dgram(), now()).dgram();
assert!(dgram.is_none()); assert!(dgram.is_none());
assert_eq!(server.active_connections().len(), 1); assert_eq!(server.active_connections().len(), 1);
@ -153,7 +155,7 @@ fn duplicate_initial_new_path() {
let mut client = default_client(); let mut client = default_client();
assert_eq!(*client.state(), State::Init); assert_eq!(*client.state(), State::Init);
let initial = client.process(None, now()).dgram().unwrap(); let initial = client.process_output(now()).dgram().unwrap();
let other = Datagram::new( let other = Datagram::new(
SocketAddr::new(initial.source().ip(), initial.source().port() ^ 23), SocketAddr::new(initial.source().ip(), initial.source().port() ^ 23),
initial.destination(), initial.destination(),
@ -161,11 +163,11 @@ fn duplicate_initial_new_path() {
&initial[..], &initial[..],
); );
let server_initial = server.process(Some(&initial), now()).dgram(); let server_initial = server.process(Some(initial), now()).dgram();
assert!(server_initial.is_some()); assert!(server_initial.is_some());
// The server should ignore a packet with the same destination connection ID. // The server should ignore a packet with the same destination connection ID.
let dgram = server.process(Some(&other), now()).dgram(); let dgram = server.process(Some(other), now()).dgram();
assert!(dgram.is_none()); assert!(dgram.is_none());
assert_eq!(server.active_connections().len(), 1); assert_eq!(server.active_connections().len(), 1);
@ -178,20 +180,16 @@ fn different_initials_same_path() {
let mut client1 = default_client(); let mut client1 = default_client();
let mut client2 = default_client(); let mut client2 = default_client();
let client_initial1 = client1.process(None, now()); let client_initial1 = client1.process_output(now());
assert!(client_initial1.as_dgram_ref().is_some()); assert!(client_initial1.as_dgram_ref().is_some());
let client_initial2 = client2.process(None, now()); let client_initial2 = client2.process_output(now());
assert!(client_initial2.as_dgram_ref().is_some()); assert!(client_initial2.as_dgram_ref().is_some());
// The server should respond to both as these came from different addresses. // The server should respond to both as these came from different addresses.
let server_initial1 = server let server_initial1 = server.process(client_initial1.dgram(), now()).dgram();
.process(client_initial1.as_dgram_ref(), now())
.dgram();
assert!(server_initial1.is_some()); assert!(server_initial1.is_some());
let server_initial2 = server let server_initial2 = server.process(client_initial2.dgram(), now()).dgram();
.process(client_initial2.as_dgram_ref(), now())
.dgram();
assert!(server_initial2.is_some()); assert!(server_initial2.is_some());
assert_eq!(server.active_connections().len(), 2); assert_eq!(server.active_connections().len(), 2);
@ -204,17 +202,19 @@ fn same_initial_after_connected() {
let mut server = default_server(); let mut server = default_server();
let mut client = default_client(); let mut client = default_client();
let client_initial = client.process(None, now()); let client_initial = client.process_output(now());
assert!(client_initial.as_dgram_ref().is_some()); assert!(client_initial.as_dgram_ref().is_some());
let server_initial = server.process(client_initial.as_dgram_ref(), now()).dgram(); let server_initial = server
.process(client_initial.as_dgram_ref().cloned(), now())
.dgram();
assert!(server_initial.is_some()); assert!(server_initial.is_some());
complete_connection(&mut client, &mut server, server_initial); complete_connection(&mut client, &mut server, server_initial);
assert_eq!(server.active_connections().len(), 1); assert_eq!(server.active_connections().len(), 1);
// Now make a new connection using the exact same initial as before. // Now make a new connection using the exact same initial as before.
// The server should respond to an attempt to connect with the same Initial. // The server should respond to an attempt to connect with the same Initial.
let dgram = server.process(client_initial.as_dgram_ref(), now()).dgram(); let dgram = server.process(client_initial.dgram(), now()).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
// The server should make a new connection object. // The server should make a new connection object.
assert_eq!(server.active_connections().len(), 2); assert_eq!(server.active_connections().len(), 2);
@ -236,7 +236,7 @@ fn drop_non_initial() {
bogus_data.resize(MIN_INITIAL_PACKET_SIZE, 66); bogus_data.resize(MIN_INITIAL_PACKET_SIZE, 66);
let bogus = datagram(bogus_data); let bogus = datagram(bogus_data);
assert!(server.process(Some(&bogus), now()).dgram().is_none()); assert!(server.process(Some(bogus), now()).dgram().is_none());
} }
#[test] #[test]
@ -255,7 +255,7 @@ fn drop_short_initial() {
bogus_data.resize(1199, 66); bogus_data.resize(1199, 66);
let bogus = datagram(bogus_data); let bogus = datagram(bogus_data);
assert!(server.process(Some(&bogus), now()).dgram().is_none()); assert!(server.process(Some(bogus), now()).dgram().is_none());
} }
#[test] #[test]
@ -272,7 +272,7 @@ fn drop_short_header_packet_for_unknown_connection() {
bogus_data.resize(MIN_INITIAL_PACKET_SIZE, 66); bogus_data.resize(MIN_INITIAL_PACKET_SIZE, 66);
let bogus = datagram(bogus_data); let bogus = datagram(bogus_data);
assert!(server.process(Some(&bogus), now()).dgram().is_none()); assert!(server.process(Some(bogus), now()).dgram().is_none());
} }
/// Verify that the server can read 0-RTT properly. A more robust server would buffer /// Verify that the server can read 0-RTT properly. A more robust server would buffer
@ -286,9 +286,9 @@ fn zero_rtt() {
// Discharge the old connection so that we don't have to worry about it. // Discharge the old connection so that we don't have to worry about it.
let mut now = now(); let mut now = now();
let t = server.process(None, now).callback(); let t = server.process_output(now).callback();
now += t; now += t;
assert_eq!(server.process(None, now), Output::None); assert_eq!(server.process_output(now), Output::None);
assert_eq!(server.active_connections().len(), 0); assert_eq!(server.active_connections().len(), 0);
let start_time = now; let start_time = now;
@ -298,12 +298,12 @@ fn zero_rtt() {
let mut client_send = || { let mut client_send = || {
let client_stream = client.stream_create(StreamType::UniDi).unwrap(); let client_stream = client.stream_create(StreamType::UniDi).unwrap();
client.stream_send(client_stream, &[1, 2, 3]).unwrap(); client.stream_send(client_stream, &[1, 2, 3]).unwrap();
match client.process(None, now) { match client.process_output(now) {
Output::Datagram(d) => d, Output::Datagram(d) => d,
Output::Callback(t) => { Output::Callback(t) => {
// Pacing... // Pacing...
now += t; now += t;
client.process(None, now).dgram().unwrap() client.process_output(now).dgram().unwrap()
} }
Output::None => panic!(), Output::None => panic!(),
} }
@ -317,12 +317,12 @@ fn zero_rtt() {
let c4 = client_send(); let c4 = client_send();
// 0-RTT packets that arrive before the handshake get dropped. // 0-RTT packets that arrive before the handshake get dropped.
mem::drop(server.process(Some(&c2), now)); mem::drop(server.process(Some(c2), now));
assert!(server.active_connections().is_empty()); assert!(server.active_connections().is_empty());
// Now handshake and let another 0-RTT packet in. // Now handshake and let another 0-RTT packet in.
let shs = server.process(Some(&c1), now); let shs = server.process(Some(c1), now);
mem::drop(server.process(Some(&c3), now)); mem::drop(server.process(Some(c3), now));
// The server will have received two STREAM frames now if it processed both packets. // The server will have received two STREAM frames now if it processed both packets.
// `ActiveConnectionRef` `Hash` implementation doesnt access any of the interior mutable types. // `ActiveConnectionRef` `Hash` implementation doesnt access any of the interior mutable types.
#[allow(clippy::mutable_key_type)] #[allow(clippy::mutable_key_type)]
@ -343,11 +343,11 @@ fn zero_rtt() {
// Complete the handshake. As the client was pacing 0-RTT packets, extend the time // Complete the handshake. As the client was pacing 0-RTT packets, extend the time
// a little so that the pacer doesn't prevent the Finished from being sent. // a little so that the pacer doesn't prevent the Finished from being sent.
now += now - start_time; now += now - start_time;
let cfin = client.process(shs.as_dgram_ref(), now); let cfin = client.process(shs.dgram(), now);
mem::drop(server.process(cfin.as_dgram_ref(), now)); mem::drop(server.process(cfin.dgram(), now));
// The server will drop this last 0-RTT packet. // The server will drop this last 0-RTT packet.
mem::drop(server.process(Some(&c4), now)); mem::drop(server.process(Some(c4), now));
// `ActiveConnectionRef` `Hash` implementation doesnt access any of the interior mutable types. // `ActiveConnectionRef` `Hash` implementation doesnt access any of the interior mutable types.
#[allow(clippy::mutable_key_type)] #[allow(clippy::mutable_key_type)]
let active = server.active_connections(); let active = server.active_connections();
@ -377,20 +377,20 @@ fn new_token_0rtt() {
let client_stream = client.stream_create(StreamType::UniDi).unwrap(); let client_stream = client.stream_create(StreamType::UniDi).unwrap();
client.stream_send(client_stream, &[1, 2, 3]).unwrap(); client.stream_send(client_stream, &[1, 2, 3]).unwrap();
let out = client.process(None, now()); // Initial w/0-RTT let out = client.process_output(now()); // Initial w/0-RTT
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
assertions::assert_initial(out.as_dgram_ref().unwrap(), true); assertions::assert_initial(out.as_dgram_ref().unwrap(), true);
assertions::assert_coalesced_0rtt(out.as_dgram_ref().unwrap()); assertions::assert_coalesced_0rtt(out.as_dgram_ref().unwrap());
let out = server.process(out.as_dgram_ref(), now()); // Initial let out = server.process(out.dgram(), now()); // Initial
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
assertions::assert_initial(out.as_dgram_ref().unwrap(), false); assertions::assert_initial(out.as_dgram_ref().unwrap(), false);
let dgram = client.process(out.as_dgram_ref(), now()); let dgram = client.process(out.as_dgram_ref().cloned(), now());
// Note: the client doesn't need to authenticate the server here // Note: the client doesn't need to authenticate the server here
// as there is no certificate; authentication is based on the ticket. // as there is no certificate; authentication is based on the ticket.
assert!(out.as_dgram_ref().is_some()); assert!(out.as_dgram_ref().is_some());
assert_eq!(*client.state(), State::Connected); assert_eq!(*client.state(), State::Connected);
let dgram = server.process(dgram.as_dgram_ref(), now()); // (done) let dgram = server.process(dgram.dgram(), now()); // (done)
assert!(dgram.as_dgram_ref().is_some()); assert!(dgram.as_dgram_ref().is_some());
connected_server(&server); connected_server(&server);
assert!(client.tls_info().unwrap().resumed()); assert!(client.tls_info().unwrap().resumed());
@ -405,7 +405,7 @@ fn new_token_different_port() {
let mut client = default_client(); let mut client = default_client();
client.enable_resumption(now(), &token).unwrap(); client.enable_resumption(now(), &token).unwrap();
let dgram = client.process(None, now()).dgram(); // Initial let dgram = client.process_output(now()).dgram(); // Initial
assert!(dgram.is_some()); assert!(dgram.is_some());
assertions::assert_initial(dgram.as_ref().unwrap(), true); assertions::assert_initial(dgram.as_ref().unwrap(), true);
@ -413,7 +413,7 @@ fn new_token_different_port() {
let d = dgram.unwrap(); let d = dgram.unwrap();
let src = SocketAddr::new(d.source().ip(), d.source().port() + 1); let src = SocketAddr::new(d.source().ip(), d.source().port() + 1);
let dgram = Some(Datagram::new(src, d.destination(), d.tos(), &d[..])); let dgram = Some(Datagram::new(src, d.destination(), d.tos(), &d[..]));
let dgram = server.process(dgram.as_ref(), now()).dgram(); // Retry let dgram = server.process(dgram, now()).dgram(); // Retry
assert!(dgram.is_some()); assert!(dgram.is_some());
assertions::assert_initial(dgram.as_ref().unwrap(), false); assertions::assert_initial(dgram.as_ref().unwrap(), false);
} }
@ -423,7 +423,7 @@ fn bad_client_initial() {
let mut client = default_client(); let mut client = default_client();
let mut server = default_server(); let mut server = default_server();
let dgram = client.process(None, now()).dgram().expect("a datagram"); let dgram = client.process_output(now()).dgram().expect("a datagram");
let (header, d_cid, s_cid, payload) = decode_initial_header(&dgram, Role::Client).unwrap(); let (header, d_cid, s_cid, payload) = decode_initial_header(&dgram, Role::Client).unwrap();
let (aead, hp) = initial_aead_and_hp(d_cid, Role::Client); let (aead, hp) = initial_aead_and_hp(d_cid, Role::Client);
let (fixed_header, pn) = remove_header_protection(&hp, header, payload); let (fixed_header, pn) = remove_header_protection(&hp, header, payload);
@ -470,7 +470,7 @@ fn bad_client_initial() {
let bad_dgram = Datagram::new(dgram.source(), dgram.destination(), dgram.tos(), ciphertext); let bad_dgram = Datagram::new(dgram.source(), dgram.destination(), dgram.tos(), ciphertext);
// The server should reject this. // The server should reject this.
let response = server.process(Some(&bad_dgram), now()); let response = server.process(Some(bad_dgram), now());
let close_dgram = response.dgram().unwrap(); let close_dgram = response.dgram().unwrap();
// The resulting datagram might contain multiple packets, but each is small. // The resulting datagram might contain multiple packets, but each is small.
let (initial_close, rest) = split_datagram(&close_dgram); let (initial_close, rest) = split_datagram(&close_dgram);
@ -484,10 +484,10 @@ fn bad_client_initial() {
// The client should accept this new and stop trying to connect. // The client should accept this new and stop trying to connect.
// It will generate a CONNECTION_CLOSE first though. // It will generate a CONNECTION_CLOSE first though.
let response = client.process(Some(&close_dgram), now()).dgram(); let response = client.process(Some(close_dgram), now()).dgram();
assert!(response.is_some()); assert!(response.is_some());
// The client will now wait out its closing period. // The client will now wait out its closing period.
let delay = client.process(None, now()).callback(); let delay = client.process_output(now()).callback();
assert_ne!(delay, Duration::from_secs(0)); assert_ne!(delay, Duration::from_secs(0));
assert!(matches!( assert!(matches!(
*client.state(), *client.state(),
@ -502,7 +502,7 @@ fn bad_client_initial() {
} }
// After sending the CONNECTION_CLOSE, the server goes idle. // After sending the CONNECTION_CLOSE, the server goes idle.
let res = server.process(None, now()); let res = server.process_output(now());
assert_eq!(res, Output::None); assert_eq!(res, Output::None);
} }
@ -511,7 +511,7 @@ fn bad_client_initial_connection_close() {
let mut client = default_client(); let mut client = default_client();
let mut server = default_server(); let mut server = default_server();
let dgram = client.process(None, now()).dgram().expect("a datagram"); let dgram = client.process_output(now()).dgram().expect("a datagram");
let (header, d_cid, s_cid, payload) = decode_initial_header(&dgram, Role::Client).unwrap(); let (header, d_cid, s_cid, payload) = decode_initial_header(&dgram, Role::Client).unwrap();
let (aead, hp) = initial_aead_and_hp(d_cid, Role::Client); let (aead, hp) = initial_aead_and_hp(d_cid, Role::Client);
let (_, pn) = remove_header_protection(&hp, header, payload); let (_, pn) = remove_header_protection(&hp, header, payload);
@ -553,9 +553,9 @@ fn bad_client_initial_connection_close() {
// The server should ignore this and go to Draining. // The server should ignore this and go to Draining.
let mut now = now(); let mut now = now();
let response = server.process(Some(&bad_dgram), now); let response = server.process(Some(bad_dgram), now);
now += response.callback(); now += response.callback();
let response = server.process(None, now); let response = server.process_output(now);
assert_eq!(response, Output::None); assert_eq!(response, Output::None);
} }
@ -565,7 +565,7 @@ fn version_negotiation_ignored() {
let mut client = default_client(); let mut client = default_client();
// Any packet will do, but let's make something that looks real. // Any packet will do, but let's make something that looks real.
let dgram = client.process(None, now()).dgram().expect("a datagram"); let dgram = client.process_output(now()).dgram().expect("a datagram");
let mut input = dgram.to_vec(); let mut input = dgram.to_vec();
input[1] ^= 0x12; input[1] ^= 0x12;
let damaged = Datagram::new( let damaged = Datagram::new(
@ -574,7 +574,7 @@ fn version_negotiation_ignored() {
dgram.tos(), dgram.tos(),
input.clone(), input.clone(),
); );
let vn = server.process(Some(&damaged), now()).dgram(); let vn = server.process(Some(damaged), now()).dgram();
let mut dec = Decoder::from(&input[5..]); // Skip past version. let mut dec = Decoder::from(&input[5..]); // Skip past version.
let d_cid = dec.decode_vec(1).expect("client DCID").to_vec(); let d_cid = dec.decode_vec(1).expect("client DCID").to_vec();
@ -595,7 +595,7 @@ fn version_negotiation_ignored() {
assert!(found, "valid version not found"); assert!(found, "valid version not found");
// Client ignores VN packet that contain negotiated version. // Client ignores VN packet that contain negotiated version.
let res = client.process(Some(&vn), now()); let res = client.process(Some(vn), now());
assert!(res.callback() > Duration::new(0, 120)); assert!(res.callback() > Duration::new(0, 120));
assert_eq!(client.state(), &State::WaitInitial); assert_eq!(client.state(), &State::WaitInitial);
} }
@ -615,9 +615,9 @@ fn version_negotiation() {
// `connect()` runs a fixed exchange, so manually run the Version Negotiation. // `connect()` runs a fixed exchange, so manually run the Version Negotiation.
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
let dgram = server.process(dgram.as_ref(), now()).dgram(); let dgram = server.process(dgram, now()).dgram();
assertions::assert_vn(dgram.as_ref().unwrap()); assertions::assert_vn(dgram.as_ref().unwrap());
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
let sconn = connect(&mut client, &mut server); let sconn = connect(&mut client, &mut server);
assert_eq!(client.version(), VN_VERSION); assert_eq!(client.version(), VN_VERSION);
@ -651,22 +651,22 @@ fn version_negotiation_and_compatible() {
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
assertions::assert_version(dgram.as_ref().unwrap(), ORIG_VERSION.wire_version()); assertions::assert_version(dgram.as_ref().unwrap(), ORIG_VERSION.wire_version());
let dgram = server.process(dgram.as_ref(), now()).dgram(); let dgram = server.process(dgram, now()).dgram();
assertions::assert_vn(dgram.as_ref().unwrap()); assertions::assert_vn(dgram.as_ref().unwrap());
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
let dgram = client.process(None, now()).dgram(); // ClientHello let dgram = client.process_output(now()).dgram(); // ClientHello
assertions::assert_version(dgram.as_ref().unwrap(), VN_VERSION.wire_version()); assertions::assert_version(dgram.as_ref().unwrap(), VN_VERSION.wire_version());
let dgram = server.process(dgram.as_ref(), now()).dgram(); // ServerHello... let dgram = server.process(dgram, now()).dgram(); // ServerHello...
assertions::assert_version(dgram.as_ref().unwrap(), COMPAT_VERSION.wire_version()); assertions::assert_version(dgram.as_ref().unwrap(), COMPAT_VERSION.wire_version());
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
client.authenticated(AuthenticationStatus::Ok, now()); client.authenticated(AuthenticationStatus::Ok, now());
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
assertions::assert_version(dgram.as_ref().unwrap(), COMPAT_VERSION.wire_version()); assertions::assert_version(dgram.as_ref().unwrap(), COMPAT_VERSION.wire_version());
assert_eq!(*client.state(), State::Connected); assert_eq!(*client.state(), State::Connected);
let dgram = server.process(dgram.as_ref(), now()).dgram(); // ACK + HANDSHAKE_DONE + NST let dgram = server.process(dgram, now()).dgram(); // ACK + HANDSHAKE_DONE + NST
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
assert_eq!(*client.state(), State::Confirmed); assert_eq!(*client.state(), State::Confirmed);
let sconn = connected_server(&server); let sconn = connected_server(&server);
@ -698,8 +698,8 @@ fn compatible_upgrade_resumption_and_vn() {
assert_eq!(server_conn.borrow().version(), COMPAT_VERSION); assert_eq!(server_conn.borrow().version(), COMPAT_VERSION);
server_conn.borrow_mut().send_ticket(now(), &[]).unwrap(); server_conn.borrow_mut().send_ticket(now(), &[]).unwrap();
let dgram = server.process(None, now()).dgram(); let dgram = server.process_output(now()).dgram();
client.process_input(&dgram.unwrap(), now()); // Consume ticket, ignore output. client.process_input(dgram.unwrap(), now()); // Consume ticket, ignore output.
let ticket = find_ticket(&mut client); let ticket = find_ticket(&mut client);
// This new server will reject the ticket, but it will also generate a VN packet. // This new server will reject the ticket, but it will also generate a VN packet.
@ -713,9 +713,9 @@ fn compatible_upgrade_resumption_and_vn() {
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
assert!(dgram.is_some()); assert!(dgram.is_some());
assertions::assert_version(dgram.as_ref().unwrap(), COMPAT_VERSION.wire_version()); assertions::assert_version(dgram.as_ref().unwrap(), COMPAT_VERSION.wire_version());
let dgram = server.process(dgram.as_ref(), now()).dgram(); let dgram = server.process(dgram, now()).dgram();
assertions::assert_vn(dgram.as_ref().unwrap()); assertions::assert_vn(dgram.as_ref().unwrap());
client.process_input(&dgram.unwrap(), now()); client.process_input(dgram.unwrap(), now());
let server_conn = connect(&mut client, &mut server); let server_conn = connect(&mut client, &mut server);
assert_eq!(client.version(), RESUMPTION_VERSION); assert_eq!(client.version(), RESUMPTION_VERSION);
@ -730,14 +730,14 @@ fn closed() {
connect(&mut client, &mut server); connect(&mut client, &mut server);
// The server will have sent a few things, so it will be on PTO. // The server will have sent a few things, so it will be on PTO.
let res = server.process(None, now()); let res = server.process_output(now());
assert!(res.callback() > Duration::new(0, 0)); assert!(res.callback() > Duration::new(0, 0));
// The client will be on the delayed ACK timer. // The client will be on the delayed ACK timer.
let res = client.process(None, now()); let res = client.process_output(now());
assert!(res.callback() > Duration::new(0, 0)); assert!(res.callback() > Duration::new(0, 0));
qtrace!("60s later"); qtrace!("60s later");
let res = server.process(None, now() + Duration::from_secs(60)); let res = server.process_output(now() + Duration::from_secs(60));
assert_eq!(res, Output::None); assert_eq!(res, Output::None);
} }
@ -825,8 +825,8 @@ fn max_streams_after_0rtt_rejection() {
client.enable_resumption(now(), &token).unwrap(); client.enable_resumption(now(), &token).unwrap();
_ = client.stream_create(StreamType::BiDi).unwrap(); _ = client.stream_create(StreamType::BiDi).unwrap();
let dgram = client.process_output(now()).dgram(); let dgram = client.process_output(now()).dgram();
let dgram = server.process(dgram.as_ref(), now()).dgram(); let dgram = server.process(dgram, now()).dgram();
let dgram = client.process(dgram.as_ref(), now()).dgram(); let dgram = client.process(dgram, now()).dgram();
assert!(dgram.is_some()); // We're far enough along to complete the test now. assert!(dgram.is_some()); // We're far enough along to complete the test now.
// Make sure that we can create MAX_STREAMS uni- and bidirectional streams. // Make sure that we can create MAX_STREAMS uni- and bidirectional streams.
@ -863,8 +863,8 @@ fn has_active_connections() {
assert!(!server.has_active_connections()); assert!(!server.has_active_connections());
let initial = client.process(None, now()); let initial = client.process_output(now());
_ = server.process(initial.as_dgram_ref(), now()).dgram(); _ = server.process(initial.dgram(), now()).dgram();
assert!(server.has_active_connections()); assert!(server.has_active_connections());
} }

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"f115cdd60c3993b4b7b5611ee8ccffe2a92e6b4180cca93fed8c198805543ace","src/lib.rs":"bf3bc79b1d799a42b73e64d2b203ce688cc0859d7afa6c66eec429ec36199ba6"},"package":null} {"files":{"Cargo.toml":"9dfe3aad758bbe584ac465f6cb35a9a7d3e32d859cb3878a23390fcff3f4f828","src/lib.rs":"d175cfb8f2ed2cc1a0e552c910fdee0e780a38a582d570554db32ff417115e55"},"package":null}

2
third_party/rust/neqo-udp/Cargo.toml поставляемый
Просмотреть файл

@ -13,7 +13,7 @@
edition = "2021" edition = "2021"
rust-version = "1.76.0" rust-version = "1.76.0"
name = "neqo-udp" name = "neqo-udp"
version = "0.9.2" version = "0.10.0"
authors = ["The Neqo Authors <necko@mozilla.com>"] authors = ["The Neqo Authors <necko@mozilla.com>"]
build = false build = false
autobins = false autobins = false

170
third_party/rust/neqo-udp/src/lib.rs поставляемый
Просмотреть файл

@ -7,10 +7,9 @@
#![allow(clippy::missing_errors_doc)] // Functions simply delegate to tokio and quinn-udp. #![allow(clippy::missing_errors_doc)] // Functions simply delegate to tokio and quinn-udp.
use std::{ use std::{
cell::RefCell,
io::{self, IoSliceMut}, io::{self, IoSliceMut},
net::SocketAddr, net::SocketAddr,
slice, slice::{self, Chunks},
}; };
use neqo_common::{qdebug, qtrace, Datagram, IpTos}; use neqo_common::{qdebug, qtrace, Datagram, IpTos};
@ -21,11 +20,7 @@ use quinn_udp::{EcnCodepoint, RecvMeta, Transmit, UdpSocketState};
/// Allows reading multiple datagrams in a single [`Socket::recv`] call. /// Allows reading multiple datagrams in a single [`Socket::recv`] call.
// //
// TODO: Experiment with different values across platforms. // TODO: Experiment with different values across platforms.
const RECV_BUF_SIZE: usize = u16::MAX as usize; pub const RECV_BUF_SIZE: usize = u16::MAX as usize;
std::thread_local! {
static RECV_BUF: RefCell<Vec<u8>> = RefCell::new(vec![0; RECV_BUF_SIZE]);
}
pub fn send_inner( pub fn send_inner(
state: &UdpSocketState, state: &UdpSocketState,
@ -57,63 +52,89 @@ use std::os::fd::AsFd as SocketRef;
#[cfg(windows)] #[cfg(windows)]
use std::os::windows::io::AsSocket as SocketRef; use std::os::windows::io::AsSocket as SocketRef;
pub fn recv_inner( pub fn recv_inner<'a>(
local_address: &SocketAddr, local_address: SocketAddr,
state: &UdpSocketState, state: &UdpSocketState,
socket: impl SocketRef, socket: impl SocketRef,
) -> Result<Vec<Datagram>, io::Error> { recv_buf: &'a mut [u8],
let dgrams = RECV_BUF.with_borrow_mut(|recv_buf| -> Result<Vec<Datagram>, io::Error> { ) -> Result<DatagramIter<'a>, io::Error> {
let mut meta; let mut meta;
loop { let data = loop {
meta = RecvMeta::default(); meta = RecvMeta::default();
state.recv( state.recv(
(&socket).into(), (&socket).into(),
&mut [IoSliceMut::new(recv_buf)], &mut [IoSliceMut::new(recv_buf)],
slice::from_mut(&mut meta), slice::from_mut(&mut meta),
)?; )?;
if meta.len == 0 || meta.stride == 0 { if meta.len == 0 || meta.stride == 0 {
qdebug!( qdebug!(
"ignoring datagram from {} to {} len {} stride {}", "ignoring datagram from {} to {} len {} stride {}",
meta.addr, meta.addr,
local_address, local_address,
meta.len, meta.len,
meta.stride meta.stride
); );
continue; continue;
}
break;
} }
Ok(recv_buf[0..meta.len] break &recv_buf[..meta.len];
.chunks(meta.stride) };
.map(|d| {
qtrace!(
"received {} bytes from {} to {}",
d.len(),
meta.addr,
local_address,
);
Datagram::new(
meta.addr,
*local_address,
meta.ecn.map(|n| IpTos::from(n as u8)).unwrap_or_default(),
d,
)
})
.collect())
})?;
qtrace!( qtrace!(
"received {} datagrams ({:?})", "received {} bytes from {} to {} in {} segments",
dgrams.len(), data.len(),
dgrams.iter().map(|d| d.len()).collect::<Vec<_>>(), meta.addr,
local_address,
data.len().div_ceil(meta.stride),
); );
Ok(dgrams) Ok(DatagramIter {
meta,
datagrams: data.chunks(meta.stride),
local_address,
})
}
pub struct DatagramIter<'a> {
meta: RecvMeta,
datagrams: Chunks<'a, u8>,
local_address: SocketAddr,
}
impl std::fmt::Debug for DatagramIter<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DatagramIter")
.field("meta", &self.meta)
.field("local_address", &self.local_address)
.finish()
}
}
impl<'a> Iterator for DatagramIter<'a> {
type Item = Datagram<&'a [u8]>;
fn next(&mut self) -> Option<Self::Item> {
self.datagrams.next().map(|d| {
Datagram::from_slice(
self.meta.addr,
self.local_address,
self.meta
.ecn
.map(|n| IpTos::from(n as u8))
.unwrap_or_default(),
d,
)
})
}
}
impl ExactSizeIterator for DatagramIter<'_> {
fn len(&self) -> usize {
self.datagrams.len()
}
} }
/// A wrapper around a UDP socket, sending and receiving [`Datagram`]s. /// A wrapper around a UDP socket, sending and receiving [`Datagram`]s.
@ -138,8 +159,12 @@ impl<S: SocketRef> Socket<S> {
/// Receive a batch of [`Datagram`]s on the given [`Socket`], each /// Receive a batch of [`Datagram`]s on the given [`Socket`], each
/// set with the provided local address. /// set with the provided local address.
pub fn recv(&self, local_address: &SocketAddr) -> Result<Vec<Datagram>, io::Error> { pub fn recv<'a>(
recv_inner(local_address, &self.state, &self.inner) &self,
local_address: SocketAddr,
recv_buf: &'a mut [u8],
) -> Result<DatagramIter<'a>, io::Error> {
recv_inner(local_address, &self.state, &self.inner, recv_buf)
} }
} }
@ -170,7 +195,8 @@ mod tests {
); );
sender.send(&datagram)?; sender.send(&datagram)?;
let res = receiver.recv(&receiver_addr); let mut recv_buf = vec![0; RECV_BUF_SIZE];
let res = receiver.recv(receiver_addr, &mut recv_buf);
assert_eq!(res.unwrap_err().kind(), std::io::ErrorKind::WouldBlock); assert_eq!(res.unwrap_err().kind(), std::io::ErrorKind::WouldBlock);
Ok(()) Ok(())
@ -191,17 +217,15 @@ mod tests {
sender.send(&datagram)?; sender.send(&datagram)?;
let received_datagram = receiver let mut recv_buf = vec![0; RECV_BUF_SIZE];
.recv(&receiver_addr) let mut received_datagrams = receiver
.expect("receive to succeed") .recv(receiver_addr, &mut recv_buf)
.into_iter() .expect("receive to succeed");
.next()
.expect("receive to yield datagram");
// Assert that the ECN is correct. // Assert that the ECN is correct.
assert_eq!( assert_eq!(
IpTosEcn::from(datagram.tos()), IpTosEcn::from(datagram.tos()),
IpTosEcn::from(received_datagram.tos()) IpTosEcn::from(received_datagrams.next().unwrap().tos())
); );
Ok(()) Ok(())
@ -236,11 +260,11 @@ mod tests {
// Allow for one GSO sendmmsg to result in multiple GRO recvmmsg. // Allow for one GSO sendmmsg to result in multiple GRO recvmmsg.
let mut num_received = 0; let mut num_received = 0;
let mut recv_buf = vec![0; RECV_BUF_SIZE];
while num_received < max_gso_segments { while num_received < max_gso_segments {
receiver receiver
.recv(&receiver_addr) .recv(receiver_addr, &mut recv_buf)
.expect("receive to succeed") .expect("receive to succeed")
.into_iter()
.for_each(|d| { .for_each(|d| {
assert_eq!( assert_eq!(
SEGMENT_SIZE, SEGMENT_SIZE,
@ -253,4 +277,20 @@ mod tests {
Ok(()) Ok(())
} }
#[test]
fn fmt_datagram_iter() {
let dgrams = [];
let i = DatagramIter {
meta: RecvMeta::default(),
datagrams: dgrams.chunks(1),
local_address: "[::]:0".parse().unwrap(),
};
assert_eq!(
&format!("{i:?}"),
"DatagramIter { meta: RecvMeta { addr: [::]:0, len: 0, stride: 0, ecn: None, dst_ip: None }, local_address: [::]:0 }"
);
}
} }