mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-17 14:25:49 +00:00
Backed out 2 changesets (bug 1772092) for causing build bustages. CLOSED TREE
Backed out changeset 30a2c0f4c97f (bug 1772092) Backed out changeset 7dd164e9428c (bug 1772092)
This commit is contained in:
parent
cebccb13b0
commit
44a8e72bfb
@ -15,7 +15,7 @@ rev = "75ada456c92a429704691a85e1cb42fef8cafc0d"
|
||||
[source."https://github.com/mozilla/neqo"]
|
||||
git = "https://github.com/mozilla/neqo"
|
||||
replace-with = "vendored-sources"
|
||||
tag = "v0.6.0"
|
||||
tag = "v0.5.7"
|
||||
|
||||
[source."https://github.com/mozilla/mp4parse-rust"]
|
||||
git = "https://github.com/mozilla/mp4parse-rust"
|
||||
|
45
Cargo.lock
generated
45
Cargo.lock
generated
@ -382,7 +382,7 @@ version = "1.1.0"
|
||||
name = "baldrdash"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"bindgen 0.59.2",
|
||||
"cranelift-codegen",
|
||||
"cranelift-wasm",
|
||||
"env_logger 0.8.999",
|
||||
@ -420,6 +420,13 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.56.999"
|
||||
dependencies = [
|
||||
"bindgen 0.59.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.59.2"
|
||||
@ -903,7 +910,7 @@ version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dff444d80630d7073077d38d40b4501fd518bd2b922c2a55edcc8b0f7be57e6"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"bindgen 0.59.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2017,7 +2024,7 @@ name = "gecko-profiler"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bindgen",
|
||||
"bindgen 0.59.2",
|
||||
"lazy_static",
|
||||
"mozbuild",
|
||||
"profiler-macros",
|
||||
@ -2527,7 +2534,7 @@ name = "http3server"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bindgen",
|
||||
"bindgen 0.59.2",
|
||||
"log",
|
||||
"mio 0.6.23",
|
||||
"mio-extras",
|
||||
@ -3090,9 +3097,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
@ -3458,7 +3465,7 @@ dependencies = [
|
||||
name = "mozilla-central-workspace-hack"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"bindgen 0.59.2",
|
||||
"libc",
|
||||
"quote",
|
||||
"serde",
|
||||
@ -3577,8 +3584,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "neqo-common"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.6.0#c9c013390ba68b401b5205c134e69d8898c2f299"
|
||||
version = "0.5.7"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.5.7#f3de275b12c40f45718ce43a0482e771ba6cd4b8"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"env_logger 0.8.999",
|
||||
@ -3590,10 +3597,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "neqo-crypto"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.6.0#c9c013390ba68b401b5205c134e69d8898c2f299"
|
||||
version = "0.5.7"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.5.7#f3de275b12c40f45718ce43a0482e771ba6cd4b8"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"bindgen 0.56.999",
|
||||
"log",
|
||||
"mozbuild",
|
||||
"neqo-common",
|
||||
@ -3604,8 +3611,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "neqo-http3"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.6.0#c9c013390ba68b401b5205c134e69d8898c2f299"
|
||||
version = "0.5.7"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.5.7#f3de275b12c40f45718ce43a0482e771ba6cd4b8"
|
||||
dependencies = [
|
||||
"enumset",
|
||||
"lazy_static",
|
||||
@ -3622,8 +3629,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "neqo-qpack"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.6.0#c9c013390ba68b401b5205c134e69d8898c2f299"
|
||||
version = "0.5.7"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.5.7#f3de275b12c40f45718ce43a0482e771ba6cd4b8"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"log",
|
||||
@ -3636,8 +3643,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "neqo-transport"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.6.0#c9c013390ba68b401b5205c134e69d8898c2f299"
|
||||
version = "0.5.7"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.5.7#f3de275b12c40f45718ce43a0482e771ba6cd4b8"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
@ -4987,7 +4994,7 @@ dependencies = [
|
||||
"app_units",
|
||||
"arrayvec",
|
||||
"atomic_refcell",
|
||||
"bindgen",
|
||||
"bindgen 0.59.2",
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"cssparser",
|
||||
|
@ -94,6 +94,9 @@ mozbuild = { path = "build/rust/mozbuild" }
|
||||
# Patch itoa 0.4 to 1.0.
|
||||
itoa = { path = "build/rust/itoa" }
|
||||
|
||||
# Patch bindgen 0.56 to 0.59.
|
||||
bindgen = { path = "build/rust/bindgen" }
|
||||
|
||||
# Patch cfg-if 0.1 to 1.0
|
||||
cfg-if = { path = "build/rust/cfg-if" }
|
||||
|
||||
|
19
build/rust/bindgen/Cargo.toml
Normal file
19
build/rust/bindgen/Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
||||
[package]
|
||||
name = "bindgen"
|
||||
version = "0.56.999"
|
||||
edition = "2018"
|
||||
license = "BSD-3-Clause"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies.bindgen]
|
||||
version = "0.59"
|
||||
default-features = false
|
||||
|
||||
[features]
|
||||
default = ["bindgen/default"]
|
||||
logging = ["bindgen/logging"]
|
||||
runtime = ["bindgen/runtime"]
|
||||
static = ["bindgen/static"]
|
||||
which-rustfmt = ["bindgen/which-rustfmt"]
|
26
build/rust/bindgen/lib.rs
Normal file
26
build/rust/bindgen/lib.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
pub use bindgen::*;
|
@ -8,10 +8,10 @@ edition = "2018"
|
||||
name = "neqo_glue"
|
||||
|
||||
[dependencies]
|
||||
neqo-http3 = { tag = "v0.6.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-transport = { tag = "v0.6.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-common = { tag = "v0.6.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-qpack = { tag = "v0.6.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-http3 = { tag = "v0.5.7", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-transport = { tag = "v0.5.7", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-common = { tag = "v0.5.7", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-qpack = { tag = "v0.5.7", git = "https://github.com/mozilla/neqo" }
|
||||
nserror = { path = "../../../xpcom/rust/nserror" }
|
||||
nsstring = { path = "../../../xpcom/rust/nsstring" }
|
||||
xpcom = { path = "../../../xpcom/rust/xpcom" }
|
||||
@ -25,7 +25,7 @@ static_prefs = { path = "../../../modules/libpref/init/static_prefs", optional =
|
||||
winapi = {version = "0.3", features = ["ws2def"] }
|
||||
|
||||
[dependencies.neqo-crypto]
|
||||
tag = "v0.6.0"
|
||||
tag = "v0.5.7"
|
||||
git = "https://github.com/mozilla/neqo"
|
||||
default-features = false
|
||||
features = ["gecko"]
|
||||
|
@ -11,7 +11,7 @@ use neqo_http3::{Error as Http3Error, Priority};
|
||||
use neqo_http3::{Http3Client, Http3ClientEvent, Http3Parameters, Http3State};
|
||||
use neqo_transport::{
|
||||
stream_id::StreamType, CongestionControlAlgorithm, ConnectionParameters,
|
||||
Error as TransportError, Output, Version, RandomConnectionIdGenerator, StreamId,
|
||||
Error as TransportError, Output, QuicVersion, RandomConnectionIdGenerator, StreamId,
|
||||
};
|
||||
use nserror::*;
|
||||
use nsstring::*;
|
||||
@ -106,17 +106,17 @@ impl NeqoHttp3Conn {
|
||||
let remote: SocketAddr = netaddr_to_socket_addr(remote_addr)?;
|
||||
|
||||
let quic_version = match alpn_conv {
|
||||
"h3-32" => Version::Draft32,
|
||||
"h3-31" => Version::Draft31,
|
||||
"h3-30" => Version::Draft30,
|
||||
"h3-29" => Version::Draft29,
|
||||
"h3" => Version::Version1,
|
||||
"h3-32" => QuicVersion::Draft32,
|
||||
"h3-31" => QuicVersion::Draft31,
|
||||
"h3-30" => QuicVersion::Draft30,
|
||||
"h3-29" => QuicVersion::Draft29,
|
||||
"h3" => QuicVersion::Version1,
|
||||
_ => return Err(NS_ERROR_INVALID_ARG),
|
||||
};
|
||||
|
||||
#[allow(unused_mut)]
|
||||
let mut params = ConnectionParameters::default()
|
||||
.versions(quic_version, vec![quic_version])
|
||||
.quic_version(quic_version)
|
||||
.cc_algorithm(CongestionControlAlgorithm::Cubic)
|
||||
.max_data(max_data)
|
||||
.max_stream_data(StreamType::BiDi, false, max_stream_data);
|
||||
@ -461,6 +461,7 @@ pub extern "C" fn neqo_htttp3conn_send_request_body(
|
||||
|
||||
fn crypto_error_code(err: neqo_crypto::Error) -> u64 {
|
||||
match err {
|
||||
neqo_crypto::Error::AeadInitFailure => 0,
|
||||
neqo_crypto::Error::AeadError => 1,
|
||||
neqo_crypto::Error::CertificateLoading => 2,
|
||||
neqo_crypto::Error::CreateSslSocket => 3,
|
||||
@ -478,7 +479,6 @@ fn crypto_error_code(err: neqo_crypto::Error) -> u64 {
|
||||
neqo_crypto::Error::UnsupportedVersion => 15,
|
||||
neqo_crypto::Error::StringError => 16,
|
||||
neqo_crypto::Error::EchRetry(_) => 17,
|
||||
neqo_crypto::Error::CipherInitFailure => 18,
|
||||
}
|
||||
}
|
||||
|
||||
@ -536,7 +536,7 @@ impl From<TransportError> for CloseError {
|
||||
TransportError::InvalidResumptionToken => CloseError::TransportInternalErrorOther(11),
|
||||
TransportError::InvalidRetry => CloseError::TransportInternalErrorOther(12),
|
||||
TransportError::InvalidStreamId => CloseError::TransportInternalErrorOther(13),
|
||||
TransportError::KeysDiscarded(_) => CloseError::TransportInternalErrorOther(14),
|
||||
TransportError::KeysDiscarded => CloseError::TransportInternalErrorOther(14),
|
||||
TransportError::KeysPending(_) => CloseError::TransportInternalErrorOther(15),
|
||||
TransportError::KeyUpdateBlocked => CloseError::TransportInternalErrorOther(16),
|
||||
TransportError::NoMoreData => CloseError::TransportInternalErrorOther(17),
|
||||
@ -551,7 +551,6 @@ impl From<TransportError> for CloseError {
|
||||
TransportError::WrongRole => CloseError::TransportInternalErrorOther(26),
|
||||
TransportError::QlogError => CloseError::TransportInternalErrorOther(27),
|
||||
TransportError::NotAvailable => CloseError::TransportInternalErrorOther(28),
|
||||
TransportError::DisabledVersion => CloseError::TransportInternalErrorOther(29),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,17 +5,17 @@ authors = ["Dragana Damjanovic <dragana.damjano@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
neqo-transport = { tag = "v0.6.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-common = { tag = "v0.6.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-http3 = { tag = "v0.6.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-qpack = { tag = "v0.6.0", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-transport = { tag = "v0.5.7", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-common = { tag = "v0.5.7", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-http3 = { tag = "v0.5.7", git = "https://github.com/mozilla/neqo" }
|
||||
neqo-qpack = { tag = "v0.5.7", git = "https://github.com/mozilla/neqo" }
|
||||
mio = "0.6.17"
|
||||
mio-extras = "2.0.5"
|
||||
log = "0.4.0"
|
||||
base64 = "0.13"
|
||||
|
||||
[dependencies.neqo-crypto]
|
||||
tag = "v0.6.0"
|
||||
tag = "v0.5.7"
|
||||
git = "https://github.com/mozilla/neqo"
|
||||
default-features = false
|
||||
features = ["gecko"]
|
||||
|
@ -882,7 +882,7 @@ version = "0.4.5"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[unaudited.log]]
|
||||
version = "0.4.17"
|
||||
version = "0.4.14"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[unaudited.mach]]
|
||||
|
2
third_party/rust/log/.cargo-checksum.json
vendored
2
third_party/rust/log/.cargo-checksum.json
vendored
@ -1 +1 @@
|
||||
{"files":{"CHANGELOG.md":"d96bb13d82aab1b8f01a077167eb3968fe27c4fbb7aa4933f0e257d42794eb76","Cargo.toml":"e0ff3b07a36ad23348c9cc7113ad787aefbc0c7b75517f5a68247863a4994e1c","LICENSE-APACHE":"7cfd738c53d61c79f07e348f622bf7707c9084237054d37fbe07788a75f5881c","LICENSE-MIT":"705aaaaecefa087c187bd2eacdb01b8ac1c5ee95b1d5d04d8d7efe0363207df8","README.md":"bd6ed9b3c1cf3329d7afca04eb03f5c36e75cf9cb0bbbffddb7f07f3f36f2ea0","benches/value.rs":"55bd5f795a524f0699b2858eb14cc456abebeb43d50c90d2bfc77cd7856e8050","build.rs":"91dd121dd1aa749c8c0c24bda658309d1313baa022afbc5af1fabd1104622376","src/kv/error.rs":"01d37bb1ecbb2ba1145cd6df0b0b9a3ea3f1a2c9586a4908d3256cb865365b7e","src/kv/key.rs":"e74b489cde28960f76d4038b02867b4cb724c206d31abd461abeaa04e73cf7ef","src/kv/mod.rs":"9d916f43fd9c2829991fcff6db32f23bb7864e1113a622d49e59f110e2f290cf","src/kv/source.rs":"3f7aadc5f30c0c821fd20d899d8529eba8088eeda0c8603814de689da25dd4e8","src/kv/value.rs":"3387875f0ffd5f4747f181c3bc5134974358993981e54b1f203d6dd835a50245","src/lib.rs":"69dd3c57d9c6438d2e5bda9dc657827dcd73561faff708358f2e6854f47a2a3d","src/macros.rs":"642640f48a9d61efed0213b3a61a2864e80e8f8ffb9541b7c44d3028d3a7f08c","src/serde.rs":"d8190561ed64398fe45142b261000255ea1bcda8707e6f1b07ef4b805da6829b","triagebot.toml":"2d1d46d069bc4e3739069676707ca2801e0e0ba58a784a264392362ff9ac4a77"},"package":"abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"}
|
||||
{"files":{"CHANGELOG.md":"5fa3f03a8dfa3934f5b1cfba9a41781700ed6e67afe0f10717cc16b6855ceb16","Cargo.toml":"2863cdd3382ede73ecc608ad22a4d8ee476abed3b0016f9724deba59e9317338","LICENSE-APACHE":"7cfd738c53d61c79f07e348f622bf7707c9084237054d37fbe07788a75f5881c","LICENSE-MIT":"705aaaaecefa087c187bd2eacdb01b8ac1c5ee95b1d5d04d8d7efe0363207df8","README.md":"ca758a44f4a226f21b3bc997d27a5356b5e77ee13a1daad24ee8bbbebb301c5d","benches/value.rs":"55bd5f795a524f0699b2858eb14cc456abebeb43d50c90d2bfc77cd7856e8050","build.rs":"2bfb7564209da7c4d10433d9639d33541a89d63fc52cbe47d479a967cf746769","src/kv/error.rs":"ba46a4bcac717e6dc58fc5101833c825d7b95777c1dd907be46c8fa573a27d2d","src/kv/key.rs":"e74b489cde28960f76d4038b02867b4cb724c206d31abd461abeaa04e73cf7ef","src/kv/mod.rs":"9d916f43fd9c2829991fcff6db32f23bb7864e1113a622d49e59f110e2f290cf","src/kv/source.rs":"3f7aadc5f30c0c821fd20d899d8529eba8088eeda0c8603814de689da25dd4e8","src/kv/value.rs":"4d46ced0adbe385701c1d80d03c0f2abde2e43acf16521a9d26f058462f43799","src/lib.rs":"320a18401e7f9edc812a52b5be029fb9ef8c6d7435ab7b52650878477d21103b","src/macros.rs":"b0174b17f5e06b6a7bafb7873c79c7f8e2c70a531686adf03c027739ee040a44","src/serde.rs":"d8190561ed64398fe45142b261000255ea1bcda8707e6f1b07ef4b805da6829b","triagebot.toml":"2d1d46d069bc4e3739069676707ca2801e0e0ba58a784a264392362ff9ac4a77"},"package":"51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"}
|
28
third_party/rust/log/CHANGELOG.md
vendored
28
third_party/rust/log/CHANGELOG.md
vendored
@ -2,29 +2,6 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.4.17] - 2022-04-29
|
||||
|
||||
* Update `kv_unstable` internal dependencies.
|
||||
|
||||
## [0.4.16] - 2022-03-22
|
||||
|
||||
* Fix a conflict with unqualified `Option` use in macros.
|
||||
|
||||
## [0.4.15] - 2022-02-23
|
||||
|
||||
* Silence a warning about the deprecated `spin_loop_hint`.
|
||||
* Relax ordering in the atomic `set_max_level` call.
|
||||
* Add thumbv4t-none-eabi to targets that don't support atomics
|
||||
* Allow levels to be iterated over.
|
||||
* Implement `Log` on some common wrapper types.
|
||||
* Improvements to test coverage.
|
||||
* Improvements to documentation.
|
||||
* Add key-value support to the `log!` macros.
|
||||
* Tighten `kv_unstable` internal dependencies so they don't bump past their current alpha.
|
||||
* Add a simple visit API to `kv_unstable`.
|
||||
* Support `NonZero*` integers as values in structured logging
|
||||
* Support static strings as keys in structured logging
|
||||
|
||||
## [0.4.14] - 2021-01-27
|
||||
|
||||
* Remove the `__private_api_log_lit` special case.
|
||||
@ -219,10 +196,7 @@ version using log 0.4.x to avoid losing module and file information.
|
||||
|
||||
Look at the [release tags] for information about older releases.
|
||||
|
||||
[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.17...HEAD
|
||||
[0.4.17]: https://github.com/rust-lang-nursery/log/compare/0.4.16...0.4.17
|
||||
[0.4.16]: https://github.com/rust-lang-nursery/log/compare/0.4.15...0.4.16
|
||||
[0.4.15]: https://github.com/rust-lang-nursery/log/compare/0.4.13...0.4.15
|
||||
[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.14...HEAD
|
||||
[0.4.14]: https://github.com/rust-lang-nursery/log/compare/0.4.13...0.4.14
|
||||
[0.4.13]: https://github.com/rust-lang-nursery/log/compare/0.4.11...0.4.13
|
||||
[0.4.12]: https://github.com/rust-lang-nursery/log/compare/0.4.11...0.4.12
|
||||
|
57
third_party/rust/log/Cargo.toml
vendored
57
third_party/rust/log/Cargo.toml
vendored
@ -3,36 +3,28 @@
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
# to registry (e.g., crates.io) dependencies
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
# editing this file be aware that the upstream Cargo.toml
|
||||
# will likely look very different (and much more reasonable)
|
||||
|
||||
[package]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
version = "0.4.14"
|
||||
authors = ["The Rust Project Developers"]
|
||||
build = "build.rs"
|
||||
exclude = ["rfcs/**/*"]
|
||||
description = """
|
||||
A lightweight logging facade for Rust
|
||||
"""
|
||||
exclude = ["rfcs/**/*", "/.travis.yml", "/appveyor.yml"]
|
||||
description = "A lightweight logging facade for Rust\n"
|
||||
documentation = "https://docs.rs/log"
|
||||
readme = "README.md"
|
||||
keywords = ["logging"]
|
||||
categories = ["development-tools::debugging"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/rust-lang/log"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = [
|
||||
"std",
|
||||
"serde",
|
||||
"kv_unstable_std",
|
||||
"kv_unstable_sval",
|
||||
"kv_unstable_serde",
|
||||
]
|
||||
features = ["std", "serde", "kv_unstable_std", "kv_unstable_sval", "kv_unstable_serde"]
|
||||
|
||||
[[test]]
|
||||
name = "filters"
|
||||
@ -43,7 +35,6 @@ harness = false
|
||||
name = "macros"
|
||||
path = "tests/macros.rs"
|
||||
harness = true
|
||||
|
||||
[dependencies.cfg-if]
|
||||
version = "1.0"
|
||||
|
||||
@ -53,18 +44,14 @@ optional = true
|
||||
default-features = false
|
||||
|
||||
[dependencies.sval]
|
||||
version = "=1.0.0-alpha.5"
|
||||
version = "1.0.0-alpha.5"
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[dependencies.value-bag]
|
||||
version = "=1.0.0-alpha.9"
|
||||
version = "1.0.0-alpha.6"
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.rustversion]
|
||||
version = "1.0"
|
||||
|
||||
[dev-dependencies.serde]
|
||||
version = "1.0"
|
||||
features = ["derive"]
|
||||
@ -73,30 +60,18 @@ features = ["derive"]
|
||||
version = "1.0"
|
||||
|
||||
[dev-dependencies.sval]
|
||||
version = "=1.0.0-alpha.5"
|
||||
version = "1.0.0-alpha.5"
|
||||
features = ["derive"]
|
||||
|
||||
[dev-dependencies.value-bag]
|
||||
version = "=1.0.0-alpha.9"
|
||||
version = "1.0.0-alpha.6"
|
||||
features = ["test"]
|
||||
|
||||
[features]
|
||||
kv_unstable = ["value-bag"]
|
||||
kv_unstable_serde = [
|
||||
"kv_unstable_std",
|
||||
"value-bag/serde",
|
||||
"serde",
|
||||
]
|
||||
kv_unstable_std = [
|
||||
"std",
|
||||
"kv_unstable",
|
||||
"value-bag/error",
|
||||
]
|
||||
kv_unstable_sval = [
|
||||
"kv_unstable",
|
||||
"value-bag/sval",
|
||||
"sval",
|
||||
]
|
||||
kv_unstable_serde = ["kv_unstable_std", "value-bag/serde", "serde"]
|
||||
kv_unstable_std = ["std", "kv_unstable", "value-bag/error"]
|
||||
kv_unstable_sval = ["kv_unstable", "value-bag/sval", "sval"]
|
||||
max_level_debug = []
|
||||
max_level_error = []
|
||||
max_level_info = []
|
||||
|
39
third_party/rust/log/README.md
vendored
39
third_party/rust/log/README.md
vendored
@ -24,7 +24,7 @@ This version is explicitly tested in CI and may be bumped in any release as need
|
||||
|
||||
## Usage
|
||||
|
||||
### In libraries
|
||||
## In libraries
|
||||
|
||||
Libraries should link only to the `log` crate, and use the provided macros to
|
||||
log whatever information will be useful to downstream consumers:
|
||||
@ -55,15 +55,15 @@ pub fn shave_the_yak(yak: &mut Yak) {
|
||||
}
|
||||
```
|
||||
|
||||
### In executables
|
||||
## In executables
|
||||
|
||||
In order to produce log output, executables have to use a logger implementation compatible with the facade.
|
||||
There are many available implementations to choose from, here are some of the most popular ones:
|
||||
|
||||
* Simple minimal loggers:
|
||||
* [`env_logger`](https://docs.rs/env_logger/*/env_logger/)
|
||||
* [`simple_logger`](https://docs.rs/simple_logger/*/simple_logger/)
|
||||
* [`simplelog`](https://docs.rs/simplelog/*/simplelog/)
|
||||
* [`simple_logger`](https://github.com/borntyping/rust-simple_logger)
|
||||
* [`simplelog`](https://github.com/drakulix/simplelog.rs)
|
||||
* [`pretty_env_logger`](https://docs.rs/pretty_env_logger/*/pretty_env_logger/)
|
||||
* [`stderrlog`](https://docs.rs/stderrlog/*/stderrlog/)
|
||||
* [`flexi_logger`](https://docs.rs/flexi_logger/*/flexi_logger/)
|
||||
@ -72,17 +72,11 @@ There are many available implementations to choose from, here are some of the mo
|
||||
* [`fern`](https://docs.rs/fern/*/fern/)
|
||||
* Adaptors for other facilities:
|
||||
* [`syslog`](https://docs.rs/syslog/*/syslog/)
|
||||
* [`systemd-journal-logger`](https://docs.rs/systemd-journal-logger/*/systemd_journal_logger/)
|
||||
* [`slog-stdlog`](https://docs.rs/slog-stdlog/*/slog_stdlog/)
|
||||
* [`android_log`](https://docs.rs/android_log/*/android_log/)
|
||||
* [`win_dbg_logger`](https://docs.rs/win_dbg_logger/*/win_dbg_logger/)
|
||||
* [`db_logger`](https://docs.rs/db_logger/*/db_logger/)
|
||||
* For WebAssembly binaries:
|
||||
* [`console_log`](https://docs.rs/console_log/*/console_log/)
|
||||
* For dynamic libraries:
|
||||
* You may need to construct [an FFI-safe wrapper over `log`](https://github.com/rust-lang/log/issues/421) to initialize in your libraries.
|
||||
* Utilities:
|
||||
* [`log_err`](https://docs.rs/log_err/*/log_err/)
|
||||
|
||||
Executables should choose a logger implementation and initialize it early in the
|
||||
runtime of the program. Logger implementations will typically include a
|
||||
@ -90,28 +84,3 @@ function to do this. Any log messages generated before the logger is
|
||||
initialized will be ignored.
|
||||
|
||||
The executable itself may use the `log` crate to log as well.
|
||||
|
||||
## Structured logging
|
||||
|
||||
If you enable the `kv_unstable` feature, you can associate structured data with your log records:
|
||||
|
||||
```rust
|
||||
use log::{info, trace, warn, as_serde, as_error};
|
||||
|
||||
pub fn shave_the_yak(yak: &mut Yak) {
|
||||
trace!(target = "yak_events", yak = as_serde!(yak); "Commencing yak shaving");
|
||||
|
||||
loop {
|
||||
match find_a_razor() {
|
||||
Ok(razor) => {
|
||||
info!(razor = razor; "Razor located");
|
||||
yak.shave(razor);
|
||||
break;
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(err = as_error!(err); "Unable to locate a razor, retrying");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
5
third_party/rust/log/build.rs
vendored
5
third_party/rust/log/build.rs
vendored
@ -33,10 +33,7 @@ fn target_has_atomic_cas(target: &str) -> bool {
|
||||
|
||||
fn target_has_atomics(target: &str) -> bool {
|
||||
match &target[..] {
|
||||
"thumbv4t-none-eabi"
|
||||
| "msp430-none-elf"
|
||||
| "riscv32i-unknown-none-elf"
|
||||
| "riscv32imc-unknown-none-elf" => false,
|
||||
"msp430-none-elf" | "riscv32i-unknown-none-elf" | "riscv32imc-unknown-none-elf" => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
20
third_party/rust/log/src/kv/error.rs
vendored
20
third_party/rust/log/src/kv/error.rs
vendored
@ -11,7 +11,6 @@ enum Inner {
|
||||
#[cfg(feature = "std")]
|
||||
Boxed(std_support::BoxedError),
|
||||
Msg(&'static str),
|
||||
Value(value_bag::Error),
|
||||
Fmt,
|
||||
}
|
||||
|
||||
@ -22,24 +21,6 @@ impl Error {
|
||||
inner: Inner::Msg(msg),
|
||||
}
|
||||
}
|
||||
|
||||
// Not public so we don't leak the `value_bag` API
|
||||
pub(super) fn from_value(err: value_bag::Error) -> Self {
|
||||
Error {
|
||||
inner: Inner::Value(err),
|
||||
}
|
||||
}
|
||||
|
||||
// Not public so we don't leak the `value_bag` API
|
||||
pub(super) fn into_value(self) -> value_bag::Error {
|
||||
match self.inner {
|
||||
Inner::Value(err) => err,
|
||||
#[cfg(feature = "kv_unstable_std")]
|
||||
_ => value_bag::Error::boxed(self),
|
||||
#[cfg(not(feature = "kv_unstable_std"))]
|
||||
_ => value_bag::Error::msg("error inspecting a value"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
@ -48,7 +29,6 @@ impl fmt::Display for Error {
|
||||
match &self.inner {
|
||||
#[cfg(feature = "std")]
|
||||
&Boxed(ref err) => err.fmt(f),
|
||||
&Value(ref err) => err.fmt(f),
|
||||
&Msg(ref msg) => msg.fmt(f),
|
||||
&Fmt => fmt::Error.fmt(f),
|
||||
}
|
||||
|
383
third_party/rust/log/src/kv/value.rs
vendored
383
third_party/rust/log/src/kv/value.rs
vendored
@ -37,49 +37,6 @@ impl<'v> ToValue for Value<'v> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a value from a type implementing `std::fmt::Debug`.
|
||||
#[macro_export]
|
||||
macro_rules! as_debug {
|
||||
($capture:expr) => {
|
||||
$crate::kv::Value::from_debug(&$capture)
|
||||
};
|
||||
}
|
||||
|
||||
/// Get a value from a type implementing `std::fmt::Display`.
|
||||
#[macro_export]
|
||||
macro_rules! as_display {
|
||||
($capture:expr) => {
|
||||
$crate::kv::Value::from_display(&$capture)
|
||||
};
|
||||
}
|
||||
|
||||
/// Get a value from an error.
|
||||
#[cfg(feature = "kv_unstable_std")]
|
||||
#[macro_export]
|
||||
macro_rules! as_error {
|
||||
($capture:expr) => {
|
||||
$crate::kv::Value::from_dyn_error(&$capture)
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "kv_unstable_serde")]
|
||||
/// Get a value from a type implementing `serde::Serialize`.
|
||||
#[macro_export]
|
||||
macro_rules! as_serde {
|
||||
($capture:expr) => {
|
||||
$crate::kv::Value::from_serde(&$capture)
|
||||
};
|
||||
}
|
||||
|
||||
/// Get a value from a type implementing `sval::value::Value`.
|
||||
#[cfg(feature = "kv_unstable_sval")]
|
||||
#[macro_export]
|
||||
macro_rules! as_sval {
|
||||
($capture:expr) => {
|
||||
$crate::kv::Value::from_sval(&$capture)
|
||||
};
|
||||
}
|
||||
|
||||
/// A value in a structured key-value pair.
|
||||
///
|
||||
/// # Capturing values
|
||||
@ -306,78 +263,6 @@ impl<'v> Value<'v> {
|
||||
pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
|
||||
self.inner.downcast_ref::<T>()
|
||||
}
|
||||
|
||||
/// Inspect this value using a simple visitor.
|
||||
pub fn visit(&self, visitor: impl Visit<'v>) -> Result<(), Error> {
|
||||
struct Visitor<V>(V);
|
||||
|
||||
impl<'v, V> value_bag::visit::Visit<'v> for Visitor<V>
|
||||
where
|
||||
V: Visit<'v>,
|
||||
{
|
||||
fn visit_any(&mut self, value: ValueBag) -> Result<(), value_bag::Error> {
|
||||
self.0
|
||||
.visit_any(Value { inner: value })
|
||||
.map_err(Error::into_value)
|
||||
}
|
||||
|
||||
fn visit_u64(&mut self, value: u64) -> Result<(), value_bag::Error> {
|
||||
self.0.visit_u64(value).map_err(Error::into_value)
|
||||
}
|
||||
|
||||
fn visit_i64(&mut self, value: i64) -> Result<(), value_bag::Error> {
|
||||
self.0.visit_i64(value).map_err(Error::into_value)
|
||||
}
|
||||
|
||||
fn visit_u128(&mut self, value: u128) -> Result<(), value_bag::Error> {
|
||||
self.0.visit_u128(value).map_err(Error::into_value)
|
||||
}
|
||||
|
||||
fn visit_i128(&mut self, value: i128) -> Result<(), value_bag::Error> {
|
||||
self.0.visit_i128(value).map_err(Error::into_value)
|
||||
}
|
||||
|
||||
fn visit_f64(&mut self, value: f64) -> Result<(), value_bag::Error> {
|
||||
self.0.visit_f64(value).map_err(Error::into_value)
|
||||
}
|
||||
|
||||
fn visit_bool(&mut self, value: bool) -> Result<(), value_bag::Error> {
|
||||
self.0.visit_bool(value).map_err(Error::into_value)
|
||||
}
|
||||
|
||||
fn visit_str(&mut self, value: &str) -> Result<(), value_bag::Error> {
|
||||
self.0.visit_str(value).map_err(Error::into_value)
|
||||
}
|
||||
|
||||
fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), value_bag::Error> {
|
||||
self.0.visit_borrowed_str(value).map_err(Error::into_value)
|
||||
}
|
||||
|
||||
fn visit_char(&mut self, value: char) -> Result<(), value_bag::Error> {
|
||||
self.0.visit_char(value).map_err(Error::into_value)
|
||||
}
|
||||
|
||||
#[cfg(feature = "kv_unstable_std")]
|
||||
fn visit_error(
|
||||
&mut self,
|
||||
err: &(dyn std::error::Error + 'static),
|
||||
) -> Result<(), value_bag::Error> {
|
||||
self.0.visit_error(err).map_err(Error::into_value)
|
||||
}
|
||||
|
||||
#[cfg(feature = "kv_unstable_std")]
|
||||
fn visit_borrowed_error(
|
||||
&mut self,
|
||||
err: &'v (dyn std::error::Error + 'static),
|
||||
) -> Result<(), value_bag::Error> {
|
||||
self.0.visit_borrowed_error(err).map_err(Error::into_value)
|
||||
}
|
||||
}
|
||||
|
||||
self.inner
|
||||
.visit(&mut Visitor(visitor))
|
||||
.map_err(Error::from_value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'v> fmt::Debug for Value<'v> {
|
||||
@ -441,62 +326,12 @@ impl ToValue for str {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToValue for u128 {
|
||||
fn to_value(&self) -> Value {
|
||||
Value::from(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToValue for i128 {
|
||||
fn to_value(&self) -> Value {
|
||||
Value::from(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToValue for std::num::NonZeroU128 {
|
||||
fn to_value(&self) -> Value {
|
||||
Value::from(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToValue for std::num::NonZeroI128 {
|
||||
fn to_value(&self) -> Value {
|
||||
Value::from(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'v> From<&'v str> for Value<'v> {
|
||||
fn from(value: &'v str) -> Self {
|
||||
Value::from_value_bag(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'v> From<&'v u128> for Value<'v> {
|
||||
fn from(value: &'v u128) -> Self {
|
||||
Value::from_value_bag(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'v> From<&'v i128> for Value<'v> {
|
||||
fn from(value: &'v i128) -> Self {
|
||||
Value::from_value_bag(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'v> From<&'v std::num::NonZeroU128> for Value<'v> {
|
||||
fn from(v: &'v std::num::NonZeroU128) -> Value<'v> {
|
||||
// SAFETY: `NonZeroU128` and `u128` have the same ABI
|
||||
Value::from_value_bag(unsafe { std::mem::transmute::<&std::num::NonZeroU128, &u128>(v) })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'v> From<&'v std::num::NonZeroI128> for Value<'v> {
|
||||
fn from(v: &'v std::num::NonZeroI128) -> Value<'v> {
|
||||
// SAFETY: `NonZeroI128` and `i128` have the same ABI
|
||||
Value::from_value_bag(unsafe { std::mem::transmute::<&std::num::NonZeroI128, &i128>(v) })
|
||||
}
|
||||
}
|
||||
|
||||
impl ToValue for () {
|
||||
fn to_value(&self) -> Value {
|
||||
Value::from_value_bag(())
|
||||
@ -533,24 +368,6 @@ macro_rules! impl_to_value_primitive {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_to_value_nonzero_primitive {
|
||||
($($into_ty:ident,)*) => {
|
||||
$(
|
||||
impl ToValue for std::num::$into_ty {
|
||||
fn to_value(&self) -> Value {
|
||||
Value::from(self.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'v> From<std::num::$into_ty> for Value<'v> {
|
||||
fn from(value: std::num::$into_ty) -> Self {
|
||||
Value::from(value.get())
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_value_to_primitive {
|
||||
($(#[doc = $doc:tt] $into_name:ident -> $into_ty:ty,)*) => {
|
||||
impl<'v> Value<'v> {
|
||||
@ -564,12 +381,8 @@ macro_rules! impl_value_to_primitive {
|
||||
}
|
||||
}
|
||||
|
||||
impl_to_value_primitive![usize, u8, u16, u32, u64, isize, i8, i16, i32, i64, f32, f64, char, bool,];
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl_to_value_nonzero_primitive![
|
||||
NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64,
|
||||
NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64,
|
||||
impl_to_value_primitive![
|
||||
usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64, char, bool,
|
||||
];
|
||||
|
||||
impl_value_to_primitive![
|
||||
@ -635,142 +448,6 @@ mod std_support {
|
||||
self.inner.to_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'v> From<&'v String> for Value<'v> {
|
||||
fn from(v: &'v String) -> Self {
|
||||
Value::from(&**v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A visitor for a `Value`.
|
||||
pub trait Visit<'v> {
|
||||
/// Visit a `Value`.
|
||||
///
|
||||
/// This is the only required method on `Visit` and acts as a fallback for any
|
||||
/// more specific methods that aren't overridden.
|
||||
/// The `Value` may be formatted using its `fmt::Debug` or `fmt::Display` implementation,
|
||||
/// or serialized using its `sval::Value` or `serde::Serialize` implementation.
|
||||
fn visit_any(&mut self, value: Value) -> Result<(), Error>;
|
||||
|
||||
/// Visit an unsigned integer.
|
||||
fn visit_u64(&mut self, value: u64) -> Result<(), Error> {
|
||||
self.visit_any(value.into())
|
||||
}
|
||||
|
||||
/// Visit a signed integer.
|
||||
fn visit_i64(&mut self, value: i64) -> Result<(), Error> {
|
||||
self.visit_any(value.into())
|
||||
}
|
||||
|
||||
/// Visit a big unsigned integer.
|
||||
fn visit_u128(&mut self, value: u128) -> Result<(), Error> {
|
||||
self.visit_any((&value).into())
|
||||
}
|
||||
|
||||
/// Visit a big signed integer.
|
||||
fn visit_i128(&mut self, value: i128) -> Result<(), Error> {
|
||||
self.visit_any((&value).into())
|
||||
}
|
||||
|
||||
/// Visit a floating point.
|
||||
fn visit_f64(&mut self, value: f64) -> Result<(), Error> {
|
||||
self.visit_any(value.into())
|
||||
}
|
||||
|
||||
/// Visit a boolean.
|
||||
fn visit_bool(&mut self, value: bool) -> Result<(), Error> {
|
||||
self.visit_any(value.into())
|
||||
}
|
||||
|
||||
/// Visit a string.
|
||||
fn visit_str(&mut self, value: &str) -> Result<(), Error> {
|
||||
self.visit_any(value.into())
|
||||
}
|
||||
|
||||
/// Visit a string.
|
||||
fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), Error> {
|
||||
self.visit_str(value)
|
||||
}
|
||||
|
||||
/// Visit a Unicode character.
|
||||
fn visit_char(&mut self, value: char) -> Result<(), Error> {
|
||||
let mut b = [0; 4];
|
||||
self.visit_str(&*value.encode_utf8(&mut b))
|
||||
}
|
||||
|
||||
/// Visit an error.
|
||||
#[cfg(feature = "kv_unstable_std")]
|
||||
fn visit_error(&mut self, err: &(dyn std::error::Error + 'static)) -> Result<(), Error> {
|
||||
self.visit_any(Value::from_dyn_error(err))
|
||||
}
|
||||
|
||||
/// Visit an error.
|
||||
#[cfg(feature = "kv_unstable_std")]
|
||||
fn visit_borrowed_error(
|
||||
&mut self,
|
||||
err: &'v (dyn std::error::Error + 'static),
|
||||
) -> Result<(), Error> {
|
||||
self.visit_any(Value::from_dyn_error(err))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'v, T: ?Sized> Visit<'v> for &'a mut T
|
||||
where
|
||||
T: Visit<'v>,
|
||||
{
|
||||
fn visit_any(&mut self, value: Value) -> Result<(), Error> {
|
||||
(**self).visit_any(value)
|
||||
}
|
||||
|
||||
fn visit_u64(&mut self, value: u64) -> Result<(), Error> {
|
||||
(**self).visit_u64(value)
|
||||
}
|
||||
|
||||
fn visit_i64(&mut self, value: i64) -> Result<(), Error> {
|
||||
(**self).visit_i64(value)
|
||||
}
|
||||
|
||||
fn visit_u128(&mut self, value: u128) -> Result<(), Error> {
|
||||
(**self).visit_u128(value)
|
||||
}
|
||||
|
||||
fn visit_i128(&mut self, value: i128) -> Result<(), Error> {
|
||||
(**self).visit_i128(value)
|
||||
}
|
||||
|
||||
fn visit_f64(&mut self, value: f64) -> Result<(), Error> {
|
||||
(**self).visit_f64(value)
|
||||
}
|
||||
|
||||
fn visit_bool(&mut self, value: bool) -> Result<(), Error> {
|
||||
(**self).visit_bool(value)
|
||||
}
|
||||
|
||||
fn visit_str(&mut self, value: &str) -> Result<(), Error> {
|
||||
(**self).visit_str(value)
|
||||
}
|
||||
|
||||
fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), Error> {
|
||||
(**self).visit_borrowed_str(value)
|
||||
}
|
||||
|
||||
fn visit_char(&mut self, value: char) -> Result<(), Error> {
|
||||
(**self).visit_char(value)
|
||||
}
|
||||
|
||||
#[cfg(feature = "kv_unstable_std")]
|
||||
fn visit_error(&mut self, err: &(dyn std::error::Error + 'static)) -> Result<(), Error> {
|
||||
(**self).visit_error(err)
|
||||
}
|
||||
|
||||
#[cfg(feature = "kv_unstable_std")]
|
||||
fn visit_borrowed_error(
|
||||
&mut self,
|
||||
err: &'v (dyn std::error::Error + 'static),
|
||||
) -> Result<(), Error> {
|
||||
(**self).visit_borrowed_error(err)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -792,11 +469,6 @@ pub(crate) mod tests {
|
||||
Value::from(32u32),
|
||||
Value::from(64u64),
|
||||
Value::from(1usize),
|
||||
Value::from(std::num::NonZeroU8::new(8).unwrap()),
|
||||
Value::from(std::num::NonZeroU16::new(16).unwrap()),
|
||||
Value::from(std::num::NonZeroU32::new(32).unwrap()),
|
||||
Value::from(std::num::NonZeroU64::new(64).unwrap()),
|
||||
Value::from(std::num::NonZeroUsize::new(1).unwrap()),
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
@ -808,11 +480,6 @@ pub(crate) mod tests {
|
||||
Value::from(-32i32),
|
||||
Value::from(-64i64),
|
||||
Value::from(-1isize),
|
||||
Value::from(std::num::NonZeroI8::new(-8).unwrap()),
|
||||
Value::from(std::num::NonZeroI16::new(-16).unwrap()),
|
||||
Value::from(std::num::NonZeroI32::new(-32).unwrap()),
|
||||
Value::from(std::num::NonZeroI64::new(-64).unwrap()),
|
||||
Value::from(std::num::NonZeroIsize::new(-1).unwrap()),
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
@ -985,50 +652,4 @@ pub(crate) mod tests {
|
||||
assert!(v.is::<Foo>());
|
||||
assert_eq!(42u64, v.downcast_ref::<Foo>().expect("invalid downcast").0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_visit_integer() {
|
||||
struct Extract(Option<u64>);
|
||||
|
||||
impl<'v> Visit<'v> for Extract {
|
||||
fn visit_any(&mut self, value: Value) -> Result<(), Error> {
|
||||
unimplemented!("unexpected value: {:?}", value)
|
||||
}
|
||||
|
||||
fn visit_u64(&mut self, value: u64) -> Result<(), Error> {
|
||||
self.0 = Some(value);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
let mut extract = Extract(None);
|
||||
Value::from(42u64).visit(&mut extract).unwrap();
|
||||
|
||||
assert_eq!(Some(42), extract.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_visit_borrowed_str() {
|
||||
struct Extract<'v>(Option<&'v str>);
|
||||
|
||||
impl<'v> Visit<'v> for Extract<'v> {
|
||||
fn visit_any(&mut self, value: Value) -> Result<(), Error> {
|
||||
unimplemented!("unexpected value: {:?}", value)
|
||||
}
|
||||
|
||||
fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), Error> {
|
||||
self.0 = Some(value);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
let mut extract = Extract(None);
|
||||
|
||||
let short_lived = String::from("A short-lived string");
|
||||
Value::from(&*short_lived).visit(&mut extract).unwrap();
|
||||
|
||||
assert_eq!(Some("A short-lived string"), extract.0);
|
||||
}
|
||||
}
|
||||
|
208
third_party/rust/log/src/lib.rs
vendored
208
third_party/rust/log/src/lib.rs
vendored
@ -24,7 +24,7 @@
|
||||
//! though that default may be overridden. Logger implementations typically use
|
||||
//! the target to filter requests based on some user configuration.
|
||||
//!
|
||||
//! # Usage
|
||||
//! # Use
|
||||
//!
|
||||
//! The basic use of the log crate is through the five logging macros: [`error!`],
|
||||
//! [`warn!`], [`info!`], [`debug!`] and [`trace!`]
|
||||
@ -86,42 +86,6 @@
|
||||
//!
|
||||
//! The logging system may only be initialized once.
|
||||
//!
|
||||
//! ## Structured logging
|
||||
//!
|
||||
//! If you enable the `kv_unstable` feature you can associate structured values
|
||||
//! with your log records. If we take the example from before, we can include
|
||||
//! some additional context besides what's in the formatted message:
|
||||
//!
|
||||
//! ```edition2018
|
||||
//! # #[macro_use] extern crate serde;
|
||||
//! # #[derive(Debug, Serialize)] pub struct Yak(String);
|
||||
//! # impl Yak { fn shave(&mut self, _: u32) {} }
|
||||
//! # fn find_a_razor() -> Result<u32, std::io::Error> { Ok(1) }
|
||||
//! # #[cfg(feature = "kv_unstable_serde")]
|
||||
//! # fn main() {
|
||||
//! use log::{info, warn, as_serde, as_error};
|
||||
//!
|
||||
//! pub fn shave_the_yak(yak: &mut Yak) {
|
||||
//! info!(target: "yak_events", yak = as_serde!(yak); "Commencing yak shaving");
|
||||
//!
|
||||
//! loop {
|
||||
//! match find_a_razor() {
|
||||
//! Ok(razor) => {
|
||||
//! info!(razor = razor; "Razor located");
|
||||
//! yak.shave(razor);
|
||||
//! break;
|
||||
//! }
|
||||
//! Err(err) => {
|
||||
//! warn!(err = as_error!(err); "Unable to locate a razor, retrying");
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! # }
|
||||
//! # #[cfg(not(feature = "kv_unstable_serde"))]
|
||||
//! # fn main() {}
|
||||
//! ```
|
||||
//!
|
||||
//! # Available logging implementations
|
||||
//!
|
||||
//! In order to produce log output executables have to use
|
||||
@ -142,14 +106,6 @@
|
||||
//! * Adaptors for other facilities:
|
||||
//! * [syslog]
|
||||
//! * [slog-stdlog]
|
||||
//! * [systemd-journal-logger]
|
||||
//! * [android_log]
|
||||
//! * [win_dbg_logger]
|
||||
//! * [db_logger]
|
||||
//! * For WebAssembly binaries:
|
||||
//! * [console_log]
|
||||
//! * For dynamic libraries:
|
||||
//! * You may need to construct an FFI-safe wrapper over `log` to initialize in your libraries
|
||||
//!
|
||||
//! # Implementing a Logger
|
||||
//!
|
||||
@ -306,18 +262,14 @@
|
||||
//! [slog-stdlog]: https://docs.rs/slog-stdlog/*/slog_stdlog/
|
||||
//! [log4rs]: https://docs.rs/log4rs/*/log4rs/
|
||||
//! [fern]: https://docs.rs/fern/*/fern/
|
||||
//! [systemd-journal-logger]: https://docs.rs/systemd-journal-logger/*/systemd_journal_logger/
|
||||
//! [android_log]: https://docs.rs/android_log/*/android_log/
|
||||
//! [win_dbg_logger]: https://docs.rs/win_dbg_logger/*/win_dbg_logger/
|
||||
//! [console_log]: https://docs.rs/console_log/*/console_log/
|
||||
|
||||
#![doc(
|
||||
html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
||||
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
|
||||
html_root_url = "https://docs.rs/log/0.4.17"
|
||||
html_root_url = "https://docs.rs/log/0.4.14"
|
||||
)]
|
||||
#![warn(missing_docs)]
|
||||
#![deny(missing_debug_implementations, unconditional_recursion)]
|
||||
#![deny(missing_debug_implementations)]
|
||||
#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
|
||||
// When compiled for the rustc compiler itself we want to make sure that this is
|
||||
// an unstable crate
|
||||
@ -608,24 +560,6 @@ impl Level {
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
LOG_LEVEL_NAMES[*self as usize]
|
||||
}
|
||||
|
||||
/// Iterate through all supported logging levels.
|
||||
///
|
||||
/// The order of iteration is from more severe to less severe log messages.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use log::Level;
|
||||
///
|
||||
/// let mut levels = Level::iter();
|
||||
///
|
||||
/// assert_eq!(Some(Level::Error), levels.next());
|
||||
/// assert_eq!(Some(Level::Trace), levels.last());
|
||||
/// ```
|
||||
pub fn iter() -> impl Iterator<Item = Self> {
|
||||
(1..6).map(|i| Self::from_usize(i).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
/// An enum representing the available verbosity level filters of the logger.
|
||||
@ -768,7 +702,6 @@ impl LevelFilter {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the most verbose logging level filter.
|
||||
#[inline]
|
||||
pub fn max() -> LevelFilter {
|
||||
@ -789,24 +722,6 @@ impl LevelFilter {
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
LOG_LEVEL_NAMES[*self as usize]
|
||||
}
|
||||
|
||||
/// Iterate through all supported filtering levels.
|
||||
///
|
||||
/// The order of iteration is from less to more verbose filtering.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use log::LevelFilter;
|
||||
///
|
||||
/// let mut levels = LevelFilter::iter();
|
||||
///
|
||||
/// assert_eq!(Some(LevelFilter::Off), levels.next());
|
||||
/// assert_eq!(Some(LevelFilter::Trace), levels.last());
|
||||
/// ```
|
||||
pub fn iter() -> impl Iterator<Item = Self> {
|
||||
(0..6).map(|i| Self::from_usize(i).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
|
||||
@ -965,7 +880,7 @@ impl<'a> Record<'a> {
|
||||
self.line
|
||||
}
|
||||
|
||||
/// The structured key-value pairs associated with the message.
|
||||
/// The structued key-value pairs associated with the message.
|
||||
#[cfg(feature = "kv_unstable")]
|
||||
#[inline]
|
||||
pub fn key_values(&self) -> &dyn kv::Source {
|
||||
@ -1000,6 +915,7 @@ impl<'a> Record<'a> {
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
///
|
||||
/// ```edition2018
|
||||
/// use log::{Level, Record};
|
||||
///
|
||||
@ -1273,18 +1189,10 @@ pub trait Log: Sync + Send {
|
||||
/// This is used by the `log_enabled!` macro to allow callers to avoid
|
||||
/// expensive computation of log message arguments if the message would be
|
||||
/// discarded anyway.
|
||||
///
|
||||
/// # For implementors
|
||||
///
|
||||
/// This method isn't called automatically by the `log!` macros.
|
||||
/// It's up to an implementation of the `Log` trait to call `enabled` in its own
|
||||
/// `log` method implementation to guarantee that filtering is applied.
|
||||
fn enabled(&self, metadata: &Metadata) -> bool;
|
||||
|
||||
/// Logs the `Record`.
|
||||
///
|
||||
/// # For implementors
|
||||
///
|
||||
/// Note that `enabled` is *not* necessarily called before this method.
|
||||
/// Implementations of `log` should perform all necessary filtering
|
||||
/// internally.
|
||||
@ -1306,22 +1214,6 @@ impl Log for NopLogger {
|
||||
fn flush(&self) {}
|
||||
}
|
||||
|
||||
impl<T> Log for &'_ T
|
||||
where
|
||||
T: ?Sized + Log,
|
||||
{
|
||||
fn enabled(&self, metadata: &Metadata) -> bool {
|
||||
(**self).enabled(metadata)
|
||||
}
|
||||
|
||||
fn log(&self, record: &Record) {
|
||||
(**self).log(record)
|
||||
}
|
||||
fn flush(&self) {
|
||||
(**self).flush()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T> Log for std::boxed::Box<T>
|
||||
where
|
||||
@ -1339,31 +1231,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T> Log for std::sync::Arc<T>
|
||||
where
|
||||
T: ?Sized + Log,
|
||||
{
|
||||
fn enabled(&self, metadata: &Metadata) -> bool {
|
||||
self.as_ref().enabled(metadata)
|
||||
}
|
||||
|
||||
fn log(&self, record: &Record) {
|
||||
self.as_ref().log(record)
|
||||
}
|
||||
fn flush(&self) {
|
||||
self.as_ref().flush()
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the global maximum log level.
|
||||
///
|
||||
/// Generally, this should only be called by the active logging implementation.
|
||||
///
|
||||
/// Note that `Trace` is the maximum level, because it provides the maximum amount of detail in the emitted logs.
|
||||
#[inline]
|
||||
pub fn set_max_level(level: LevelFilter) {
|
||||
MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::Relaxed)
|
||||
MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::SeqCst)
|
||||
}
|
||||
|
||||
/// Returns the current maximum log level.
|
||||
@ -1489,8 +1362,6 @@ where
|
||||
}
|
||||
INITIALIZING => {
|
||||
while STATE.load(Ordering::SeqCst) == INITIALIZING {
|
||||
// TODO: replace with `hint::spin_loop` once MSRV is 1.49.0.
|
||||
#[allow(deprecated)]
|
||||
std::sync::atomic::spin_loop_hint();
|
||||
}
|
||||
Err(SetLoggerError(()))
|
||||
@ -1581,39 +1452,10 @@ pub fn logger() -> &'static dyn Log {
|
||||
|
||||
// WARNING: this is not part of the crate's public API and is subject to change at any time
|
||||
#[doc(hidden)]
|
||||
#[cfg(not(feature = "kv_unstable"))]
|
||||
pub fn __private_api_log(
|
||||
args: fmt::Arguments,
|
||||
level: Level,
|
||||
&(target, module_path, file, line): &(&str, &'static str, &'static str, u32),
|
||||
kvs: Option<&[(&str, &str)]>,
|
||||
) {
|
||||
if kvs.is_some() {
|
||||
panic!(
|
||||
"key-value support is experimental and must be enabled using the `kv_unstable` feature"
|
||||
)
|
||||
}
|
||||
|
||||
logger().log(
|
||||
&Record::builder()
|
||||
.args(args)
|
||||
.level(level)
|
||||
.target(target)
|
||||
.module_path_static(Some(module_path))
|
||||
.file_static(Some(file))
|
||||
.line(Some(line))
|
||||
.build(),
|
||||
);
|
||||
}
|
||||
|
||||
// WARNING: this is not part of the crate's public API and is subject to change at any time
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "kv_unstable")]
|
||||
pub fn __private_api_log(
|
||||
args: fmt::Arguments,
|
||||
level: Level,
|
||||
&(target, module_path, file, line): &(&str, &'static str, &'static str, u32),
|
||||
kvs: Option<&[(&str, &dyn kv::ToValue)]>,
|
||||
) {
|
||||
logger().log(
|
||||
&Record::builder()
|
||||
@ -1623,7 +1465,6 @@ pub fn __private_api_log(
|
||||
.module_path_static(Some(module_path))
|
||||
.file_static(Some(file))
|
||||
.line(Some(line))
|
||||
.key_values(&kvs)
|
||||
.build(),
|
||||
);
|
||||
}
|
||||
@ -1634,12 +1475,6 @@ pub fn __private_api_enabled(level: Level, target: &str) -> bool {
|
||||
logger().enabled(&Metadata::builder().level(level).target(target).build())
|
||||
}
|
||||
|
||||
// WARNING: this is not part of the crate's public API and is subject to change at any time
|
||||
#[doc(hidden)]
|
||||
pub mod __private_api {
|
||||
pub use std::option::Option;
|
||||
}
|
||||
|
||||
/// The statically resolved maximum log level.
|
||||
///
|
||||
/// See the crate level documentation for information on how to configure this.
|
||||
@ -1937,35 +1772,4 @@ mod tests {
|
||||
.expect("invalid value")
|
||||
);
|
||||
}
|
||||
|
||||
// Test that the `impl Log for Foo` blocks work
|
||||
// This test mostly operates on a type level, so failures will be compile errors
|
||||
#[test]
|
||||
fn test_foreign_impl() {
|
||||
use super::Log;
|
||||
#[cfg(feature = "std")]
|
||||
use std::sync::Arc;
|
||||
|
||||
fn assert_is_log<T: Log + ?Sized>() {}
|
||||
|
||||
assert_is_log::<&dyn Log>();
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
assert_is_log::<Box<dyn Log>>();
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
assert_is_log::<Arc<dyn Log>>();
|
||||
|
||||
// Assert these statements for all T: Log + ?Sized
|
||||
#[allow(unused)]
|
||||
fn forall<T: Log + ?Sized>() {
|
||||
#[cfg(feature = "std")]
|
||||
assert_is_log::<Box<T>>();
|
||||
|
||||
assert_is_log::<&T>();
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
assert_is_log::<Arc<T>>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
92
third_party/rust/log/src/macros.rs
vendored
92
third_party/rust/log/src/macros.rs
vendored
@ -29,20 +29,6 @@
|
||||
/// ```
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! log {
|
||||
// log!(target: "my_target", Level::Info; key1 = 42, key2 = true; "a {} event", "log");
|
||||
(target: $target:expr, $lvl:expr, $($key:tt = $value:expr),+; $($arg:tt)+) => ({
|
||||
let lvl = $lvl;
|
||||
if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() {
|
||||
$crate::__private_api_log(
|
||||
__log_format_args!($($arg)+),
|
||||
lvl,
|
||||
&($target, __log_module_path!(), __log_file!(), __log_line!()),
|
||||
$crate::__private_api::Option::Some(&[$((__log_key!($key), &$value)),+])
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// log!(target: "my_target", Level::Info; "a {} event", "log");
|
||||
(target: $target:expr, $lvl:expr, $($arg:tt)+) => ({
|
||||
let lvl = $lvl;
|
||||
if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() {
|
||||
@ -50,13 +36,10 @@ macro_rules! log {
|
||||
__log_format_args!($($arg)+),
|
||||
lvl,
|
||||
&($target, __log_module_path!(), __log_file!(), __log_line!()),
|
||||
$crate::__private_api::Option::None,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// log!(Level::Info, "a log event")
|
||||
($lvl:expr, $($arg:tt)+) => (log!(target: __log_module_path!(), $lvl, $($arg)+));
|
||||
($lvl:expr, $($arg:tt)+) => (log!(target: __log_module_path!(), $lvl, $($arg)+))
|
||||
}
|
||||
|
||||
/// Logs a message at the error level.
|
||||
@ -75,12 +58,12 @@ macro_rules! log {
|
||||
/// ```
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! error {
|
||||
// error!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log")
|
||||
// error!(target: "my_target", "a {} event", "log")
|
||||
(target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Error, $($arg)+));
|
||||
|
||||
// error!("a {} event", "log")
|
||||
($($arg:tt)+) => (log!($crate::Level::Error, $($arg)+))
|
||||
(target: $target:expr, $($arg:tt)+) => (
|
||||
log!(target: $target, $crate::Level::Error, $($arg)+)
|
||||
);
|
||||
($($arg:tt)+) => (
|
||||
log!($crate::Level::Error, $($arg)+)
|
||||
)
|
||||
}
|
||||
|
||||
/// Logs a message at the warn level.
|
||||
@ -99,12 +82,12 @@ macro_rules! error {
|
||||
/// ```
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! warn {
|
||||
// warn!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log")
|
||||
// warn!(target: "my_target", "a {} event", "log")
|
||||
(target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Warn, $($arg)+));
|
||||
|
||||
// warn!("a {} event", "log")
|
||||
($($arg:tt)+) => (log!($crate::Level::Warn, $($arg)+))
|
||||
(target: $target:expr, $($arg:tt)+) => (
|
||||
log!(target: $target, $crate::Level::Warn, $($arg)+)
|
||||
);
|
||||
($($arg:tt)+) => (
|
||||
log!($crate::Level::Warn, $($arg)+)
|
||||
)
|
||||
}
|
||||
|
||||
/// Logs a message at the info level.
|
||||
@ -125,12 +108,12 @@ macro_rules! warn {
|
||||
/// ```
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! info {
|
||||
// info!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log")
|
||||
// info!(target: "my_target", "a {} event", "log")
|
||||
(target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Info, $($arg)+));
|
||||
|
||||
// info!("a {} event", "log")
|
||||
($($arg:tt)+) => (log!($crate::Level::Info, $($arg)+))
|
||||
(target: $target:expr, $($arg:tt)+) => (
|
||||
log!(target: $target, $crate::Level::Info, $($arg)+)
|
||||
);
|
||||
($($arg:tt)+) => (
|
||||
log!($crate::Level::Info, $($arg)+)
|
||||
)
|
||||
}
|
||||
|
||||
/// Logs a message at the debug level.
|
||||
@ -150,12 +133,12 @@ macro_rules! info {
|
||||
/// ```
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! debug {
|
||||
// debug!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log")
|
||||
// debug!(target: "my_target", "a {} event", "log")
|
||||
(target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Debug, $($arg)+));
|
||||
|
||||
// debug!("a {} event", "log")
|
||||
($($arg:tt)+) => (log!($crate::Level::Debug, $($arg)+))
|
||||
(target: $target:expr, $($arg:tt)+) => (
|
||||
log!(target: $target, $crate::Level::Debug, $($arg)+)
|
||||
);
|
||||
($($arg:tt)+) => (
|
||||
log!($crate::Level::Debug, $($arg)+)
|
||||
)
|
||||
}
|
||||
|
||||
/// Logs a message at the trace level.
|
||||
@ -177,12 +160,12 @@ macro_rules! debug {
|
||||
/// ```
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! trace {
|
||||
// trace!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log")
|
||||
// trace!(target: "my_target", "a {} event", "log")
|
||||
(target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Trace, $($arg)+));
|
||||
|
||||
// trace!("a {} event", "log")
|
||||
($($arg:tt)+) => (log!($crate::Level::Trace, $($arg)+))
|
||||
(target: $target:expr, $($arg:tt)+) => (
|
||||
log!(target: $target, $crate::Level::Trace, $($arg)+)
|
||||
);
|
||||
($($arg:tt)+) => (
|
||||
log!($crate::Level::Trace, $($arg)+)
|
||||
)
|
||||
}
|
||||
|
||||
/// Determines if a message logged at the specified level in that module will
|
||||
@ -265,16 +248,3 @@ macro_rules! __log_line {
|
||||
line!()
|
||||
};
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! __log_key {
|
||||
// key1 = 42
|
||||
($($args:ident)*) => {
|
||||
stringify!($($args)*)
|
||||
};
|
||||
// "key1" = 42
|
||||
($($args:expr)*) => {
|
||||
$($args)*
|
||||
};
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"3509b10365d7049c8cce1652272706091dd192cde27d8cb6fa029e46fec8e7c1","build.rs":"a17b1bb1bd3de3fc958f72d4d1357f7bc4432faa26640c95b5fbfccf40579d67","src/codec.rs":"18b1ed94cfd66e29f847b66c73836dfb5be99b3f8a9f40b082acc364f5198743","src/datagram.rs":"569f8d9e34d7ee17144bf63d34136ecd9778da0d337e513f338738c50284615e","src/event.rs":"f60fee9f4b09ef47ff5e4bfa21c07e45ffd5873c292f2605f24d834070127d62","src/header.rs":"b7d4eeb40952b36f71ae1f37ce82c9617af8b84c171576de4eca9d50a3071103","src/hrtime.rs":"c5f9f65a642b5782589a4caaf1e758845daa7ebf56c58dc9ef9f836e48026d29","src/incrdecoder.rs":"458f0228e41018d58f5a83c7895c9ea283f310fcb91c969e22026eb8ca3c84c9","src/lib.rs":"0a3679ab0bc67817097701010881e1c2f48ad1ab0700f12babc46cc59c5c788b","src/log.rs":"f3fb6a1b269a9745b18893a5b31645e541c525f4197cdeec5e9e88abb42c994e","src/qlog.rs":"ca323c91d61810ebef2ebeb967836dda384a60a9fb492c2b8d1b235a98f2e4bf","src/timer.rs":"e63af7e7df968bf702583f263cfb63e6dca4e599bacffa2de0a6383d85333636","tests/log.rs":"480b165b7907ec642c508b303d63005eee1427115d6973a349eaf6b2242ed18d"},"package":null}
|
||||
{"files":{"Cargo.toml":"9013a62945e20404cfc3624df017feeb3b86e096b6882b0fd2254c4e87d24b6b","build.rs":"a17b1bb1bd3de3fc958f72d4d1357f7bc4432faa26640c95b5fbfccf40579d67","src/codec.rs":"876fe7da558964046765aa2a2d7ebad9d53e1d4b31a1bf233d47b939f417dba1","src/datagram.rs":"569f8d9e34d7ee17144bf63d34136ecd9778da0d337e513f338738c50284615e","src/event.rs":"f60fee9f4b09ef47ff5e4bfa21c07e45ffd5873c292f2605f24d834070127d62","src/header.rs":"b7d4eeb40952b36f71ae1f37ce82c9617af8b84c171576de4eca9d50a3071103","src/hrtime.rs":"45a608ce9f00e2666ce95422a278c6dc0ff4e229b114e7bcf0b4c0d9dc61ad56","src/incrdecoder.rs":"97eb93502afabf13d46de37ca05430c49e876bfa9f013ce264231639eaf9df64","src/lib.rs":"0a3679ab0bc67817097701010881e1c2f48ad1ab0700f12babc46cc59c5c788b","src/log.rs":"b69e492af85e65866cb6588138e8a337dd897d3ce399cb4e9fb8cc04ac042b7f","src/qlog.rs":"ca323c91d61810ebef2ebeb967836dda384a60a9fb492c2b8d1b235a98f2e4bf","src/timer.rs":"e63af7e7df968bf702583f263cfb63e6dca4e599bacffa2de0a6383d85333636","tests/log.rs":"480b165b7907ec642c508b303d63005eee1427115d6973a349eaf6b2242ed18d"},"package":null}
|
5
third_party/rust/neqo-common/Cargo.toml
vendored
5
third_party/rust/neqo-common/Cargo.toml
vendored
@ -1,14 +1,13 @@
|
||||
[package]
|
||||
name = "neqo-common"
|
||||
version = "0.6.0"
|
||||
version = "0.5.7"
|
||||
authors = ["Bobby Holley <bobbyholley@gmail.com>"]
|
||||
edition = "2018"
|
||||
rust-version = "1.57.0"
|
||||
license = "MIT/Apache-2.0"
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
log = {version = "0.4.16", default-features = false}
|
||||
log = {version = "0.4.0", default-features = false}
|
||||
env_logger = {version = "0.8", default-features = false}
|
||||
lazy_static = "1.3.0"
|
||||
qlog = "0.4.0"
|
||||
|
62
third_party/rust/neqo-common/src/codec.rs
vendored
62
third_party/rust/neqo-common/src/codec.rs
vendored
@ -6,6 +6,7 @@
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt::Debug;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use crate::hex_with_len;
|
||||
|
||||
@ -158,18 +159,18 @@ impl<'a> Decoder<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// Implement `AsRef` for `Decoder` so that values can be examined without
|
||||
// moving the cursor.
|
||||
impl<'a> AsRef<[u8]> for Decoder<'a> {
|
||||
// Implement `Deref` for `Decoder` so that values can be examined without moving the cursor.
|
||||
impl<'a> Deref for Decoder<'a> {
|
||||
type Target = [u8];
|
||||
#[must_use]
|
||||
fn as_ref(&self) -> &'a [u8] {
|
||||
fn deref(&self) -> &[u8] {
|
||||
&self.buf[self.offset..]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Debug for Decoder<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
f.write_str(&hex_with_len(self.as_ref()))
|
||||
f.write_str(&hex_with_len(&self[..]))
|
||||
}
|
||||
}
|
||||
|
||||
@ -247,24 +248,11 @@ impl Encoder {
|
||||
self.buf.capacity()
|
||||
}
|
||||
|
||||
/// Get the length of the underlying buffer: the number of bytes that have
|
||||
/// been written to the buffer.
|
||||
#[must_use]
|
||||
pub fn len(&self) -> usize {
|
||||
self.buf.len()
|
||||
}
|
||||
|
||||
/// Returns true if the encoder buffer contains no elements.
|
||||
#[must_use]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.buf.is_empty()
|
||||
}
|
||||
|
||||
/// Create a view of the current contents of the buffer.
|
||||
/// Note: for a view of a slice, use `Decoder::new(&enc[s..e])`
|
||||
#[must_use]
|
||||
pub fn as_decoder(&self) -> Decoder {
|
||||
Decoder::new(self.as_ref())
|
||||
Decoder::new(self)
|
||||
}
|
||||
|
||||
/// Don't use this except in testing.
|
||||
@ -287,7 +275,7 @@ impl Encoder {
|
||||
|
||||
/// Generic encode routine for arbitrary data.
|
||||
pub fn encode(&mut self, data: &[u8]) -> &mut Self {
|
||||
self.buf.extend_from_slice(data.as_ref());
|
||||
self.buf.extend_from_slice(data);
|
||||
self
|
||||
}
|
||||
|
||||
@ -329,7 +317,7 @@ impl Encoder {
|
||||
/// # Panics
|
||||
/// When `v` is longer than 2^64.
|
||||
pub fn encode_vec(&mut self, n: usize, v: &[u8]) -> &mut Self {
|
||||
self.encode_uint(n, u64::try_from(v.as_ref().len()).unwrap())
|
||||
self.encode_uint(n, u64::try_from(v.len()).unwrap())
|
||||
.encode(v)
|
||||
}
|
||||
|
||||
@ -353,7 +341,7 @@ impl Encoder {
|
||||
/// # Panics
|
||||
/// When `v` is longer than 2^64.
|
||||
pub fn encode_vvec(&mut self, v: &[u8]) -> &mut Self {
|
||||
self.encode_varint(u64::try_from(v.as_ref().len()).unwrap())
|
||||
self.encode_varint(u64::try_from(v.len()).unwrap())
|
||||
.encode(v)
|
||||
}
|
||||
|
||||
@ -423,12 +411,6 @@ impl AsRef<[u8]> for Encoder {
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<[u8]> for Encoder {
|
||||
fn as_mut(&mut self) -> &mut [u8] {
|
||||
self.buf.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Decoder<'a>> for Encoder {
|
||||
#[must_use]
|
||||
fn from(dec: Decoder<'a>) -> Self {
|
||||
@ -452,6 +434,20 @@ impl From<Encoder> for Vec<u8> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Encoder {
|
||||
type Target = [u8];
|
||||
#[must_use]
|
||||
fn deref(&self) -> &[u8] {
|
||||
&self.buf[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Encoder {
|
||||
fn deref_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.buf[..]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Decoder, Encoder};
|
||||
@ -753,7 +749,7 @@ mod tests {
|
||||
fn encode_vec_with() {
|
||||
let mut enc = Encoder::default();
|
||||
enc.encode_vec_with(2, |enc_inner| {
|
||||
enc_inner.encode(Encoder::from_hex("02").as_ref());
|
||||
enc_inner.encode(&Encoder::from_hex("02"));
|
||||
});
|
||||
assert_eq!(enc, Encoder::from_hex("000102"));
|
||||
}
|
||||
@ -778,7 +774,7 @@ mod tests {
|
||||
fn encode_vvec_with() {
|
||||
let mut enc = Encoder::default();
|
||||
enc.encode_vvec_with(|enc_inner| {
|
||||
enc_inner.encode(Encoder::from_hex("02").as_ref());
|
||||
enc_inner.encode(&Encoder::from_hex("02"));
|
||||
});
|
||||
assert_eq!(enc, Encoder::from_hex("0102"));
|
||||
}
|
||||
@ -798,7 +794,7 @@ mod tests {
|
||||
fn encode_builder() {
|
||||
let mut enc = Encoder::from_hex("ff");
|
||||
let enc2 = Encoder::from_hex("010234");
|
||||
enc.encode(enc2.as_ref());
|
||||
enc.encode(&enc2);
|
||||
assert_eq!(enc, Encoder::from_hex("ff010234"));
|
||||
}
|
||||
|
||||
@ -808,14 +804,14 @@ mod tests {
|
||||
let mut enc = Encoder::from_hex("ff");
|
||||
let enc2 = Encoder::from_hex("010234");
|
||||
let v = enc2.as_decoder();
|
||||
enc.encode(v.as_ref());
|
||||
enc.encode(&v);
|
||||
assert_eq!(enc, Encoder::from_hex("ff010234"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_mutate() {
|
||||
let mut enc = Encoder::from_hex("010234");
|
||||
enc.as_mut()[0] = 0xff;
|
||||
enc[0] = 0xff;
|
||||
assert_eq!(enc, Encoder::from_hex("ff0234"));
|
||||
}
|
||||
|
||||
|
5
third_party/rust/neqo-common/src/hrtime.rs
vendored
5
third_party/rust/neqo-common/src/hrtime.rs
vendored
@ -82,7 +82,6 @@ impl PeriodSet {
|
||||
#[allow(non_camel_case_types)]
|
||||
mod mac {
|
||||
use std::mem::size_of;
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
// These are manually extracted from the many bindings generated
|
||||
// by bindgen when provided with the simple header:
|
||||
@ -163,7 +162,7 @@ mod mac {
|
||||
thread_policy_set(
|
||||
pthread_mach_thread_np(pthread_self()),
|
||||
THREAD_TIME_CONSTRAINT_POLICY,
|
||||
addr_of_mut!(policy) as _, // horror!
|
||||
&mut policy as *mut thread_time_constraint_policy as *mut _,
|
||||
THREAD_TIME_CONSTRAINT_POLICY_COUNT,
|
||||
)
|
||||
};
|
||||
@ -198,7 +197,7 @@ mod mac {
|
||||
thread_policy_get(
|
||||
pthread_mach_thread_np(pthread_self()),
|
||||
THREAD_TIME_CONSTRAINT_POLICY,
|
||||
addr_of_mut!(policy) as _, // horror!
|
||||
&mut policy as *mut thread_time_constraint_policy as *mut _,
|
||||
&mut count,
|
||||
&mut get_default,
|
||||
)
|
||||
|
10
third_party/rust/neqo-common/src/incrdecoder.rs
vendored
10
third_party/rust/neqo-common/src/incrdecoder.rs
vendored
@ -178,7 +178,7 @@ mod tests {
|
||||
|
||||
for tail in 1..db.len() {
|
||||
let split = db.len() - tail;
|
||||
let mut dv = Decoder::from(&db.as_ref()[0..split]);
|
||||
let mut dv = Decoder::from(&db[0..split]);
|
||||
eprintln!(" split at {}: {:?}", split, dv);
|
||||
|
||||
// Clone the basic decoder for each iteration of the loop.
|
||||
@ -192,7 +192,7 @@ mod tests {
|
||||
if tail > 1 {
|
||||
assert_eq!(res, None);
|
||||
assert!(dec.min_remaining() > 0);
|
||||
let mut dv = Decoder::from(&db.as_ref()[split..]);
|
||||
let mut dv = Decoder::from(&db[split..]);
|
||||
eprintln!(" split remainder {}: {:?}", split, dv);
|
||||
res = dec.consume(&mut dv);
|
||||
assert_eq!(dv.remaining(), 1);
|
||||
@ -230,7 +230,7 @@ mod tests {
|
||||
#[test]
|
||||
fn zero_len() {
|
||||
let enc = Encoder::from_hex("ff");
|
||||
let mut dec = Decoder::new(enc.as_ref());
|
||||
let mut dec = Decoder::new(&enc);
|
||||
let mut incr = IncrementalDecoderBuffer::new(0);
|
||||
assert_eq!(incr.consume(&mut dec), Some(Vec::new()));
|
||||
assert_eq!(dec.remaining(), enc.len());
|
||||
@ -244,7 +244,7 @@ mod tests {
|
||||
|
||||
for tail in 1..db.len() {
|
||||
let split = db.len() - tail;
|
||||
let mut dv = Decoder::from(&db.as_ref()[0..split]);
|
||||
let mut dv = Decoder::from(&db[0..split]);
|
||||
eprintln!(" split at {}: {:?}", split, dv);
|
||||
|
||||
// Clone the basic decoder for each iteration of the loop.
|
||||
@ -256,7 +256,7 @@ mod tests {
|
||||
if tail > 1 {
|
||||
assert!(!res);
|
||||
assert!(dec.min_remaining() > 0);
|
||||
let mut dv = Decoder::from(&db.as_ref()[split..]);
|
||||
let mut dv = Decoder::from(&db[split..]);
|
||||
eprintln!(" split remainder {}: {:?}", split, dv);
|
||||
res = dec.consume(&mut dv);
|
||||
assert_eq!(dv.remaining(), 1);
|
||||
|
1
third_party/rust/neqo-common/src/log.rs
vendored
1
third_party/rust/neqo-common/src/log.rs
vendored
@ -17,7 +17,6 @@ macro_rules! do_log {
|
||||
::log::__log_format_args!($($arg)+),
|
||||
lvl,
|
||||
&($target, ::log::__log_module_path!(), ::log::__log_file!(), ::log::__log_line!()),
|
||||
None,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"622b21547b8323877a40dc2661e95b330aee84c0f038a5f28ec3c6dc65f04388","TODO":"ac0f1c2ebcca03f5b3c0cc56c5aedbb030a4b511e438bc07a57361c789f91e9f","bindings/bindings.toml":"cb3e29ac6d1fd7083ffab81494afe1b9a2d9e41c60774438fd9681974c87c252","bindings/mozpkix.hpp":"77072c8bb0f6eb6bfe8cbadc111dcd92e0c79936d13f2e501aae1e5d289a6675","bindings/nspr_err.h":"2d5205d017b536c2d838bcf9bc4ec79f96dd50e7bb9b73892328781f1ee6629d","bindings/nspr_error.h":"e41c03c77b8c22046f8618832c9569fbcc7b26d8b9bbc35eea7168f35e346889","bindings/nspr_io.h":"085b289849ef0e77f88512a27b4d9bdc28252bd4d39c6a17303204e46ef45f72","bindings/nspr_time.h":"2e637fd338a5cf0fd3fb0070a47f474a34c2a7f4447f31b6875f5a9928d0a261","bindings/nss_ciphers.h":"95ec6344a607558b3c5ba8510f463b6295f3a2fb3f538a01410531045a5f62d1","bindings/nss_init.h":"ef49045063782fb612aff459172cc6a89340f15005808608ade5320ca9974310","bindings/nss_p11.h":"0b81e64fe6db49b2ecff94edd850be111ef99ec11220e88ceb1c67be90143a78","bindings/nss_secerr.h":"713e8368bdae5159af7893cfa517dabfe5103cede051dee9c9557c850a2defc6","bindings/nss_ssl.h":"af222fb957b989e392e762fa2125c82608a0053aff4fb97e556691646c88c335","bindings/nss_sslerr.h":"24b97f092183d8486f774cdaef5030d0249221c78343570d83a4ee5b594210ae","bindings/nss_sslopt.h":"b7807eb7abdad14db6ad7bc51048a46b065a0ea65a4508c95a12ce90e59d1eea","build.rs":"99df86d0c11da5a8cbcc3be2560e6d764234a21b5d9b5f7ab1b70696e4f8670e","src/aead.rs":"140f77ffb5016836c970c39c6c3a42db9581a14b797b9cd05386d0dd0831fe63","src/aead_fuzzing.rs":"4e60d5a2ee6dedfd08602fa36318239e731244825df2cb801ca1d88f5f2a41c1","src/agent.rs":"392ec3a815114c1d83510cf6b4941d3dd427dc69f5ac1a92ab8bf0249aa67fff","src/agentio.rs":"bce4c3dfcfa433209a409ac0c0752f8c95ab37bb6239a42f99b83858e8747bd1","src/auth.rs":"e821dac1511691151a6e64b7c7130a07d941dffad4529b2631f20ddd07d3f20c","src/cert.rs":"628fc2384cdeb2a32bfbecb83c99af393df97fd6a76c6e8827e8240c0d47328b","src/constants.rs":"998e77bee88197a240032c1bfbddcff417a25ba82e576a0d2fe18ee9b63cefc7","src/ech.rs":"447f6297f50914249d0c92ec61d74df6c65ce4affceecb8cafe40927e855fe1d","src/err.rs":"f2cc71de2b40d7bba8119eeaee200337db9a0126176ba06e4902d7312facdb58","src/exp.rs":"61586662407359c1ecb8ed4987bc3c702f26ba2e203a091a51b6d6363cbd510f","src/ext.rs":"361277879194dc32f741b8d1894afe5fd3fcc8eb244f7dd5914eeb959b85717d","src/hkdf.rs":"3ff432cc9d40e1dc56e9f983b54b593647c4063a5ae0f16de0a64d033ac9bd94","src/hp.rs":"722a798a7d280b66bd0f8adc6f9135f7d8130f7f0ef45ea12b85d47a88adefda","src/lib.rs":"8d1bfe33999b20eeb5f7eef70d4c634de560de5376029f81b2412bca60176c39","src/once.rs":"b9850384899a1a016e839743d3489c0d4d916e1973746ef8c89872105d7d9736","src/p11.rs":"2ff35a2512bcf894684f24b94640e7fe9d4df6a20264aa3714f2f02fdb99e73d","src/prio.rs":"d9bd43a4d84db70fd552239d0852ea60b960957912f614b929d27dadccca803a","src/replay.rs":"c9bc0261fe1ae22e7212774c315a2669784e57762ca975a15250d4a33dbf3ea3","src/result.rs":"cef34dfcb907723e195b56501132e4560e250b327783cb5e41201da5b63e9b5c","src/secrets.rs":"d5d98e34b100568fecade932832379c52530c70a51ad2d37ee6b2dd008865f01","src/selfencrypt.rs":"f11ae7f6f1e6b602b6e729d71597116fb172190b57102af4f76b22fbe78c8b6a","src/ssl.rs":"ace1a162c3b189d52b5e5f9827c4300b7d47d3b2ae29a976d3bbc46c52328253","src/time.rs":"7ea035bb261665c50920ba3dfaaf2582caf5bf3a3464c49b251d15cc39154dc0","tests/aead.rs":"31b5b4374cc5ca2deee6267c4d5b4858defc74e694ec85af196339a76548a17c","tests/agent.rs":"94819f9eeba2afa0c25adc821755900f1488fd47af6d84d9507a112c29d1752a","tests/ext.rs":"eba9f03accdd598e38292ac88263a81b367d60d5a736a43117a3663de105ec48","tests/handshake.rs":"0fcfa8958686aacb42c56c51c6b234842fe990470d2069a67509869baaa18452","tests/hkdf.rs":"47830c1ea58a02d100522bdde6fabc02bb447ccb85affa0cdc44bc25da1be32a","tests/hp.rs":"316973740210fc1f8166920582795a41347a0aec9024fdc480e2ee83a7a5332d","tests/init.rs":"fc9e392b1efa0d8efb28952f73ffc05e5348e7b2b69207b60e375c3888a252a2","tests/selfencrypt.rs":"1125c858ec4e0a6994f34d162aa066cb003c61b324f268529ea04bcb641347cb"},"package":null}
|
||||
{"files":{"Cargo.toml":"561d34c14380159b08a88a2461a31355e63fbf410725dd28a12bbb3769596675","TODO":"ac0f1c2ebcca03f5b3c0cc56c5aedbb030a4b511e438bc07a57361c789f91e9f","bindings/bindings.toml":"d136f82a333b0ee1499e7858fdfc3d630f7ff37501a3c51028a4eeb7e2f136b4","bindings/mozpkix.hpp":"77072c8bb0f6eb6bfe8cbadc111dcd92e0c79936d13f2e501aae1e5d289a6675","bindings/nspr_err.h":"2d5205d017b536c2d838bcf9bc4ec79f96dd50e7bb9b73892328781f1ee6629d","bindings/nspr_error.h":"e41c03c77b8c22046f8618832c9569fbcc7b26d8b9bbc35eea7168f35e346889","bindings/nspr_io.h":"085b289849ef0e77f88512a27b4d9bdc28252bd4d39c6a17303204e46ef45f72","bindings/nspr_time.h":"2e637fd338a5cf0fd3fb0070a47f474a34c2a7f4447f31b6875f5a9928d0a261","bindings/nss_ciphers.h":"95ec6344a607558b3c5ba8510f463b6295f3a2fb3f538a01410531045a5f62d1","bindings/nss_init.h":"ef49045063782fb612aff459172cc6a89340f15005808608ade5320ca9974310","bindings/nss_p11.h":"0b81e64fe6db49b2ecff94edd850be111ef99ec11220e88ceb1c67be90143a78","bindings/nss_secerr.h":"713e8368bdae5159af7893cfa517dabfe5103cede051dee9c9557c850a2defc6","bindings/nss_ssl.h":"af222fb957b989e392e762fa2125c82608a0053aff4fb97e556691646c88c335","bindings/nss_sslerr.h":"24b97f092183d8486f774cdaef5030d0249221c78343570d83a4ee5b594210ae","bindings/nss_sslopt.h":"b7807eb7abdad14db6ad7bc51048a46b065a0ea65a4508c95a12ce90e59d1eea","build.rs":"659943cfae3c65be50e92d4b5b499c4580b4c522e9905ba567b434c2081784bc","src/aead.rs":"140f77ffb5016836c970c39c6c3a42db9581a14b797b9cd05386d0dd0831fe63","src/aead_fuzzing.rs":"4e60d5a2ee6dedfd08602fa36318239e731244825df2cb801ca1d88f5f2a41c1","src/agent.rs":"5caad7dfe81b0afbadb4c12e46634961880d12daa4820d9adcfa84c240a36ac2","src/agentio.rs":"bce4c3dfcfa433209a409ac0c0752f8c95ab37bb6239a42f99b83858e8747bd1","src/auth.rs":"e821dac1511691151a6e64b7c7130a07d941dffad4529b2631f20ddd07d3f20c","src/cert.rs":"04d7328ab59a5268f2f48b3f880192bf28d42c09c362ef5906ee66e087c754d1","src/constants.rs":"998e77bee88197a240032c1bfbddcff417a25ba82e576a0d2fe18ee9b63cefc7","src/ech.rs":"1b6ee298855d34310a0d65367b21fdc38678a9c37fc7e1d9579c3c8dfd753377","src/err.rs":"d4dbe63e2faba3a1f08dca015549c32550cb18907592abc3831e05e330f0a93b","src/exp.rs":"61586662407359c1ecb8ed4987bc3c702f26ba2e203a091a51b6d6363cbd510f","src/ext.rs":"361277879194dc32f741b8d1894afe5fd3fcc8eb244f7dd5914eeb959b85717d","src/hkdf.rs":"3ff432cc9d40e1dc56e9f983b54b593647c4063a5ae0f16de0a64d033ac9bd94","src/hp.rs":"46a2023c421d89fda8d09b356b648272857fd20ee5cf5829143ac88402b32e4b","src/lib.rs":"db8cbe315dbfd32c187d63000b15a2fc758104b844714a96e47330bbf746be57","src/once.rs":"b9850384899a1a016e839743d3489c0d4d916e1973746ef8c89872105d7d9736","src/p11.rs":"ae054861719fdead8227220dd5a28b92882756683a436676470b672ee26b9a4e","src/prio.rs":"4224a65f25d7de9bf7d6cb18b15597a39650b3c4fcf7d184a4e4bd7f65cebccd","src/replay.rs":"c9bc0261fe1ae22e7212774c315a2669784e57762ca975a15250d4a33dbf3ea3","src/result.rs":"cef34dfcb907723e195b56501132e4560e250b327783cb5e41201da5b63e9b5c","src/secrets.rs":"48790a330994d892742048000bd12460b7eee2c3daaa444481b8527406d0a4c7","src/selfencrypt.rs":"4a9af42ccefbc77c65baedf00ef389de4fa7ed855d7ab3b60542b5931050667d","src/ssl.rs":"32e934e6dc5df4e4b4cbe96bae53921cf09a684959cb5ad3469cd65965f3164c","src/time.rs":"ddecb9f6cb6b3367852943d27fc89fd36d3c0ca0c9b5c9797494b74de2d8b5c7","tests/aead.rs":"a0fe826aa3bfcce22dbe1b06b74823cb2334331ffe6ce6152952613e9e1ccae5","tests/agent.rs":"94819f9eeba2afa0c25adc821755900f1488fd47af6d84d9507a112c29d1752a","tests/ext.rs":"eba9f03accdd598e38292ac88263a81b367d60d5a736a43117a3663de105ec48","tests/handshake.rs":"0fcfa8958686aacb42c56c51c6b234842fe990470d2069a67509869baaa18452","tests/hkdf.rs":"47830c1ea58a02d100522bdde6fabc02bb447ccb85affa0cdc44bc25da1be32a","tests/hp.rs":"92e062538c01fa7a474225714ed238d846ceb8c8feb9d79eb05be6111b00fb1e","tests/init.rs":"fc9e392b1efa0d8efb28952f73ffc05e5348e7b2b69207b60e375c3888a252a2","tests/selfencrypt.rs":"1125c858ec4e0a6994f34d162aa066cb003c61b324f268529ea04bcb641347cb"},"package":null}
|
5
third_party/rust/neqo-crypto/Cargo.toml
vendored
5
third_party/rust/neqo-crypto/Cargo.toml
vendored
@ -1,9 +1,8 @@
|
||||
[package]
|
||||
name = "neqo-crypto"
|
||||
version = "0.6.0"
|
||||
version = "0.5.7"
|
||||
authors = ["Martin Thomson <mt@lowentropy.net>"]
|
||||
edition = "2018"
|
||||
rust-version = "1.57.0"
|
||||
build = "build.rs"
|
||||
license = "MIT/Apache-2.0"
|
||||
|
||||
@ -12,7 +11,7 @@ neqo-common = { path = "../neqo-common" }
|
||||
log = {version = "0.4.0", default-features = false}
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = {version = "0.59", default-features = false, features= ["runtime"]}
|
||||
bindgen = {version = "0.56", default-features = false, features= ["runtime"]}
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
toml = "0.4"
|
||||
|
@ -137,7 +137,6 @@ variables = [
|
||||
types = [
|
||||
"CERTCertList",
|
||||
"CERTCertListNode",
|
||||
"CK_CHACHA20_PARAMS",
|
||||
"CK_ATTRIBUTE_TYPE",
|
||||
"CK_FLAGS",
|
||||
"CK_MECHANISM_TYPE",
|
||||
@ -151,9 +150,6 @@ functions = [
|
||||
"CERT_DestroyCertificate",
|
||||
"CERT_DestroyCertList",
|
||||
"CERT_GetCertificateDer",
|
||||
"PK11_CipherOp",
|
||||
"PK11_CreateContextBySymKey",
|
||||
"PK11_DestroyContext",
|
||||
"PK11_Encrypt",
|
||||
"PK11_ExtractKeyValue",
|
||||
"PK11_FindCertFromNickname",
|
||||
@ -188,7 +184,6 @@ enums = [
|
||||
]
|
||||
opaque = [
|
||||
"CERTCertificate",
|
||||
"PK11Context",
|
||||
"PK11SlotInfo",
|
||||
"PK11SymKey",
|
||||
"SECKEYPrivateKey",
|
||||
@ -196,16 +191,15 @@ opaque = [
|
||||
]
|
||||
variables = [
|
||||
"CKA_DERIVE",
|
||||
"CKA_ENCRYPT",
|
||||
"CKA_VALUE",
|
||||
"CKF_DERIVE",
|
||||
"CKM_AES_ECB",
|
||||
"CKM_AES_GCM",
|
||||
"CKM_CHACHA20",
|
||||
"CKM_CHACHA20_POLY1305",
|
||||
"CKM_EC_KEY_PAIR_GEN",
|
||||
"CKM_HKDF_DERIVE",
|
||||
"CKM_INVALID_MECHANISM",
|
||||
"CKM_NSS_CHACHA20_CTR",
|
||||
"CKM_NSS_CHACHA20_POLY1305",
|
||||
"PK11_ATTR_INSENSITIVE",
|
||||
"PK11_ATTR_PRIVATE",
|
||||
"PK11_ATTR_PUBLIC",
|
||||
|
15
third_party/rust/neqo-crypto/build.rs
vendored
15
third_party/rust/neqo-crypto/build.rs
vendored
@ -91,12 +91,7 @@ fn setup_clang() {
|
||||
|
||||
fn nss_dir() -> PathBuf {
|
||||
let dir = if let Ok(dir) = env::var("NSS_DIR") {
|
||||
let path = PathBuf::from(dir.trim());
|
||||
assert!(
|
||||
!path.is_relative(),
|
||||
"The NSS_DIR environment variable is expected to be an absolute path."
|
||||
);
|
||||
path
|
||||
PathBuf::from(dir.trim())
|
||||
} else {
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
let dir = Path::new(&out_dir).join("nss");
|
||||
@ -261,16 +256,16 @@ fn build_bindings(base: &str, bindings: &Bindings, flags: &[String], gecko: bool
|
||||
|
||||
// Apply the configuration.
|
||||
for v in &bindings.types {
|
||||
builder = builder.allowlist_type(v);
|
||||
builder = builder.whitelist_type(v);
|
||||
}
|
||||
for v in &bindings.functions {
|
||||
builder = builder.allowlist_function(v);
|
||||
builder = builder.whitelist_function(v);
|
||||
}
|
||||
for v in &bindings.variables {
|
||||
builder = builder.allowlist_var(v);
|
||||
builder = builder.whitelist_var(v);
|
||||
}
|
||||
for v in &bindings.exclude {
|
||||
builder = builder.blocklist_item(v);
|
||||
builder = builder.blacklist_item(v);
|
||||
}
|
||||
for v in &bindings.opaque {
|
||||
builder = builder.opaque_type(v);
|
||||
|
20
third_party/rust/neqo-crypto/src/agent.rs
vendored
20
third_party/rust/neqo-crypto/src/agent.rs
vendored
@ -87,11 +87,8 @@ fn get_alpn(fd: *mut ssl::PRFileDesc, pre: bool) -> Res<Option<String>> {
|
||||
|
||||
let alpn = match (pre, alpn_state) {
|
||||
(true, ssl::SSLNextProtoState::SSL_NEXT_PROTO_EARLY_VALUE)
|
||||
| (
|
||||
false,
|
||||
ssl::SSLNextProtoState::SSL_NEXT_PROTO_NEGOTIATED
|
||||
| ssl::SSLNextProtoState::SSL_NEXT_PROTO_SELECTED,
|
||||
) => {
|
||||
| (false, ssl::SSLNextProtoState::SSL_NEXT_PROTO_NEGOTIATED)
|
||||
| (false, ssl::SSLNextProtoState::SSL_NEXT_PROTO_SELECTED) => {
|
||||
chosen.truncate(usize::try_from(chosen_len)?);
|
||||
Some(match String::from_utf8(chosen) {
|
||||
Ok(a) => a,
|
||||
@ -805,8 +802,6 @@ impl ResumptionToken {
|
||||
pub struct Client {
|
||||
agent: SecretAgent,
|
||||
|
||||
/// The name of the server we're attempting a connection to.
|
||||
server_name: String,
|
||||
/// Records the resumption tokens we've received.
|
||||
resumption: Pin<Box<Vec<ResumptionToken>>>,
|
||||
}
|
||||
@ -816,15 +811,13 @@ impl Client {
|
||||
///
|
||||
/// # Errors
|
||||
/// Errors returned if the socket can't be created or configured.
|
||||
pub fn new(server_name: impl Into<String>) -> Res<Self> {
|
||||
let server_name = server_name.into();
|
||||
pub fn new(server_name: &str) -> Res<Self> {
|
||||
let mut agent = SecretAgent::new()?;
|
||||
let url = CString::new(server_name.as_bytes())?;
|
||||
let url = CString::new(server_name)?;
|
||||
secstatus_to_res(unsafe { ssl::SSL_SetURL(agent.fd, url.as_ptr()) })?;
|
||||
agent.ready(false)?;
|
||||
let mut client = Self {
|
||||
agent,
|
||||
server_name,
|
||||
resumption: Box::pin(Vec::new()),
|
||||
};
|
||||
client.ready()?;
|
||||
@ -873,11 +866,6 @@ impl Client {
|
||||
ssl::SECSuccess
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn server_name(&self) -> &str {
|
||||
&self.server_name
|
||||
}
|
||||
|
||||
fn ready(&mut self) -> Res<()> {
|
||||
let fd = self.fd;
|
||||
unsafe {
|
||||
|
8
third_party/rust/neqo-crypto/src/cert.rs
vendored
8
third_party/rust/neqo-crypto/src/cert.rs
vendored
@ -5,7 +5,9 @@
|
||||
// except according to those terms.
|
||||
|
||||
use crate::err::secstatus_to_res;
|
||||
use crate::p11::{CERTCertListNode, CERT_GetCertificateDer, CertList, Item, SECItem, SECItemArray};
|
||||
use crate::p11::{
|
||||
CERTCertListNode, CERT_GetCertificateDer, CertList, Item, PRCList, SECItem, SECItemArray,
|
||||
};
|
||||
use crate::ssl::{
|
||||
PRFileDesc, SSL_PeerCertificateChain, SSL_PeerSignedCertTimestamps,
|
||||
SSL_PeerStapledOCSPResponses,
|
||||
@ -13,7 +15,7 @@ use crate::ssl::{
|
||||
use neqo_common::qerror;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::ptr::{addr_of, NonNull};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use std::slice;
|
||||
|
||||
@ -88,7 +90,7 @@ impl CertificateInfo {
|
||||
|
||||
fn head(certs: &CertList) -> *const CERTCertListNode {
|
||||
// Three stars: one for the reference, one for the wrapper, one to deference the pointer.
|
||||
unsafe { addr_of!((***certs).list).cast() }
|
||||
unsafe { (&(***certs).list as *const PRCList).cast() }
|
||||
}
|
||||
}
|
||||
|
||||
|
7
third_party/rust/neqo-crypto/src/ech.rs
vendored
7
third_party/rust/neqo-crypto/src/ech.rs
vendored
@ -14,7 +14,7 @@ use neqo_common::qtrace;
|
||||
use std::convert::TryFrom;
|
||||
use std::ffi::CString;
|
||||
use std::os::raw::{c_char, c_uint};
|
||||
use std::ptr::{addr_of_mut, null_mut};
|
||||
use std::ptr::null_mut;
|
||||
|
||||
pub use crate::p11::{HpkeAeadId as AeadId, HpkeKdfId as KdfId, HpkeKemId as KemId};
|
||||
pub use crate::ssl::HpkeSymmetricSuite as SymmetricSuite;
|
||||
@ -98,7 +98,6 @@ pub fn generate_keys() -> Res<(PrivateKey, PublicKey)> {
|
||||
params.extend_from_slice(oid_slc);
|
||||
|
||||
let mut public_ptr: *mut SECKEYPublicKey = null_mut();
|
||||
let mut param_item = Item::wrap(¶ms);
|
||||
|
||||
// If we have tracing on, try to ensure that key data can be read.
|
||||
let insensitive_secret_ptr = if log::log_enabled!(log::Level::Trace) {
|
||||
@ -106,7 +105,7 @@ pub fn generate_keys() -> Res<(PrivateKey, PublicKey)> {
|
||||
p11::PK11_GenerateKeyPairWithOpFlags(
|
||||
*slot,
|
||||
p11::CK_MECHANISM_TYPE::from(p11::CKM_EC_KEY_PAIR_GEN),
|
||||
addr_of_mut!(param_item).cast(),
|
||||
(&mut Item::wrap(¶ms) as *mut SECItem).cast(),
|
||||
&mut public_ptr,
|
||||
p11::PK11_ATTR_SESSION | p11::PK11_ATTR_INSENSITIVE | p11::PK11_ATTR_PUBLIC,
|
||||
p11::CK_FLAGS::from(p11::CKF_DERIVE),
|
||||
@ -123,7 +122,7 @@ pub fn generate_keys() -> Res<(PrivateKey, PublicKey)> {
|
||||
p11::PK11_GenerateKeyPairWithOpFlags(
|
||||
*slot,
|
||||
p11::CK_MECHANISM_TYPE::from(p11::CKM_EC_KEY_PAIR_GEN),
|
||||
addr_of_mut!(param_item).cast(),
|
||||
(&mut Item::wrap(¶ms) as *mut SECItem).cast(),
|
||||
&mut public_ptr,
|
||||
p11::PK11_ATTR_SESSION | p11::PK11_ATTR_SENSITIVE | p11::PK11_ATTR_PRIVATE,
|
||||
p11::CK_FLAGS::from(p11::CKF_DERIVE),
|
||||
|
3
third_party/rust/neqo-crypto/src/err.rs
vendored
3
third_party/rust/neqo-crypto/src/err.rs
vendored
@ -29,10 +29,11 @@ pub mod nspr {
|
||||
pub type Res<T> = Result<T, Error>;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
|
||||
#[allow(renamed_and_removed_lints, clippy::pub_enum_variant_names)] // rust 1.54 will require a different approach
|
||||
pub enum Error {
|
||||
AeadInitFailure,
|
||||
AeadError,
|
||||
CertificateLoading,
|
||||
CipherInitFailure,
|
||||
CreateSslSocket,
|
||||
EchRetry(Vec<u8>),
|
||||
HkdfError,
|
||||
|
140
third_party/rust/neqo-crypto/src/hp.rs
vendored
140
third_party/rust/neqo-crypto/src/hp.rs
vendored
@ -9,17 +9,14 @@ use crate::constants::{
|
||||
};
|
||||
use crate::err::{secstatus_to_res, Error, Res};
|
||||
use crate::p11::{
|
||||
Context, Item, PK11SymKey, PK11_CipherOp, PK11_CreateContextBySymKey, PK11_Encrypt,
|
||||
PK11_GetBlockSize, SymKey, CKA_ENCRYPT, CKM_AES_ECB, CKM_CHACHA20, CK_ATTRIBUTE_TYPE,
|
||||
CK_CHACHA20_PARAMS, CK_MECHANISM_TYPE,
|
||||
Item, PK11SymKey, PK11_Encrypt, PK11_GetBlockSize, PK11_GetMechanism, SECItem, SymKey,
|
||||
CKM_AES_ECB, CKM_NSS_CHACHA20_CTR, CK_MECHANISM_TYPE,
|
||||
};
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt::{self, Debug};
|
||||
use std::os::raw::{c_char, c_int, c_uint};
|
||||
use std::ptr::{addr_of_mut, null, null_mut};
|
||||
use std::rc::Rc;
|
||||
use std::os::raw::{c_char, c_uint};
|
||||
use std::ptr::{null, null_mut};
|
||||
|
||||
experimental_api!(SSL_HkdfExpandLabelWithMech(
|
||||
version: Version,
|
||||
@ -35,43 +32,29 @@ experimental_api!(SSL_HkdfExpandLabelWithMech(
|
||||
));
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum HpKey {
|
||||
/// An AES encryption context.
|
||||
/// Note: as we need to clone this object, we clone the pointer and
|
||||
/// track references using `Rc`. `PK11Context` can't be used with `PK11_CloneContext`
|
||||
/// as that is not supported for these contexts.
|
||||
Aes(Rc<RefCell<Context>>),
|
||||
/// The ChaCha20 mask has to invoke a new PK11_Encrypt every time as it needs to
|
||||
/// change the counter and nonce on each invocation.
|
||||
Chacha(SymKey),
|
||||
}
|
||||
pub struct HpKey(SymKey);
|
||||
|
||||
impl Debug for HpKey {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "HpKey")
|
||||
write!(f, "HP-{:?}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl HpKey {
|
||||
const SAMPLE_SIZE: usize = 16;
|
||||
|
||||
/// QUIC-specific API for extracting a header-protection key.
|
||||
///
|
||||
/// # Errors
|
||||
/// Errors if HKDF fails or if the label is too long to fit in a `c_uint`.
|
||||
/// # Panics
|
||||
/// When `cipher` is not known to this code.
|
||||
#[allow(clippy::cast_sign_loss)] // Cast for PK11_GetBlockSize is safe.
|
||||
pub fn extract(version: Version, cipher: Cipher, prk: &SymKey, label: &str) -> Res<Self> {
|
||||
const ZERO: &[u8] = &[0; 12];
|
||||
|
||||
let l = label.as_bytes();
|
||||
let mut secret: *mut PK11SymKey = null_mut();
|
||||
|
||||
let (mech, key_size) = match cipher {
|
||||
TLS_AES_128_GCM_SHA256 => (CK_MECHANISM_TYPE::from(CKM_AES_ECB), 16),
|
||||
TLS_AES_256_GCM_SHA384 => (CK_MECHANISM_TYPE::from(CKM_AES_ECB), 32),
|
||||
TLS_CHACHA20_POLY1305_SHA256 => (CK_MECHANISM_TYPE::from(CKM_CHACHA20), 32),
|
||||
TLS_CHACHA20_POLY1305_SHA256 => (CK_MECHANISM_TYPE::from(CKM_NSS_CHACHA20_CTR), 32),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
@ -91,44 +74,18 @@ impl HpKey {
|
||||
&mut secret,
|
||||
)
|
||||
}?;
|
||||
let key = SymKey::from_ptr(secret).or(Err(Error::HkdfError))?;
|
||||
|
||||
let res = match cipher {
|
||||
TLS_AES_128_GCM_SHA256 | TLS_AES_256_GCM_SHA384 => {
|
||||
let context_ptr = unsafe {
|
||||
PK11_CreateContextBySymKey(
|
||||
mech,
|
||||
CK_ATTRIBUTE_TYPE::from(CKA_ENCRYPT),
|
||||
*key,
|
||||
&Item::wrap(&ZERO[..0]), // Borrow a zero-length slice of ZERO.
|
||||
)
|
||||
};
|
||||
let context = Context::from_ptr(context_ptr).or(Err(Error::CipherInitFailure))?;
|
||||
Self::Aes(Rc::new(RefCell::new(context)))
|
||||
}
|
||||
TLS_CHACHA20_POLY1305_SHA256 => Self::Chacha(key),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
debug_assert_eq!(
|
||||
res.block_size(),
|
||||
usize::try_from(unsafe { PK11_GetBlockSize(mech, null_mut()) }).unwrap()
|
||||
);
|
||||
Ok(res)
|
||||
let sym_key = SymKey::from_ptr(secret).or(Err(Error::HkdfError))?;
|
||||
Ok(HpKey(sym_key))
|
||||
}
|
||||
|
||||
/// Get the sample size, which is also the output size.
|
||||
#[allow(clippy::cast_sign_loss)]
|
||||
#[must_use]
|
||||
#[allow(clippy::unused_self)] // To maintain an API contract.
|
||||
pub fn sample_size(&self) -> usize {
|
||||
Self::SAMPLE_SIZE
|
||||
}
|
||||
|
||||
fn block_size(&self) -> usize {
|
||||
match self {
|
||||
Self::Aes(_) => 16,
|
||||
Self::Chacha(_) => 64,
|
||||
}
|
||||
let k: *mut PK11SymKey = *self.0;
|
||||
let mech = unsafe { PK11_GetMechanism(k) };
|
||||
// Cast is safe because block size is always greater than or equal to 0
|
||||
(unsafe { PK11_GetBlockSize(mech, null_mut()) }) as usize
|
||||
}
|
||||
|
||||
/// Generate a header protection mask for QUIC.
|
||||
@ -139,49 +96,36 @@ impl HpKey {
|
||||
/// # Panics
|
||||
/// When the mechanism for our key is not supported.
|
||||
pub fn mask(&self, sample: &[u8]) -> Res<Vec<u8>> {
|
||||
let mut output = vec![0_u8; self.block_size()];
|
||||
let k: *mut PK11SymKey = *self.0;
|
||||
let mech = unsafe { PK11_GetMechanism(k) };
|
||||
let block_size = self.sample_size();
|
||||
|
||||
match self {
|
||||
Self::Aes(context) => {
|
||||
let mut output_len: c_int = 0;
|
||||
secstatus_to_res(unsafe {
|
||||
PK11_CipherOp(
|
||||
**context.borrow_mut(),
|
||||
output.as_mut_ptr(),
|
||||
&mut output_len,
|
||||
c_int::try_from(output.len())?,
|
||||
(&sample[..Self::SAMPLE_SIZE]).as_ptr().cast(),
|
||||
c_int::try_from(Self::SAMPLE_SIZE).unwrap(),
|
||||
)
|
||||
})?;
|
||||
assert_eq!(usize::try_from(output_len).unwrap(), output.len());
|
||||
Ok(output)
|
||||
}
|
||||
let mut output = vec![0_u8; block_size];
|
||||
let output_slice = &mut output[..];
|
||||
let mut output_len: c_uint = 0;
|
||||
|
||||
Self::Chacha(key) => {
|
||||
let params: CK_CHACHA20_PARAMS = CK_CHACHA20_PARAMS {
|
||||
pBlockCounter: sample.as_ptr() as *mut u8,
|
||||
blockCounterBits: 32,
|
||||
pNonce: (&sample[4..Self::SAMPLE_SIZE]).as_ptr() as *mut _,
|
||||
ulNonceBits: 96,
|
||||
};
|
||||
let mut output_len: c_uint = 0;
|
||||
let mut param_item = Item::wrap_struct(¶ms);
|
||||
secstatus_to_res(unsafe {
|
||||
PK11_Encrypt(
|
||||
**key,
|
||||
CK_MECHANISM_TYPE::from(CKM_CHACHA20),
|
||||
addr_of_mut!(param_item),
|
||||
(&mut output[..]).as_mut_ptr(),
|
||||
&mut output_len,
|
||||
c_uint::try_from(output.len())?,
|
||||
(&output[..]).as_ptr(),
|
||||
c_uint::try_from(output.len())?,
|
||||
)
|
||||
})?;
|
||||
assert_eq!(usize::try_from(output_len).unwrap(), output.len());
|
||||
Ok(output)
|
||||
let zero = vec![0_u8; block_size];
|
||||
let mut wrapped_sample = Item::wrap(sample);
|
||||
let (iv, inbuf) = match () {
|
||||
_ if mech == CK_MECHANISM_TYPE::from(CKM_AES_ECB) => (null_mut(), sample),
|
||||
_ if mech == CK_MECHANISM_TYPE::from(CKM_NSS_CHACHA20_CTR) => {
|
||||
(&mut wrapped_sample as *mut SECItem, &zero[..])
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
secstatus_to_res(unsafe {
|
||||
PK11_Encrypt(
|
||||
k,
|
||||
mech,
|
||||
iv,
|
||||
output_slice.as_mut_ptr(),
|
||||
&mut output_len,
|
||||
c_uint::try_from(output.len())?,
|
||||
inbuf.as_ptr().cast(),
|
||||
c_uint::try_from(inbuf.len())?,
|
||||
)
|
||||
})?;
|
||||
assert_eq!(output_len as usize, block_size);
|
||||
Ok(output)
|
||||
}
|
||||
}
|
||||
|
3
third_party/rust/neqo-crypto/src/lib.rs
vendored
3
third_party/rust/neqo-crypto/src/lib.rs
vendored
@ -73,11 +73,10 @@ use std::ffi::CString;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::ptr::null;
|
||||
|
||||
const MINIMUM_NSS_VERSION: &str = "3.74";
|
||||
const MINIMUM_NSS_VERSION: &str = "3.66";
|
||||
|
||||
#[allow(non_upper_case_globals, clippy::redundant_static_lifetimes)]
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
#[allow(unknown_lints, clippy::borrow_as_ptr)]
|
||||
mod nss {
|
||||
include!(concat!(env!("OUT_DIR"), "/nss_init.rs"));
|
||||
}
|
||||
|
24
third_party/rust/neqo-crypto/src/p11.rs
vendored
24
third_party/rust/neqo-crypto/src/p11.rs
vendored
@ -14,15 +14,13 @@ use crate::err::{secstatus_to_res, Error, Res};
|
||||
use neqo_common::hex_with_len;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::os::raw::{c_int, c_uint};
|
||||
use std::ptr::null_mut;
|
||||
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
#[allow(unknown_lints, deref_nullptr)] // Until bindgen#1651 is fixed.
|
||||
#[allow(unknown_lints, deref_nullptr)] // Until we require rust 1.53 or bindgen#1651 is fixed.
|
||||
#[allow(clippy::unreadable_literal)]
|
||||
#[allow(unknown_lints, clippy::borrow_as_ptr)]
|
||||
mod nss_p11 {
|
||||
include!(concat!(env!("OUT_DIR"), "/nss_p11.rs"));
|
||||
}
|
||||
@ -219,11 +217,6 @@ impl std::fmt::Debug for SymKey {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn destroy_pk11_context(ctxt: *mut PK11Context) {
|
||||
PK11_DestroyContext(ctxt, PRBool::from(true));
|
||||
}
|
||||
scoped_ptr!(Context, PK11Context, destroy_pk11_context);
|
||||
|
||||
unsafe fn destroy_secitem(item: *mut SECItem) {
|
||||
SECITEM_FreeItem(item, PRBool::from(true));
|
||||
}
|
||||
@ -232,8 +225,7 @@ scoped_ptr!(Item, SECItem, destroy_secitem);
|
||||
impl Item {
|
||||
/// Create a wrapper for a slice of this object.
|
||||
/// Creating this object is technically safe, but using it is extremely dangerous.
|
||||
/// Minimally, it can only be passed as a `const SECItem*` argument to functions,
|
||||
/// or those that treat their argument as `const`.
|
||||
/// Minimally, it can only be passed as a `const SECItem*` argument to functions.
|
||||
pub fn wrap(buf: &[u8]) -> SECItem {
|
||||
SECItem {
|
||||
type_: SECItemType::siBuffer,
|
||||
@ -242,18 +234,6 @@ impl Item {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a wrapper for a struct.
|
||||
/// Creating this object is technically safe, but using it is extremely dangerous.
|
||||
/// Minimally, it can only be passed as a `const SECItem*` argument to functions,
|
||||
/// or those that treat their argument as `const`.
|
||||
pub fn wrap_struct<T>(v: &T) -> SECItem {
|
||||
SECItem {
|
||||
type_: SECItemType::siBuffer,
|
||||
data: (v as *const T as *mut T).cast(),
|
||||
len: c_uint::try_from(mem::size_of::<T>()).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Make an empty `SECItem` for passing as a mutable `SECItem*` argument.
|
||||
pub fn make_empty() -> SECItem {
|
||||
SECItem {
|
||||
|
6
third_party/rust/neqo-crypto/src/prio.rs
vendored
6
third_party/rust/neqo-crypto/src/prio.rs
vendored
@ -5,16 +5,14 @@
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(clippy::upper_case_acronyms)]
|
||||
#![allow(unknown_lints, deref_nullptr)] // Until bindgen#1651 is fixed.
|
||||
#![allow(unknown_lints, deref_nullptr)] // Until we require rust 1.53 or bindgen#1651 is fixed.
|
||||
#![allow(
|
||||
dead_code,
|
||||
non_upper_case_globals,
|
||||
non_snake_case,
|
||||
clippy::cognitive_complexity,
|
||||
clippy::empty_enum,
|
||||
clippy::too_many_lines,
|
||||
unknown_lints,
|
||||
clippy::borrow_as_ptr
|
||||
clippy::too_many_lines
|
||||
)]
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/nspr_io.rs"));
|
||||
|
2
third_party/rust/neqo-crypto/src/secrets.rs
vendored
2
third_party/rust/neqo-crypto/src/secrets.rs
vendored
@ -87,7 +87,7 @@ impl Secrets {
|
||||
}
|
||||
|
||||
fn put(&mut self, dir: SecretDirection, epoch: Epoch, key: SymKey) {
|
||||
qdebug!("{:?} secret available for {:?}: {:?}", dir, epoch, key);
|
||||
qdebug!("{:?} secret available for {:?}", dir, epoch);
|
||||
let keys = match dir {
|
||||
SecretDirection::Read => &mut self.r,
|
||||
SecretDirection::Write => &mut self.w,
|
||||
|
@ -90,7 +90,7 @@ impl SelfEncrypt {
|
||||
let offset = enc.len();
|
||||
let mut output: Vec<u8> = enc.into();
|
||||
output.resize(encoded_len, 0);
|
||||
cipher.encrypt(0, extended_aad.as_ref(), plaintext, &mut output[offset..])?;
|
||||
cipher.encrypt(0, &extended_aad, plaintext, &mut output[offset..])?;
|
||||
qtrace!(
|
||||
["SelfEncrypt"],
|
||||
"seal {} {} -> {}",
|
||||
@ -139,8 +139,7 @@ impl SelfEncrypt {
|
||||
// NSS insists on having extra space available for decryption.
|
||||
let padded_len = ciphertext.len() - offset;
|
||||
let mut output = vec![0; padded_len];
|
||||
let decrypted =
|
||||
aead.decrypt(0, extended_aad.as_ref(), &ciphertext[offset..], &mut output)?;
|
||||
let decrypted = aead.decrypt(0, &extended_aad, &ciphertext[offset..], &mut output)?;
|
||||
let final_len = decrypted.len();
|
||||
output.truncate(final_len);
|
||||
qtrace!(
|
||||
|
6
third_party/rust/neqo-crypto/src/ssl.rs
vendored
6
third_party/rust/neqo-crypto/src/ssl.rs
vendored
@ -10,11 +10,9 @@
|
||||
non_snake_case,
|
||||
clippy::cognitive_complexity,
|
||||
clippy::too_many_lines,
|
||||
clippy::upper_case_acronyms,
|
||||
unknown_lints,
|
||||
clippy::borrow_as_ptr
|
||||
clippy::upper_case_acronyms
|
||||
)]
|
||||
#![allow(unknown_lints, deref_nullptr)] // Until bindgen#1651 is fixed.
|
||||
#![allow(unknown_lints, deref_nullptr)] // Until we require rust 1.53 or bindgen#1651 is fixed.
|
||||
|
||||
use crate::constants::Epoch;
|
||||
use crate::err::{secstatus_to_res, Res};
|
||||
|
6
third_party/rust/neqo-crypto/src/time.rs
vendored
6
third_party/rust/neqo-crypto/src/time.rs
vendored
@ -119,10 +119,8 @@ impl TryInto<PRTime> for Time {
|
||||
type Error = Error;
|
||||
fn try_into(self) -> Res<PRTime> {
|
||||
let base = get_base();
|
||||
let delta = self
|
||||
.t
|
||||
.checked_duration_since(base.instant)
|
||||
.ok_or(Error::TimeTravelError)?;
|
||||
// TODO(mt) use checked_duration_since when that is available.
|
||||
let delta = self.t.duration_since(base.instant);
|
||||
if let Ok(d) = PRTime::try_from(delta.as_micros()) {
|
||||
d.checked_add(base.prtime).ok_or(Error::TimeTravelError)
|
||||
} else {
|
||||
|
2
third_party/rust/neqo-crypto/tests/aead.rs
vendored
2
third_party/rust/neqo-crypto/tests/aead.rs
vendored
@ -37,7 +37,7 @@ fn make_aead(cipher: Cipher) -> Aead {
|
||||
TLS_VERSION_1_3,
|
||||
cipher,
|
||||
&secret,
|
||||
"quic ", // QUICv1 label prefix; note the trailing space here.
|
||||
"quic ", // Note the trailing space here.
|
||||
)
|
||||
.expect("can make an AEAD")
|
||||
}
|
||||
|
51
third_party/rust/neqo-crypto/tests/hp.rs
vendored
51
third_party/rust/neqo-crypto/tests/hp.rs
vendored
@ -2,34 +2,18 @@
|
||||
#![warn(clippy::pedantic)]
|
||||
|
||||
use neqo_crypto::constants::{
|
||||
Cipher, TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256,
|
||||
TLS_VERSION_1_3,
|
||||
Cipher, TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_VERSION_1_3,
|
||||
};
|
||||
use neqo_crypto::hkdf;
|
||||
use neqo_crypto::hp::HpKey;
|
||||
use std::mem;
|
||||
use test_fixture::fixture_init;
|
||||
|
||||
fn make_hp(cipher: Cipher) -> HpKey {
|
||||
fixture_init();
|
||||
let ikm = hkdf::import_key(TLS_VERSION_1_3, &[0; 16]).expect("import IKM");
|
||||
let prk = hkdf::extract(TLS_VERSION_1_3, cipher, None, &ikm).expect("extract works");
|
||||
HpKey::extract(TLS_VERSION_1_3, cipher, &prk, "hp").expect("extract label works")
|
||||
}
|
||||
|
||||
fn hp_test(cipher: Cipher, expected: &[u8]) {
|
||||
let hp = make_hp(cipher);
|
||||
let mask = hp.mask(&[0; 16]).expect("should produce a mask");
|
||||
assert_eq!(mask, expected, "first invocation should be correct");
|
||||
|
||||
let hp2 = hp.clone();
|
||||
let mask = hp2.mask(&[0; 16]).expect("clone produces mask");
|
||||
assert_eq!(mask, expected, "clone should produce the same mask");
|
||||
|
||||
let mask = hp.mask(&[0; 16]).expect("should produce a mask again");
|
||||
assert_eq!(mask, expected, "second invocation should be the same");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn aes128() {
|
||||
const EXPECTED: &[u8] = &[
|
||||
@ -37,7 +21,11 @@ fn aes128() {
|
||||
0x14,
|
||||
];
|
||||
|
||||
hp_test(TLS_AES_128_GCM_SHA256, EXPECTED);
|
||||
fixture_init();
|
||||
let mask = make_hp(TLS_AES_128_GCM_SHA256)
|
||||
.mask(&[0; 16])
|
||||
.expect("should produce a mask");
|
||||
assert_eq!(mask, EXPECTED);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -47,9 +35,14 @@ fn aes256() {
|
||||
0x2b,
|
||||
];
|
||||
|
||||
hp_test(TLS_AES_256_GCM_SHA384, EXPECTED);
|
||||
fixture_init();
|
||||
let mask = make_hp(TLS_AES_256_GCM_SHA384)
|
||||
.mask(&[0; 16])
|
||||
.expect("should produce a mask");
|
||||
assert_eq!(mask, EXPECTED);
|
||||
}
|
||||
|
||||
#[cfg(feature = "chacha")]
|
||||
#[test]
|
||||
fn chacha20_ctr() {
|
||||
const EXPECTED: &[u8] = &[
|
||||
@ -60,19 +53,9 @@ fn chacha20_ctr() {
|
||||
0x2f, 0x52, 0x46, 0x89,
|
||||
];
|
||||
|
||||
hp_test(TLS_CHACHA20_POLY1305_SHA256, EXPECTED);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn aes_short() {
|
||||
let hp = make_hp(TLS_AES_128_GCM_SHA256);
|
||||
mem::drop(hp.mask(&[0; 15]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn chacha20_short() {
|
||||
let hp = make_hp(TLS_CHACHA20_POLY1305_SHA256);
|
||||
mem::drop(hp.mask(&[0; 15]));
|
||||
fixture_init();
|
||||
let mask = make_hp(TLS_CHACHA20_POLY1305_SHA256)
|
||||
.mask(&[0; 16])
|
||||
.expect("should produce a mask");
|
||||
assert_eq!(mask, EXPECTED);
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"fa6db9805e426106bbba24a64efbb782c0c3308669ff040ec9085e2fac06ea79","src/buffered_send_stream.rs":"0e4ad4914451943e49c88565661d88475ab2bbd8756e200e2a19312bafd64847","src/client_events.rs":"9d86145febad2f3fb05007eae3f5ad4834c78dd709fe388f05590405e34a614b","src/conn_params.rs":"7e33526de9c83c163049a2caf2bff0f997351cc61fad76fb6e8c6ec4b9f09938","src/connection.rs":"72c3c2a3c19481d519f4c1928c51dc7c1d4ab6e6cb2bd9ecfdfc5d5c09f485bb","src/connection_client.rs":"e4914a8e44eb6045615382eacf2499b0195574f19ce36e161ad3d3e186f69ebb","src/connection_server.rs":"de1e0359b902b1e98c923a8d5488302a68a3312b466590fdddaee6ec8327813b","src/control_stream_local.rs":"b86e1f869ad59bf2663501942a1a65d94c1dbc3e8770982459e0b620be4b6cf0","src/control_stream_remote.rs":"7a261ac7df77e90a428ab0f92457a934a92a8c581462fc1818efd3de0c0ebd69","src/features/extended_connect/mod.rs":"2bc2f0570b11318f3225173001dad1a5f05e4bf60dee49a2bf9d40e3a411e138","src/features/extended_connect/webtransport_session.rs":"abf84892c429c2ee79efd8e215bfd9da182163ba859cd24b6ee4ba6becceb6bd","src/features/extended_connect/webtransport_streams.rs":"784c5e317bb6af33f653ba82c1a5666b657c2a210263a415e913494f61613464","src/features/mod.rs":"a981ebbd03e7bb7ea2313e883452e44f052c48f28edb7fd53a0825911b490230","src/frames/hframe.rs":"da4829b30303d02fd044729a3f6571c596eaa66dceaf51c3a833c61497d6736b","src/frames/mod.rs":"258dd4bdf2daca19a62cd697d2c7f4709a35668b2b4dce3203675e814c9b40b8","src/frames/reader.rs":"0802cd8b41204bcec424fc6ed704a3bdbed0e5d38444f7a9b0550ad877b076a6","src/frames/tests/hframe.rs":"33a30bb98bb512606a06ae1752e1ed9e4588b7d3f5e9439ec83bb2e779d4ac80","src/frames/tests/mod.rs":"4933c519069ee4dac23587588f2b792c12d1363e92d0105e1eb169082e213559","src/frames/tests/reader.rs":"312a3deda7b3a4bbd7afed879c94d0644fce8e34435365ef9cae1fbaa62496af","src/frames/tests/wtframe.rs":"589ebe1e62ce4da63b37b7d22cde7ba572ddbf29336fdcdbbcd0a745f79dacd8","src/frames/wtframe.rs":"1d87964fe76945bfe3e59834632ce1e3a000b5e26164b71bdcd129f8a4e73ae3","src/headers_checks.rs":"b80c1da2d9f336fa88f7b7f2a834d8e90e826260811771c7729785fdc92b20d4","src/lib.rs":"5ac7d69f04b3d748b2a566271fed0a21c2e510e54532a298d5fd8096c8d7a49a","src/priority.rs":"ae0fa461031893b4f7e0d12666072e7a4da80b1e8a1c0663ab9f9e27b3242754","src/push_controller.rs":"aa2a64180d8cb1b87682d0d8bbc42167188e8e1890261cb4cabb76de1fcc708b","src/qlog.rs":"44b6cdbb1d9d6ca47b793e9dbe531b8fdbd40147375f7e4c89aeab536c5d286b","src/qpack_decoder_receiver.rs":"75008d8ea5d538ee34aca4df72e58489417604ccafb61b064280782d6754dd0d","src/qpack_encoder_receiver.rs":"f95cc7d49e4d442b93d522f14ddfc581629664d84d6e13d03a520e855bbe442d","src/recv_message.rs":"5f70fb474e387653d7982374131b3b0c08417509469f273ccebf842bfcee836f","src/request_target.rs":"9182b641f7a7b55272e0e2e872d24a35b1207f35399221b08b899857c3e873ab","src/send_message.rs":"9e1b22ede2a105a79d7c02178801e1a46b06a80dc1c0d2a7d69b0eea7e89f319","src/server.rs":"ab00f395f7767d733091af3e3317527e5c302b2e5062b33943211ede75f10109","src/server_connection_events.rs":"3d89c2d9a30ee719acfbaae4b7720cb354eb73b11bc6ceb44571d68b05192b8b","src/server_events.rs":"3081fdd1e1950aeecae031452cd683335fb0a9dcec51722e614c5939f747b9d9","src/settings.rs":"8a8919cd31683f476dec281b8b545ea3cedb0c7d60cd1e29b097bae605822d47","src/stream_type_reader.rs":"a294dab84f06d375890ba908296bb19251b1ff32f7155e4952ca0a69f0660539","tests/httpconn.rs":"f8d6e6a693d17cf2eb192a730e6fc929bd2814552356ce8d4423a0e3eac8c59d","tests/mod.rs":"fd6aee37243713e80fc526552f21f0222338cec9890409b6575a2a637b17ec1f","tests/priority.rs":"a606e5fa03451e09e28c7d5f1820ee85a4567e3969a1690c979761e62123bf54","tests/send_message.rs":"673ae1d0bf2dce46c21ee8353f45f189d2cb64a2f6e137ae38da6b2262ad066e","tests/webtransport/mod.rs":"635c0b0fe682a844f4366335a40b8b3a6539abe30843ee1bcfaf87a34b1d476c","tests/webtransport/negotiation.rs":"2da85dfd45e3dfdbab7608768d734e1f150e1b0ba14e982cbb6de16ba62789c2","tests/webtransport/sessions.rs":"5b4d8483ac018ad5a28adad5e778e2ed48db9c441d1354f6cf21d8e5c6f1a8b3","tests/webtransport/streams.rs":"fd5f075d93f0241290566f59f747d95530d2df579890fd0f6b9e79a557c89a67"},"package":null}
|
||||
{"files":{"Cargo.toml":"9ff10a0f34e30e86b9c005058e50ba588b39a78330ece04e29e8b1e3ef060471","src/buffered_send_stream.rs":"0e4ad4914451943e49c88565661d88475ab2bbd8756e200e2a19312bafd64847","src/client_events.rs":"9d86145febad2f3fb05007eae3f5ad4834c78dd709fe388f05590405e34a614b","src/conn_params.rs":"00e3f42636f482f91cd6b86d7bebaa85a9f0407143503767fffb66a3cdfbbe43","src/connection.rs":"ef2e70c08a59a8a60c7852c8beb6545e3cb37d8da94302798bdc2fc38e4f76c0","src/connection_client.rs":"fabd645653c5991b8d2ec6f2a3c4e16e32c4faa292da47f5c5eb405ef39f8a7a","src/connection_server.rs":"de1e0359b902b1e98c923a8d5488302a68a3312b466590fdddaee6ec8327813b","src/control_stream_local.rs":"9ceb1aae8079dfca8e2f38fb555d47e84f3001d9501f2c909e8245841974f49c","src/control_stream_remote.rs":"7a261ac7df77e90a428ab0f92457a934a92a8c581462fc1818efd3de0c0ebd69","src/features/extended_connect/mod.rs":"2bc2f0570b11318f3225173001dad1a5f05e4bf60dee49a2bf9d40e3a411e138","src/features/extended_connect/webtransport_session.rs":"791734e1891bd35541be33cbf744d6edee6278e760fedb12839dd052a0cf91ba","src/features/extended_connect/webtransport_streams.rs":"784c5e317bb6af33f653ba82c1a5666b657c2a210263a415e913494f61613464","src/features/mod.rs":"a981ebbd03e7bb7ea2313e883452e44f052c48f28edb7fd53a0825911b490230","src/frames/hframe.rs":"67018ad85ecb9ec0476dafc4b25f6b7015e49531cd19f8e81d204af0e29ee3ea","src/frames/mod.rs":"258dd4bdf2daca19a62cd697d2c7f4709a35668b2b4dce3203675e814c9b40b8","src/frames/reader.rs":"0802cd8b41204bcec424fc6ed704a3bdbed0e5d38444f7a9b0550ad877b076a6","src/frames/tests/hframe.rs":"33a30bb98bb512606a06ae1752e1ed9e4588b7d3f5e9439ec83bb2e779d4ac80","src/frames/tests/mod.rs":"fd2e9d4a28c3bd2fd349f4e3844cefa37e9addb09561e9261b393ca7a37e6c6e","src/frames/tests/reader.rs":"312a3deda7b3a4bbd7afed879c94d0644fce8e34435365ef9cae1fbaa62496af","src/frames/tests/wtframe.rs":"589ebe1e62ce4da63b37b7d22cde7ba572ddbf29336fdcdbbcd0a745f79dacd8","src/frames/wtframe.rs":"1d87964fe76945bfe3e59834632ce1e3a000b5e26164b71bdcd129f8a4e73ae3","src/headers_checks.rs":"0893d48fde97687b712e86457e75f2a1b802e7589ce38df30ff65684d8cf59c0","src/lib.rs":"4876915dd7f03021cce3a166e12e0a3763ac2c44e6ad81d223cda1f555b7a2c2","src/priority.rs":"ae0fa461031893b4f7e0d12666072e7a4da80b1e8a1c0663ab9f9e27b3242754","src/push_controller.rs":"aa2a64180d8cb1b87682d0d8bbc42167188e8e1890261cb4cabb76de1fcc708b","src/qlog.rs":"44b6cdbb1d9d6ca47b793e9dbe531b8fdbd40147375f7e4c89aeab536c5d286b","src/qpack_decoder_receiver.rs":"75008d8ea5d538ee34aca4df72e58489417604ccafb61b064280782d6754dd0d","src/qpack_encoder_receiver.rs":"f95cc7d49e4d442b93d522f14ddfc581629664d84d6e13d03a520e855bbe442d","src/recv_message.rs":"5f70fb474e387653d7982374131b3b0c08417509469f273ccebf842bfcee836f","src/request_target.rs":"9182b641f7a7b55272e0e2e872d24a35b1207f35399221b08b899857c3e873ab","src/send_message.rs":"f3503bf135af5acdb3663a8b591b1db2d160e3dcec37aafd2053f2f150f68d2a","src/server.rs":"3cde23011de0a63ee4900e41368e9319ce100a1584f90bf5463e054adcc8875c","src/server_connection_events.rs":"3d89c2d9a30ee719acfbaae4b7720cb354eb73b11bc6ceb44571d68b05192b8b","src/server_events.rs":"3081fdd1e1950aeecae031452cd683335fb0a9dcec51722e614c5939f747b9d9","src/settings.rs":"8a8919cd31683f476dec281b8b545ea3cedb0c7d60cd1e29b097bae605822d47","src/stream_type_reader.rs":"d63727341d925241ec17c7373d81145aba1464cac4c9eedfc05f24c453435f67","tests/httpconn.rs":"f8d6e6a693d17cf2eb192a730e6fc929bd2814552356ce8d4423a0e3eac8c59d","tests/mod.rs":"fd6aee37243713e80fc526552f21f0222338cec9890409b6575a2a637b17ec1f","tests/priority.rs":"a606e5fa03451e09e28c7d5f1820ee85a4567e3969a1690c979761e62123bf54","tests/send_message.rs":"673ae1d0bf2dce46c21ee8353f45f189d2cb64a2f6e137ae38da6b2262ad066e","tests/webtransport/mod.rs":"635c0b0fe682a844f4366335a40b8b3a6539abe30843ee1bcfaf87a34b1d476c","tests/webtransport/negotiation.rs":"fd46a3a77c75dfb701ac075cdb0aabb58f82b5d5c03c5a965412bbf6ad020f00","tests/webtransport/sessions.rs":"5b4d8483ac018ad5a28adad5e778e2ed48db9c441d1354f6cf21d8e5c6f1a8b3","tests/webtransport/streams.rs":"fd5f075d93f0241290566f59f747d95530d2df579890fd0f6b9e79a557c89a67"},"package":null}
|
3
third_party/rust/neqo-http3/Cargo.toml
vendored
3
third_party/rust/neqo-http3/Cargo.toml
vendored
@ -1,9 +1,8 @@
|
||||
[package]
|
||||
name = "neqo-http3"
|
||||
version = "0.6.0"
|
||||
version = "0.5.7"
|
||||
authors = ["Dragana Damjanovic <dragana.damjano@gmail.com>"]
|
||||
edition = "2018"
|
||||
rust-version = "1.57.0"
|
||||
license = "MIT/Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
|
@ -14,7 +14,7 @@ const QPACK_MAX_BLOCKED_STREAMS_DEFAULT: u16 = 20;
|
||||
const MAX_PUSH_STREAM_DEFAULT: u64 = 0;
|
||||
const WEBTRANSPORT_DEFAULT: bool = false;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Http3Parameters {
|
||||
conn_params: ConnectionParameters,
|
||||
qpack_settings: QpackSettings,
|
||||
|
12
third_party/rust/neqo-http3/src/connection.rs
vendored
12
third_party/rust/neqo-http3/src/connection.rs
vendored
@ -203,8 +203,8 @@ impl Http3Connection {
|
||||
self.qpack_decoder.borrow_mut().send(conn)?;
|
||||
match self.qpack_encoder.borrow_mut().send_encoder_updates(conn) {
|
||||
Ok(())
|
||||
| Err(neqo_qpack::Error::EncoderStreamBlocked | neqo_qpack::Error::DynamicTableFull) => {
|
||||
}
|
||||
| Err(neqo_qpack::Error::EncoderStreamBlocked)
|
||||
| Err(neqo_qpack::Error::DynamicTableFull) => {}
|
||||
Err(e) => return Err(Error::QpackError(e)),
|
||||
}
|
||||
Ok(())
|
||||
@ -300,9 +300,9 @@ impl Http3Connection {
|
||||
}
|
||||
Ok(ReceiveOutput::ControlFrames(rest))
|
||||
}
|
||||
ReceiveOutput::NewStream(
|
||||
NewStreamType::Push(_) | NewStreamType::Http | NewStreamType::WebTransportStream(_),
|
||||
) => Ok(output),
|
||||
ReceiveOutput::NewStream(NewStreamType::Push(_))
|
||||
| ReceiveOutput::NewStream(NewStreamType::Http)
|
||||
| ReceiveOutput::NewStream(NewStreamType::WebTransportStream(_)) => Ok(output),
|
||||
ReceiveOutput::NewStream(_) => {
|
||||
unreachable!("NewStream should have been handled already")
|
||||
}
|
||||
@ -355,7 +355,7 @@ impl Http3Connection {
|
||||
match state {
|
||||
State::Handshaking => {
|
||||
if self.role == Role::Server
|
||||
&& conn.zero_rtt_state() == ZeroRttState::AcceptedServer
|
||||
&& conn.zero_rtt_state() == &ZeroRttState::AcceptedServer
|
||||
{
|
||||
self.state = Http3State::ZeroRtt;
|
||||
self.initialize_http3_connection(conn)?;
|
||||
|
103
third_party/rust/neqo-http3/src/connection_client.rs
vendored
103
third_party/rust/neqo-http3/src/connection_client.rs
vendored
@ -22,7 +22,7 @@ use neqo_crypto::{agent::CertificateInfo, AuthenticationStatus, ResumptionToken,
|
||||
use neqo_qpack::Stats as QpackStats;
|
||||
use neqo_transport::{
|
||||
AppError, Connection, ConnectionEvent, ConnectionId, ConnectionIdGenerator, Output,
|
||||
Stats as TransportStats, StreamId, StreamType, Version, ZeroRttState,
|
||||
QuicVersion, Stats as TransportStats, StreamId, StreamType, ZeroRttState,
|
||||
};
|
||||
use std::cell::RefCell;
|
||||
use std::fmt::Debug;
|
||||
@ -49,13 +49,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn alpn_from_quic_version(version: Version) -> &'static str {
|
||||
fn alpn_from_quic_version(version: QuicVersion) -> &'static str {
|
||||
match version {
|
||||
Version::Version2 | Version::Version1 => "h3",
|
||||
Version::Draft29 => "h3-29",
|
||||
Version::Draft30 => "h3-30",
|
||||
Version::Draft31 => "h3-31",
|
||||
Version::Draft32 => "h3-32",
|
||||
QuicVersion::Version1 => "h3",
|
||||
QuicVersion::Draft29 => "h3-29",
|
||||
QuicVersion::Draft30 => "h3-30",
|
||||
QuicVersion::Draft31 => "h3-31",
|
||||
QuicVersion::Draft32 => "h3-32",
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,7 +77,7 @@ impl Http3Client {
|
||||
/// Making a `neqo-transport::connection` may produce an error. This can only be a crypto error if
|
||||
/// the socket can't be created or configured.
|
||||
pub fn new(
|
||||
server_name: impl Into<String>,
|
||||
server_name: &str,
|
||||
cid_manager: Rc<RefCell<dyn ConnectionIdGenerator>>,
|
||||
local_addr: SocketAddr,
|
||||
remote_addr: SocketAddr,
|
||||
@ -90,13 +90,12 @@ impl Http3Client {
|
||||
&[alpn_from_quic_version(
|
||||
http3_parameters
|
||||
.get_connection_parameters()
|
||||
.get_versions()
|
||||
.initial(),
|
||||
.get_quic_version(),
|
||||
)],
|
||||
cid_manager,
|
||||
local_addr,
|
||||
remote_addr,
|
||||
http3_parameters.get_connection_parameters().clone(),
|
||||
*http3_parameters.get_connection_parameters(),
|
||||
now,
|
||||
)?,
|
||||
http3_parameters,
|
||||
@ -106,16 +105,17 @@ impl Http3Client {
|
||||
#[must_use]
|
||||
pub fn new_with_conn(c: Connection, http3_parameters: Http3Parameters) -> Self {
|
||||
let events = Http3ClientEvents::default();
|
||||
let webtransport = http3_parameters.get_webtransport();
|
||||
let push_streams = http3_parameters.get_max_concurrent_push_streams();
|
||||
let mut base_handler = Http3Connection::new(http3_parameters, Role::Client);
|
||||
if webtransport {
|
||||
if http3_parameters.get_webtransport() {
|
||||
base_handler.set_features_listener(events.clone());
|
||||
}
|
||||
Self {
|
||||
conn: c,
|
||||
events: events.clone(),
|
||||
push_handler: Rc::new(RefCell::new(PushController::new(push_streams, events))),
|
||||
push_handler: Rc::new(RefCell::new(PushController::new(
|
||||
http3_parameters.get_max_concurrent_push_streams(),
|
||||
events,
|
||||
))),
|
||||
base_handler,
|
||||
}
|
||||
}
|
||||
@ -219,7 +219,7 @@ impl Http3Client {
|
||||
debug_assert_eq!(Ok(true), res);
|
||||
return Err(Error::FatalError);
|
||||
}
|
||||
if self.conn.zero_rtt_state() == ZeroRttState::Sending {
|
||||
if *self.conn.zero_rtt_state() == ZeroRttState::Sending {
|
||||
self.base_handler
|
||||
.set_0rtt_settings(&mut self.conn, settings)?;
|
||||
self.events
|
||||
@ -834,16 +834,17 @@ mod tests {
|
||||
use neqo_common::{event::Provider, qtrace, Datagram, Decoder, Encoder};
|
||||
use neqo_crypto::{AllowZeroRtt, AntiReplay, ResumptionToken};
|
||||
use neqo_qpack::{encoder::QPackEncoder, QpackSettings};
|
||||
use neqo_transport::tparams::{self, TransportParameter};
|
||||
use neqo_transport::{
|
||||
ConnectionError, ConnectionEvent, ConnectionParameters, Output, State, StreamId,
|
||||
StreamType, Version, RECV_BUFFER_SIZE, SEND_BUFFER_SIZE,
|
||||
StreamType, RECV_BUFFER_SIZE, SEND_BUFFER_SIZE,
|
||||
};
|
||||
use std::convert::TryFrom;
|
||||
use std::mem;
|
||||
use std::time::Duration;
|
||||
use test_fixture::{
|
||||
addr, anti_replay, default_server_h3, fixture_init, new_server, now,
|
||||
CountingConnectionIdGenerator, DEFAULT_ALPN_H3, DEFAULT_KEYS, DEFAULT_SERVER_NAME,
|
||||
addr, anti_replay, default_server_h3, fixture_init, now, CountingConnectionIdGenerator,
|
||||
DEFAULT_ALPN_H3, DEFAULT_KEYS, DEFAULT_SERVER_NAME,
|
||||
};
|
||||
|
||||
fn assert_closed(client: &Http3Client, expected: &Error) {
|
||||
@ -868,11 +869,6 @@ mod tests {
|
||||
addr(),
|
||||
addr(),
|
||||
Http3Parameters::default()
|
||||
.connection_parameters(
|
||||
// Disable compatible upgrade, which complicates tests.
|
||||
ConnectionParameters::default()
|
||||
.versions(Version::default(), vec![Version::default()]),
|
||||
)
|
||||
.max_table_size_encoder(max_table_size)
|
||||
.max_table_size_decoder(max_table_size)
|
||||
.max_blocked_streams(100)
|
||||
@ -1021,9 +1017,9 @@ mod tests {
|
||||
self.settings.encode(&mut enc);
|
||||
assert_eq!(
|
||||
self.conn
|
||||
.stream_send(self.control_stream_id.unwrap(), enc.as_ref())
|
||||
.stream_send(self.control_stream_id.unwrap(), &enc[..])
|
||||
.unwrap(),
|
||||
enc.len()
|
||||
enc[..].len()
|
||||
);
|
||||
}
|
||||
|
||||
@ -1164,10 +1160,19 @@ mod tests {
|
||||
.borrow_mut()
|
||||
.encode_header_block(&mut self.conn, headers, stream_id);
|
||||
let hframe = HFrame::Headers {
|
||||
header_block: header_block.as_ref().to_vec(),
|
||||
header_block: header_block.to_vec(),
|
||||
};
|
||||
hframe.encode(encoder);
|
||||
}
|
||||
|
||||
pub fn set_max_uni_stream(&mut self, max_stream: u64) {
|
||||
self.conn
|
||||
.set_local_tparam(
|
||||
tparams::INITIAL_MAX_STREAMS_UNI,
|
||||
TransportParameter::Integer(max_stream),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn handshake_only(client: &mut Http3Client, server: &mut TestServer) -> Output {
|
||||
@ -1419,13 +1424,10 @@ mod tests {
|
||||
client: &mut Http3Client,
|
||||
server: &mut TestServer,
|
||||
stream_id: StreamId,
|
||||
response: impl AsRef<[u8]>,
|
||||
response: &[u8],
|
||||
close_stream: bool,
|
||||
) {
|
||||
let _ = server
|
||||
.conn
|
||||
.stream_send(stream_id, response.as_ref())
|
||||
.unwrap();
|
||||
let _ = server.conn.stream_send(stream_id, response).unwrap();
|
||||
if close_stream {
|
||||
server.conn.stream_close_send(stream_id).unwrap();
|
||||
}
|
||||
@ -1457,7 +1459,7 @@ mod tests {
|
||||
};
|
||||
let mut d = Encoder::default();
|
||||
frame.encode(&mut d);
|
||||
let _ = conn.stream_send(stream_id, d.as_ref()).unwrap();
|
||||
let _ = conn.stream_send(stream_id, &d).unwrap();
|
||||
}
|
||||
|
||||
fn send_push_data_and_exchange_packets(
|
||||
@ -1498,7 +1500,7 @@ mod tests {
|
||||
frame.encode(&mut d);
|
||||
server
|
||||
.conn
|
||||
.stream_send(server.control_stream_id.unwrap(), d.as_ref())
|
||||
.stream_send(server.control_stream_id.unwrap(), &d)
|
||||
.unwrap();
|
||||
|
||||
let out = server.conn.process(None, now());
|
||||
@ -1534,13 +1536,13 @@ mod tests {
|
||||
conn: &mut Connection,
|
||||
push_stream_id: StreamId,
|
||||
push_id: u8,
|
||||
data: impl AsRef<[u8]>,
|
||||
data: &[u8],
|
||||
close_push_stream: bool,
|
||||
) {
|
||||
// send data
|
||||
let _ = conn.stream_send(push_stream_id, PUSH_STREAM_TYPE).unwrap();
|
||||
let _ = conn.stream_send(push_stream_id, &[push_id]).unwrap();
|
||||
let _ = conn.stream_send(push_stream_id, data.as_ref()).unwrap();
|
||||
let _ = conn.stream_send(push_stream_id, data).unwrap();
|
||||
if close_push_stream {
|
||||
conn.stream_close_send(push_stream_id).unwrap();
|
||||
}
|
||||
@ -2410,7 +2412,7 @@ mod tests {
|
||||
let mut enc = Encoder::default();
|
||||
data_frame.encode(&mut enc);
|
||||
|
||||
(vec![0_u8; size], enc.as_ref().to_vec())
|
||||
(vec![0_u8; size], enc.to_vec())
|
||||
}
|
||||
|
||||
// Send 2 frames. For the second one we can only send 63 bytes.
|
||||
@ -3890,7 +3892,7 @@ mod tests {
|
||||
server.settings.encode(&mut enc);
|
||||
let mut sent = server.conn.stream_send(control_stream, CONTROL_STREAM_TYPE);
|
||||
assert_eq!(sent.unwrap(), CONTROL_STREAM_TYPE.len());
|
||||
sent = server.conn.stream_send(control_stream, enc.as_ref());
|
||||
sent = server.conn.stream_send(control_stream, &enc);
|
||||
assert_eq!(sent.unwrap(), enc.len());
|
||||
|
||||
let out = server.conn.process(None, now());
|
||||
@ -4529,10 +4531,7 @@ mod tests {
|
||||
let d_frame = HFrame::Data { len: 3 };
|
||||
d_frame.encode(&mut d);
|
||||
d.encode(&[0x61, 0x62, 0x63]);
|
||||
let _ = server
|
||||
.conn
|
||||
.stream_send(request_stream_id, d.as_ref())
|
||||
.unwrap();
|
||||
let _ = server.conn.stream_send(request_stream_id, &d[..]).unwrap();
|
||||
server.conn.stream_close_send(request_stream_id).unwrap();
|
||||
|
||||
let out = server.conn.process(None, now());
|
||||
@ -6088,9 +6087,9 @@ mod tests {
|
||||
for f in H3_RESERVED_FRAME_TYPES {
|
||||
let mut enc = Encoder::default();
|
||||
enc.encode_varint(*f);
|
||||
test_wrong_frame_on_control_stream(enc.as_ref());
|
||||
test_wrong_frame_on_push_stream(enc.as_ref());
|
||||
test_wrong_frame_on_request_stream(enc.as_ref());
|
||||
test_wrong_frame_on_control_stream(&enc);
|
||||
test_wrong_frame_on_push_stream(&enc);
|
||||
test_wrong_frame_on_request_stream(&enc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6111,7 +6110,7 @@ mod tests {
|
||||
// The settings frame contains a reserved settings type and some value (0x1).
|
||||
enc.encode_varint(*s);
|
||||
enc.encode_varint(1_u64);
|
||||
let sent = server.conn.stream_send(control_stream, enc.as_ref());
|
||||
let sent = server.conn.stream_send(control_stream, &enc);
|
||||
assert_eq!(sent, Ok(4));
|
||||
let out = server.conn.process(None, now());
|
||||
client.process(out.dgram(), now());
|
||||
@ -6370,10 +6369,8 @@ mod tests {
|
||||
#[test]
|
||||
fn client_control_stream_create_failed() {
|
||||
let mut client = default_http3_client();
|
||||
let mut server = TestServer::new_with_conn(new_server(
|
||||
DEFAULT_ALPN_H3,
|
||||
ConnectionParameters::default().max_streams(StreamType::UniDi, 0),
|
||||
));
|
||||
let mut server = TestServer::new();
|
||||
server.set_max_uni_stream(0);
|
||||
handshake_client_error(&mut client, &mut server, &Error::StreamLimitError);
|
||||
}
|
||||
|
||||
@ -6381,10 +6378,8 @@ mod tests {
|
||||
#[test]
|
||||
fn client_qpack_stream_create_failed() {
|
||||
let mut client = default_http3_client();
|
||||
let mut server = TestServer::new_with_conn(new_server(
|
||||
DEFAULT_ALPN_H3,
|
||||
ConnectionParameters::default().max_streams(StreamType::UniDi, 2),
|
||||
));
|
||||
let mut server = TestServer::new();
|
||||
server.set_max_uni_stream(2);
|
||||
handshake_client_error(&mut client, &mut server, &Error::StreamLimitError);
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ impl ControlStreamLocal {
|
||||
pub fn queue_frame(&mut self, f: &HFrame) {
|
||||
let mut enc = Encoder::default();
|
||||
f.encode(&mut enc);
|
||||
self.stream.buffer(enc.as_ref());
|
||||
self.stream.buffer(&enc);
|
||||
}
|
||||
|
||||
pub fn queue_update_priority(&mut self, stream_id: StreamId) {
|
||||
@ -80,7 +80,7 @@ impl ControlStreamLocal {
|
||||
if let Some(hframe) = stream.priority_update_frame() {
|
||||
let mut enc = Encoder::new();
|
||||
hframe.encode(&mut enc);
|
||||
if self.stream.send_atomic(conn, enc.as_ref())? {
|
||||
if self.stream.send_atomic(conn, &enc)? {
|
||||
stream.priority_update_sent();
|
||||
} else {
|
||||
self.outstanding_priority_update.push_front(update_id);
|
||||
|
@ -377,8 +377,7 @@ impl WebTransportSession {
|
||||
};
|
||||
let mut encoder = Encoder::default();
|
||||
close_frame.encode(&mut encoder);
|
||||
self.control_stream_send
|
||||
.send_data_atomic(conn, encoder.as_ref())?;
|
||||
self.control_stream_send.send_data_atomic(conn, &encoder)?;
|
||||
self.control_stream_send.close(conn)?;
|
||||
self.state = if self.control_stream_send.done() {
|
||||
SessionState::Done
|
||||
|
@ -138,7 +138,7 @@ impl HFrame {
|
||||
|
||||
update_frame.encode(&priority_enc);
|
||||
enc.encode_varint(update_frame.len() as u64);
|
||||
enc.encode(update_frame.as_ref());
|
||||
enc.encode(&update_frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ use test_fixture::{default_client, default_server, now};
|
||||
pub fn enc_dec<T: FrameDecoder<T>>(d: &Encoder, st: &str, remaining: usize) -> T {
|
||||
// For data, headers and push_promise we do not read all bytes from the buffer
|
||||
let d2 = Encoder::from_hex(st);
|
||||
assert_eq!(d.as_ref(), &d2.as_ref()[..d.as_ref().len()]);
|
||||
assert_eq!(&d[..], &d2[..d.len()]);
|
||||
|
||||
let mut conn_c = default_client();
|
||||
let mut conn_s = default_server();
|
||||
@ -36,7 +36,7 @@ pub fn enc_dec<T: FrameDecoder<T>>(d: &Encoder, st: &str, remaining: usize) -> T
|
||||
|
||||
// conver string into u8 vector
|
||||
let buf = Encoder::from_hex(st);
|
||||
conn_s.stream_send(stream_id, buf.as_ref()).unwrap();
|
||||
conn_s.stream_send(stream_id, &buf[..]).unwrap();
|
||||
let out = conn_s.process(None, now());
|
||||
mem::drop(conn_c.process(out.dgram(), now()));
|
||||
|
||||
|
@ -114,7 +114,7 @@ pub fn headers_valid(headers: &[Header], message_type: MessageType) -> Res<()> {
|
||||
let pseudo_header_mask = match message_type {
|
||||
MessageType::Response => enum_set!(PseudoHeaderState::Status),
|
||||
MessageType::Request => {
|
||||
if method_value == Some("CONNECT") {
|
||||
if method_value == Some(&"CONNECT".to_string()) {
|
||||
PseudoHeaderState::Method | PseudoHeaderState::Authority
|
||||
} else {
|
||||
PseudoHeaderState::Method | PseudoHeaderState::Scheme | PseudoHeaderState::Path
|
||||
@ -124,7 +124,7 @@ pub fn headers_valid(headers: &[Header], message_type: MessageType) -> Res<()> {
|
||||
|
||||
if (MessageType::Request == message_type)
|
||||
&& pseudo_state.contains(PseudoHeaderState::Protocol)
|
||||
&& method_value != Some("CONNECT")
|
||||
&& method_value != Some(&"CONNECT".to_string())
|
||||
{
|
||||
return Err(Error::InvalidHeader);
|
||||
}
|
||||
|
15
third_party/rust/neqo-http3/src/lib.rs
vendored
15
third_party/rust/neqo-http3/src/lib.rs
vendored
@ -60,6 +60,11 @@ pub use stream_type_reader::NewStreamType;
|
||||
type Res<T> = Result<T, Error>;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[allow(
|
||||
renamed_and_removed_lints,
|
||||
clippy::pub_enum_variant_names,
|
||||
clippy::enum_variant_names
|
||||
)]
|
||||
pub enum Error {
|
||||
HttpNoError,
|
||||
HttpGeneralProtocol,
|
||||
@ -148,7 +153,8 @@ impl Error {
|
||||
| Self::HttpId
|
||||
| Self::HttpSettings
|
||||
| Self::HttpMissingSettings
|
||||
| Self::QpackError(QpackError::EncoderStream | QpackError::DecoderStream)
|
||||
| Self::QpackError(QpackError::EncoderStream)
|
||||
| Self::QpackError(QpackError::DecoderStream)
|
||||
)
|
||||
}
|
||||
|
||||
@ -162,9 +168,10 @@ impl Error {
|
||||
#[must_use]
|
||||
pub fn map_stream_send_errors(err: &Error) -> Self {
|
||||
match err {
|
||||
Self::TransportError(
|
||||
TransportError::InvalidStreamId | TransportError::FinalSizeError,
|
||||
) => Error::TransportStreamDoesNotExist,
|
||||
Self::TransportError(TransportError::InvalidStreamId)
|
||||
| Self::TransportError(TransportError::FinalSizeError) => {
|
||||
Error::TransportStreamDoesNotExist
|
||||
}
|
||||
Self::TransportError(TransportError::InvalidInput) => Error::InvalidInput,
|
||||
_ => {
|
||||
debug_assert!(false, "Unexpected error");
|
||||
|
@ -210,7 +210,7 @@ impl SendStream for SendMessage {
|
||||
data_frame.encode(&mut enc);
|
||||
let sent_fh = self
|
||||
.stream
|
||||
.send_atomic(conn, enc.as_ref())
|
||||
.send_atomic(conn, &enc)
|
||||
.map_err(|e| Error::map_stream_send_errors(&e))?;
|
||||
debug_assert!(sent_fh);
|
||||
|
||||
@ -300,7 +300,7 @@ impl SendStream for SendMessage {
|
||||
};
|
||||
let mut enc = Encoder::default();
|
||||
data_frame.encode(&mut enc);
|
||||
self.stream.buffer(enc.as_ref());
|
||||
self.stream.buffer(&enc);
|
||||
self.stream.buffer(buf);
|
||||
mem::drop(self.stream.send_buffer(conn)?);
|
||||
Ok(())
|
||||
|
35
third_party/rust/neqo-http3/src/server.rs
vendored
35
third_party/rust/neqo-http3/src/server.rs
vendored
@ -62,9 +62,9 @@ impl Http3Server {
|
||||
protocols,
|
||||
anti_replay,
|
||||
zero_rtt_checker
|
||||
.unwrap_or_else(|| Box::new(HttpZeroRttChecker::new(http3_parameters.clone()))),
|
||||
.unwrap_or_else(|| Box::new(HttpZeroRttChecker::new(http3_parameters))),
|
||||
cid_manager,
|
||||
http3_parameters.get_connection_parameters().clone(),
|
||||
*http3_parameters.get_connection_parameters(),
|
||||
)?,
|
||||
http3_parameters,
|
||||
http3_handlers: HashMap::new(),
|
||||
@ -150,12 +150,10 @@ impl Http3Server {
|
||||
|
||||
fn process_events(&mut self, conn: &mut ActiveConnectionRef, now: Instant) {
|
||||
let mut remove = false;
|
||||
let http3_parameters = &self.http3_parameters;
|
||||
let http3_parameters = self.http3_parameters;
|
||||
{
|
||||
let handler = self.http3_handlers.entry(conn.clone()).or_insert_with(|| {
|
||||
Rc::new(RefCell::new(Http3ServerHandler::new(
|
||||
http3_parameters.clone(),
|
||||
)))
|
||||
Rc::new(RefCell::new(Http3ServerHandler::new(http3_parameters)))
|
||||
});
|
||||
handler
|
||||
.borrow_mut()
|
||||
@ -344,7 +342,12 @@ mod tests {
|
||||
|
||||
fn assert_closed(hconn: &mut Http3Server, expected: &Error) {
|
||||
let err = ConnectionError::Application(expected.code());
|
||||
let closed = |e| matches!(e, Http3ServerEvent::StateChange{ state: Http3State::Closing(e) | Http3State::Closed(e), .. } if e == err);
|
||||
let closed = |e| {
|
||||
matches!(e,
|
||||
Http3ServerEvent::StateChange{ state: Http3State::Closing(e), .. }
|
||||
| Http3ServerEvent::StateChange{ state: Http3State::Closed(e), .. }
|
||||
if e == err)
|
||||
};
|
||||
assert!(hconn.events().any(closed));
|
||||
}
|
||||
|
||||
@ -611,7 +614,7 @@ mod tests {
|
||||
};
|
||||
let mut e = Encoder::default();
|
||||
frame.encode(&mut e);
|
||||
peer_conn.control_send(e.as_ref());
|
||||
peer_conn.control_send(&e);
|
||||
let out = peer_conn.process(None, now());
|
||||
hconn.process(out.dgram(), now());
|
||||
// check if the given connection got closed on invalid stream ids
|
||||
@ -1140,7 +1143,7 @@ mod tests {
|
||||
|
||||
/// Perform a handshake, then another with the token from the first.
|
||||
/// The second should always resume, but it might not always accept early data.
|
||||
fn zero_rtt_with_settings(conn_params: Http3Parameters, zero_rtt: ZeroRttState) {
|
||||
fn zero_rtt_with_settings(conn_params: Http3Parameters, zero_rtt: &ZeroRttState) {
|
||||
let (_, mut client) = connect();
|
||||
let token = client.events().find_map(|e| {
|
||||
if let ConnectionEvent::ResumptionToken(token) = e {
|
||||
@ -1162,7 +1165,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn zero_rtt() {
|
||||
zero_rtt_with_settings(http3params(DEFAULT_SETTINGS), ZeroRttState::AcceptedClient);
|
||||
zero_rtt_with_settings(http3params(DEFAULT_SETTINGS), &ZeroRttState::AcceptedClient);
|
||||
}
|
||||
|
||||
/// A larger QPACK decoder table size isn't an impediment to 0-RTT.
|
||||
@ -1173,7 +1176,7 @@ mod tests {
|
||||
max_table_size_decoder: DEFAULT_SETTINGS.max_table_size_decoder + 1,
|
||||
..DEFAULT_SETTINGS
|
||||
}),
|
||||
ZeroRttState::AcceptedClient,
|
||||
&ZeroRttState::AcceptedClient,
|
||||
);
|
||||
}
|
||||
|
||||
@ -1185,7 +1188,7 @@ mod tests {
|
||||
max_table_size_decoder: DEFAULT_SETTINGS.max_table_size_decoder - 1,
|
||||
..DEFAULT_SETTINGS
|
||||
}),
|
||||
ZeroRttState::Rejected,
|
||||
&ZeroRttState::Rejected,
|
||||
);
|
||||
}
|
||||
|
||||
@ -1197,7 +1200,7 @@ mod tests {
|
||||
max_blocked_streams: DEFAULT_SETTINGS.max_blocked_streams + 1,
|
||||
..DEFAULT_SETTINGS
|
||||
}),
|
||||
ZeroRttState::AcceptedClient,
|
||||
&ZeroRttState::AcceptedClient,
|
||||
);
|
||||
}
|
||||
|
||||
@ -1209,7 +1212,7 @@ mod tests {
|
||||
max_blocked_streams: DEFAULT_SETTINGS.max_blocked_streams - 1,
|
||||
..DEFAULT_SETTINGS
|
||||
}),
|
||||
ZeroRttState::Rejected,
|
||||
&ZeroRttState::Rejected,
|
||||
);
|
||||
}
|
||||
|
||||
@ -1221,7 +1224,7 @@ mod tests {
|
||||
max_table_size_encoder: DEFAULT_SETTINGS.max_table_size_encoder - 1,
|
||||
..DEFAULT_SETTINGS
|
||||
}),
|
||||
ZeroRttState::AcceptedClient,
|
||||
&ZeroRttState::AcceptedClient,
|
||||
);
|
||||
}
|
||||
|
||||
@ -1301,6 +1304,6 @@ mod tests {
|
||||
|
||||
connect_transport(&mut server, &mut client, true);
|
||||
assert!(client.tls_info().unwrap().resumed());
|
||||
assert_eq!(client.zero_rtt_state(), ZeroRttState::Rejected);
|
||||
assert_eq!(client.zero_rtt_state(), &ZeroRttState::Rejected);
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ impl NewStreamType {
|
||||
}
|
||||
(_, StreamType::BiDi, Role::Server) => Err(Error::HttpFrame),
|
||||
(HTTP3_UNI_STREAM_TYPE_PUSH, StreamType::UniDi, Role::Server)
|
||||
| (H3_FRAME_TYPE_HEADERS, StreamType::BiDi, Role::Client)
|
||||
| (_, StreamType::BiDi, Role::Client) => Err(Error::HttpStreamCreation),
|
||||
_ => Ok(Some(NewStreamType::Unknown)),
|
||||
}
|
||||
@ -196,13 +197,13 @@ impl NewStreamHeadReader {
|
||||
|
||||
fn map_stream_fin(decoded: Option<NewStreamType>) -> Res<Option<NewStreamType>> {
|
||||
match decoded {
|
||||
Some(NewStreamType::Control | NewStreamType::Encoder | NewStreamType::Decoder) => {
|
||||
Err(Error::HttpClosedCriticalStream)
|
||||
}
|
||||
Some(NewStreamType::Control)
|
||||
| Some(NewStreamType::Encoder)
|
||||
| Some(NewStreamType::Decoder) => Err(Error::HttpClosedCriticalStream),
|
||||
None => Err(Error::HttpStreamCreation),
|
||||
Some(NewStreamType::Http) => Err(Error::HttpFrame),
|
||||
Some(NewStreamType::Unknown) => Ok(decoded),
|
||||
Some(NewStreamType::Push(_) | NewStreamType::WebTransportStream(_)) => {
|
||||
Some(NewStreamType::Push(_)) | Some(NewStreamType::WebTransportStream(_)) => {
|
||||
unreachable!("PushStream and WebTransport are mapped to None at this stage.")
|
||||
}
|
||||
}
|
||||
@ -317,7 +318,7 @@ mod tests {
|
||||
for i in to_encode {
|
||||
enc.encode_varint(*i);
|
||||
}
|
||||
self.decode_buffer(enc.as_ref(), fin, outcome, done);
|
||||
self.decode_buffer(&enc[..], fin, outcome, done);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,8 +139,8 @@ fn wrong_setting_value() {
|
||||
};
|
||||
settings.encode(&mut enc);
|
||||
assert_eq!(
|
||||
server.stream_send(control, enc.as_ref()).unwrap(),
|
||||
enc.as_ref().len()
|
||||
server.stream_send(control, &enc[..]).unwrap(),
|
||||
enc[..].len()
|
||||
);
|
||||
|
||||
exchange_packets2(&mut client, &mut server);
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"be8c8af80d916302d316e9e457bb3dc7a9f9469f4f15fb89d7eb1d5e8f1bad3d","src/decoder.rs":"8bd336c91cca989883106a9d0bf26b117d224e0e7643960c3e97d0168d1853c4","src/decoder_instructions.rs":"19d47158bc09551b449be205f5cd5ea83e6984c4e4d3e7d4b95938b09617015e","src/encoder.rs":"b888a819595fec47037d508b943f5ff04ed52ea376bef1f90e08edc6576e773c","src/encoder_instructions.rs":"a7f1d3a4f8ae941286d0aba81037a8df3ef85e275392ef31d9938e9314c706db","src/header_block.rs":"7910ddc28b44d2065070cb2d87ab3cfbb905cce912b23d8b12b0f0add5691ceb","src/huffman.rs":"3a9edaf827343ec6e43cfd50fcc0d0077287947160ae630da5c3ddaaefedd010","src/huffman_decode_helper.rs":"2970c57f052878b727c2f764490c54184f5c2608e1d6aa961c3b01509e290122","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"4e42b609aabfbe4c19582c13007abbc82a6560c174d56559ea344975c3473454","src/prefix.rs":"72c587c40aef4ed38cf13b2de91091d671611679be2a9da6f0b24abafaf50dc5","src/qlog.rs":"7618085e27bb3fb1f4d1c73ba501b9a293723293c4020b7cc4129676eb278131","src/qpack_send_buf.rs":"49ded6607ec0859cb3edc5a38ff48f4d2d292f0721673d4e20700d07ac324557","src/reader.rs":"be265cc8c317512f266fafdcc835d0e413caf5280a7cc945bfe6e7e849529d67","src/static_table.rs":"fda9d5c6f38f94b0bf92d3afdf8432dce6e27e189736596e16727090c77b78ec","src/stats.rs":"624dfa3b40858c304097bb0ce5b1be1bb4d7916b1abfc222f1aa705907009730","src/table.rs":"f7091bdd9ad1f8fe3b2298a7dbfd3d285c212d69569cda54f9bcf251cb758a21"},"package":null}
|
||||
{"files":{"Cargo.toml":"ffbf61e358a81f58d8b4f0ca89031d53879ec8e45851a0f1bc2b583229feb815","src/decoder.rs":"8bd336c91cca989883106a9d0bf26b117d224e0e7643960c3e97d0168d1853c4","src/decoder_instructions.rs":"19d47158bc09551b449be205f5cd5ea83e6984c4e4d3e7d4b95938b09617015e","src/encoder.rs":"e72cbcdbe24cbe13ad5cbcbb0df8981a2ea67331f296ec7784480bc28ae01eef","src/encoder_instructions.rs":"a7f1d3a4f8ae941286d0aba81037a8df3ef85e275392ef31d9938e9314c706db","src/header_block.rs":"7910ddc28b44d2065070cb2d87ab3cfbb905cce912b23d8b12b0f0add5691ceb","src/huffman.rs":"3a9edaf827343ec6e43cfd50fcc0d0077287947160ae630da5c3ddaaefedd010","src/huffman_decode_helper.rs":"2970c57f052878b727c2f764490c54184f5c2608e1d6aa961c3b01509e290122","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"29c5e47f8a4cf9c0a5dfdc614594868db22bc25b9688e5efdbc041cd222a17e5","src/prefix.rs":"72c587c40aef4ed38cf13b2de91091d671611679be2a9da6f0b24abafaf50dc5","src/qlog.rs":"7618085e27bb3fb1f4d1c73ba501b9a293723293c4020b7cc4129676eb278131","src/qpack_send_buf.rs":"49ded6607ec0859cb3edc5a38ff48f4d2d292f0721673d4e20700d07ac324557","src/reader.rs":"be265cc8c317512f266fafdcc835d0e413caf5280a7cc945bfe6e7e849529d67","src/static_table.rs":"fda9d5c6f38f94b0bf92d3afdf8432dce6e27e189736596e16727090c77b78ec","src/stats.rs":"624dfa3b40858c304097bb0ce5b1be1bb4d7916b1abfc222f1aa705907009730","src/table.rs":"f7091bdd9ad1f8fe3b2298a7dbfd3d285c212d69569cda54f9bcf251cb758a21"},"package":null}
|
3
third_party/rust/neqo-qpack/Cargo.toml
vendored
3
third_party/rust/neqo-qpack/Cargo.toml
vendored
@ -1,9 +1,8 @@
|
||||
[package]
|
||||
name = "neqo-qpack"
|
||||
version = "0.6.0"
|
||||
version = "0.5.7"
|
||||
authors = ["Dragana Damjanovic <dragana.damjano@gmail.com>"]
|
||||
edition = "2018"
|
||||
rust-version = "1.57.0"
|
||||
license = "MIT/Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
|
5
third_party/rust/neqo-qpack/src/encoder.rs
vendored
5
third_party/rust/neqo-qpack/src/encoder.rs
vendored
@ -516,7 +516,7 @@ mod tests {
|
||||
use crate::QpackSettings;
|
||||
use neqo_transport::{ConnectionParameters, StreamId, StreamType};
|
||||
use std::mem;
|
||||
use test_fixture::{default_client, default_server, handshake, new_server, now, DEFAULT_ALPN};
|
||||
use test_fixture::{configure_server, default_client, default_server, handshake, now};
|
||||
|
||||
struct TestEncoder {
|
||||
encoder: QPackEncoder,
|
||||
@ -571,8 +571,7 @@ mod tests {
|
||||
fn connect_generic(huffman: bool, max_data: Option<u64>) -> TestEncoder {
|
||||
let mut conn = default_client();
|
||||
let mut peer_conn = max_data.map_or_else(default_server, |max| {
|
||||
new_server(
|
||||
DEFAULT_ALPN,
|
||||
configure_server(
|
||||
ConnectionParameters::default()
|
||||
.max_stream_data(StreamType::UniDi, true, max)
|
||||
.max_stream_data(StreamType::BiDi, true, max)
|
||||
|
5
third_party/rust/neqo-qpack/src/lib.rs
vendored
5
third_party/rust/neqo-qpack/src/lib.rs
vendored
@ -39,6 +39,11 @@ pub struct QpackSettings {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[allow(
|
||||
renamed_and_removed_lints,
|
||||
clippy::pub_enum_variant_names,
|
||||
clippy::enum_variant_names
|
||||
)]
|
||||
pub enum Error {
|
||||
DecompressionFailed,
|
||||
EncoderStream,
|
||||
|
File diff suppressed because one or more lines are too long
3
third_party/rust/neqo-transport/Cargo.toml
vendored
3
third_party/rust/neqo-transport/Cargo.toml
vendored
@ -1,9 +1,8 @@
|
||||
[package]
|
||||
name = "neqo-transport"
|
||||
version = "0.6.0"
|
||||
version = "0.5.7"
|
||||
authors = ["EKR <ekr@rtfm.com>", "Andy Grover <agrover@mozilla.com>"]
|
||||
edition = "2018"
|
||||
rust-version = "1.57.0"
|
||||
license = "MIT/Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
|
@ -127,7 +127,7 @@ impl AddressValidation {
|
||||
|
||||
// Include the token identifier ("Retry"/~) in the AAD, then keep it for plaintext.
|
||||
let mut buf = Self::encode_aad(peer_address, retry);
|
||||
let encrypted = self.self_encrypt.seal(buf.as_ref(), data.as_ref())?;
|
||||
let encrypted = self.self_encrypt.seal(&buf, &data)?;
|
||||
buf.truncate(TOKEN_IDENTIFIER_RETRY.len());
|
||||
buf.encode(&encrypted);
|
||||
Ok(buf.into())
|
||||
@ -165,7 +165,7 @@ impl AddressValidation {
|
||||
now: Instant,
|
||||
) -> Option<ConnectionId> {
|
||||
let peer_addr = Self::encode_aad(peer_address, retry);
|
||||
let data = self.self_encrypt.open(peer_addr.as_ref(), token).ok()?;
|
||||
let data = self.self_encrypt.open(&peer_addr, token).ok()?;
|
||||
let mut dec = Decoder::new(&data);
|
||||
match dec.decode_uint(4) {
|
||||
Some(d) => {
|
||||
|
@ -152,7 +152,7 @@ impl<T: WindowAdjustment> CongestionControl for ClassicCongestionControl<T> {
|
||||
let is_app_limited = self.app_limited();
|
||||
qtrace!(
|
||||
[self],
|
||||
"limited={}, bytes_in_flight={}, cwnd={}, state={:?} pacing_burst_size={}",
|
||||
"app limited={}, bytes_in_flight:{}, cwnd: {}, state: {:?} pacing_burst_size: {}",
|
||||
is_app_limited,
|
||||
self.bytes_in_flight,
|
||||
self.congestion_window,
|
||||
@ -413,7 +413,7 @@ impl<T: WindowAdjustment> ClassicCongestionControl<T> {
|
||||
continue;
|
||||
}
|
||||
if let Some(t) = start {
|
||||
if p.time_sent.checked_duration_since(t).unwrap() > pc_period {
|
||||
if p.time_sent.duration_since(t) > pc_period {
|
||||
qinfo!([self], "persistent congestion");
|
||||
self.congestion_window = CWND_MIN;
|
||||
self.acked_bytes = 0;
|
||||
|
6
third_party/rust/neqo-transport/src/cid.rs
vendored
6
third_party/rust/neqo-transport/src/cid.rs
vendored
@ -450,10 +450,6 @@ impl ConnectionIdManager {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generator(&self) -> Rc<RefCell<dyn ConnectionIdGenerator>> {
|
||||
Rc::clone(&self.generator)
|
||||
}
|
||||
|
||||
pub fn decoder(&self) -> ConnectionIdDecoderRef {
|
||||
ConnectionIdDecoderRef {
|
||||
generator: self.generator.deref().borrow(),
|
||||
@ -492,8 +488,6 @@ impl ConnectionIdManager {
|
||||
|
||||
/// During the handshake, a server needs to regard the client's choice of destination
|
||||
/// connection ID as valid. This function saves it in the store in a special place.
|
||||
/// Note that this is only done *after* an Initial packet from the client is
|
||||
/// successfully processed.
|
||||
pub fn add_odcid(&mut self, cid: ConnectionId) {
|
||||
let entry = ConnectionIdEntry::new(CONNECTION_ID_SEQNO_ODCID, cid, ());
|
||||
self.connection_ids.add_local(entry);
|
||||
|
@ -41,7 +41,9 @@ use crate::frame::{
|
||||
CloseError, Frame, FrameType, FRAME_TYPE_CONNECTION_CLOSE_APPLICATION,
|
||||
FRAME_TYPE_CONNECTION_CLOSE_TRANSPORT,
|
||||
};
|
||||
use crate::packet::{DecryptedPacket, PacketBuilder, PacketNumber, PacketType, PublicPacket};
|
||||
use crate::packet::{
|
||||
DecryptedPacket, PacketBuilder, PacketNumber, PacketType, PublicPacket, QuicVersion,
|
||||
};
|
||||
use crate::path::{Path, PathRef, Paths};
|
||||
use crate::quic_datagrams::{DatagramTracking, QuicDatagrams};
|
||||
use crate::recovery::{LossRecovery, RecoveryToken, SendProfile};
|
||||
@ -50,12 +52,10 @@ pub use crate::send_stream::{RetransmissionPriority, TransmissionPriority};
|
||||
use crate::stats::{Stats, StatsCell};
|
||||
use crate::stream_id::StreamType;
|
||||
use crate::streams::Streams;
|
||||
use crate::tparams::{
|
||||
self, TransportParameter, TransportParameterId, TransportParameters, TransportParametersHandler,
|
||||
};
|
||||
use crate::tparams::{self, TransportParameter, TransportParameters, TransportParametersHandler};
|
||||
use crate::tracking::{AckTracker, PacketNumberSpace, SentPacket};
|
||||
use crate::version::{Version, WireVersion};
|
||||
use crate::{qlog, AppError, ConnectionError, Error, Res, StreamId};
|
||||
use crate::{qlog, StreamId};
|
||||
use crate::{AppError, ConnectionError, Error, Res};
|
||||
|
||||
mod idle;
|
||||
pub mod params;
|
||||
@ -79,7 +79,7 @@ struct Packet(Vec<u8>);
|
||||
/// handshake. This is a hack, but a useful one.
|
||||
const EXTRA_INITIALS: usize = 4;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum ZeroRttState {
|
||||
Init,
|
||||
Sending,
|
||||
@ -218,7 +218,6 @@ impl AddressValidationInfo {
|
||||
/// remote) continue processing until `state()` returns `Closed`.
|
||||
pub struct Connection {
|
||||
role: Role,
|
||||
version: Version,
|
||||
state: State,
|
||||
tps: Rc<RefCell<TransportParametersHandler>>,
|
||||
/// What we are doing with 0-RTT.
|
||||
@ -247,8 +246,6 @@ pub struct Connection {
|
||||
/// when they are either just reordered or we haven't been able to install keys yet.
|
||||
/// In particular, this occurs when asynchronous certificate validation happens.
|
||||
saved_datagrams: SavedDatagrams,
|
||||
/// Some packets were received, but not tracked.
|
||||
received_untracked: bool,
|
||||
|
||||
/// This is responsible for the QuicDatagrams' handling:
|
||||
/// https://datatracker.ietf.org/doc/html/draft-ietf-quic-datagram
|
||||
@ -296,7 +293,7 @@ impl Connection {
|
||||
|
||||
/// Create a new QUIC connection with Client role.
|
||||
pub fn new_client(
|
||||
server_name: impl Into<String>,
|
||||
server_name: &str,
|
||||
protocols: &[impl AsRef<str>],
|
||||
cid_generator: Rc<RefCell<dyn ConnectionIdGenerator>>,
|
||||
local_addr: SocketAddr,
|
||||
@ -307,16 +304,12 @@ impl Connection {
|
||||
let dcid = ConnectionId::generate_initial();
|
||||
let mut c = Self::new(
|
||||
Role::Client,
|
||||
Agent::from(Client::new(server_name.into())?),
|
||||
Client::new(server_name)?.into(),
|
||||
cid_generator,
|
||||
protocols,
|
||||
conn_params,
|
||||
)?;
|
||||
c.crypto.states.init(
|
||||
c.conn_params.get_versions().compatible(),
|
||||
Role::Client,
|
||||
&dcid,
|
||||
);
|
||||
c.crypto.states.init(c.version(), Role::Client, &dcid);
|
||||
c.original_destination_cid = Some(dcid);
|
||||
let path = Path::temporary(
|
||||
local_addr,
|
||||
@ -338,18 +331,18 @@ impl Connection {
|
||||
) -> Res<Self> {
|
||||
Self::new(
|
||||
Role::Server,
|
||||
Agent::from(Server::new(certs)?),
|
||||
Server::new(certs)?.into(),
|
||||
cid_generator,
|
||||
protocols,
|
||||
conn_params,
|
||||
)
|
||||
}
|
||||
|
||||
fn new<P: AsRef<str>>(
|
||||
fn new(
|
||||
role: Role,
|
||||
agent: Agent,
|
||||
cid_generator: Rc<RefCell<dyn ConnectionIdGenerator>>,
|
||||
protocols: &[P],
|
||||
protocols: &[impl AsRef<str>],
|
||||
conn_params: ConnectionParameters,
|
||||
) -> Res<Self> {
|
||||
// Setup the local connection ID.
|
||||
@ -367,9 +360,9 @@ impl Connection {
|
||||
|
||||
let tphandler = Rc::new(RefCell::new(tps));
|
||||
let crypto = Crypto::new(
|
||||
conn_params.get_versions().initial(),
|
||||
conn_params.get_quic_version(),
|
||||
agent,
|
||||
protocols.iter().map(P::as_ref).map(String::from).collect(),
|
||||
protocols,
|
||||
Rc::clone(&tphandler),
|
||||
)?;
|
||||
|
||||
@ -384,7 +377,6 @@ impl Connection {
|
||||
|
||||
let c = Self {
|
||||
role,
|
||||
version: conn_params.get_versions().initial(),
|
||||
state: State::Init,
|
||||
paths: Paths::default(),
|
||||
cid_manager,
|
||||
@ -395,7 +387,6 @@ impl Connection {
|
||||
remote_initial_source_cid: None,
|
||||
original_destination_cid: None,
|
||||
saved_datagrams: SavedDatagrams::default(),
|
||||
received_untracked: false,
|
||||
crypto,
|
||||
acks: AckTracker::default(),
|
||||
idle_timeout: IdleTimeout::new(conn_params.get_idle_timeout()),
|
||||
@ -466,15 +457,13 @@ impl Connection {
|
||||
}
|
||||
|
||||
/// Set a local transport parameter, possibly overriding a default value.
|
||||
/// This only sets transport parameters without dealing with other aspects of
|
||||
/// setting the value.
|
||||
/// # Panics
|
||||
/// This panics if the transport parameter is known to this crate.
|
||||
pub fn set_local_tparam(&self, tp: TransportParameterId, value: TransportParameter) -> Res<()> {
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
assert!(!tparams::INTERNAL_TRANSPORT_PARAMETERS.contains(&tp));
|
||||
}
|
||||
/// In general, this method should not be used. This only sets transport parameters
|
||||
/// without dealing with other aspects of setting the value.
|
||||
pub fn set_local_tparam(
|
||||
&self,
|
||||
tp: crate::tparams::TransportParameterId,
|
||||
value: TransportParameter,
|
||||
) -> Res<()> {
|
||||
if *self.state() == State::Init {
|
||||
self.tps.borrow_mut().local.set(tp, value);
|
||||
Ok(())
|
||||
@ -549,7 +538,6 @@ impl Connection {
|
||||
.remote
|
||||
.as_ref()
|
||||
.expect("should have transport parameters"),
|
||||
self.version,
|
||||
u64::try_from(rtt.as_millis()).unwrap_or(0),
|
||||
)
|
||||
.unwrap()
|
||||
@ -650,13 +638,6 @@ impl Connection {
|
||||
);
|
||||
let mut dec = Decoder::from(token.as_ref());
|
||||
|
||||
let version =
|
||||
Version::try_from(dec.decode_uint(4).ok_or(Error::InvalidResumptionToken)? as u32)?;
|
||||
qtrace!([self], " version {:?}", version);
|
||||
if !self.conn_params.get_versions().all().contains(&version) {
|
||||
return Err(Error::DisabledVersion);
|
||||
}
|
||||
|
||||
let rtt = Duration::from_millis(dec.decode_varint().ok_or(Error::InvalidResumptionToken)?);
|
||||
qtrace!([self], " RTT {:?}", rtt);
|
||||
|
||||
@ -671,7 +652,6 @@ impl Connection {
|
||||
|
||||
let tok = dec.decode_remainder();
|
||||
qtrace!([self], " TLS token {}", hex(&tok));
|
||||
|
||||
match self.crypto.tls {
|
||||
Agent::Client(ref mut c) => {
|
||||
let res = c.enable_resumption(&tok);
|
||||
@ -683,9 +663,6 @@ impl Connection {
|
||||
Agent::Server(_) => return Err(Error::WrongRole),
|
||||
}
|
||||
|
||||
self.version = version;
|
||||
self.conn_params.get_versions_mut().set_initial(version);
|
||||
self.tps.borrow_mut().set_version(version);
|
||||
self.tps.borrow_mut().remote_0rtt = Some(tp);
|
||||
if !init_token.is_empty() {
|
||||
self.address_validation = AddressValidationInfo::NewToken(init_token.to_vec());
|
||||
@ -718,7 +695,7 @@ impl Connection {
|
||||
tps.borrow().local.encode(enc_inner);
|
||||
});
|
||||
enc.encode(extra);
|
||||
let records = s.send_ticket(now, enc.as_ref())?;
|
||||
let records = s.send_ticket(now, &enc)?;
|
||||
qinfo!([self], "send session ticket {}", hex(&enc));
|
||||
self.crypto.buffer_records(records)?;
|
||||
} else {
|
||||
@ -763,7 +740,7 @@ impl Connection {
|
||||
pub fn authenticated(&mut self, status: AuthenticationStatus, now: Instant) {
|
||||
qinfo!([self], "Authenticated {:?}", status);
|
||||
self.crypto.tls.authenticated(status);
|
||||
let res = self.handshake(now, self.version, PacketNumberSpace::Handshake, None);
|
||||
let res = self.handshake(now, PacketNumberSpace::Handshake, None);
|
||||
self.absorb_error(now, res);
|
||||
self.process_saved(now);
|
||||
}
|
||||
@ -779,13 +756,13 @@ impl Connection {
|
||||
}
|
||||
|
||||
/// The QUIC version in use.
|
||||
pub fn version(&self) -> Version {
|
||||
self.version
|
||||
pub fn version(&self) -> QuicVersion {
|
||||
self.conn_params.get_quic_version()
|
||||
}
|
||||
|
||||
/// Get the 0-RTT state of the connection.
|
||||
pub fn zero_rtt_state(&self) -> ZeroRttState {
|
||||
self.zero_rtt_state
|
||||
pub fn zero_rtt_state(&self) -> &ZeroRttState {
|
||||
&self.zero_rtt_state
|
||||
}
|
||||
|
||||
/// Get a snapshot of collected statistics.
|
||||
@ -1023,7 +1000,7 @@ impl Connection {
|
||||
self.process_output(now)
|
||||
}
|
||||
|
||||
fn handle_retry(&mut self, packet: &PublicPacket, now: Instant) {
|
||||
fn handle_retry(&mut self, packet: &PublicPacket) {
|
||||
qinfo!([self], "received Retry");
|
||||
if matches!(self.address_validation, AddressValidationInfo::Retry { .. }) {
|
||||
self.stats.borrow_mut().pkt_dropped("Extra Retry");
|
||||
@ -1052,14 +1029,12 @@ impl Connection {
|
||||
retry_scid
|
||||
);
|
||||
|
||||
let lost_packets = self.loss_recovery.retry(&path, now);
|
||||
let lost_packets = self.loss_recovery.retry(&path);
|
||||
self.handle_lost_packets(&lost_packets);
|
||||
|
||||
self.crypto.states.init(
|
||||
self.conn_params.get_versions().compatible(),
|
||||
self.role,
|
||||
&retry_scid,
|
||||
);
|
||||
self.crypto
|
||||
.states
|
||||
.init(self.version(), self.role, &retry_scid);
|
||||
self.address_validation = AddressValidationInfo::Retry {
|
||||
token: packet.token().to_vec(),
|
||||
retry_source_cid: retry_scid,
|
||||
@ -1111,7 +1086,7 @@ impl Connection {
|
||||
fn process_saved(&mut self, now: Instant) {
|
||||
while let Some(cspace) = self.saved_datagrams.available() {
|
||||
qdebug!([self], "process saved for space {:?}", cspace);
|
||||
debug_assert!(self.crypto.states.rx_hp(self.version, cspace).is_some());
|
||||
debug_assert!(self.crypto.states.rx_hp(cspace).is_some());
|
||||
for saved in self.saved_datagrams.take_saved() {
|
||||
qtrace!([self], "input saved @{:?}: {:?}", saved.t, saved.d);
|
||||
self.input(saved.d, saved.t, now);
|
||||
@ -1131,44 +1106,6 @@ impl Connection {
|
||||
self.stats.borrow_mut().saved_datagrams += 1;
|
||||
}
|
||||
|
||||
/// Perform version negotiation.
|
||||
fn version_negotiation(&mut self, supported: &[WireVersion], now: Instant) -> Res<()> {
|
||||
debug_assert_eq!(self.role, Role::Client);
|
||||
|
||||
if let Some(version) = self.conn_params.get_versions().preferred(supported) {
|
||||
assert_ne!(self.version, version);
|
||||
|
||||
qinfo!([self], "Version negotiation: trying {:?}", version);
|
||||
let local_addr = self.paths.primary().borrow().local_address();
|
||||
let remote_addr = self.paths.primary().borrow().remote_address();
|
||||
let conn_params = self
|
||||
.conn_params
|
||||
.clone()
|
||||
.versions(version, self.conn_params.get_versions().all().to_vec());
|
||||
let mut c = Self::new_client(
|
||||
self.crypto.server_name().unwrap(),
|
||||
self.crypto.protocols(),
|
||||
self.cid_manager.generator(),
|
||||
local_addr,
|
||||
remote_addr,
|
||||
conn_params,
|
||||
now,
|
||||
)?;
|
||||
c.conn_params
|
||||
.get_versions_mut()
|
||||
.set_initial(self.conn_params.get_versions().initial());
|
||||
mem::swap(self, &mut c);
|
||||
Ok(())
|
||||
} else {
|
||||
qinfo!([self], "Version negotiation: failed with {:?}", supported);
|
||||
// This error goes straight to closed.
|
||||
self.set_state(State::Closed(ConnectionError::Transport(
|
||||
Error::VersionNegotiation,
|
||||
)));
|
||||
Err(Error::VersionNegotiation)
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform any processing that we might have to do on packets prior to
|
||||
/// attempting to remove protection.
|
||||
fn preprocess_packet(
|
||||
@ -1198,10 +1135,7 @@ impl Connection {
|
||||
|
||||
match (packet.packet_type(), &self.state, &self.role) {
|
||||
(PacketType::Initial, State::Init, Role::Server) => {
|
||||
let version = *packet.version().as_ref().unwrap();
|
||||
if !packet.is_valid_initial()
|
||||
|| !self.conn_params.get_versions().all().contains(&version)
|
||||
{
|
||||
if !packet.is_valid_initial() {
|
||||
self.stats.borrow_mut().pkt_dropped("Invalid Initial");
|
||||
return Ok(PreprocessResult::Next);
|
||||
}
|
||||
@ -1211,12 +1145,10 @@ impl Connection {
|
||||
packet.scid(),
|
||||
packet.dcid()
|
||||
);
|
||||
// Record the client's selected CID so that it can be accepted until
|
||||
// the client starts using a real connection ID.
|
||||
let dcid = ConnectionId::from(packet.dcid());
|
||||
self.crypto.states.init_server(version, &dcid);
|
||||
self.original_destination_cid = Some(dcid);
|
||||
self.set_state(State::WaitInitial);
|
||||
self.crypto
|
||||
.states
|
||||
.init(self.version(), self.role, packet.dcid());
|
||||
|
||||
// We need to make sure that we set this transport parameter.
|
||||
// This has to happen prior to processing the packet so that
|
||||
@ -1232,9 +1164,8 @@ impl Connection {
|
||||
match packet.supported_versions() {
|
||||
Ok(versions) => {
|
||||
if versions.is_empty()
|
||||
|| versions.contains(&self.version().wire_version())
|
||||
|| versions.contains(&0)
|
||||
|| packet.scid() != self.odcid().unwrap()
|
||||
|| versions.contains(&self.version().as_u32())
|
||||
|| packet.dcid() != self.odcid().unwrap()
|
||||
|| matches!(
|
||||
self.address_validation,
|
||||
AddressValidationInfo::Retry { .. }
|
||||
@ -1247,17 +1178,19 @@ impl Connection {
|
||||
return Ok(PreprocessResult::End);
|
||||
}
|
||||
|
||||
self.version_negotiation(&versions, now)?;
|
||||
return Ok(PreprocessResult::End);
|
||||
self.set_state(State::Closed(ConnectionError::Transport(
|
||||
Error::VersionNegotiation,
|
||||
)));
|
||||
return Err(Error::VersionNegotiation);
|
||||
}
|
||||
Err(_) => {
|
||||
self.stats.borrow_mut().pkt_dropped("VN with no versions");
|
||||
self.stats.borrow_mut().pkt_dropped("Invalid VN");
|
||||
return Ok(PreprocessResult::End);
|
||||
}
|
||||
}
|
||||
}
|
||||
(PacketType::Retry, State::WaitInitial, Role::Client) => {
|
||||
self.handle_retry(packet, now);
|
||||
self.handle_retry(packet);
|
||||
return Ok(PreprocessResult::Next);
|
||||
}
|
||||
(PacketType::Handshake, State::WaitInitial, Role::Client)
|
||||
@ -1293,7 +1226,7 @@ impl Connection {
|
||||
PreprocessResult::Next
|
||||
}
|
||||
State::WaitInitial => PreprocessResult::Continue,
|
||||
State::WaitVersion | State::Handshaking | State::Connected | State::Confirmed => {
|
||||
State::Handshaking | State::Connected | State::Confirmed => {
|
||||
if !self.cid_manager.is_valid(packet.dcid()) {
|
||||
self.stats
|
||||
.borrow_mut()
|
||||
@ -1336,7 +1269,6 @@ impl Connection {
|
||||
if self.state == State::WaitInitial {
|
||||
self.start_handshake(path, packet, now);
|
||||
}
|
||||
|
||||
if self.state.connected() {
|
||||
self.handle_migration(path, d, migrate, now);
|
||||
} else if self.role != Role::Client
|
||||
@ -1433,12 +1365,6 @@ impl Connection {
|
||||
// Exhausting read keys is fatal.
|
||||
return Err(e);
|
||||
}
|
||||
Error::KeysDiscarded(cspace) => {
|
||||
// This was a valid-appearing Initial packet: maybe probe with
|
||||
// a Handshake packet to keep the handshake moving.
|
||||
self.received_untracked |=
|
||||
self.role == Role::Client && cspace == CryptoSpace::Initial;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
// Decryption failure, or not having keys is not fatal.
|
||||
@ -1492,30 +1418,15 @@ impl Connection {
|
||||
ack_eliciting |= f.ack_eliciting();
|
||||
probing &= f.path_probing();
|
||||
let t = f.get_type();
|
||||
if let Err(e) = self.input_frame(path, packet.version(), packet.packet_type(), f, now) {
|
||||
if let Err(e) = self.input_frame(path, packet.packet_type(), f, now) {
|
||||
self.capture_error(Some(Rc::clone(path)), now, t, Err(e))?;
|
||||
}
|
||||
}
|
||||
|
||||
let largest_received = if let Some(space) = self
|
||||
let largest_received = self
|
||||
.acks
|
||||
.get_mut(PacketNumberSpace::from(packet.packet_type()))
|
||||
{
|
||||
space.set_received(now, packet.pn(), ack_eliciting)
|
||||
} else {
|
||||
qdebug!(
|
||||
[self],
|
||||
"processed a {:?} packet without tracking it",
|
||||
packet.packet_type(),
|
||||
);
|
||||
// This was a valid packet that caused the same packet number to be
|
||||
// discarded. This happens when the client discards the Initial packet
|
||||
// number space after receiving the ServerHello. Remember this so
|
||||
// that we guarantee that we send a Handshake packet.
|
||||
self.received_untracked = true;
|
||||
// We don't migrate during the handshake, so return false.
|
||||
false
|
||||
};
|
||||
.unwrap()
|
||||
.set_received(now, packet.pn(), ack_eliciting);
|
||||
|
||||
Ok(largest_received && !probing)
|
||||
}
|
||||
@ -1523,7 +1434,6 @@ impl Connection {
|
||||
/// During connection setup, the first path needs to be setup.
|
||||
/// This uses the connection IDs that were provided during the handshake
|
||||
/// to setup that path.
|
||||
#[allow(clippy::or_fun_call)] // Remove when MSRV >= 1.59
|
||||
fn setup_handshake_path(&mut self, path: &PathRef, now: Instant) {
|
||||
self.paths.make_permanent(
|
||||
path,
|
||||
@ -1533,7 +1443,7 @@ impl Connection {
|
||||
ConnectionIdEntry::initial_remote(
|
||||
self.remote_initial_source_cid
|
||||
.as_ref()
|
||||
.or(self.original_destination_cid.as_ref())
|
||||
.or_else(|| self.original_destination_cid.as_ref())
|
||||
.unwrap()
|
||||
.clone(),
|
||||
),
|
||||
@ -1585,35 +1495,29 @@ impl Connection {
|
||||
debug_assert_eq!(packet.packet_type(), PacketType::Initial);
|
||||
self.remote_initial_source_cid = Some(ConnectionId::from(packet.scid()));
|
||||
|
||||
let got_version = if self.role == Role::Server {
|
||||
self.cid_manager
|
||||
.add_odcid(self.original_destination_cid.as_ref().unwrap().clone());
|
||||
if self.role == Role::Server {
|
||||
// Record the client's selected CID so that it can be accepted until
|
||||
// the client starts using a real connection ID.
|
||||
let dcid = ConnectionId::from(packet.dcid());
|
||||
self.original_destination_cid = Some(dcid.clone());
|
||||
self.cid_manager.add_odcid(dcid);
|
||||
// Make a path on which to run the handshake.
|
||||
self.setup_handshake_path(path, now);
|
||||
|
||||
self.zero_rtt_state = match self.crypto.enable_0rtt(self.version, self.role) {
|
||||
self.zero_rtt_state = match self.crypto.enable_0rtt(self.role) {
|
||||
Ok(true) => {
|
||||
qdebug!([self], "Accepted 0-RTT");
|
||||
ZeroRttState::AcceptedServer
|
||||
}
|
||||
_ => ZeroRttState::Rejected,
|
||||
};
|
||||
|
||||
// The server knows the final version if it has remote transport parameters.
|
||||
self.tps.borrow().remote.is_some()
|
||||
} else {
|
||||
qdebug!([self], "Changing to use Server CID={}", packet.scid());
|
||||
debug_assert!(path.borrow().is_primary());
|
||||
path.borrow_mut().set_remote_cid(packet.scid());
|
||||
|
||||
// The client knows the final version if it processed a CRYPTO frame.
|
||||
self.stats.borrow().frame_rx.crypto > 0
|
||||
};
|
||||
if got_version {
|
||||
self.set_state(State::Handshaking);
|
||||
} else {
|
||||
self.set_state(State::WaitVersion);
|
||||
}
|
||||
|
||||
self.set_state(State::Handshaking);
|
||||
}
|
||||
|
||||
/// Migrate to the provided path.
|
||||
@ -1743,7 +1647,6 @@ impl Connection {
|
||||
let res = match &self.state {
|
||||
State::Init
|
||||
| State::WaitInitial
|
||||
| State::WaitVersion
|
||||
| State::Handshaking
|
||||
| State::Connected
|
||||
| State::Confirmed => {
|
||||
@ -1773,7 +1676,7 @@ impl Connection {
|
||||
encoder: Encoder,
|
||||
tx: &CryptoDxState,
|
||||
address_validation: &AddressValidationInfo,
|
||||
version: Version,
|
||||
quic_version: QuicVersion,
|
||||
grease_quic_bit: bool,
|
||||
) -> (PacketType, PacketBuilder) {
|
||||
let pt = PacketType::from(cspace);
|
||||
@ -1788,7 +1691,13 @@ impl Connection {
|
||||
path.local_cid(),
|
||||
);
|
||||
|
||||
PacketBuilder::long(encoder, pt, version, path.remote_cid(), path.local_cid())
|
||||
PacketBuilder::long(
|
||||
encoder,
|
||||
pt,
|
||||
quic_version,
|
||||
path.remote_cid(),
|
||||
path.local_cid(),
|
||||
)
|
||||
};
|
||||
if builder.remaining() > 0 {
|
||||
builder.scramble(grease_quic_bit);
|
||||
@ -1839,12 +1748,11 @@ impl Connection {
|
||||
let grease_quic_bit = self.can_grease_quic_bit();
|
||||
let version = self.version();
|
||||
for space in PacketNumberSpace::iter() {
|
||||
let (cspace, tx) =
|
||||
if let Some(crypto) = self.crypto.states.select_tx_mut(self.version, *space) {
|
||||
crypto
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
let (cspace, tx) = if let Some(crypto) = self.crypto.states.select_tx_mut(*space) {
|
||||
crypto
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let path = close.path().borrow();
|
||||
let (_, mut builder) = Self::build_packet_header(
|
||||
@ -1977,18 +1885,13 @@ impl Connection {
|
||||
tokens: &mut Vec<RecoveryToken>,
|
||||
now: Instant,
|
||||
) -> bool {
|
||||
let untracked = self.received_untracked && !self.state.connected();
|
||||
self.received_untracked = false;
|
||||
|
||||
// Anything written after an ACK already elicits acknowledgment.
|
||||
// If we need to probe and nothing has been written, send a PING.
|
||||
if builder.len() > ack_end {
|
||||
return true;
|
||||
}
|
||||
|
||||
let probe = if untracked && builder.packet_empty() || force_probe {
|
||||
// If we received an untracked packet and we aren't probing already
|
||||
// or the PTO timer fired: probe.
|
||||
let probe = if force_probe {
|
||||
// The packet might be empty, but we need to probe.
|
||||
true
|
||||
} else {
|
||||
let pto = path.borrow().rtt().pto(PacketNumberSpace::ApplicationData);
|
||||
@ -2109,12 +2012,11 @@ impl Connection {
|
||||
let mut encoder = Encoder::with_capacity(profile.limit());
|
||||
for space in PacketNumberSpace::iter() {
|
||||
// Ensure we have tx crypto state for this epoch, or skip it.
|
||||
let (cspace, tx) =
|
||||
if let Some(crypto) = self.crypto.states.select_tx_mut(self.version, *space) {
|
||||
crypto
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
let (cspace, tx) = if let Some(crypto) = self.crypto.states.select_tx_mut(*space) {
|
||||
crypto
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let header_start = encoder.len();
|
||||
let (pt, mut builder) = Self::build_packet_header(
|
||||
@ -2157,25 +2059,17 @@ impl Connection {
|
||||
continue;
|
||||
}
|
||||
|
||||
dump_packet(
|
||||
self,
|
||||
path,
|
||||
"TX ->",
|
||||
pt,
|
||||
pn,
|
||||
&builder.as_ref()[payload_start..],
|
||||
);
|
||||
dump_packet(self, path, "TX ->", pt, pn, &builder[payload_start..]);
|
||||
qlog::packet_sent(
|
||||
&mut self.qlog,
|
||||
pt,
|
||||
pn,
|
||||
builder.len() - header_start + aead_expansion,
|
||||
&builder.as_ref()[payload_start..],
|
||||
&builder[payload_start..],
|
||||
);
|
||||
|
||||
self.stats.borrow_mut().packets_tx += 1;
|
||||
let tx = self.crypto.states.tx_mut(self.version, cspace).unwrap();
|
||||
encoder = builder.build(tx)?;
|
||||
encoder = builder.build(self.crypto.states.tx_mut(cspace).unwrap())?;
|
||||
debug_assert!(encoder.len() <= mtu);
|
||||
self.crypto.states.auto_update()?;
|
||||
|
||||
@ -2205,13 +2099,14 @@ impl Connection {
|
||||
self.loss_recovery.on_packet_sent(path, sent);
|
||||
}
|
||||
|
||||
if *space == PacketNumberSpace::Handshake
|
||||
&& self.role == Role::Server
|
||||
&& self.state == State::Confirmed
|
||||
{
|
||||
// We could discard handshake keys in set_state,
|
||||
// but wait until after sending an ACK.
|
||||
self.discard_keys(PacketNumberSpace::Handshake, now);
|
||||
if *space == PacketNumberSpace::Handshake {
|
||||
if self.role == Role::Client {
|
||||
// Client can send Handshake packets -> discard Initial keys and states
|
||||
self.discard_keys(PacketNumberSpace::Initial, now);
|
||||
} else if self.state == State::Confirmed {
|
||||
// We could discard handshake keys in set_state, but wait until after sending an ACK.
|
||||
self.discard_keys(PacketNumberSpace::Handshake, now);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2255,9 +2150,9 @@ impl Connection {
|
||||
debug_assert_eq!(self.role, Role::Client);
|
||||
qlog::client_connection_started(&mut self.qlog, &self.paths.primary());
|
||||
|
||||
self.handshake(now, self.version, PacketNumberSpace::Initial, None)?;
|
||||
self.handshake(now, PacketNumberSpace::Initial, None)?;
|
||||
self.set_state(State::WaitInitial);
|
||||
self.zero_rtt_state = if self.crypto.enable_0rtt(self.version, self.role)? {
|
||||
self.zero_rtt_state = if self.crypto.enable_0rtt(self.role)? {
|
||||
qdebug!([self], "Enabled 0-RTT");
|
||||
ZeroRttState::Sending
|
||||
} else {
|
||||
@ -2310,7 +2205,6 @@ impl Connection {
|
||||
/// Process the final set of transport parameters.
|
||||
fn process_tps(&mut self) -> Res<()> {
|
||||
self.validate_cids()?;
|
||||
self.validate_versions()?;
|
||||
{
|
||||
let tps = self.tps.borrow();
|
||||
let remote = tps.remote.as_ref().unwrap();
|
||||
@ -2421,91 +2315,9 @@ impl Connection {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Validate the `version_negotiation` transport parameter from the peer.
|
||||
fn validate_versions(&mut self) -> Res<()> {
|
||||
let tph = self.tps.borrow();
|
||||
let remote_tps = tph.remote.as_ref().unwrap();
|
||||
// `current` and `other` are the value from the peer's transport parameters.
|
||||
// We're checking that these match our expectations.
|
||||
if let Some((current, other)) = remote_tps.get_versions() {
|
||||
qtrace!(
|
||||
[self],
|
||||
"validate_versions: current={:x} chosen={:x} other={:x?}",
|
||||
self.version.wire_version(),
|
||||
current,
|
||||
other,
|
||||
);
|
||||
if self.role == Role::Server {
|
||||
// 1. A server acts on transport parameters, with validation
|
||||
// of `current` happening in the transport parameter handler.
|
||||
// All we need to do is confirm that the transport parameter
|
||||
// was provided.
|
||||
Ok(())
|
||||
} else if self.version().wire_version() != current {
|
||||
qinfo!([self], "validate_versions: current version mismatch");
|
||||
Err(Error::VersionNegotiation)
|
||||
} else if self
|
||||
.conn_params
|
||||
.get_versions()
|
||||
.initial()
|
||||
.is_compatible(self.version)
|
||||
{
|
||||
// 2. The current version is compatible with what we attempted.
|
||||
// That's a compatible upgrade and that's OK.
|
||||
Ok(())
|
||||
} else {
|
||||
// 3. The initial version we attempted isn't compatible. Check that
|
||||
// the one we would have chosen is compatible with this one.
|
||||
let mut all_versions = other.to_owned();
|
||||
all_versions.push(current);
|
||||
if self
|
||||
.conn_params
|
||||
.get_versions()
|
||||
.preferred(&all_versions)
|
||||
.ok_or(Error::VersionNegotiation)?
|
||||
.is_compatible(self.version)
|
||||
{
|
||||
Ok(())
|
||||
} else {
|
||||
qinfo!([self], "validate_versions: failed");
|
||||
Err(Error::VersionNegotiation)
|
||||
}
|
||||
}
|
||||
} else if self.version != Version::Version1 && !self.version.is_draft() {
|
||||
qinfo!([self], "validate_versions: missing extension");
|
||||
Err(Error::VersionNegotiation)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn confirm_version(&mut self, v: Version) {
|
||||
if self.version != v {
|
||||
qinfo!([self], "Compatible upgrade {:?} ==> {:?}", self.version, v);
|
||||
}
|
||||
self.crypto.confirm_version(v);
|
||||
self.version = v;
|
||||
}
|
||||
|
||||
fn compatible_upgrade(&mut self, packet_version: Version) {
|
||||
if !matches!(self.state, State::WaitInitial | State::WaitVersion) {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.role == Role::Client {
|
||||
self.confirm_version(packet_version);
|
||||
} else if self.tps.borrow().remote.is_some() {
|
||||
let version = self.tps.borrow().version();
|
||||
let dcid = self.original_destination_cid.as_ref().unwrap();
|
||||
self.crypto.states.init_server(version, dcid);
|
||||
self.confirm_version(version);
|
||||
}
|
||||
}
|
||||
|
||||
fn handshake(
|
||||
&mut self,
|
||||
now: Instant,
|
||||
packet_version: Version,
|
||||
space: PacketNumberSpace,
|
||||
data: Option<&[u8]>,
|
||||
) -> Res<()> {
|
||||
@ -2529,19 +2341,13 @@ impl Connection {
|
||||
}
|
||||
|
||||
// There is a chance that this could be called less often, but getting the
|
||||
// conditions right is a little tricky, so call whenever CRYPTO data is used.
|
||||
// conditions right is a little tricky, so call it on every CRYPTO frame.
|
||||
if try_update {
|
||||
self.compatible_upgrade(packet_version);
|
||||
// We have transport parameters, it's go time.
|
||||
if self.tps.borrow().remote.is_some() {
|
||||
self.set_initial_limits();
|
||||
}
|
||||
if self.crypto.install_keys(self.role)? {
|
||||
if self.role == Role::Client {
|
||||
// We won't acknowledge Initial packets as a result of this, but the
|
||||
// server can rely on implicit acknowledgment.
|
||||
self.discard_keys(PacketNumberSpace::Initial, now);
|
||||
}
|
||||
self.saved_datagrams.make_available(CryptoSpace::Handshake);
|
||||
}
|
||||
}
|
||||
@ -2552,17 +2358,16 @@ impl Connection {
|
||||
fn input_frame(
|
||||
&mut self,
|
||||
path: &PathRef,
|
||||
packet_version: Version,
|
||||
packet_type: PacketType,
|
||||
ptype: PacketType,
|
||||
frame: Frame,
|
||||
now: Instant,
|
||||
) -> Res<()> {
|
||||
if !frame.is_allowed(packet_type) {
|
||||
qinfo!("frame not allowed: {:?} {:?}", frame, packet_type);
|
||||
if !frame.is_allowed(ptype) {
|
||||
qinfo!("frame not allowed: {:?} {:?}", frame, ptype);
|
||||
return Err(Error::ProtocolViolation);
|
||||
}
|
||||
self.stats.borrow_mut().frame_rx.all += 1;
|
||||
let space = PacketNumberSpace::from(packet_type);
|
||||
let space = PacketNumberSpace::from(ptype);
|
||||
if frame.is_stream() {
|
||||
return self
|
||||
.streams
|
||||
@ -2607,7 +2412,7 @@ impl Connection {
|
||||
let mut buf = Vec::new();
|
||||
let read = self.crypto.streams.read_to_end(space, &mut buf);
|
||||
qdebug!("Read {} bytes", read);
|
||||
self.handshake(now, packet_version, space, Some(&buf))?;
|
||||
self.handshake(now, space, Some(&buf))?;
|
||||
self.create_resumption_token(now);
|
||||
} else {
|
||||
// If we get a useless CRYPTO frame send outstanding CRYPTO frames again.
|
||||
@ -2811,14 +2616,14 @@ impl Connection {
|
||||
}
|
||||
|
||||
/// When the server rejects 0-RTT we need to drop a bunch of stuff.
|
||||
fn client_0rtt_rejected(&mut self, now: Instant) {
|
||||
fn client_0rtt_rejected(&mut self) {
|
||||
if !matches!(self.zero_rtt_state, ZeroRttState::Sending) {
|
||||
return;
|
||||
}
|
||||
qdebug!([self], "0-RTT rejected");
|
||||
|
||||
// Tell 0-RTT packets that they were "lost".
|
||||
let dropped = self.loss_recovery.drop_0rtt(&self.paths.primary(), now);
|
||||
let dropped = self.loss_recovery.drop_0rtt(&self.paths.primary());
|
||||
self.handle_lost_packets(&dropped);
|
||||
|
||||
self.streams.zero_rtt_rejected();
|
||||
@ -2846,15 +2651,14 @@ impl Connection {
|
||||
self.zero_rtt_state = if self.crypto.tls.info().unwrap().early_data_accepted() {
|
||||
ZeroRttState::AcceptedClient
|
||||
} else {
|
||||
self.client_0rtt_rejected(now);
|
||||
self.client_0rtt_rejected();
|
||||
ZeroRttState::Rejected
|
||||
};
|
||||
}
|
||||
|
||||
// Setting application keys has to occur after 0-RTT rejection.
|
||||
let pto = self.pto();
|
||||
self.crypto
|
||||
.install_application_keys(self.version, now + pto)?;
|
||||
self.crypto.install_application_keys(now + pto)?;
|
||||
self.process_tps()?;
|
||||
self.set_state(State::Connected);
|
||||
self.create_resumption_token(now);
|
||||
@ -3040,7 +2844,7 @@ impl Connection {
|
||||
let (cspace, tx) = if let Some(crypto) = self
|
||||
.crypto
|
||||
.states
|
||||
.select_tx(self.version, PacketNumberSpace::ApplicationData)
|
||||
.select_tx(PacketNumberSpace::ApplicationData)
|
||||
{
|
||||
crypto
|
||||
} else {
|
||||
|
@ -11,8 +11,7 @@ use crate::rtt::GRANULARITY;
|
||||
use crate::stream_id::StreamType;
|
||||
use crate::tparams::{self, PreferredAddress, TransportParameter, TransportParametersHandler};
|
||||
use crate::tracking::DEFAULT_ACK_DELAY;
|
||||
use crate::version::{Version, VersionConfig};
|
||||
use crate::{CongestionControlAlgorithm, Res};
|
||||
use crate::{CongestionControlAlgorithm, QuicVersion, Res};
|
||||
use std::cmp::max;
|
||||
use std::convert::TryFrom;
|
||||
use std::time::Duration;
|
||||
@ -43,9 +42,9 @@ pub enum PreferredAddressConfig {
|
||||
/// ConnectionParameters use for setting intitial value for QUIC parameters.
|
||||
/// This collects configuration like initial limits, protocol version, and
|
||||
/// congestion control algorithm.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct ConnectionParameters {
|
||||
versions: VersionConfig,
|
||||
quic_version: QuicVersion,
|
||||
cc_algorithm: CongestionControlAlgorithm,
|
||||
/// Initial connection-level flow control limit.
|
||||
max_data: u64,
|
||||
@ -78,7 +77,7 @@ pub struct ConnectionParameters {
|
||||
impl Default for ConnectionParameters {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
versions: VersionConfig::default(),
|
||||
quic_version: QuicVersion::default(),
|
||||
cc_algorithm: CongestionControlAlgorithm::NewReno,
|
||||
max_data: LOCAL_MAX_DATA,
|
||||
max_stream_data_bidi_remote: u64::try_from(RECV_BUFFER_SIZE).unwrap(),
|
||||
@ -98,20 +97,12 @@ impl Default for ConnectionParameters {
|
||||
}
|
||||
|
||||
impl ConnectionParameters {
|
||||
pub fn get_versions(&self) -> &VersionConfig {
|
||||
&self.versions
|
||||
pub fn get_quic_version(&self) -> QuicVersion {
|
||||
self.quic_version
|
||||
}
|
||||
|
||||
pub(crate) fn get_versions_mut(&mut self) -> &mut VersionConfig {
|
||||
&mut self.versions
|
||||
}
|
||||
|
||||
/// Describe the initial version that should be attempted and all the
|
||||
/// versions that should be enabled. This list should contain the initial
|
||||
/// version and be in order of preference, with more preferred versions
|
||||
/// before less preferred.
|
||||
pub fn versions(mut self, initial: Version, all: Vec<Version>) -> Self {
|
||||
self.versions = VersionConfig::new(initial, all);
|
||||
pub fn quic_version(mut self, v: QuicVersion) -> Self {
|
||||
self.quic_version = v;
|
||||
self
|
||||
}
|
||||
|
||||
@ -287,7 +278,7 @@ impl ConnectionParameters {
|
||||
role: Role,
|
||||
cid_manager: &mut ConnectionIdManager,
|
||||
) -> Res<TransportParametersHandler> {
|
||||
let mut tps = TransportParametersHandler::new(role, self.versions.clone());
|
||||
let mut tps = TransportParametersHandler::default();
|
||||
// default parameters
|
||||
tps.local.set_integer(
|
||||
tparams::ACTIVE_CONNECTION_ID_LIMIT,
|
||||
|
@ -22,17 +22,8 @@ use crate::{ConnectionError, Error, Res};
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
/// The state of the Connection.
|
||||
pub enum State {
|
||||
/// A newly created connection.
|
||||
Init,
|
||||
/// Waiting for the first Initial packet.
|
||||
WaitInitial,
|
||||
/// Waiting to confirm which version was selected.
|
||||
/// For a client, this is confirmed when a CRYPTO frame is received;
|
||||
/// the version of the packet determines the version.
|
||||
/// For a server, this is confirmed when transport parameters are
|
||||
/// received and processed.
|
||||
WaitVersion,
|
||||
/// Exchanging Handshake packets.
|
||||
Handshaking,
|
||||
Connected,
|
||||
Confirmed,
|
||||
@ -90,8 +81,6 @@ impl Ord for State {
|
||||
(_, Self::Init) => Ordering::Greater,
|
||||
(Self::WaitInitial, _) => Ordering::Less,
|
||||
(_, Self::WaitInitial) => Ordering::Greater,
|
||||
(Self::WaitVersion, _) => Ordering::Less,
|
||||
(_, Self::WaitVersion) => Ordering::Greater,
|
||||
(Self::Handshaking, _) => Ordering::Less,
|
||||
(_, Self::Handshaking) => Ordering::Greater,
|
||||
(Self::Connected, _) => Ordering::Less,
|
||||
|
@ -7,8 +7,8 @@
|
||||
use super::super::{Connection, Output, State};
|
||||
use super::{
|
||||
assert_error, connect, connect_force_idle, connect_with_rtt, default_client, default_server,
|
||||
get_tokens, handshake, maybe_authenticate, resumed_server, send_something,
|
||||
CountingConnectionIdGenerator, AT_LEAST_PTO, DEFAULT_RTT, DEFAULT_STREAM_DATA,
|
||||
get_tokens, handshake, maybe_authenticate, send_something, CountingConnectionIdGenerator,
|
||||
AT_LEAST_PTO, DEFAULT_RTT, DEFAULT_STREAM_DATA,
|
||||
};
|
||||
use crate::connection::AddressValidation;
|
||||
use crate::events::ConnectionEvent;
|
||||
@ -17,7 +17,8 @@ use crate::server::ValidateAddress;
|
||||
use crate::tparams::{TransportParameter, MIN_ACK_DELAY};
|
||||
use crate::tracking::DEFAULT_ACK_DELAY;
|
||||
use crate::{
|
||||
ConnectionError, ConnectionParameters, EmptyConnectionIdGenerator, Error, StreamType, Version,
|
||||
ConnectionError, ConnectionParameters, EmptyConnectionIdGenerator, Error, QuicVersion,
|
||||
StreamType,
|
||||
};
|
||||
|
||||
use neqo_common::{event::Provider, qdebug, Datagram};
|
||||
@ -355,7 +356,7 @@ fn reorder_05rtt_with_0rtt() {
|
||||
let token = get_tokens(&mut client).pop().unwrap();
|
||||
let mut client = default_client();
|
||||
client.enable_resumption(now, token).unwrap();
|
||||
let mut server = resumed_server(&client);
|
||||
let mut server = default_server();
|
||||
|
||||
// Send ClientHello and some 0-RTT.
|
||||
let c1 = send_something(&mut client, now);
|
||||
@ -397,9 +398,7 @@ fn reorder_05rtt_with_0rtt() {
|
||||
now += RTT / 2;
|
||||
server.process_input(c4.unwrap(), now);
|
||||
assert_eq!(*server.state(), State::Confirmed);
|
||||
// Don't check server RTT as it will be massively inflated by a
|
||||
// poor initial estimate received when the server dropped the
|
||||
// Initial packet number space.
|
||||
assert_eq!(server.paths.rtt(), RTT);
|
||||
}
|
||||
|
||||
/// Test that a server that coalesces 0.5 RTT with handshake packets
|
||||
@ -523,9 +522,7 @@ fn reorder_handshake() {
|
||||
now += RTT / 2;
|
||||
let s3 = server.process(c3, now).dgram();
|
||||
assert_eq!(*server.state(), State::Confirmed);
|
||||
// Don't check server RTT estimate as it will be inflated due to
|
||||
// it making a guess based on retransmissions when it dropped
|
||||
// the Initial packet number space.
|
||||
assert_eq!(server.paths.rtt(), RTT);
|
||||
|
||||
now += RTT / 2;
|
||||
client.process_input(s3.unwrap(), now);
|
||||
@ -569,8 +566,9 @@ fn reorder_1rtt() {
|
||||
now += RTT / 2;
|
||||
let s2 = server.process(c2, now).dgram();
|
||||
// The server has now received those packets, and saved them.
|
||||
// The two additional are a Handshake and a 1-RTT (w/ NEW_CONNECTION_ID).
|
||||
assert_eq!(server.stats().packets_rx, PACKETS * 2 + 4);
|
||||
// The three additional are: an Initial ACK, a Handshake,
|
||||
// and a 1-RTT (containing NEW_CONNECTION_ID).
|
||||
assert_eq!(server.stats().packets_rx, PACKETS * 2 + 5);
|
||||
assert_eq!(server.stats().saved_datagrams, PACKETS);
|
||||
assert_eq!(server.stats().dropped_rx, 1);
|
||||
assert_eq!(*server.state(), State::Confirmed);
|
||||
@ -716,36 +714,51 @@ fn extra_initial_invalid_cid() {
|
||||
assert!(nothing.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn connect_one_version() {
|
||||
fn connect_v(version: Version) {
|
||||
fixture_init();
|
||||
let mut client = Connection::new_client(
|
||||
test_fixture::DEFAULT_SERVER_NAME,
|
||||
test_fixture::DEFAULT_ALPN,
|
||||
Rc::new(RefCell::new(CountingConnectionIdGenerator::default())),
|
||||
addr(),
|
||||
addr(),
|
||||
ConnectionParameters::default().versions(version, vec![version]),
|
||||
now(),
|
||||
)
|
||||
.unwrap();
|
||||
let mut server = Connection::new_server(
|
||||
test_fixture::DEFAULT_KEYS,
|
||||
test_fixture::DEFAULT_ALPN,
|
||||
Rc::new(RefCell::new(CountingConnectionIdGenerator::default())),
|
||||
ConnectionParameters::default().versions(version, vec![version]),
|
||||
)
|
||||
.unwrap();
|
||||
connect_force_idle(&mut client, &mut server);
|
||||
assert_eq!(client.version(), version);
|
||||
assert_eq!(server.version(), version);
|
||||
}
|
||||
fn connect_version(version: QuicVersion) {
|
||||
fixture_init();
|
||||
let mut client = Connection::new_client(
|
||||
test_fixture::DEFAULT_SERVER_NAME,
|
||||
test_fixture::DEFAULT_ALPN,
|
||||
Rc::new(RefCell::new(CountingConnectionIdGenerator::default())),
|
||||
addr(),
|
||||
addr(),
|
||||
ConnectionParameters::default().quic_version(version),
|
||||
now(),
|
||||
)
|
||||
.unwrap();
|
||||
let mut server = Connection::new_server(
|
||||
test_fixture::DEFAULT_KEYS,
|
||||
test_fixture::DEFAULT_ALPN,
|
||||
Rc::new(RefCell::new(CountingConnectionIdGenerator::default())),
|
||||
ConnectionParameters::default().quic_version(version),
|
||||
)
|
||||
.unwrap();
|
||||
connect_force_idle(&mut client, &mut server);
|
||||
}
|
||||
|
||||
for v in Version::all() {
|
||||
println!("Connecting with {:?}", v);
|
||||
connect_v(v);
|
||||
}
|
||||
#[test]
|
||||
fn connect_v1() {
|
||||
connect_version(QuicVersion::Version1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn connect_29() {
|
||||
connect_version(QuicVersion::Draft29);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn connect_30() {
|
||||
connect_version(QuicVersion::Draft30);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn connect_31() {
|
||||
connect_version(QuicVersion::Draft31);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn connect_32() {
|
||||
connect_version(QuicVersion::Draft32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -784,9 +797,9 @@ fn anti_amplification() {
|
||||
let ack = client.process(Some(s_init3), now).dgram().unwrap();
|
||||
assert!(!maybe_authenticate(&mut client)); // No need yet.
|
||||
|
||||
// The client sends a padded datagram, with just ACK for Handshake.
|
||||
assert_eq!(client.stats().frame_tx.ack, ack_count + 1);
|
||||
assert_eq!(client.stats().frame_tx.all, frame_count + 1);
|
||||
// The client sends a padded datagram, with just ACK for Initial + Handshake.
|
||||
assert_eq!(client.stats().frame_tx.ack, ack_count + 2);
|
||||
assert_eq!(client.stats().frame_tx.all, frame_count + 2);
|
||||
assert_ne!(ack.len(), PATH_MTU_V6); // Not padded (it includes Handshake).
|
||||
|
||||
now += DEFAULT_RTT / 2;
|
||||
@ -1015,115 +1028,3 @@ fn bad_min_ack_delay() {
|
||||
)))
|
||||
);
|
||||
}
|
||||
|
||||
/// Ensure that the client probes correctly if it only receives Initial packets
|
||||
/// from the server.
|
||||
#[test]
|
||||
fn only_server_initial() {
|
||||
let mut server = default_server();
|
||||
let mut client = default_client();
|
||||
let mut now = now();
|
||||
|
||||
let client_dgram = client.process_output(now).dgram();
|
||||
|
||||
// Now fetch two flights of messages from the server.
|
||||
let server_dgram1 = server.process(client_dgram, now).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.
|
||||
let (initial, handshake) = split_datagram(&server_dgram1.unwrap());
|
||||
assert!(handshake.is_some());
|
||||
|
||||
// The client will not acknowledge the Initial as it discards keys.
|
||||
// It sends a Handshake probe instead, containing just a PING frame.
|
||||
assert_eq!(client.stats().frame_tx.ping, 0);
|
||||
let probe = client.process(Some(initial), now).dgram();
|
||||
assertions::assert_handshake(&probe.unwrap());
|
||||
assert_eq!(client.stats().dropped_rx, 0);
|
||||
assert_eq!(client.stats().frame_tx.ping, 1);
|
||||
|
||||
let (initial, handshake) = split_datagram(&server_dgram2.unwrap());
|
||||
assert!(handshake.is_some());
|
||||
|
||||
// The same happens after a PTO, even though the client will discard the Initial packet.
|
||||
now += AT_LEAST_PTO;
|
||||
assert_eq!(client.stats().frame_tx.ping, 1);
|
||||
let discarded = client.stats().dropped_rx;
|
||||
let probe = client.process(Some(initial), now).dgram();
|
||||
assertions::assert_handshake(&probe.unwrap());
|
||||
assert_eq!(client.stats().frame_tx.ping, 2);
|
||||
assert_eq!(client.stats().dropped_rx, discarded + 1);
|
||||
|
||||
// Pass the Handshake packet and complete the handshake.
|
||||
client.process_input(handshake.unwrap(), now);
|
||||
maybe_authenticate(&mut client);
|
||||
let dgram = client.process_output(now).dgram();
|
||||
let dgram = server.process(dgram, now).dgram();
|
||||
client.process_input(dgram.unwrap(), now);
|
||||
|
||||
assert_eq!(*client.state(), State::Confirmed);
|
||||
assert_eq!(*server.state(), State::Confirmed);
|
||||
}
|
||||
|
||||
// Collect a few spare Initial packets as the handshake is exchanged.
|
||||
// Later, replay those packets to see if they result in additional probes; they should not.
|
||||
#[test]
|
||||
fn no_extra_probes_after_confirmed() {
|
||||
let mut server = default_server();
|
||||
let mut client = default_client();
|
||||
let mut now = now();
|
||||
|
||||
// First, collect a client Initial.
|
||||
let spare_initial = client.process_output(now).dgram();
|
||||
assert!(spare_initial.is_some());
|
||||
|
||||
// Collect ANOTHER client Initial.
|
||||
now += AT_LEAST_PTO;
|
||||
let dgram = client.process_output(now).dgram();
|
||||
let (replay_initial, _) = split_datagram(dgram.as_ref().unwrap());
|
||||
|
||||
// Finally, run the handshake.
|
||||
now += AT_LEAST_PTO * 2;
|
||||
let dgram = client.process_output(now).dgram();
|
||||
let dgram = server.process(dgram, now).dgram();
|
||||
|
||||
// The server should have dropped the Initial keys now, so passing in the Initial
|
||||
// should elicit a retransmit rather than having it completely ignored.
|
||||
let spare_handshake = server.process(Some(replay_initial), now).dgram();
|
||||
assert!(spare_handshake.is_some());
|
||||
|
||||
client.process_input(dgram.unwrap(), now);
|
||||
maybe_authenticate(&mut client);
|
||||
let dgram = client.process_output(now).dgram();
|
||||
let dgram = server.process(dgram, now).dgram();
|
||||
client.process_input(dgram.unwrap(), now);
|
||||
|
||||
assert_eq!(*client.state(), State::Confirmed);
|
||||
assert_eq!(*server.state(), State::Confirmed);
|
||||
|
||||
let probe = server.process(spare_initial, now).dgram();
|
||||
assert!(probe.is_none());
|
||||
let probe = client.process(spare_handshake, now).dgram();
|
||||
assert!(probe.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn implicit_rtt_server() {
|
||||
const RTT: Duration = Duration::from_secs(2);
|
||||
let mut server = default_server();
|
||||
let mut client = default_client();
|
||||
let mut now = now();
|
||||
|
||||
let dgram = client.process_output(now).dgram();
|
||||
now += RTT / 2;
|
||||
let dgram = server.process(dgram, now).dgram();
|
||||
now += RTT / 2;
|
||||
let dgram = client.process(dgram, now).dgram();
|
||||
assertions::assert_handshake(dgram.as_ref().unwrap());
|
||||
now += RTT / 2;
|
||||
server.process_input(dgram.unwrap(), now);
|
||||
|
||||
// The server doesn't receive any acknowledgments, but it can infer
|
||||
// an RTT estimate from having discarded the Initial packet number space.
|
||||
assert_eq!(server.stats().rtt, RTT);
|
||||
}
|
||||
|
@ -18,19 +18,13 @@ use neqo_common::{qdebug, Datagram};
|
||||
use std::mem;
|
||||
use test_fixture::{self, now};
|
||||
|
||||
fn check_discarded(
|
||||
peer: &mut Connection,
|
||||
pkt: Datagram,
|
||||
response: bool,
|
||||
dropped: usize,
|
||||
dups: usize,
|
||||
) {
|
||||
fn check_discarded(peer: &mut Connection, pkt: Datagram, dropped: usize, dups: usize) {
|
||||
// Make sure to flush any saved datagrams before doing this.
|
||||
mem::drop(peer.process_output(now()));
|
||||
|
||||
let before = peer.stats();
|
||||
let out = peer.process(Some(pkt), now());
|
||||
assert_eq!(out.as_dgram_ref().is_some(), response);
|
||||
assert!(out.as_dgram_ref().is_none());
|
||||
let after = peer.stats();
|
||||
assert_eq!(dropped, after.dropped_rx - before.dropped_rx);
|
||||
assert_eq!(dups, after.dups_rx - before.dups_rx);
|
||||
@ -66,12 +60,11 @@ fn discarded_initial_keys() {
|
||||
let out = client.process(init_pkt_s.clone(), now()).dgram();
|
||||
assert!(out.is_some());
|
||||
|
||||
// The client has received a handshake packet. It will remove the Initial keys.
|
||||
// The client has received handshake packet. It will remove the Initial keys.
|
||||
// We will check this by processing init_pkt_s a second time.
|
||||
// The initial packet should be dropped. The packet contains a Handshake packet as well, which
|
||||
// will be marked as dup. And it will contain padding, which will be "dropped".
|
||||
// The client will generate a Handshake packet here to avoid stalling.
|
||||
check_discarded(&mut client, init_pkt_s.unwrap(), true, 2, 1);
|
||||
check_discarded(&mut client, init_pkt_s.unwrap(), 2, 1);
|
||||
|
||||
assert!(maybe_authenticate(&mut client));
|
||||
|
||||
@ -79,7 +72,7 @@ fn discarded_initial_keys() {
|
||||
// packet from the client.
|
||||
// We will check this by processing init_pkt_c a second time.
|
||||
// The dropped packet is padding. The Initial packet has been mark dup.
|
||||
check_discarded(&mut server, init_pkt_c.clone().unwrap(), false, 1, 1);
|
||||
check_discarded(&mut server, init_pkt_c.clone().unwrap(), 1, 1);
|
||||
|
||||
qdebug!("---- client: SH..FIN -> FIN");
|
||||
let out = client.process(None, now()).dgram();
|
||||
@ -94,7 +87,7 @@ fn discarded_initial_keys() {
|
||||
// We will check this by processing init_pkt_c a third time.
|
||||
// The Initial packet has been dropped and padding that follows it.
|
||||
// There is no dups, everything has been dropped.
|
||||
check_discarded(&mut server, init_pkt_c.unwrap(), false, 1, 0);
|
||||
check_discarded(&mut server, init_pkt_c.unwrap(), 1, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -207,7 +200,7 @@ fn key_update_consecutive() {
|
||||
|
||||
// However, as the server didn't wait long enough to update again, the
|
||||
// client hasn't rotated its keys, so the packet gets dropped.
|
||||
check_discarded(&mut client, dgram, false, 1, 0);
|
||||
check_discarded(&mut client, dgram, 1, 0);
|
||||
}
|
||||
|
||||
// Key updates can't be initiated too early.
|
||||
|
@ -16,7 +16,6 @@ use crate::recovery::ACK_ONLY_SIZE_LIMIT;
|
||||
use crate::stats::{FrameStats, Stats, MAX_PTO_COUNTS};
|
||||
use crate::{
|
||||
ConnectionIdDecoder, ConnectionIdGenerator, ConnectionParameters, Error, StreamId, StreamType,
|
||||
Version,
|
||||
};
|
||||
|
||||
use std::cell::RefCell;
|
||||
@ -129,9 +128,6 @@ pub fn new_server(params: ConnectionParameters) -> Connection {
|
||||
pub fn default_server() -> Connection {
|
||||
new_server(ConnectionParameters::default())
|
||||
}
|
||||
pub fn resumed_server(client: &Connection) -> Connection {
|
||||
new_server(ConnectionParameters::default().versions(client.version(), Version::all()))
|
||||
}
|
||||
|
||||
/// If state is `AuthenticationNeeded` call `authenticated()`. This function will
|
||||
/// consume all outstanding events on the connection.
|
||||
@ -215,10 +211,10 @@ fn connect(client: &mut Connection, server: &mut Connection) {
|
||||
connect_with_rtt(client, server, now(), Duration::new(0, 0));
|
||||
}
|
||||
|
||||
fn assert_error(c: &Connection, expected: &ConnectionError) {
|
||||
fn assert_error(c: &Connection, err: &ConnectionError) {
|
||||
match c.state() {
|
||||
State::Closing { error, .. } | State::Draining { error, .. } | State::Closed(error) => {
|
||||
assert_eq!(*error, *expected, "{} error mismatch", c);
|
||||
assert_eq!(*error, *err);
|
||||
}
|
||||
_ => panic!("bad state {:?}", c.state()),
|
||||
}
|
||||
|
@ -6,10 +6,9 @@
|
||||
|
||||
use super::{
|
||||
connect, connect_with_rtt, default_client, default_server, exchange_ticket, get_tokens,
|
||||
new_client, resumed_server, send_something, AT_LEAST_PTO,
|
||||
send_something, AT_LEAST_PTO,
|
||||
};
|
||||
use crate::addr_valid::{AddressValidation, ValidateAddress};
|
||||
use crate::{ConnectionParameters, Error, Version};
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::mem;
|
||||
@ -28,7 +27,7 @@ fn resume() {
|
||||
client
|
||||
.enable_resumption(now(), token)
|
||||
.expect("should set token");
|
||||
let mut server = resumed_server(&client);
|
||||
let mut server = default_server();
|
||||
connect(&mut client, &mut server);
|
||||
assert!(client.tls_info().unwrap().resumed());
|
||||
assert!(server.tls_info().unwrap().resumed());
|
||||
@ -59,13 +58,13 @@ fn remember_smoothed_rtt() {
|
||||
let token = get_tokens(&mut client).pop().unwrap();
|
||||
|
||||
let mut client = default_client();
|
||||
let mut server = default_server();
|
||||
client.enable_resumption(now, token).unwrap();
|
||||
assert_eq!(
|
||||
client.paths.rtt(),
|
||||
RTT1,
|
||||
"client should remember previous RTT"
|
||||
);
|
||||
let mut server = resumed_server(&client);
|
||||
|
||||
connect_with_rtt(&mut client, &mut server, now, RTT2);
|
||||
assert_eq!(
|
||||
@ -90,7 +89,7 @@ fn address_validation_token_resume() {
|
||||
let token = exchange_ticket(&mut client, &mut server, now);
|
||||
let mut client = default_client();
|
||||
client.enable_resumption(now, token).unwrap();
|
||||
let mut server = resumed_server(&client);
|
||||
let mut server = default_server();
|
||||
|
||||
// Grab an Initial packet from the client.
|
||||
let dgram = client.process(None, now).dgram();
|
||||
@ -194,53 +193,3 @@ fn take_token() {
|
||||
let token = client.take_resumption_token(now()).unwrap();
|
||||
can_resume(&token, false);
|
||||
}
|
||||
|
||||
/// If a version is selected and subsequently disabled, resumption fails.
|
||||
#[test]
|
||||
fn resume_disabled_version() {
|
||||
let mut client = new_client(
|
||||
ConnectionParameters::default().versions(Version::Version1, vec![Version::Version1]),
|
||||
);
|
||||
let mut server = default_server();
|
||||
connect(&mut client, &mut server);
|
||||
let token = exchange_ticket(&mut client, &mut server, now());
|
||||
|
||||
let mut client = new_client(
|
||||
ConnectionParameters::default().versions(Version::Version2, vec![Version::Version2]),
|
||||
);
|
||||
assert_eq!(
|
||||
client.enable_resumption(now(), token).unwrap_err(),
|
||||
Error::DisabledVersion
|
||||
);
|
||||
}
|
||||
|
||||
/// It's not possible to resume once a packet has been sent.
|
||||
#[test]
|
||||
fn resume_after_packet() {
|
||||
let mut client = default_client();
|
||||
let mut server = default_server();
|
||||
connect(&mut client, &mut server);
|
||||
let token = exchange_ticket(&mut client, &mut server, now());
|
||||
|
||||
let mut client = default_client();
|
||||
mem::drop(client.process_output(now()).dgram().unwrap());
|
||||
assert_eq!(
|
||||
client.enable_resumption(now(), token).unwrap_err(),
|
||||
Error::ConnectionState
|
||||
);
|
||||
}
|
||||
|
||||
/// It's not possible to resume at the server.
|
||||
#[test]
|
||||
fn resume_server() {
|
||||
let mut client = default_client();
|
||||
let mut server = default_server();
|
||||
connect(&mut client, &mut server);
|
||||
let token = exchange_ticket(&mut client, &mut server, now());
|
||||
|
||||
let mut server = default_server();
|
||||
assert_eq!(
|
||||
server.enable_resumption(now(), token).unwrap_err(),
|
||||
Error::ConnectionState
|
||||
);
|
||||
}
|
||||
|
@ -4,19 +4,15 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use super::super::{ConnectionError, ConnectionEvent, Output, State, ZeroRttState};
|
||||
use super::{
|
||||
connect, connect_fail, default_client, default_server, exchange_ticket, new_client, new_server,
|
||||
send_something,
|
||||
};
|
||||
use super::super::{ConnectionError, Output, State};
|
||||
use super::{default_client, default_server};
|
||||
use crate::packet::PACKET_BIT_LONG;
|
||||
use crate::tparams::{self, TransportParameter};
|
||||
use crate::{ConnectionParameters, Error, Version};
|
||||
use crate::{Error, QuicVersion};
|
||||
|
||||
use neqo_common::{event::Provider, Datagram, Decoder, Encoder};
|
||||
use neqo_common::{Datagram, Decoder, Encoder};
|
||||
use std::mem;
|
||||
use std::time::Duration;
|
||||
use test_fixture::{self, addr, assertions, now};
|
||||
use test_fixture::{self, addr, now};
|
||||
|
||||
// The expected PTO duration after the first Initial is sent.
|
||||
const INITIAL_PTO: Duration = Duration::from_millis(300);
|
||||
@ -62,8 +58,8 @@ fn create_vn(initial_pkt: &[u8], versions: &[u32]) -> Vec<u8> {
|
||||
let mut encoder = Encoder::default();
|
||||
encoder.encode_byte(PACKET_BIT_LONG);
|
||||
encoder.encode(&[0; 4]); // Zero version == VN.
|
||||
encoder.encode_vec(1, src_cid);
|
||||
encoder.encode_vec(1, dst_cid);
|
||||
encoder.encode_vec(1, src_cid);
|
||||
|
||||
for v in versions {
|
||||
encoder.encode_uint(4, *v);
|
||||
@ -83,7 +79,7 @@ fn version_negotiation_current_version() {
|
||||
|
||||
let vn = create_vn(
|
||||
&initial_pkt,
|
||||
&[0x1a1a_1a1a, Version::default().wire_version()],
|
||||
&[0x1a1a_1a1a, QuicVersion::default().as_u32()],
|
||||
);
|
||||
|
||||
let dgram = Datagram::new(addr(), addr(), vn);
|
||||
@ -93,25 +89,6 @@ fn version_negotiation_current_version() {
|
||||
assert_eq!(1, client.stats().dropped_rx);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn version_negotiation_version0() {
|
||||
let mut client = default_client();
|
||||
// Start the handshake.
|
||||
let initial_pkt = client
|
||||
.process(None, now())
|
||||
.dgram()
|
||||
.expect("a datagram")
|
||||
.to_vec();
|
||||
|
||||
let vn = create_vn(&initial_pkt, &[0, 0x1a1a_1a1a]);
|
||||
|
||||
let dgram = Datagram::new(addr(), addr(), vn);
|
||||
let delay = client.process(Some(dgram), now()).callback();
|
||||
assert_eq!(delay, INITIAL_PTO);
|
||||
assert_eq!(*client.state(), State::WaitInitial);
|
||||
assert_eq!(1, client.stats().dropped_rx);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn version_negotiation_only_reserved() {
|
||||
let mut client = default_client();
|
||||
@ -183,8 +160,11 @@ fn version_negotiation_not_supported() {
|
||||
.to_vec();
|
||||
|
||||
let vn = create_vn(&initial_pkt, &[0x1a1a_1a1a, 0x2a2a_2a2a, 0xff00_0001]);
|
||||
let dgram = Datagram::new(addr(), addr(), vn);
|
||||
assert_eq!(client.process(Some(dgram), now()), Output::None);
|
||||
|
||||
assert_eq!(
|
||||
client.process(Some(Datagram::new(addr(), addr(), vn)), now(),),
|
||||
Output::None
|
||||
);
|
||||
match client.state() {
|
||||
State::Closed(err) => {
|
||||
assert_eq!(*err, ConnectionError::Transport(Error::VersionNegotiation));
|
||||
@ -197,14 +177,14 @@ fn version_negotiation_not_supported() {
|
||||
fn version_negotiation_bad_cid() {
|
||||
let mut client = default_client();
|
||||
// Start the handshake.
|
||||
let mut initial_pkt = client
|
||||
let initial_pkt = client
|
||||
.process(None, now())
|
||||
.dgram()
|
||||
.expect("a datagram")
|
||||
.to_vec();
|
||||
|
||||
initial_pkt[6] ^= 0xc4;
|
||||
let vn = create_vn(&initial_pkt, &[0x1a1a_1a1a, 0x2a2a_2a2a, 0xff00_0001]);
|
||||
let mut vn = create_vn(&initial_pkt, &[0x1a1a_1a1a, 0x2a2a_2a2a, 0xff00_0001]);
|
||||
vn[6] ^= 0xc4;
|
||||
|
||||
let dgram = Datagram::new(addr(), addr(), vn);
|
||||
let delay = client.process(Some(dgram), now()).callback();
|
||||
@ -212,275 +192,3 @@ fn version_negotiation_bad_cid() {
|
||||
assert_eq!(*client.state(), State::WaitInitial);
|
||||
assert_eq!(1, client.stats().dropped_rx);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compatible_upgrade() {
|
||||
let mut client = default_client();
|
||||
let mut server = default_server();
|
||||
|
||||
connect(&mut client, &mut server);
|
||||
assert_eq!(client.version(), Version::Version2);
|
||||
assert_eq!(server.version(), Version::Version2);
|
||||
}
|
||||
|
||||
/// When the first packet from the client is gigantic, the server might generate acknowledgment packets in
|
||||
/// version 1. Both client and server need to handle that gracefully.
|
||||
#[test]
|
||||
fn compatible_upgrade_large_initial() {
|
||||
let params = ConnectionParameters::default().versions(
|
||||
Version::Version1,
|
||||
vec![Version::Version2, Version::Version1],
|
||||
);
|
||||
let mut client = new_client(params.clone());
|
||||
client
|
||||
.set_local_tparam(
|
||||
0x0845_de37_00ac_a5f9,
|
||||
TransportParameter::Bytes(vec![0; 2048]),
|
||||
)
|
||||
.unwrap();
|
||||
let mut server = new_server(params);
|
||||
|
||||
// Client Initial should take 2 packets.
|
||||
// Each should elicit a Version 1 ACK from the server.
|
||||
let dgram = client.process_output(now()).dgram();
|
||||
assert!(dgram.is_some());
|
||||
let dgram = server.process(dgram, now()).dgram();
|
||||
assert!(dgram.is_some());
|
||||
// The following uses the Version from *outside* this crate.
|
||||
assertions::assert_version(dgram.as_ref().unwrap(), Version::Version1.wire_version());
|
||||
client.process_input(dgram.unwrap(), now());
|
||||
|
||||
connect(&mut client, &mut server);
|
||||
assert_eq!(client.version(), Version::Version2);
|
||||
assert_eq!(server.version(), Version::Version2);
|
||||
// Only handshake padding is "dropped".
|
||||
assert_eq!(client.stats().dropped_rx, 1);
|
||||
assert_eq!(server.stats().dropped_rx, 1);
|
||||
}
|
||||
|
||||
/// A server that supports versions 1 and 2 might prefer version 1 and that's OK.
|
||||
/// This one starts with version 1 and stays there.
|
||||
#[test]
|
||||
fn compatible_no_upgrade() {
|
||||
let mut client = new_client(ConnectionParameters::default().versions(
|
||||
Version::Version1,
|
||||
vec![Version::Version2, Version::Version1],
|
||||
));
|
||||
let mut server = new_server(ConnectionParameters::default().versions(
|
||||
Version::Version1,
|
||||
vec![Version::Version1, Version::Version2],
|
||||
));
|
||||
|
||||
connect(&mut client, &mut server);
|
||||
assert_eq!(client.version(), Version::Version1);
|
||||
assert_eq!(server.version(), Version::Version1);
|
||||
}
|
||||
|
||||
/// A server that supports versions 1 and 2 might prefer version 1 and that's OK.
|
||||
/// This one starts with version 2 and downgrades to version 1.
|
||||
#[test]
|
||||
fn compatible_downgrade() {
|
||||
let mut client = new_client(ConnectionParameters::default().versions(
|
||||
Version::Version2,
|
||||
vec![Version::Version2, Version::Version1],
|
||||
));
|
||||
let mut server = new_server(ConnectionParameters::default().versions(
|
||||
Version::Version2,
|
||||
vec![Version::Version1, Version::Version2],
|
||||
));
|
||||
|
||||
connect(&mut client, &mut server);
|
||||
assert_eq!(client.version(), Version::Version1);
|
||||
assert_eq!(server.version(), Version::Version1);
|
||||
}
|
||||
|
||||
/// Inject a Version Negotiation packet, which the client detects when it validates the
|
||||
/// server `version_negotiation` transport parameter.
|
||||
#[test]
|
||||
fn version_negotiation_downgrade() {
|
||||
const DOWNGRADE: Version = Version::Draft29;
|
||||
|
||||
let mut client = default_client();
|
||||
// The server sets the current version in the transport parameter and
|
||||
// protects Initial packets with the version in its configuration.
|
||||
// When a server `Connection` is created by a `Server`, the configuration is set
|
||||
// to match the version of the packet it first receives. This replicates that.
|
||||
let mut server =
|
||||
new_server(ConnectionParameters::default().versions(DOWNGRADE, Version::all()));
|
||||
|
||||
// Start the handshake and spoof a VN packet.
|
||||
let initial = client.process_output(now()).dgram().unwrap();
|
||||
let vn = create_vn(&initial, &[DOWNGRADE.wire_version()]);
|
||||
let dgram = Datagram::new(addr(), addr(), vn);
|
||||
client.process_input(dgram, now());
|
||||
|
||||
connect_fail(
|
||||
&mut client,
|
||||
&mut server,
|
||||
Error::VersionNegotiation,
|
||||
Error::PeerError(Error::VersionNegotiation.code()),
|
||||
);
|
||||
}
|
||||
|
||||
/// A server connection needs to be configured with the version that the client attempts.
|
||||
/// Otherwise, it will object to the client transport parameters and not do anything.
|
||||
#[test]
|
||||
fn invalid_server_version() {
|
||||
let mut client =
|
||||
new_client(ConnectionParameters::default().versions(Version::Version1, Version::all()));
|
||||
let mut server =
|
||||
new_server(ConnectionParameters::default().versions(Version::Version2, Version::all()));
|
||||
|
||||
let dgram = client.process_output(now()).dgram();
|
||||
server.process_input(dgram.unwrap(), now());
|
||||
|
||||
// One packet received.
|
||||
assert_eq!(server.stats().packets_rx, 1);
|
||||
// None dropped; the server will have decrypted it successfully.
|
||||
assert_eq!(server.stats().dropped_rx, 0);
|
||||
assert_eq!(server.stats().saved_datagrams, 0);
|
||||
// The server effectively hasn't reacted here.
|
||||
match server.state() {
|
||||
State::Closed(err) => {
|
||||
assert_eq!(*err, ConnectionError::Transport(Error::CryptoAlert(47)));
|
||||
}
|
||||
_ => panic!("invalid server state"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_current_version_client() {
|
||||
const OTHER_VERSION: Version = Version::Draft29;
|
||||
|
||||
let mut client = default_client();
|
||||
let mut server = default_server();
|
||||
|
||||
assert_ne!(OTHER_VERSION, client.version());
|
||||
client
|
||||
.set_local_tparam(
|
||||
tparams::VERSION_NEGOTIATION,
|
||||
TransportParameter::Versions {
|
||||
current: OTHER_VERSION.wire_version(),
|
||||
other: Version::all()
|
||||
.iter()
|
||||
.copied()
|
||||
.map(Version::wire_version)
|
||||
.collect(),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
connect_fail(
|
||||
&mut client,
|
||||
&mut server,
|
||||
Error::PeerError(Error::CryptoAlert(47).code()),
|
||||
Error::CryptoAlert(47),
|
||||
);
|
||||
}
|
||||
|
||||
/// To test this, we need to disable compatible upgrade so that the server doesn't update
|
||||
/// its transport parameters. Then, we can overwrite its transport parameters without
|
||||
/// them being overwritten. Otherwise, it would be hard to find a window during which
|
||||
/// the transport parameter can be modified.
|
||||
#[test]
|
||||
fn invalid_current_version_server() {
|
||||
const OTHER_VERSION: Version = Version::Draft29;
|
||||
|
||||
let mut client = default_client();
|
||||
let mut server = new_server(
|
||||
ConnectionParameters::default().versions(Version::default(), vec![Version::default()]),
|
||||
);
|
||||
|
||||
assert!(!Version::default().is_compatible(OTHER_VERSION));
|
||||
server
|
||||
.set_local_tparam(
|
||||
tparams::VERSION_NEGOTIATION,
|
||||
TransportParameter::Versions {
|
||||
current: OTHER_VERSION.wire_version(),
|
||||
other: vec![OTHER_VERSION.wire_version()],
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
connect_fail(
|
||||
&mut client,
|
||||
&mut server,
|
||||
Error::CryptoAlert(47),
|
||||
Error::PeerError(Error::CryptoAlert(47).code()),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_compatible_version() {
|
||||
const OTHER_VERSION: Version = Version::Draft29;
|
||||
|
||||
let mut client = default_client();
|
||||
let mut server = default_server();
|
||||
|
||||
assert_ne!(OTHER_VERSION, client.version());
|
||||
client
|
||||
.set_local_tparam(
|
||||
tparams::VERSION_NEGOTIATION,
|
||||
TransportParameter::Versions {
|
||||
current: Version::default().wire_version(),
|
||||
other: vec![OTHER_VERSION.wire_version()],
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
connect_fail(
|
||||
&mut client,
|
||||
&mut server,
|
||||
Error::PeerError(Error::CryptoAlert(47).code()),
|
||||
Error::CryptoAlert(47),
|
||||
);
|
||||
}
|
||||
|
||||
/// When a compatible upgrade chooses a different version, 0-RTT is rejected.
|
||||
#[test]
|
||||
fn compatible_upgrade_0rtt_rejected() {
|
||||
// This is the baseline configuration where v1 is attempted and v2 preferred.
|
||||
let prefer_v2 = ConnectionParameters::default().versions(
|
||||
Version::Version1,
|
||||
vec![Version::Version2, Version::Version1],
|
||||
);
|
||||
let mut client = new_client(prefer_v2.clone());
|
||||
// The server will start with this so that the client resumes with v1.
|
||||
let just_v1 =
|
||||
ConnectionParameters::default().versions(Version::Version1, vec![Version::Version1]);
|
||||
let mut server = new_server(just_v1);
|
||||
|
||||
connect(&mut client, &mut server);
|
||||
assert_eq!(client.version(), Version::Version1);
|
||||
let token = exchange_ticket(&mut client, &mut server, now());
|
||||
|
||||
// Now upgrade the server to the preferred configuration.
|
||||
let mut client = new_client(prefer_v2.clone());
|
||||
let mut server = new_server(prefer_v2);
|
||||
client.enable_resumption(now(), token).unwrap();
|
||||
|
||||
// Create a packet with 0-RTT from the client.
|
||||
let initial = send_something(&mut client, now());
|
||||
assertions::assert_version(&initial, Version::Version1.wire_version());
|
||||
assertions::assert_coalesced_0rtt(&initial);
|
||||
server.process_input(initial, now());
|
||||
assert!(!server
|
||||
.events()
|
||||
.any(|e| matches!(e, ConnectionEvent::NewStream { .. })));
|
||||
|
||||
// Finalize the connection. Don't use connect() because it uses
|
||||
// maybe_authenticate() too liberally and that eats the events we want to check.
|
||||
let dgram = server.process_output(now()).dgram(); // ServerHello flight
|
||||
let dgram = client.process(dgram, now()).dgram(); // Client Finished (note: no authentication)
|
||||
let dgram = server.process(dgram, now()).dgram(); // HANDSHAKE_DONE
|
||||
client.process_input(dgram.unwrap(), now());
|
||||
|
||||
assert!(matches!(client.state(), State::Confirmed));
|
||||
assert!(matches!(server.state(), State::Confirmed));
|
||||
|
||||
assert!(client.events().any(|e| {
|
||||
println!(" client event: {:?}", e);
|
||||
matches!(e, ConnectionEvent::ZeroRttRejected)
|
||||
}));
|
||||
assert_eq!(client.zero_rtt_state(), ZeroRttState::Rejected);
|
||||
}
|
||||
|
@ -6,11 +6,11 @@
|
||||
|
||||
use super::super::Connection;
|
||||
use super::{
|
||||
connect, default_client, default_server, exchange_ticket, new_server, resumed_server,
|
||||
connect, default_client, default_server, exchange_ticket, new_server,
|
||||
CountingConnectionIdGenerator,
|
||||
};
|
||||
use crate::events::ConnectionEvent;
|
||||
use crate::{ConnectionParameters, Error, StreamType, Version};
|
||||
use crate::{ConnectionParameters, Error, StreamType};
|
||||
|
||||
use neqo_common::event::Provider;
|
||||
use neqo_crypto::{AllowZeroRtt, AntiReplay};
|
||||
@ -31,7 +31,7 @@ fn zero_rtt_negotiate() {
|
||||
client
|
||||
.enable_resumption(now(), token)
|
||||
.expect("should set token");
|
||||
let mut server = resumed_server(&client);
|
||||
let mut server = default_server();
|
||||
connect(&mut client, &mut server);
|
||||
assert!(client.tls_info().unwrap().early_data_accepted());
|
||||
assert!(server.tls_info().unwrap().early_data_accepted());
|
||||
@ -48,7 +48,7 @@ fn zero_rtt_send_recv() {
|
||||
client
|
||||
.enable_resumption(now(), token)
|
||||
.expect("should set token");
|
||||
let mut server = resumed_server(&client);
|
||||
let mut server = default_server();
|
||||
|
||||
// Send ClientHello.
|
||||
let client_hs = client.process(None, now());
|
||||
@ -93,7 +93,7 @@ fn zero_rtt_send_coalesce() {
|
||||
client
|
||||
.enable_resumption(now(), token)
|
||||
.expect("should set token");
|
||||
let mut server = resumed_server(&client);
|
||||
let mut server = default_server();
|
||||
|
||||
// Write 0-RTT before generating any packets.
|
||||
// This should result in a datagram that coalesces Initial and 0-RTT.
|
||||
@ -140,7 +140,7 @@ fn zero_rtt_send_reject() {
|
||||
test_fixture::DEFAULT_KEYS,
|
||||
test_fixture::DEFAULT_ALPN,
|
||||
Rc::new(RefCell::new(CountingConnectionIdGenerator::default())),
|
||||
ConnectionParameters::default().versions(client.version(), Version::all()),
|
||||
ConnectionParameters::default(),
|
||||
)
|
||||
.unwrap();
|
||||
// Using a freshly initialized anti-replay context
|
||||
@ -221,8 +221,7 @@ fn zero_rtt_update_flow_control() {
|
||||
let mut server = new_server(
|
||||
ConnectionParameters::default()
|
||||
.max_stream_data(StreamType::UniDi, true, HIGH)
|
||||
.max_stream_data(StreamType::BiDi, true, HIGH)
|
||||
.versions(client.version, Version::all()),
|
||||
.max_stream_data(StreamType::BiDi, true, HIGH),
|
||||
);
|
||||
|
||||
// Stream limits should be low for 0-RTT.
|
||||
|
294
third_party/rust/neqo-transport/src/crypto.rs
vendored
294
third_party/rust/neqo-transport/src/crypto.rs
vendored
@ -6,7 +6,6 @@
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::cmp::{max, min};
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::mem;
|
||||
use std::ops::{Index, IndexMut, Range};
|
||||
@ -23,15 +22,13 @@ use neqo_crypto::{
|
||||
TLS_VERSION_1_3,
|
||||
};
|
||||
|
||||
use crate::cid::ConnectionIdRef;
|
||||
use crate::packet::{PacketBuilder, PacketNumber};
|
||||
use crate::packet::{PacketBuilder, PacketNumber, QuicVersion};
|
||||
use crate::recovery::RecoveryToken;
|
||||
use crate::recv_stream::RxStreamOrderer;
|
||||
use crate::send_stream::TxBuffer;
|
||||
use crate::stats::FrameStats;
|
||||
use crate::tparams::{TpZeroRttChecker, TransportParameters, TransportParametersHandler};
|
||||
use crate::tracking::PacketNumberSpace;
|
||||
use crate::version::Version;
|
||||
use crate::{Error, Res};
|
||||
|
||||
const MAX_AUTH_TAG: usize = 32;
|
||||
@ -51,8 +48,6 @@ thread_local!(pub(crate) static OVERWRITE_INVOCATIONS: RefCell<Option<PacketNumb
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Crypto {
|
||||
version: Version,
|
||||
protocols: Vec<String>,
|
||||
pub(crate) tls: Agent,
|
||||
pub(crate) streams: CryptoStreams,
|
||||
pub(crate) states: CryptoStates,
|
||||
@ -62,9 +57,9 @@ type TpHandler = Rc<RefCell<TransportParametersHandler>>;
|
||||
|
||||
impl Crypto {
|
||||
pub fn new(
|
||||
version: Version,
|
||||
version: QuicVersion,
|
||||
mut agent: Agent,
|
||||
protocols: Vec<String>,
|
||||
protocols: &[impl AsRef<str>],
|
||||
tphandler: TpHandler,
|
||||
) -> Res<Self> {
|
||||
agent.set_version_range(TLS_VERSION_1_3, TLS_VERSION_1_3)?;
|
||||
@ -73,7 +68,7 @@ impl Crypto {
|
||||
TLS_AES_256_GCM_SHA384,
|
||||
TLS_CHACHA20_POLY1305_SHA256,
|
||||
])?;
|
||||
agent.set_alpn(&protocols)?;
|
||||
agent.set_alpn(protocols)?;
|
||||
agent.disable_end_of_early_data()?;
|
||||
// Always enable 0-RTT on the client, but the server needs
|
||||
// more configuration passed to server_enable_0rtt.
|
||||
@ -81,33 +76,20 @@ impl Crypto {
|
||||
c.enable_0rtt()?;
|
||||
}
|
||||
let extension = match version {
|
||||
Version::Version2 | Version::Version1 => 0x39,
|
||||
Version::Draft29 | Version::Draft30 | Version::Draft31 | Version::Draft32 => 0xffa5,
|
||||
QuicVersion::Version1 => 0x39,
|
||||
QuicVersion::Draft29
|
||||
| QuicVersion::Draft30
|
||||
| QuicVersion::Draft31
|
||||
| QuicVersion::Draft32 => 0xffa5,
|
||||
};
|
||||
agent.extension_handler(extension, tphandler)?;
|
||||
Ok(Self {
|
||||
version,
|
||||
protocols,
|
||||
tls: agent,
|
||||
streams: Default::default(),
|
||||
states: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the name of the server. (Only works for the client currently).
|
||||
pub fn server_name(&self) -> Option<&str> {
|
||||
if let Agent::Client(c) = &self.tls {
|
||||
Some(c.server_name())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the set of enabled protocols.
|
||||
pub fn protocols(&self) -> &[String] {
|
||||
&self.protocols
|
||||
}
|
||||
|
||||
pub fn server_enable_0rtt(
|
||||
&mut self,
|
||||
tphandler: TpHandler,
|
||||
@ -192,7 +174,7 @@ impl Crypto {
|
||||
}
|
||||
|
||||
/// Enable 0-RTT and return `true` if it is enabled successfully.
|
||||
pub fn enable_0rtt(&mut self, version: Version, role: Role) -> Res<bool> {
|
||||
pub fn enable_0rtt(&mut self, role: Role) -> Res<bool> {
|
||||
let info = self.tls.preinfo()?;
|
||||
// `info.early_data()` returns false for a server,
|
||||
// so use `early_data_cipher()` to tell if 0-RTT is enabled.
|
||||
@ -211,23 +193,16 @@ impl Crypto {
|
||||
),
|
||||
};
|
||||
let secret = secret.ok_or(Error::InternalError(1))?;
|
||||
self.states
|
||||
.set_0rtt_keys(version, dir, &secret, cipher.unwrap());
|
||||
self.states.set_0rtt_keys(dir, &secret, cipher.unwrap());
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
/// Lock in a compatible upgrade.
|
||||
pub fn confirm_version(&mut self, confirmed: Version) {
|
||||
self.states.confirm_version(self.version, confirmed);
|
||||
self.version = confirmed;
|
||||
}
|
||||
|
||||
/// Returns true if new handshake keys were installed.
|
||||
pub fn install_keys(&mut self, role: Role) -> Res<bool> {
|
||||
if !self.tls.state().is_final() {
|
||||
let installed_hs = self.install_handshake_keys()?;
|
||||
if role == Role::Server {
|
||||
self.maybe_install_application_write_key(self.version)?;
|
||||
self.maybe_install_application_write_key()?;
|
||||
}
|
||||
Ok(installed_hs)
|
||||
} else {
|
||||
@ -253,22 +228,22 @@ impl Crypto {
|
||||
}
|
||||
.ok_or(Error::InternalError(3))?;
|
||||
self.states
|
||||
.set_handshake_keys(self.version, &write_secret, &read_secret, cipher);
|
||||
.set_handshake_keys(&write_secret, &read_secret, cipher);
|
||||
qdebug!([self], "Handshake keys installed");
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn maybe_install_application_write_key(&mut self, version: Version) -> Res<()> {
|
||||
fn maybe_install_application_write_key(&mut self) -> Res<()> {
|
||||
qtrace!([self], "Attempt to install application write key");
|
||||
if let Some(secret) = self.tls.write_secret(TLS_EPOCH_APPLICATION_DATA) {
|
||||
self.states.set_application_write_key(version, secret)?;
|
||||
self.states.set_application_write_key(secret)?;
|
||||
qdebug!([self], "Application write key installed");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn install_application_keys(&mut self, version: Version, expire_0rtt: Instant) -> Res<()> {
|
||||
self.maybe_install_application_write_key(version)?;
|
||||
pub fn install_application_keys(&mut self, expire_0rtt: Instant) -> Res<()> {
|
||||
self.maybe_install_application_write_key()?;
|
||||
// The write key might have been installed earlier, but it should
|
||||
// always be installed now.
|
||||
debug_assert!(self.states.app_write.is_some());
|
||||
@ -277,7 +252,7 @@ impl Crypto {
|
||||
.read_secret(TLS_EPOCH_APPLICATION_DATA)
|
||||
.ok_or(Error::InternalError(4))?;
|
||||
self.states
|
||||
.set_application_read_key(version, read_secret, expire_0rtt)?;
|
||||
.set_application_read_key(read_secret, expire_0rtt)?;
|
||||
qdebug!([self], "application read keys installed");
|
||||
Ok(())
|
||||
}
|
||||
@ -341,21 +316,19 @@ impl Crypto {
|
||||
&mut self,
|
||||
new_token: Option<&[u8]>,
|
||||
tps: &TransportParameters,
|
||||
version: Version,
|
||||
rtt: u64,
|
||||
) -> Option<ResumptionToken> {
|
||||
if let Agent::Client(ref mut c) = self.tls {
|
||||
if let Some(ref t) = c.resumption_token() {
|
||||
qtrace!("TLS token {}", hex(t.as_ref()));
|
||||
let mut enc = Encoder::default();
|
||||
enc.encode_uint(4, version.wire_version());
|
||||
enc.encode_varint(rtt);
|
||||
enc.encode_vvec_with(|enc_inner| {
|
||||
tps.encode(enc_inner);
|
||||
});
|
||||
enc.encode_vvec(new_token.unwrap_or(&[]));
|
||||
enc.encode(t.as_ref());
|
||||
qinfo!("resumption token {}", hex_snip_middle(enc.as_ref()));
|
||||
qinfo!("resumption token {}", hex_snip_middle(&enc[..]));
|
||||
Some(ResumptionToken::new(enc.into(), t.expiration_time()))
|
||||
} else {
|
||||
None
|
||||
@ -388,9 +361,6 @@ pub enum CryptoDxDirection {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CryptoDxState {
|
||||
/// The QUIC version.
|
||||
version: Version,
|
||||
/// Whether packets protected with this state will be read or written.
|
||||
direction: CryptoDxDirection,
|
||||
/// The epoch of this crypto state. This initially tracks TLS epochs
|
||||
/// via DTLS: 0 = initial, 1 = 0-RTT, 2 = handshake, 3 = application.
|
||||
@ -413,26 +383,22 @@ pub struct CryptoDxState {
|
||||
impl CryptoDxState {
|
||||
#[allow(clippy::reversed_empty_ranges)] // To initialize an empty range.
|
||||
pub fn new(
|
||||
version: Version,
|
||||
direction: CryptoDxDirection,
|
||||
epoch: Epoch,
|
||||
secret: &SymKey,
|
||||
cipher: Cipher,
|
||||
) -> Self {
|
||||
qinfo!(
|
||||
"Making {:?} {} CryptoDxState, v={:?} cipher={}",
|
||||
"Making {:?} {} CryptoDxState, cipher={}",
|
||||
direction,
|
||||
epoch,
|
||||
version,
|
||||
cipher,
|
||||
cipher
|
||||
);
|
||||
let hplabel = String::from(version.label_prefix()) + "hp";
|
||||
Self {
|
||||
version,
|
||||
direction,
|
||||
epoch: usize::from(epoch),
|
||||
aead: Aead::new(TLS_VERSION_1_3, cipher, secret, version.label_prefix()).unwrap(),
|
||||
hpkey: HpKey::extract(TLS_VERSION_1_3, cipher, secret, &hplabel).unwrap(),
|
||||
aead: Aead::new(TLS_VERSION_1_3, cipher, secret, "quic ").unwrap(),
|
||||
hpkey: HpKey::extract(TLS_VERSION_1_3, cipher, secret, "quic hp").unwrap(),
|
||||
used_pn: 0..0,
|
||||
min_pn: 0,
|
||||
invocations: Self::limit(direction, cipher),
|
||||
@ -440,13 +406,27 @@ impl CryptoDxState {
|
||||
}
|
||||
|
||||
pub fn new_initial(
|
||||
version: Version,
|
||||
quic_version: QuicVersion,
|
||||
direction: CryptoDxDirection,
|
||||
label: &str,
|
||||
dcid: &[u8],
|
||||
) -> Self {
|
||||
qtrace!("new_initial {:?} {}", version, ConnectionIdRef::from(dcid));
|
||||
let salt = version.initial_salt();
|
||||
const INITIAL_SALT_V1: &[u8] = &[
|
||||
0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8,
|
||||
0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a,
|
||||
];
|
||||
const INITIAL_SALT_29_32: &[u8] = &[
|
||||
0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2, 0x4c, 0x9e, 0x97, 0x86, 0xf1, 0x9c, 0x61,
|
||||
0x11, 0xe0, 0x43, 0x90, 0xa8, 0x99,
|
||||
];
|
||||
qtrace!("new_initial for {:?}", quic_version);
|
||||
let salt = match quic_version {
|
||||
QuicVersion::Version1 => INITIAL_SALT_V1,
|
||||
QuicVersion::Draft29
|
||||
| QuicVersion::Draft30
|
||||
| QuicVersion::Draft31
|
||||
| QuicVersion::Draft32 => INITIAL_SALT_29_32,
|
||||
};
|
||||
let cipher = TLS_AES_128_GCM_SHA256;
|
||||
let initial_secret = hkdf::extract(
|
||||
TLS_VERSION_1_3,
|
||||
@ -459,7 +439,7 @@ impl CryptoDxState {
|
||||
let secret =
|
||||
hkdf::expand_label(TLS_VERSION_1_3, cipher, &initial_secret, &[], label).unwrap();
|
||||
|
||||
Self::new(version, direction, TLS_EPOCH_INITIAL, &secret, cipher)
|
||||
Self::new(direction, TLS_EPOCH_INITIAL, &secret, cipher)
|
||||
}
|
||||
|
||||
/// Determine the confidentiality and integrity limits for the cipher.
|
||||
@ -515,16 +495,9 @@ impl CryptoDxState {
|
||||
Self::limit(CryptoDxDirection::Write, cipher)
|
||||
};
|
||||
Self {
|
||||
version: self.version,
|
||||
direction: self.direction,
|
||||
epoch: self.epoch + 1,
|
||||
aead: Aead::new(
|
||||
TLS_VERSION_1_3,
|
||||
cipher,
|
||||
next_secret,
|
||||
self.version.label_prefix(),
|
||||
)
|
||||
.unwrap(),
|
||||
aead: Aead::new(TLS_VERSION_1_3, cipher, next_secret, "quic ").unwrap(),
|
||||
hpkey: self.hpkey.clone(),
|
||||
used_pn: pn..pn,
|
||||
min_pn: pn,
|
||||
@ -532,11 +505,6 @@ impl CryptoDxState {
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn version(&self) -> Version {
|
||||
self.version
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn key_phase(&self) -> bool {
|
||||
// Epoch 3 => 0, 4 => 1, 5 => 0, 6 => 1, ...
|
||||
@ -549,7 +517,8 @@ impl CryptoDxState {
|
||||
debug_assert_eq!(self.direction, prev.direction);
|
||||
let next = prev.next_pn();
|
||||
self.min_pn = next;
|
||||
if self.used_pn.is_empty() {
|
||||
// TODO(mt) use Range::is_empty() when available
|
||||
if self.used_pn.start == self.used_pn.end {
|
||||
self.used_pn = next..next;
|
||||
Ok(())
|
||||
} else if prev.used_pn.end > self.used_pn.start {
|
||||
@ -669,7 +638,7 @@ impl CryptoDxState {
|
||||
// This matches the value in packet.rs
|
||||
const CLIENT_CID: &[u8] = &[0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08];
|
||||
Self::new_initial(
|
||||
Version::default(),
|
||||
QuicVersion::default(),
|
||||
CryptoDxDirection::Write,
|
||||
"server in",
|
||||
CLIENT_CID,
|
||||
@ -729,14 +698,9 @@ pub(crate) struct CryptoDxAppData {
|
||||
}
|
||||
|
||||
impl CryptoDxAppData {
|
||||
pub fn new(
|
||||
version: Version,
|
||||
dir: CryptoDxDirection,
|
||||
secret: SymKey,
|
||||
cipher: Cipher,
|
||||
) -> Res<Self> {
|
||||
pub fn new(dir: CryptoDxDirection, secret: SymKey, cipher: Cipher) -> Res<Self> {
|
||||
Ok(Self {
|
||||
dx: CryptoDxState::new(version, dir, TLS_EPOCH_APPLICATION_DATA, &secret, cipher),
|
||||
dx: CryptoDxState::new(dir, TLS_EPOCH_APPLICATION_DATA, &secret, cipher),
|
||||
cipher,
|
||||
next_secret: Self::update_secret(cipher, &secret)?,
|
||||
})
|
||||
@ -773,14 +737,9 @@ pub enum CryptoSpace {
|
||||
ApplicationData,
|
||||
}
|
||||
|
||||
/// All of the keying material needed for a connection.
|
||||
///
|
||||
/// Note that the methods on this struct take a version but those are only ever
|
||||
/// used for Initial keys; a version has been selected at the time we need to
|
||||
/// get other keys, so those have fixed versions.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct CryptoStates {
|
||||
initials: HashMap<Version, CryptoState>,
|
||||
initial: Option<CryptoState>,
|
||||
handshake: Option<CryptoState>,
|
||||
zero_rtt: Option<CryptoDxState>, // One direction only!
|
||||
cipher: Cipher,
|
||||
@ -798,15 +757,14 @@ impl CryptoStates {
|
||||
/// not yet available.
|
||||
pub fn select_tx_mut(
|
||||
&mut self,
|
||||
version: Version,
|
||||
space: PacketNumberSpace,
|
||||
) -> Option<(CryptoSpace, &mut CryptoDxState)> {
|
||||
match space {
|
||||
PacketNumberSpace::Initial => self
|
||||
.tx_mut(version, CryptoSpace::Initial)
|
||||
.tx_mut(CryptoSpace::Initial)
|
||||
.map(|dx| (CryptoSpace::Initial, dx)),
|
||||
PacketNumberSpace::Handshake => self
|
||||
.tx_mut(version, CryptoSpace::Handshake)
|
||||
.tx_mut(CryptoSpace::Handshake)
|
||||
.map(|dx| (CryptoSpace::Handshake, dx)),
|
||||
PacketNumberSpace::ApplicationData => {
|
||||
if let Some(app) = self.app_write.as_mut() {
|
||||
@ -818,14 +776,10 @@ impl CryptoStates {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tx_mut<'a>(
|
||||
&'a mut self,
|
||||
version: Version,
|
||||
cspace: CryptoSpace,
|
||||
) -> Option<&'a mut CryptoDxState> {
|
||||
pub fn tx_mut<'a>(&'a mut self, cspace: CryptoSpace) -> Option<&'a mut CryptoDxState> {
|
||||
let tx = |k: Option<&'a mut CryptoState>| k.map(|dx| &mut dx.tx);
|
||||
match cspace {
|
||||
CryptoSpace::Initial => tx(self.initials.get_mut(&version)),
|
||||
CryptoSpace::Initial => tx(self.initial.as_mut()),
|
||||
CryptoSpace::ZeroRtt => self
|
||||
.zero_rtt
|
||||
.as_mut()
|
||||
@ -835,10 +789,10 @@ impl CryptoStates {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tx<'a>(&'a self, version: Version, cspace: CryptoSpace) -> Option<&'a CryptoDxState> {
|
||||
pub fn tx<'a>(&'a self, cspace: CryptoSpace) -> Option<&'a CryptoDxState> {
|
||||
let tx = |k: Option<&'a CryptoState>| k.map(|dx| &dx.tx);
|
||||
match cspace {
|
||||
CryptoSpace::Initial => tx(self.initials.get(&version)),
|
||||
CryptoSpace::Initial => tx(self.initial.as_ref()),
|
||||
CryptoSpace::ZeroRtt => self
|
||||
.zero_rtt
|
||||
.as_ref()
|
||||
@ -848,17 +802,13 @@ impl CryptoStates {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn select_tx(
|
||||
&self,
|
||||
version: Version,
|
||||
space: PacketNumberSpace,
|
||||
) -> Option<(CryptoSpace, &CryptoDxState)> {
|
||||
pub fn select_tx(&self, space: PacketNumberSpace) -> Option<(CryptoSpace, &CryptoDxState)> {
|
||||
match space {
|
||||
PacketNumberSpace::Initial => self
|
||||
.tx(version, CryptoSpace::Initial)
|
||||
.tx(CryptoSpace::Initial)
|
||||
.map(|dx| (CryptoSpace::Initial, dx)),
|
||||
PacketNumberSpace::Handshake => self
|
||||
.tx(version, CryptoSpace::Handshake)
|
||||
.tx(CryptoSpace::Handshake)
|
||||
.map(|dx| (CryptoSpace::Handshake, dx)),
|
||||
PacketNumberSpace::ApplicationData => {
|
||||
if let Some(app) = self.app_write.as_ref() {
|
||||
@ -870,23 +820,22 @@ impl CryptoStates {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rx_hp(&mut self, version: Version, cspace: CryptoSpace) -> Option<&mut CryptoDxState> {
|
||||
pub fn rx_hp(&mut self, cspace: CryptoSpace) -> Option<&mut CryptoDxState> {
|
||||
if let CryptoSpace::ApplicationData = cspace {
|
||||
self.app_read.as_mut().map(|ar| &mut ar.dx)
|
||||
} else {
|
||||
self.rx(version, cspace, false)
|
||||
self.rx(cspace, false)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rx<'a>(
|
||||
&'a mut self,
|
||||
version: Version,
|
||||
cspace: CryptoSpace,
|
||||
key_phase: bool,
|
||||
) -> Option<&'a mut CryptoDxState> {
|
||||
let rx = |x: Option<&'a mut CryptoState>| x.map(|dx| &mut dx.rx);
|
||||
match cspace {
|
||||
CryptoSpace::Initial => rx(self.initials.get_mut(&version)),
|
||||
CryptoSpace::Initial => rx(self.initial.as_mut()),
|
||||
CryptoSpace::ZeroRtt => self
|
||||
.zero_rtt
|
||||
.as_mut()
|
||||
@ -915,101 +864,52 @@ impl CryptoStates {
|
||||
pub fn rx_pending(&self, space: CryptoSpace) -> bool {
|
||||
match space {
|
||||
CryptoSpace::Initial | CryptoSpace::ZeroRtt => false,
|
||||
CryptoSpace::Handshake => self.handshake.is_none() && !self.initials.is_empty(),
|
||||
CryptoSpace::Handshake => self.handshake.is_none() && self.initial.is_some(),
|
||||
CryptoSpace::ApplicationData => self.app_read.is_none(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create the initial crypto state.
|
||||
/// Note that the version here can change and that's OK.
|
||||
pub fn init<'v, V>(&mut self, versions: V, role: Role, dcid: &[u8])
|
||||
where
|
||||
V: IntoIterator<Item = &'v Version>,
|
||||
{
|
||||
pub fn init(&mut self, quic_version: QuicVersion, role: Role, dcid: &[u8]) {
|
||||
const CLIENT_INITIAL_LABEL: &str = "client in";
|
||||
const SERVER_INITIAL_LABEL: &str = "server in";
|
||||
|
||||
qinfo!(
|
||||
[self],
|
||||
"Creating initial cipher state role={:?} dcid={}",
|
||||
role,
|
||||
hex(dcid)
|
||||
);
|
||||
|
||||
let (write, read) = match role {
|
||||
Role::Client => (CLIENT_INITIAL_LABEL, SERVER_INITIAL_LABEL),
|
||||
Role::Server => (SERVER_INITIAL_LABEL, CLIENT_INITIAL_LABEL),
|
||||
};
|
||||
|
||||
for v in versions {
|
||||
let mut initial = CryptoState {
|
||||
tx: CryptoDxState::new_initial(quic_version, CryptoDxDirection::Write, write, dcid),
|
||||
rx: CryptoDxState::new_initial(quic_version, CryptoDxDirection::Read, read, dcid),
|
||||
};
|
||||
if let Some(prev) = &self.initial {
|
||||
qinfo!(
|
||||
[self],
|
||||
"Creating initial cipher state v={:?}, role={:?} dcid={}",
|
||||
v,
|
||||
role,
|
||||
hex(dcid)
|
||||
"Continue packet numbers for initial after retry (write is {:?})",
|
||||
prev.rx.used_pn,
|
||||
);
|
||||
|
||||
let mut initial = CryptoState {
|
||||
tx: CryptoDxState::new_initial(*v, CryptoDxDirection::Write, write, dcid),
|
||||
rx: CryptoDxState::new_initial(*v, CryptoDxDirection::Read, read, dcid),
|
||||
};
|
||||
if let Some(prev) = self.initials.get(v) {
|
||||
qinfo!(
|
||||
[self],
|
||||
"Continue packet numbers for initial after retry (write is {:?})",
|
||||
prev.rx.used_pn,
|
||||
);
|
||||
initial.tx.continuation(&prev.tx).unwrap();
|
||||
}
|
||||
self.initials.insert(*v, initial);
|
||||
initial.tx.continuation(&prev.tx).unwrap();
|
||||
}
|
||||
self.initial = Some(initial);
|
||||
}
|
||||
|
||||
/// At a server, we can be more targeted in initializing.
|
||||
/// Initialize on demand: either to decrypt Initial packets that we receive
|
||||
/// or after a version has been selected.
|
||||
/// This is maybe slightly inefficient in the first case, because we might
|
||||
/// not need the send keys if the packet is subsequently discarded, but
|
||||
/// the overall effort is small enough to write off.
|
||||
pub fn init_server(&mut self, version: Version, dcid: &[u8]) {
|
||||
if !self.initials.contains_key(&version) {
|
||||
self.init(&[version], Role::Server, dcid);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn confirm_version(&mut self, orig: Version, confirmed: Version) {
|
||||
if orig != confirmed {
|
||||
// This part where the old data is removed and then re-added is to
|
||||
// appease the borrow checker.
|
||||
// Note that on the server, we might not have initials for |orig| if it
|
||||
// was configured for |orig| and only |confirmed| Initial packets arrived.
|
||||
if let Some(prev) = self.initials.remove(&orig) {
|
||||
let next = self.initials.get_mut(&confirmed).unwrap();
|
||||
next.tx.continuation(&prev.tx).unwrap();
|
||||
self.initials.insert(orig, prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_0rtt_keys(
|
||||
&mut self,
|
||||
version: Version,
|
||||
dir: CryptoDxDirection,
|
||||
secret: &SymKey,
|
||||
cipher: Cipher,
|
||||
) {
|
||||
pub fn set_0rtt_keys(&mut self, dir: CryptoDxDirection, secret: &SymKey, cipher: Cipher) {
|
||||
qtrace!([self], "install 0-RTT keys");
|
||||
self.zero_rtt = Some(CryptoDxState::new(
|
||||
version,
|
||||
dir,
|
||||
TLS_EPOCH_ZERO_RTT,
|
||||
secret,
|
||||
cipher,
|
||||
));
|
||||
self.zero_rtt = Some(CryptoDxState::new(dir, TLS_EPOCH_ZERO_RTT, secret, cipher));
|
||||
}
|
||||
|
||||
/// Discard keys and return true if that happened.
|
||||
pub fn discard(&mut self, space: PacketNumberSpace) -> bool {
|
||||
match space {
|
||||
PacketNumberSpace::Initial => {
|
||||
let empty = self.initials.is_empty();
|
||||
self.initials.clear();
|
||||
!empty
|
||||
}
|
||||
PacketNumberSpace::Initial => self.initial.take().is_some(),
|
||||
PacketNumberSpace::Handshake => self.handshake.take().is_some(),
|
||||
PacketNumberSpace::ApplicationData => panic!("Can't drop application data keys"),
|
||||
}
|
||||
@ -1026,7 +926,6 @@ impl CryptoStates {
|
||||
|
||||
pub fn set_handshake_keys(
|
||||
&mut self,
|
||||
version: Version,
|
||||
write_secret: &SymKey,
|
||||
read_secret: &SymKey,
|
||||
cipher: Cipher,
|
||||
@ -1034,14 +933,12 @@ impl CryptoStates {
|
||||
self.cipher = cipher;
|
||||
self.handshake = Some(CryptoState {
|
||||
tx: CryptoDxState::new(
|
||||
version,
|
||||
CryptoDxDirection::Write,
|
||||
TLS_EPOCH_HANDSHAKE,
|
||||
write_secret,
|
||||
cipher,
|
||||
),
|
||||
rx: CryptoDxState::new(
|
||||
version,
|
||||
CryptoDxDirection::Read,
|
||||
TLS_EPOCH_HANDSHAKE,
|
||||
read_secret,
|
||||
@ -1050,10 +947,10 @@ impl CryptoStates {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_application_write_key(&mut self, version: Version, secret: SymKey) -> Res<()> {
|
||||
pub fn set_application_write_key(&mut self, secret: SymKey) -> Res<()> {
|
||||
debug_assert!(self.app_write.is_none());
|
||||
debug_assert_ne!(self.cipher, 0);
|
||||
let mut app = CryptoDxAppData::new(version, CryptoDxDirection::Write, secret, self.cipher)?;
|
||||
let mut app = CryptoDxAppData::new(CryptoDxDirection::Write, secret, self.cipher)?;
|
||||
if let Some(z) = &self.zero_rtt {
|
||||
if z.direction == CryptoDxDirection::Write {
|
||||
app.dx.continuation(z)?;
|
||||
@ -1064,15 +961,10 @@ impl CryptoStates {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_application_read_key(
|
||||
&mut self,
|
||||
version: Version,
|
||||
secret: SymKey,
|
||||
expire_0rtt: Instant,
|
||||
) -> Res<()> {
|
||||
pub fn set_application_read_key(&mut self, secret: SymKey, expire_0rtt: Instant) -> Res<()> {
|
||||
debug_assert!(self.app_write.is_some(), "should have write keys installed");
|
||||
debug_assert!(self.app_read.is_none());
|
||||
let mut app = CryptoDxAppData::new(version, CryptoDxDirection::Read, secret, self.cipher)?;
|
||||
let mut app = CryptoDxAppData::new(CryptoDxDirection::Read, secret, self.cipher)?;
|
||||
if let Some(z) = &self.zero_rtt {
|
||||
if z.direction == CryptoDxDirection::Read {
|
||||
app.dx.continuation(z)?;
|
||||
@ -1228,16 +1120,11 @@ impl CryptoStates {
|
||||
cipher: TLS_AES_128_GCM_SHA256,
|
||||
next_secret: hkdf::import_key(TLS_VERSION_1_3, &[0xaa; 32]).unwrap(),
|
||||
};
|
||||
let mut initials = HashMap::new();
|
||||
initials.insert(
|
||||
Version::Version1,
|
||||
CryptoState {
|
||||
Self {
|
||||
initial: Some(CryptoState {
|
||||
tx: CryptoDxState::test_default(),
|
||||
rx: read(0),
|
||||
},
|
||||
);
|
||||
Self {
|
||||
initials,
|
||||
}),
|
||||
handshake: None,
|
||||
zero_rtt: None,
|
||||
cipher: TLS_AES_128_GCM_SHA256,
|
||||
@ -1259,14 +1146,13 @@ impl CryptoStates {
|
||||
let secret = hkdf::import_key(TLS_VERSION_1_3, SECRET).unwrap();
|
||||
let app_read = |epoch| CryptoDxAppData {
|
||||
dx: CryptoDxState {
|
||||
version: Version::Version1,
|
||||
direction: CryptoDxDirection::Read,
|
||||
epoch,
|
||||
aead: Aead::new(
|
||||
TLS_VERSION_1_3,
|
||||
TLS_CHACHA20_POLY1305_SHA256,
|
||||
&secret,
|
||||
"quic ", // This is a v1 test so hard-code the label.
|
||||
"quic ",
|
||||
)
|
||||
.unwrap(),
|
||||
hpkey: HpKey::extract(
|
||||
@ -1284,7 +1170,7 @@ impl CryptoStates {
|
||||
next_secret: secret.clone(),
|
||||
};
|
||||
Self {
|
||||
initials: HashMap::new(),
|
||||
initial: None,
|
||||
handshake: None,
|
||||
zero_rtt: None,
|
||||
cipher: TLS_CHACHA20_POLY1305_SHA256,
|
||||
|
7
third_party/rust/neqo-transport/src/lib.rs
vendored
7
third_party/rust/neqo-transport/src/lib.rs
vendored
@ -36,7 +36,6 @@ pub mod stream_id;
|
||||
pub mod streams;
|
||||
pub mod tparams;
|
||||
mod tracking;
|
||||
pub mod version;
|
||||
|
||||
pub use self::cc::CongestionControlAlgorithm;
|
||||
pub use self::cid::{
|
||||
@ -48,9 +47,9 @@ pub use self::connection::{
|
||||
};
|
||||
pub use self::events::{ConnectionEvent, ConnectionEvents};
|
||||
pub use self::frame::CloseError;
|
||||
pub use self::packet::QuicVersion;
|
||||
pub use self::stats::Stats;
|
||||
pub use self::stream_id::{StreamId, StreamType};
|
||||
pub use self::version::Version;
|
||||
|
||||
pub use self::recv_stream::RECV_BUFFER_SIZE;
|
||||
pub use self::send_stream::SEND_BUFFER_SIZE;
|
||||
@ -87,7 +86,6 @@ pub enum Error {
|
||||
ConnectionState,
|
||||
DecodingFrame,
|
||||
DecryptError,
|
||||
DisabledVersion,
|
||||
HandshakeFailed,
|
||||
IdleTimeout,
|
||||
IntegerOverflow,
|
||||
@ -97,7 +95,7 @@ pub enum Error {
|
||||
InvalidResumptionToken,
|
||||
InvalidRetry,
|
||||
InvalidStreamId,
|
||||
KeysDiscarded(crypto::CryptoSpace),
|
||||
KeysDiscarded,
|
||||
/// Packet protection keys are exhausted.
|
||||
/// Also used when too many key updates have happened.
|
||||
KeysExhausted,
|
||||
@ -145,7 +143,6 @@ impl Error {
|
||||
// As we have a special error code for ECH fallbacks, we lose the alert.
|
||||
// Send the server "ech_required" directly.
|
||||
Self::EchRetry(_) => 0x100 + 121,
|
||||
Self::VersionNegotiation => 0x53f8,
|
||||
// All the rest are internal errors.
|
||||
_ => 1,
|
||||
}
|
||||
|
326
third_party/rust/neqo-transport/src/packet/mod.rs
vendored
326
third_party/rust/neqo-transport/src/packet/mod.rs
vendored
@ -7,7 +7,6 @@
|
||||
// Encoding and decoding packets off the wire.
|
||||
use crate::cid::{ConnectionId, ConnectionIdDecoder, ConnectionIdRef, MAX_CONNECTION_ID_LEN};
|
||||
use crate::crypto::{CryptoDxState, CryptoSpace, CryptoStates};
|
||||
use crate::version::{Version, WireVersion};
|
||||
use crate::{Error, Res};
|
||||
|
||||
use neqo_common::{hex, hex_with_len, qtrace, qwarn, Decoder, Encoder};
|
||||
@ -20,6 +19,11 @@ use std::iter::ExactSizeIterator;
|
||||
use std::ops::{Deref, DerefMut, Range};
|
||||
use std::time::Instant;
|
||||
|
||||
const PACKET_TYPE_INITIAL: u8 = 0x0;
|
||||
const PACKET_TYPE_0RTT: u8 = 0x01;
|
||||
const PACKET_TYPE_HANDSHAKE: u8 = 0x2;
|
||||
const PACKET_TYPE_RETRY: u8 = 0x03;
|
||||
|
||||
pub const PACKET_BIT_LONG: u8 = 0x80;
|
||||
const PACKET_BIT_SHORT: u8 = 0x00;
|
||||
const PACKET_BIT_FIXED_QUIC: u8 = 0x40;
|
||||
@ -36,6 +40,7 @@ const MAX_PACKET_NUMBER_LEN: usize = 4;
|
||||
mod retry;
|
||||
|
||||
pub type PacketNumber = u64;
|
||||
type Version = u32;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum PacketType {
|
||||
@ -50,29 +55,15 @@ pub enum PacketType {
|
||||
|
||||
impl PacketType {
|
||||
#[must_use]
|
||||
fn from_byte(t: u8, v: Version) -> Self {
|
||||
// Version2 adds one to the type, modulo 4
|
||||
match t.wrapping_sub(u8::from(v == Version::Version2)) & 3 {
|
||||
0 => Self::Initial,
|
||||
1 => Self::ZeroRtt,
|
||||
2 => Self::Handshake,
|
||||
3 => Self::Retry,
|
||||
_ => panic!("packet type out of range"),
|
||||
fn code(self) -> u8 {
|
||||
match self {
|
||||
Self::Initial => PACKET_TYPE_INITIAL,
|
||||
Self::ZeroRtt => PACKET_TYPE_0RTT,
|
||||
Self::Handshake => PACKET_TYPE_HANDSHAKE,
|
||||
Self::Retry => PACKET_TYPE_RETRY,
|
||||
_ => panic!("shouldn't be here"),
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn to_byte(self, v: Version) -> u8 {
|
||||
let t = match self {
|
||||
Self::Initial => 0,
|
||||
Self::ZeroRtt => 1,
|
||||
Self::Handshake => 2,
|
||||
Self::Retry => 3,
|
||||
_ => panic!("not a long header packet type"),
|
||||
};
|
||||
// Version2 adds one to the type, modulo 4
|
||||
(t + u8::from(v == Version::Version2)) & 3
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PacketType> for CryptoSpace {
|
||||
@ -98,6 +89,53 @@ impl From<CryptoSpace> for PacketType {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum QuicVersion {
|
||||
Version1,
|
||||
Draft29,
|
||||
Draft30,
|
||||
Draft31,
|
||||
Draft32,
|
||||
}
|
||||
|
||||
impl QuicVersion {
|
||||
pub fn as_u32(self) -> Version {
|
||||
match self {
|
||||
Self::Version1 => 1,
|
||||
Self::Draft29 => 0xff00_0000 + 29,
|
||||
Self::Draft30 => 0xff00_0000 + 30,
|
||||
Self::Draft31 => 0xff00_0000 + 31,
|
||||
Self::Draft32 => 0xff00_0000 + 32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for QuicVersion {
|
||||
fn default() -> Self {
|
||||
Self::Version1
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Version> for QuicVersion {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(ver: Version) -> Res<Self> {
|
||||
if ver == 1 {
|
||||
Ok(Self::Version1)
|
||||
} else if ver == 0xff00_0000 + 29 {
|
||||
Ok(Self::Draft29)
|
||||
} else if ver == 0xff00_0000 + 30 {
|
||||
Ok(Self::Draft30)
|
||||
} else if ver == 0xff00_0000 + 31 {
|
||||
Ok(Self::Draft31)
|
||||
} else if ver == 0xff00_0000 + 32 {
|
||||
Ok(Self::Draft32)
|
||||
} else {
|
||||
Err(Error::VersionNegotiation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct PacketBuilderOffsets {
|
||||
/// The bits of the first octet that need masking.
|
||||
first_byte_mask: u8,
|
||||
@ -176,7 +214,7 @@ impl PacketBuilder {
|
||||
pub fn long(
|
||||
mut encoder: Encoder,
|
||||
pt: PacketType,
|
||||
version: Version,
|
||||
quic_version: QuicVersion,
|
||||
dcid: impl AsRef<[u8]>,
|
||||
scid: impl AsRef<[u8]>,
|
||||
) -> Self {
|
||||
@ -187,8 +225,8 @@ impl PacketBuilder {
|
||||
if limit > encoder.len()
|
||||
&& 11 + dcid.as_ref().len() + scid.as_ref().len() < limit - encoder.len()
|
||||
{
|
||||
encoder.encode_byte(PACKET_BIT_LONG | PACKET_BIT_FIXED_QUIC | pt.to_byte(version) << 4);
|
||||
encoder.encode_uint(4, version.wire_version());
|
||||
encoder.encode_byte(PACKET_BIT_LONG | PACKET_BIT_FIXED_QUIC | pt.code() << 4);
|
||||
encoder.encode_uint(4, quic_version.as_u32());
|
||||
encoder.encode_vec(1, dcid.as_ref());
|
||||
encoder.encode_vec(1, scid.as_ref());
|
||||
} else {
|
||||
@ -210,7 +248,7 @@ impl PacketBuilder {
|
||||
}
|
||||
|
||||
fn is_long(&self) -> bool {
|
||||
self.as_ref()[self.header.start] & 0x80 == PACKET_BIT_LONG
|
||||
self[self.header.start] & 0x80 == PACKET_BIT_LONG
|
||||
}
|
||||
|
||||
/// This stores a value that can be used as a limit. This does not cause
|
||||
@ -267,12 +305,16 @@ impl PacketBuilder {
|
||||
let mask = if quic_bit { PACKET_BIT_FIXED_QUIC } else { 0 }
|
||||
| if self.is_long() { 0 } else { PACKET_BIT_SPIN };
|
||||
let first = self.header.start;
|
||||
self.encoder.as_mut()[first] ^= random(1)[0] & mask;
|
||||
self[first] ^= random(1)[0] & mask;
|
||||
}
|
||||
|
||||
/// For an Initial packet, encode the token.
|
||||
/// If you fail to do this, then you will not get a valid packet.
|
||||
pub fn initial_token(&mut self, token: &[u8]) {
|
||||
debug_assert_eq!(
|
||||
self.encoder[self.header.start] & 0xb0,
|
||||
PACKET_BIT_LONG | PACKET_TYPE_INITIAL << 4
|
||||
);
|
||||
if Encoder::vvec_len(token.len()) < self.remaining() {
|
||||
self.encoder.encode_vvec(token);
|
||||
} else {
|
||||
@ -306,15 +348,15 @@ impl PacketBuilder {
|
||||
self.offsets.pn = pn_offset..self.encoder.len();
|
||||
|
||||
// Now encode the packet number length and save the header length.
|
||||
self.encoder.as_mut()[self.header.start] |= u8::try_from(pn_len - 1).unwrap();
|
||||
self.encoder[self.header.start] |= u8::try_from(pn_len - 1).unwrap();
|
||||
self.header.end = self.encoder.len();
|
||||
self.pn = pn;
|
||||
}
|
||||
|
||||
fn write_len(&mut self, expansion: usize) {
|
||||
let len = self.encoder.len() - (self.offsets.len + 2) + expansion;
|
||||
self.encoder.as_mut()[self.offsets.len] = 0x40 | ((len >> 8) & 0x3f) as u8;
|
||||
self.encoder.as_mut()[self.offsets.len + 1] = (len & 0xff) as u8;
|
||||
self.encoder[self.offsets.len] = 0x40 | ((len >> 8) & 0x3f) as u8;
|
||||
self.encoder[self.offsets.len + 1] = (len & 0xff) as u8;
|
||||
}
|
||||
|
||||
fn pad_for_crypto(&mut self, crypto: &mut CryptoDxState) {
|
||||
@ -360,8 +402,8 @@ impl PacketBuilder {
|
||||
self.write_len(crypto.expansion());
|
||||
}
|
||||
|
||||
let hdr = &self.encoder.as_ref()[self.header.clone()];
|
||||
let body = &self.encoder.as_ref()[self.header.end..];
|
||||
let hdr = &self.encoder[self.header.clone()];
|
||||
let body = &self.encoder[self.header.end..];
|
||||
qtrace!(
|
||||
"Packet build pn={} hdr={} body={}",
|
||||
self.pn,
|
||||
@ -377,9 +419,9 @@ impl PacketBuilder {
|
||||
let mask = crypto.compute_mask(sample)?;
|
||||
|
||||
// Apply the mask.
|
||||
self.encoder.as_mut()[self.header.start] ^= mask[0] & self.offsets.first_byte_mask;
|
||||
self.encoder[self.header.start] ^= mask[0] & self.offsets.first_byte_mask;
|
||||
for (i, j) in (1..=self.offsets.pn.len()).zip(self.offsets.pn) {
|
||||
self.encoder.as_mut()[j] ^= mask[i];
|
||||
self.encoder[j] ^= mask[i];
|
||||
}
|
||||
|
||||
// Finally, cut off the plaintext and add back the ciphertext.
|
||||
@ -407,7 +449,7 @@ impl PacketBuilder {
|
||||
/// As Retry is odd (it has to be constructed with leading bytes),
|
||||
/// this returns a Vec<u8> rather than building on an encoder.
|
||||
pub fn retry(
|
||||
version: Version,
|
||||
quic_version: QuicVersion,
|
||||
dcid: &[u8],
|
||||
scid: &[u8],
|
||||
token: &[u8],
|
||||
@ -419,17 +461,17 @@ impl PacketBuilder {
|
||||
encoder.encode_byte(
|
||||
PACKET_BIT_LONG
|
||||
| PACKET_BIT_FIXED_QUIC
|
||||
| (PacketType::Retry.to_byte(version) << 4)
|
||||
| (PACKET_TYPE_RETRY << 4)
|
||||
| (random(1)[0] & 0xf),
|
||||
);
|
||||
encoder.encode_uint(4, version.wire_version());
|
||||
encoder.encode_uint(4, quic_version.as_u32());
|
||||
encoder.encode_vec(1, dcid);
|
||||
encoder.encode_vec(1, scid);
|
||||
debug_assert_ne!(token.len(), 0);
|
||||
encoder.encode(token);
|
||||
let tag = retry::use_aead(version, |aead| {
|
||||
let tag = retry::use_aead(quic_version, |aead| {
|
||||
let mut buf = vec![0; aead.expansion()];
|
||||
Ok(aead.encrypt(0, encoder.as_ref(), &[], &mut buf)?.to_vec())
|
||||
Ok(aead.encrypt(0, &encoder, &[], &mut buf)?.to_vec())
|
||||
})?;
|
||||
encoder.encode(&tag);
|
||||
let mut complete: Vec<u8> = encoder.into();
|
||||
@ -437,34 +479,25 @@ impl PacketBuilder {
|
||||
}
|
||||
|
||||
/// Make a Version Negotiation packet.
|
||||
pub fn version_negotiation(
|
||||
dcid: &[u8],
|
||||
scid: &[u8],
|
||||
client_version: u32,
|
||||
versions: &[Version],
|
||||
) -> Vec<u8> {
|
||||
pub fn version_negotiation(dcid: &[u8], scid: &[u8]) -> Vec<u8> {
|
||||
let mut encoder = Encoder::default();
|
||||
let mut grease = random(4);
|
||||
let mut grease = random(5);
|
||||
// This will not include the "QUIC bit" sometimes. Intentionally.
|
||||
encoder.encode_byte(PACKET_BIT_LONG | (grease[3] & 0x7f));
|
||||
encoder.encode_byte(PACKET_BIT_LONG | (grease[4] & 0x7f));
|
||||
encoder.encode(&[0; 4]); // Zero version == VN.
|
||||
encoder.encode_vec(1, dcid);
|
||||
encoder.encode_vec(1, scid);
|
||||
|
||||
for v in versions {
|
||||
encoder.encode_uint(4, v.wire_version());
|
||||
}
|
||||
encoder.encode_uint(4, QuicVersion::Version1.as_u32());
|
||||
encoder.encode_uint(4, QuicVersion::Draft29.as_u32());
|
||||
encoder.encode_uint(4, QuicVersion::Draft30.as_u32());
|
||||
encoder.encode_uint(4, QuicVersion::Draft31.as_u32());
|
||||
encoder.encode_uint(4, QuicVersion::Draft32.as_u32());
|
||||
// Add a greased version, using the randomness already generated.
|
||||
for g in &mut grease[..3] {
|
||||
for g in &mut grease[..4] {
|
||||
*g = *g & 0xf0 | 0x0a;
|
||||
}
|
||||
|
||||
// Ensure our greased version does not collide with the client version
|
||||
// by making the last byte differ from the client initial.
|
||||
grease[3] = (client_version.wrapping_add(0x10) & 0xf0) as u8 | 0x0a;
|
||||
encoder.encode(&grease[..4]);
|
||||
|
||||
Vec::from(encoder)
|
||||
encoder.encode(&grease[0..4]);
|
||||
encoder.into()
|
||||
}
|
||||
}
|
||||
|
||||
@ -503,7 +536,7 @@ pub struct PublicPacket<'a> {
|
||||
/// The size of the header, not including the packet number.
|
||||
header_len: usize,
|
||||
/// Protocol version, if present in header.
|
||||
version: Option<WireVersion>,
|
||||
quic_version: Option<QuicVersion>,
|
||||
/// A reference to the entire packet, including the header.
|
||||
data: &'a [u8],
|
||||
}
|
||||
@ -523,11 +556,11 @@ impl<'a> PublicPacket<'a> {
|
||||
fn decode_long(
|
||||
decoder: &mut Decoder<'a>,
|
||||
packet_type: PacketType,
|
||||
version: Version,
|
||||
quic_version: QuicVersion,
|
||||
) -> Res<(&'a [u8], usize)> {
|
||||
if packet_type == PacketType::Retry {
|
||||
let header_len = decoder.offset();
|
||||
let expansion = retry::expansion(version);
|
||||
let expansion = retry::expansion(quic_version);
|
||||
let token = Self::opt(decoder.decode(decoder.remaining() - expansion))?;
|
||||
if token.is_empty() {
|
||||
return Err(Error::InvalidPacket);
|
||||
@ -570,7 +603,7 @@ impl<'a> PublicPacket<'a> {
|
||||
scid: None,
|
||||
token: &[],
|
||||
header_len,
|
||||
version: None,
|
||||
quic_version: None,
|
||||
data,
|
||||
},
|
||||
&[],
|
||||
@ -578,7 +611,7 @@ impl<'a> PublicPacket<'a> {
|
||||
}
|
||||
|
||||
// Generic long header.
|
||||
let version = WireVersion::try_from(Self::opt(decoder.decode_uint(4))?).unwrap();
|
||||
let version = Version::try_from(Self::opt(decoder.decode_uint(4))?).unwrap();
|
||||
let dcid = ConnectionIdRef::from(Self::opt(decoder.decode_vec(1))?);
|
||||
let scid = ConnectionIdRef::from(Self::opt(decoder.decode_vec(1))?);
|
||||
|
||||
@ -591,7 +624,7 @@ impl<'a> PublicPacket<'a> {
|
||||
scid: Some(scid),
|
||||
token: &[],
|
||||
header_len: decoder.offset(),
|
||||
version: None,
|
||||
quic_version: None,
|
||||
data,
|
||||
},
|
||||
&[],
|
||||
@ -599,7 +632,7 @@ impl<'a> PublicPacket<'a> {
|
||||
}
|
||||
|
||||
// Check that this is a long header from a supported version.
|
||||
let version = if let Ok(v) = Version::try_from(version) {
|
||||
let quic_version = if let Ok(v) = QuicVersion::try_from(version) {
|
||||
v
|
||||
} else {
|
||||
return Ok((
|
||||
@ -609,7 +642,7 @@ impl<'a> PublicPacket<'a> {
|
||||
scid: Some(scid),
|
||||
token: &[],
|
||||
header_len: decoder.offset(),
|
||||
version: Some(version),
|
||||
quic_version: None,
|
||||
data,
|
||||
},
|
||||
&[],
|
||||
@ -619,10 +652,16 @@ impl<'a> PublicPacket<'a> {
|
||||
if dcid.len() > MAX_CONNECTION_ID_LEN || scid.len() > MAX_CONNECTION_ID_LEN {
|
||||
return Err(Error::InvalidPacket);
|
||||
}
|
||||
let packet_type = PacketType::from_byte((first >> 4) & 3, version);
|
||||
let packet_type = match (first >> 4) & 3 {
|
||||
PACKET_TYPE_INITIAL => PacketType::Initial,
|
||||
PACKET_TYPE_0RTT => PacketType::ZeroRtt,
|
||||
PACKET_TYPE_HANDSHAKE => PacketType::Handshake,
|
||||
PACKET_TYPE_RETRY => PacketType::Retry,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
// The type-specific code includes a token. This consumes the remainder of the packet.
|
||||
let (token, header_len) = Self::decode_long(&mut decoder, packet_type, version)?;
|
||||
let (token, header_len) = Self::decode_long(&mut decoder, packet_type, quic_version)?;
|
||||
let end = data.len() - decoder.remaining();
|
||||
let (data, remainder) = data.split_at(end);
|
||||
Ok((
|
||||
@ -632,7 +671,7 @@ impl<'a> PublicPacket<'a> {
|
||||
scid: Some(scid),
|
||||
token,
|
||||
header_len,
|
||||
version: Some(version.wire_version()),
|
||||
quic_version: Some(quic_version),
|
||||
data,
|
||||
},
|
||||
remainder,
|
||||
@ -644,7 +683,7 @@ impl<'a> PublicPacket<'a> {
|
||||
if self.packet_type != PacketType::Retry {
|
||||
return false;
|
||||
}
|
||||
let version = self.version().unwrap();
|
||||
let version = self.quic_version.unwrap();
|
||||
let expansion = retry::expansion(version);
|
||||
if self.data.len() <= expansion {
|
||||
return false;
|
||||
@ -655,7 +694,7 @@ impl<'a> PublicPacket<'a> {
|
||||
encoder.encode(header);
|
||||
retry::use_aead(version, |aead| {
|
||||
let mut buf = vec![0; expansion];
|
||||
Ok(aead.decrypt(0, encoder.as_ref(), tag, &mut buf)?.is_empty())
|
||||
Ok(aead.decrypt(0, &encoder, tag, &mut buf)?.is_empty())
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
@ -685,13 +724,8 @@ impl<'a> PublicPacket<'a> {
|
||||
self.token
|
||||
}
|
||||
|
||||
pub fn version(&self) -> Option<Version> {
|
||||
self.version.and_then(|v| Version::try_from(v).ok())
|
||||
}
|
||||
|
||||
pub fn wire_version(&self) -> WireVersion {
|
||||
debug_assert!(self.version.is_some());
|
||||
self.version.unwrap_or(0)
|
||||
pub fn version(&self) -> Option<QuicVersion> {
|
||||
self.quic_version
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
@ -774,20 +808,16 @@ impl<'a> PublicPacket<'a> {
|
||||
|
||||
pub fn decrypt(&self, crypto: &mut CryptoStates, release_at: Instant) -> Res<DecryptedPacket> {
|
||||
let cspace: CryptoSpace = self.packet_type.into();
|
||||
// When we don't have a version, the crypto code doesn't need a version
|
||||
// for lookup, so use the default, but fix it up if decryption succeeds.
|
||||
let version = self.version().unwrap_or_default();
|
||||
// This has to work in two stages because we need to remove header protection
|
||||
// before picking the keys to use.
|
||||
if let Some(rx) = crypto.rx_hp(version, cspace) {
|
||||
if let Some(rx) = crypto.rx_hp(cspace) {
|
||||
// Note that this will dump early, which creates a side-channel.
|
||||
// This is OK in this case because we the only reason this can
|
||||
// fail is if the cryptographic module is bad or the packet is
|
||||
// too small (which is public information).
|
||||
let (key_phase, pn, header, body) = self.decrypt_header(rx)?;
|
||||
qtrace!([rx], "decoded header: {:?}", header);
|
||||
let rx = crypto.rx(version, cspace, key_phase).unwrap();
|
||||
let version = rx.version(); // Version fixup; see above.
|
||||
let rx = crypto.rx(cspace, key_phase).unwrap();
|
||||
let d = rx.decrypt(pn, &header, body)?;
|
||||
// If this is the first packet ever successfully decrypted
|
||||
// using `rx`, make sure to initiate a key update.
|
||||
@ -796,7 +826,6 @@ impl<'a> PublicPacket<'a> {
|
||||
}
|
||||
crypto.check_pn_overlap()?;
|
||||
Ok(DecryptedPacket {
|
||||
version,
|
||||
pt: self.packet_type,
|
||||
pn,
|
||||
data: d,
|
||||
@ -805,16 +834,16 @@ impl<'a> PublicPacket<'a> {
|
||||
Err(Error::KeysPending(cspace))
|
||||
} else {
|
||||
qtrace!("keys for {:?} already discarded", cspace);
|
||||
Err(Error::KeysDiscarded(cspace))
|
||||
Err(Error::KeysDiscarded)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn supported_versions(&self) -> Res<Vec<WireVersion>> {
|
||||
pub fn supported_versions(&self) -> Res<Vec<Version>> {
|
||||
assert_eq!(self.packet_type, PacketType::VersionNegotiation);
|
||||
let mut decoder = Decoder::new(&self.data[self.header_len..]);
|
||||
let mut res = Vec::new();
|
||||
while decoder.remaining() > 0 {
|
||||
let version = WireVersion::try_from(Self::opt(decoder.decode_uint(4))?)?;
|
||||
let version = Version::try_from(Self::opt(decoder.decode_uint(4))?)?;
|
||||
res.push(version);
|
||||
}
|
||||
Ok(res)
|
||||
@ -834,17 +863,12 @@ impl fmt::Debug for PublicPacket<'_> {
|
||||
}
|
||||
|
||||
pub struct DecryptedPacket {
|
||||
version: Version,
|
||||
pt: PacketType,
|
||||
pn: PacketNumber,
|
||||
data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl DecryptedPacket {
|
||||
pub fn version(&self) -> Version {
|
||||
self.version
|
||||
}
|
||||
|
||||
pub fn packet_type(&self) -> PacketType {
|
||||
self.pt
|
||||
}
|
||||
@ -866,7 +890,7 @@ impl Deref for DecryptedPacket {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::crypto::{CryptoDxState, CryptoStates};
|
||||
use crate::{EmptyConnectionIdGenerator, RandomConnectionIdGenerator, Version};
|
||||
use crate::{EmptyConnectionIdGenerator, QuicVersion, RandomConnectionIdGenerator};
|
||||
use neqo_common::Encoder;
|
||||
use test_fixture::{fixture_init, now};
|
||||
|
||||
@ -912,7 +936,7 @@ mod tests {
|
||||
let mut builder = PacketBuilder::long(
|
||||
Encoder::new(),
|
||||
PacketType::Initial,
|
||||
Version::default(),
|
||||
QuicVersion::default(),
|
||||
&ConnectionId::from(&[][..]),
|
||||
&ConnectionId::from(SERVER_CID),
|
||||
);
|
||||
@ -920,7 +944,7 @@ mod tests {
|
||||
builder.pn(1, 2);
|
||||
builder.encode(SAMPLE_INITIAL_PAYLOAD);
|
||||
let packet = builder.build(&mut prot).expect("build");
|
||||
assert_eq!(packet.as_ref(), SAMPLE_INITIAL);
|
||||
assert_eq!(&packet[..], SAMPLE_INITIAL);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -947,24 +971,24 @@ mod tests {
|
||||
fn disallow_long_dcid() {
|
||||
let mut enc = Encoder::new();
|
||||
enc.encode_byte(PACKET_BIT_LONG | PACKET_BIT_FIXED_QUIC);
|
||||
enc.encode_uint(4, Version::default().wire_version());
|
||||
enc.encode_uint(4, QuicVersion::default().as_u32());
|
||||
enc.encode_vec(1, &[0x00; MAX_CONNECTION_ID_LEN + 1]);
|
||||
enc.encode_vec(1, &[]);
|
||||
enc.encode(&[0xff; 40]); // junk
|
||||
|
||||
assert!(PublicPacket::decode(enc.as_ref(), &cid_mgr()).is_err());
|
||||
assert!(PublicPacket::decode(&enc, &cid_mgr()).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn disallow_long_scid() {
|
||||
let mut enc = Encoder::new();
|
||||
enc.encode_byte(PACKET_BIT_LONG | PACKET_BIT_FIXED_QUIC);
|
||||
enc.encode_uint(4, Version::default().wire_version());
|
||||
enc.encode_uint(4, QuicVersion::default().as_u32());
|
||||
enc.encode_vec(1, &[]);
|
||||
enc.encode_vec(1, &[0x00; MAX_CONNECTION_ID_LEN + 2]);
|
||||
enc.encode(&[0xff; 40]); // junk
|
||||
|
||||
assert!(PublicPacket::decode(enc.as_ref(), &cid_mgr()).is_err());
|
||||
assert!(PublicPacket::decode(&enc, &cid_mgr()).is_err());
|
||||
}
|
||||
|
||||
const SAMPLE_SHORT: &[u8] = &[
|
||||
@ -983,7 +1007,7 @@ mod tests {
|
||||
let packet = builder
|
||||
.build(&mut CryptoDxState::test_default())
|
||||
.expect("build");
|
||||
assert_eq!(packet.as_ref(), SAMPLE_SHORT);
|
||||
assert_eq!(&packet[..], SAMPLE_SHORT);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -995,7 +1019,7 @@ mod tests {
|
||||
PacketBuilder::short(Encoder::new(), true, &ConnectionId::from(SERVER_CID));
|
||||
builder.scramble(true);
|
||||
builder.pn(0, 1);
|
||||
firsts.push(builder.as_ref()[0]);
|
||||
firsts.push(builder[0]);
|
||||
}
|
||||
let is_set = |bit| move |v| v & bit == bit;
|
||||
// There should be at least one value with the QUIC bit set:
|
||||
@ -1053,7 +1077,7 @@ mod tests {
|
||||
let mut builder = PacketBuilder::long(
|
||||
Encoder::new(),
|
||||
PacketType::Handshake,
|
||||
Version::default(),
|
||||
QuicVersion::default(),
|
||||
&ConnectionId::from(SERVER_CID),
|
||||
&ConnectionId::from(CLIENT_CID),
|
||||
);
|
||||
@ -1068,8 +1092,8 @@ mod tests {
|
||||
builder.encode(&[0]); // Minimal size (packet number is big enough).
|
||||
let encoder = builder.build(&mut prot).expect("build");
|
||||
assert_eq!(
|
||||
first.as_ref(),
|
||||
&encoder.as_ref()[..first.len()],
|
||||
&first[..],
|
||||
&encoder[..first.len()],
|
||||
"the first packet should be a prefix"
|
||||
);
|
||||
assert_eq!(encoder.len(), 45 + 29);
|
||||
@ -1087,14 +1111,14 @@ mod tests {
|
||||
let mut builder = PacketBuilder::long(
|
||||
Encoder::new(),
|
||||
PacketType::Handshake,
|
||||
Version::default(),
|
||||
QuicVersion::default(),
|
||||
&ConnectionId::from(&[][..]),
|
||||
&ConnectionId::from(&[][..]),
|
||||
);
|
||||
builder.pn(0, 1);
|
||||
builder.encode(&[1, 2, 3]);
|
||||
let packet = builder.build(&mut CryptoDxState::test_default()).unwrap();
|
||||
assert_eq!(packet.as_ref(), EXPECTED);
|
||||
assert_eq!(&packet[..], EXPECTED);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1106,13 +1130,13 @@ mod tests {
|
||||
let mut builder = PacketBuilder::long(
|
||||
Encoder::new(),
|
||||
PacketType::Handshake,
|
||||
Version::default(),
|
||||
QuicVersion::default(),
|
||||
&ConnectionId::from(&[][..]),
|
||||
&ConnectionId::from(&[][..]),
|
||||
);
|
||||
builder.pn(0, 1);
|
||||
builder.scramble(true);
|
||||
if (builder.as_ref()[0] & PACKET_BIT_FIXED_QUIC) == 0 {
|
||||
if (builder[0] & PACKET_BIT_FIXED_QUIC) == 0 {
|
||||
found_unset = true;
|
||||
} else {
|
||||
found_set = true;
|
||||
@ -1127,7 +1151,7 @@ mod tests {
|
||||
let mut builder = PacketBuilder::long(
|
||||
Encoder::new(),
|
||||
PacketType::Initial,
|
||||
Version::default(),
|
||||
QuicVersion::default(),
|
||||
&ConnectionId::from(&[][..]),
|
||||
&ConnectionId::from(SERVER_CID),
|
||||
);
|
||||
@ -1161,7 +1185,7 @@ mod tests {
|
||||
let builder = PacketBuilder::long(
|
||||
encoder,
|
||||
PacketType::Initial,
|
||||
Version::default(),
|
||||
QuicVersion::default(),
|
||||
&ConnectionId::from(SERVER_CID),
|
||||
&ConnectionId::from(SERVER_CID),
|
||||
);
|
||||
@ -1169,12 +1193,6 @@ mod tests {
|
||||
assert_eq!(builder.abort(), encoder_copy);
|
||||
}
|
||||
|
||||
const SAMPLE_RETRY_V2: &[u8] = &[
|
||||
0xcf, 0x70, 0x9a, 0x50, 0xc4, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5,
|
||||
0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x1d, 0xc7, 0x11, 0x30, 0xcd, 0x1e, 0xd3, 0x9d, 0x6e, 0xfc,
|
||||
0xee, 0x5c, 0x85, 0x80, 0x65, 0x01,
|
||||
];
|
||||
|
||||
const SAMPLE_RETRY_V1: &[u8] = &[
|
||||
0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5,
|
||||
0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x04, 0xa2, 0x65, 0xba, 0x2e, 0xff, 0x4d, 0x82, 0x90, 0x58,
|
||||
@ -1207,10 +1225,10 @@ mod tests {
|
||||
|
||||
const RETRY_TOKEN: &[u8] = b"token";
|
||||
|
||||
fn build_retry_single(version: Version, sample_retry: &[u8]) {
|
||||
fn build_retry_single(quic_version: QuicVersion, sample_retry: &[u8]) {
|
||||
fixture_init();
|
||||
let retry =
|
||||
PacketBuilder::retry(version, &[], SERVER_CID, RETRY_TOKEN, CLIENT_CID).unwrap();
|
||||
PacketBuilder::retry(quic_version, &[], SERVER_CID, RETRY_TOKEN, CLIENT_CID).unwrap();
|
||||
|
||||
let (packet, remainder) = PublicPacket::decode(&retry, &cid_mgr()).unwrap();
|
||||
assert!(packet.is_valid_retry(&ConnectionId::from(CLIENT_CID)));
|
||||
@ -1222,43 +1240,35 @@ mod tests {
|
||||
assert_eq!(&retry, &sample_retry);
|
||||
} else {
|
||||
// Otherwise, just check that the header is OK.
|
||||
assert_eq!(
|
||||
retry[0] & 0xf0,
|
||||
0xc0 | (PacketType::Retry.to_byte(version) << 4)
|
||||
);
|
||||
assert_eq!(retry[0] & 0xf0, 0xf0);
|
||||
let header_range = 1..retry.len() - 16;
|
||||
assert_eq!(&retry[header_range.clone()], &sample_retry[header_range]);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_retry_v2() {
|
||||
build_retry_single(Version::Version2, SAMPLE_RETRY_V2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_retry_v1() {
|
||||
build_retry_single(Version::Version1, SAMPLE_RETRY_V1);
|
||||
build_retry_single(QuicVersion::Version1, SAMPLE_RETRY_V1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_retry_29() {
|
||||
build_retry_single(Version::Draft29, SAMPLE_RETRY_29);
|
||||
build_retry_single(QuicVersion::Draft29, SAMPLE_RETRY_29);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_retry_30() {
|
||||
build_retry_single(Version::Draft30, SAMPLE_RETRY_30);
|
||||
build_retry_single(QuicVersion::Draft30, SAMPLE_RETRY_30);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_retry_31() {
|
||||
build_retry_single(Version::Draft31, SAMPLE_RETRY_31);
|
||||
build_retry_single(QuicVersion::Draft31, SAMPLE_RETRY_31);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_retry_32() {
|
||||
build_retry_single(Version::Draft32, SAMPLE_RETRY_32);
|
||||
build_retry_single(QuicVersion::Draft32, SAMPLE_RETRY_32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1267,7 +1277,6 @@ mod tests {
|
||||
// Odds are approximately 1 in 8 that the full comparison doesn't happen
|
||||
// for a given version.
|
||||
for _ in 0..32 {
|
||||
build_retry_v2();
|
||||
build_retry_v1();
|
||||
build_retry_29();
|
||||
build_retry_30();
|
||||
@ -1276,46 +1285,36 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn decode_retry(version: Version, sample_retry: &[u8]) {
|
||||
fn decode_retry(quic_version: QuicVersion, sample_retry: &[u8]) {
|
||||
fixture_init();
|
||||
let (packet, remainder) =
|
||||
PublicPacket::decode(sample_retry, &RandomConnectionIdGenerator::new(5)).unwrap();
|
||||
assert!(packet.is_valid_retry(&ConnectionId::from(CLIENT_CID)));
|
||||
assert_eq!(Some(version), packet.version());
|
||||
assert_eq!(Some(quic_version), packet.quic_version);
|
||||
assert!(packet.dcid().is_empty());
|
||||
assert_eq!(&packet.scid()[..], SERVER_CID);
|
||||
assert_eq!(packet.token(), RETRY_TOKEN);
|
||||
assert!(remainder.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_retry_v2() {
|
||||
decode_retry(Version::Version2, SAMPLE_RETRY_V2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_retry_v1() {
|
||||
decode_retry(Version::Version1, SAMPLE_RETRY_V1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_retry_29() {
|
||||
decode_retry(Version::Draft29, SAMPLE_RETRY_29);
|
||||
decode_retry(QuicVersion::Draft29, SAMPLE_RETRY_29);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_retry_30() {
|
||||
decode_retry(Version::Draft30, SAMPLE_RETRY_30);
|
||||
decode_retry(QuicVersion::Draft30, SAMPLE_RETRY_30);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_retry_31() {
|
||||
decode_retry(Version::Draft31, SAMPLE_RETRY_31);
|
||||
decode_retry(QuicVersion::Draft31, SAMPLE_RETRY_31);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_retry_32() {
|
||||
decode_retry(Version::Draft32, SAMPLE_RETRY_32);
|
||||
decode_retry(QuicVersion::Draft32, SAMPLE_RETRY_32);
|
||||
}
|
||||
|
||||
/// Check some packets that are clearly not valid Retry packets.
|
||||
@ -1327,11 +1326,11 @@ mod tests {
|
||||
|
||||
assert!(PublicPacket::decode(&[], &cid_mgr).is_err());
|
||||
|
||||
let (packet, remainder) = PublicPacket::decode(SAMPLE_RETRY_V1, &cid_mgr).unwrap();
|
||||
let (packet, remainder) = PublicPacket::decode(SAMPLE_RETRY_29, &cid_mgr).unwrap();
|
||||
assert!(remainder.is_empty());
|
||||
assert!(packet.is_valid_retry(&odcid));
|
||||
|
||||
let mut damaged_retry = SAMPLE_RETRY_V1.to_vec();
|
||||
let mut damaged_retry = SAMPLE_RETRY_29.to_vec();
|
||||
let last = damaged_retry.len() - 1;
|
||||
damaged_retry[last] ^= 66;
|
||||
let (packet, remainder) = PublicPacket::decode(&damaged_retry, &cid_mgr).unwrap();
|
||||
@ -1353,16 +1352,15 @@ mod tests {
|
||||
|
||||
const SAMPLE_VN: &[u8] = &[
|
||||
0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5, 0x08,
|
||||
0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08, 0x70, 0x9a, 0x50, 0xc4, 0x00, 0x00, 0x00,
|
||||
0x01, 0xff, 0x00, 0x00, 0x20, 0xff, 0x00, 0x00, 0x1f, 0xff, 0x00, 0x00, 0x1e, 0xff, 0x00,
|
||||
0x00, 0x1d, 0x0a, 0x0a, 0x0a, 0x0a,
|
||||
0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08, 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00,
|
||||
0x1d, 0xff, 0x00, 0x00, 0x1e, 0xff, 0x00, 0x00, 0x1f, 0xff, 0x00, 0x00, 0x20, 0x0a, 0x0a,
|
||||
0x0a, 0x0a,
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn build_vn() {
|
||||
fixture_init();
|
||||
let mut vn =
|
||||
PacketBuilder::version_negotiation(SERVER_CID, CLIENT_CID, 0x0a0a0a0a, &Version::all());
|
||||
let mut vn = PacketBuilder::version_negotiation(SERVER_CID, CLIENT_CID);
|
||||
// Erase randomness from greasing...
|
||||
assert_eq!(vn.len(), SAMPLE_VN.len());
|
||||
vn[0] &= 0x80;
|
||||
@ -1372,14 +1370,6 @@ mod tests {
|
||||
assert_eq!(&vn, &SAMPLE_VN);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vn_do_not_repeat_client_grease() {
|
||||
fixture_init();
|
||||
let vn =
|
||||
PacketBuilder::version_negotiation(SERVER_CID, CLIENT_CID, 0x0a0a0a0a, &Version::all());
|
||||
assert_ne!(&vn[SAMPLE_VN.len() - 4..], &[0x0a, 0x0a, 0x0a, 0x0a]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_vn() {
|
||||
let (packet, remainder) =
|
||||
@ -1400,11 +1390,11 @@ mod tests {
|
||||
enc.encode_vec(1, BIG_DCID);
|
||||
enc.encode_vec(1, BIG_SCID);
|
||||
enc.encode_uint(4, 0x1a2a_3a4a_u64);
|
||||
enc.encode_uint(4, Version::default().wire_version());
|
||||
enc.encode_uint(4, QuicVersion::default().as_u32());
|
||||
enc.encode_uint(4, 0x5a6a_7a8a_u64);
|
||||
|
||||
let (packet, remainder) =
|
||||
PublicPacket::decode(enc.as_ref(), &EmptyConnectionIdGenerator::default()).unwrap();
|
||||
PublicPacket::decode(&enc, &EmptyConnectionIdGenerator::default()).unwrap();
|
||||
assert!(remainder.is_empty());
|
||||
assert_eq!(&packet.dcid[..], BIG_DCID);
|
||||
assert!(packet.scid.is_some());
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#![deny(clippy::pedantic)]
|
||||
|
||||
use crate::version::Version;
|
||||
use crate::packet::QuicVersion;
|
||||
use crate::{Error, Res};
|
||||
|
||||
use neqo_common::qerror;
|
||||
@ -14,33 +14,37 @@ use neqo_crypto::{hkdf, Aead, TLS_AES_128_GCM_SHA256, TLS_VERSION_1_3};
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
||||
const RETRY_SECRET_29: &[u8] = &[
|
||||
0x8b, 0x0d, 0x37, 0xeb, 0x85, 0x35, 0x02, 0x2e, 0xbc, 0x8d, 0x76, 0xa2, 0x07, 0xd8, 0x0d, 0xf2,
|
||||
0x26, 0x46, 0xec, 0x06, 0xdc, 0x80, 0x96, 0x42, 0xc3, 0x0a, 0x8b, 0xaa, 0x2b, 0xaa, 0xff, 0x4c,
|
||||
];
|
||||
const RETRY_SECRET_V1: &[u8] = &[
|
||||
0xd9, 0xc9, 0x94, 0x3e, 0x61, 0x01, 0xfd, 0x20, 0x00, 0x21, 0x50, 0x6b, 0xcc, 0x02, 0x81, 0x4c,
|
||||
0x73, 0x03, 0x0f, 0x25, 0xc7, 0x9d, 0x71, 0xce, 0x87, 0x6e, 0xca, 0x87, 0x6e, 0x6f, 0xca, 0x8e,
|
||||
];
|
||||
|
||||
/// The AEAD used for Retry is fixed, so use thread local storage.
|
||||
fn make_aead(version: Version) -> Aead {
|
||||
fn make_aead(secret: &[u8]) -> Aead {
|
||||
#[cfg(debug_assertions)]
|
||||
::neqo_crypto::assert_initialized();
|
||||
|
||||
let secret = hkdf::import_key(TLS_VERSION_1_3, version.retry_secret()).unwrap();
|
||||
Aead::new(
|
||||
TLS_VERSION_1_3,
|
||||
TLS_AES_128_GCM_SHA256,
|
||||
&secret,
|
||||
version.label_prefix(),
|
||||
)
|
||||
.unwrap()
|
||||
let secret = hkdf::import_key(TLS_VERSION_1_3, secret).unwrap();
|
||||
Aead::new(TLS_VERSION_1_3, TLS_AES_128_GCM_SHA256, &secret, "quic ").unwrap()
|
||||
}
|
||||
thread_local!(static RETRY_AEAD_29: RefCell<Aead> = RefCell::new(make_aead(Version::Draft29)));
|
||||
thread_local!(static RETRY_AEAD_V1: RefCell<Aead> = RefCell::new(make_aead(Version::Version1)));
|
||||
thread_local!(static RETRY_AEAD_V2: RefCell<Aead> = RefCell::new(make_aead(Version::Version2)));
|
||||
thread_local!(static RETRY_AEAD_29: RefCell<Aead> = RefCell::new(make_aead(RETRY_SECRET_29)));
|
||||
thread_local!(static RETRY_AEAD_V1: RefCell<Aead> = RefCell::new(make_aead(RETRY_SECRET_V1)));
|
||||
|
||||
/// Run a function with the appropriate Retry AEAD.
|
||||
pub fn use_aead<F, T>(version: Version, f: F) -> Res<T>
|
||||
pub fn use_aead<F, T>(quic_version: QuicVersion, f: F) -> Res<T>
|
||||
where
|
||||
F: FnOnce(&Aead) -> Res<T>,
|
||||
{
|
||||
match version {
|
||||
Version::Version2 => &RETRY_AEAD_V2,
|
||||
Version::Version1 => &RETRY_AEAD_V1,
|
||||
Version::Draft29 | Version::Draft30 | Version::Draft31 | Version::Draft32 => &RETRY_AEAD_29,
|
||||
match quic_version {
|
||||
QuicVersion::Version1 => &RETRY_AEAD_V1,
|
||||
QuicVersion::Draft29
|
||||
| QuicVersion::Draft30
|
||||
| QuicVersion::Draft31
|
||||
| QuicVersion::Draft32 => &RETRY_AEAD_29,
|
||||
}
|
||||
.try_with(|aead| f(&aead.borrow()))
|
||||
.map_err(|e| {
|
||||
@ -50,8 +54,8 @@ where
|
||||
}
|
||||
|
||||
/// Determine how large the expansion is for a given key.
|
||||
pub fn expansion(version: Version) -> usize {
|
||||
if let Ok(ex) = use_aead(version, |aead| Ok(aead.expansion())) {
|
||||
pub fn expansion(quic_version: QuicVersion) -> usize {
|
||||
if let Ok(ex) = use_aead(quic_version, |aead| Ok(aead.expansion())) {
|
||||
ex
|
||||
} else {
|
||||
panic!("Unable to access Retry AEAD")
|
||||
|
28
third_party/rust/neqo-transport/src/path.rs
vendored
28
third_party/rust/neqo-transport/src/path.rs
vendored
@ -539,9 +539,6 @@ pub struct Path {
|
||||
received_bytes: usize,
|
||||
/// The number of bytes sent on this path.
|
||||
sent_bytes: usize,
|
||||
|
||||
/// For logging of events.
|
||||
qlog: NeqoQlog,
|
||||
}
|
||||
|
||||
impl Path {
|
||||
@ -555,7 +552,7 @@ impl Path {
|
||||
now: Instant,
|
||||
) -> Self {
|
||||
let mut sender = PacketSender::new(cc, Self::mtu_by_addr(remote.ip()), now);
|
||||
sender.set_qlog(qlog.clone());
|
||||
sender.set_qlog(qlog);
|
||||
Self {
|
||||
local,
|
||||
remote,
|
||||
@ -569,7 +566,6 @@ impl Path {
|
||||
sender,
|
||||
received_bytes: 0,
|
||||
sent_bytes: 0,
|
||||
qlog,
|
||||
}
|
||||
}
|
||||
|
||||
@ -932,27 +928,7 @@ impl Path {
|
||||
}
|
||||
|
||||
/// Discard a packet that previously might have been in-flight.
|
||||
pub fn discard_packet(&mut self, sent: &SentPacket, now: Instant) {
|
||||
if self.rtt.first_sample_time().is_none() {
|
||||
// When discarding a packet there might not be a good RTT estimate.
|
||||
// But discards only occur after receiving something, so that means
|
||||
// that there is some RTT information, which is better than nothing.
|
||||
// Two cases: 1. at the client when handling a Retry and
|
||||
// 2. at the server when disposing the Initial packet number space.
|
||||
qinfo!(
|
||||
[self],
|
||||
"discarding a packet without an RTT estimate; guessing RTT={:?}",
|
||||
now - sent.time_sent
|
||||
);
|
||||
self.rtt.update(
|
||||
&mut self.qlog,
|
||||
now - sent.time_sent,
|
||||
Duration::new(0, 0),
|
||||
false,
|
||||
now,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn discard_packet(&mut self, sent: &SentPacket) {
|
||||
self.sender.discard(sent);
|
||||
}
|
||||
|
||||
|
6
third_party/rust/neqo-transport/src/qlog.rs
vendored
6
third_party/rust/neqo-transport/src/qlog.rs
vendored
@ -22,7 +22,7 @@ use crate::path::PathRef;
|
||||
use crate::stream_id::StreamType as NeqoStreamType;
|
||||
use crate::tparams::{self, TransportParametersHandler};
|
||||
use crate::tracking::SentPacket;
|
||||
use crate::Version;
|
||||
use crate::QuicVersion;
|
||||
|
||||
pub fn connection_tparams_set(qlog: &mut NeqoQlog, tph: &TransportParametersHandler) {
|
||||
qlog.add_event(|| {
|
||||
@ -98,7 +98,7 @@ fn connection_started(qlog: &mut NeqoQlog, path: &PathRef) {
|
||||
Some("QUIC".into()),
|
||||
p.local_address().port().into(),
|
||||
p.remote_address().port().into(),
|
||||
Some(format!("{:x}", Version::default().wire_version())),
|
||||
Some(format!("{:x}", QuicVersion::default().as_u32())),
|
||||
Some(format!("{}", p.local_cid())),
|
||||
Some(format!("{}", p.remote_cid())),
|
||||
))
|
||||
@ -110,7 +110,7 @@ pub fn connection_state_updated(qlog: &mut NeqoQlog, new: &State) {
|
||||
Some(Event::connection_state_updated_min(match new {
|
||||
State::Init => qlog::ConnectionState::Attempted,
|
||||
State::WaitInitial => qlog::ConnectionState::Attempted,
|
||||
State::WaitVersion | State::Handshaking => qlog::ConnectionState::Handshake,
|
||||
State::Handshaking => qlog::ConnectionState::Handshake,
|
||||
State::Connected => qlog::ConnectionState::Active,
|
||||
State::Confirmed => qlog::ConnectionState::Active,
|
||||
State::Closing { .. } => qlog::ConnectionState::Draining,
|
||||
|
@ -14,6 +14,7 @@ use neqo_common::Encoder;
|
||||
use std::cmp::min;
|
||||
use std::collections::VecDeque;
|
||||
use std::convert::TryFrom;
|
||||
use std::ops::Deref;
|
||||
|
||||
pub const MAX_QUIC_DATAGRAM: u64 = 65535;
|
||||
|
||||
@ -52,9 +53,10 @@ impl QuicDatagram {
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for QuicDatagram {
|
||||
impl Deref for QuicDatagram {
|
||||
type Target = [u8];
|
||||
#[must_use]
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
fn deref(&self) -> &[u8] {
|
||||
&self.data[..]
|
||||
}
|
||||
}
|
||||
@ -108,17 +110,17 @@ impl QuicDatagrams {
|
||||
stats: &mut Stats,
|
||||
) {
|
||||
while let Some(dgram) = self.datagrams.pop_front() {
|
||||
let len = dgram.as_ref().len();
|
||||
let len = dgram.len();
|
||||
if builder.remaining() > len {
|
||||
// We need 1 more than `len` for the Frame type.
|
||||
let length_len = Encoder::varint_len(u64::try_from(len).unwrap());
|
||||
// Include a length if there is space for another frame after this one.
|
||||
if builder.remaining() >= 1 + length_len + len + PacketBuilder::MINIMUM_FRAME_SIZE {
|
||||
builder.encode_varint(FRAME_TYPE_DATAGRAM_WITH_LEN);
|
||||
builder.encode_vvec(dgram.as_ref());
|
||||
builder.encode_vvec(&dgram);
|
||||
} else {
|
||||
builder.encode_varint(FRAME_TYPE_DATAGRAM);
|
||||
builder.encode(dgram.as_ref());
|
||||
builder.encode(&dgram);
|
||||
builder.mark_full();
|
||||
}
|
||||
debug_assert!(builder.len() <= builder.limit());
|
||||
|
29
third_party/rust/neqo-transport/src/recovery.rs
vendored
29
third_party/rust/neqo-transport/src/recovery.rs
vendored
@ -590,7 +590,7 @@ impl LossRecovery {
|
||||
self.qlog = qlog;
|
||||
}
|
||||
|
||||
pub fn drop_0rtt(&mut self, primary_path: &PathRef, now: Instant) -> Vec<SentPacket> {
|
||||
pub fn drop_0rtt(&mut self, primary_path: &PathRef) -> Vec<SentPacket> {
|
||||
// The largest acknowledged or loss_time should still be unset.
|
||||
// The client should not have received any ACK frames when it drops 0-RTT.
|
||||
assert!(self
|
||||
@ -607,7 +607,7 @@ impl LossRecovery {
|
||||
.collect::<Vec<_>>();
|
||||
let mut path = primary_path.borrow_mut();
|
||||
for p in &mut dropped {
|
||||
path.discard_packet(p, now);
|
||||
path.discard_packet(p);
|
||||
}
|
||||
dropped
|
||||
}
|
||||
@ -737,7 +737,7 @@ impl LossRecovery {
|
||||
|
||||
/// When receiving a retry, get all the sent packets so that they can be flushed.
|
||||
/// We also need to pretend that they never happened for the purposes of congestion control.
|
||||
pub fn retry(&mut self, primary_path: &PathRef, now: Instant) -> Vec<SentPacket> {
|
||||
pub fn retry(&mut self, primary_path: &PathRef) -> Vec<SentPacket> {
|
||||
self.pto_state = None;
|
||||
let mut dropped = self
|
||||
.spaces
|
||||
@ -746,7 +746,7 @@ impl LossRecovery {
|
||||
.collect::<Vec<_>>();
|
||||
let mut path = primary_path.borrow_mut();
|
||||
for p in &mut dropped {
|
||||
path.discard_packet(p, now);
|
||||
path.discard_packet(p);
|
||||
}
|
||||
dropped
|
||||
}
|
||||
@ -779,7 +779,7 @@ impl LossRecovery {
|
||||
qdebug!([self], "Reset loss recovery state for {}", space);
|
||||
let mut path = primary_path.borrow_mut();
|
||||
for p in self.spaces.drop_space(space) {
|
||||
path.discard_packet(&p, now);
|
||||
path.discard_packet(&p);
|
||||
}
|
||||
|
||||
// We just made progress, so discard PTO count.
|
||||
@ -1494,25 +1494,6 @@ mod tests {
|
||||
#[test]
|
||||
fn rearm_pto_after_confirmed() {
|
||||
let mut lr = Fixture::default();
|
||||
lr.on_packet_sent(SentPacket::new(
|
||||
PacketType::Initial,
|
||||
0,
|
||||
now(),
|
||||
true,
|
||||
Vec::new(),
|
||||
ON_SENT_SIZE,
|
||||
));
|
||||
// Set the RTT to the initial value so that discarding doesn't
|
||||
// alter the estimate.
|
||||
let rtt = lr.path.borrow().rtt().estimate();
|
||||
lr.on_ack_received(
|
||||
PacketNumberSpace::Initial,
|
||||
0,
|
||||
vec![0..=0],
|
||||
Duration::new(0, 0),
|
||||
now() + rtt,
|
||||
);
|
||||
|
||||
lr.on_packet_sent(SentPacket::new(
|
||||
PacketType::Handshake,
|
||||
0,
|
||||
|
@ -1966,10 +1966,7 @@ mod tests {
|
||||
&mut tokens,
|
||||
&mut stats,
|
||||
);
|
||||
qtrace!(
|
||||
"STREAM frame: {}",
|
||||
hex_with_len(&builder.as_ref()[header_len..])
|
||||
);
|
||||
qtrace!("STREAM frame: {}", hex_with_len(&builder[header_len..]));
|
||||
stats.stream > 0
|
||||
}
|
||||
|
||||
|
44
third_party/rust/neqo-transport/src/server.rs
vendored
44
third_party/rust/neqo-transport/src/server.rs
vendored
@ -20,7 +20,7 @@ use crate::addr_valid::{AddressValidation, AddressValidationResult};
|
||||
use crate::cid::{ConnectionId, ConnectionIdDecoder, ConnectionIdGenerator, ConnectionIdRef};
|
||||
use crate::connection::{Connection, Output, State};
|
||||
use crate::packet::{PacketBuilder, PacketType, PublicPacket};
|
||||
use crate::{ConnectionParameters, Res, Version};
|
||||
use crate::{ConnectionParameters, QuicVersion, Res};
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{HashMap, HashSet, VecDeque};
|
||||
@ -109,7 +109,7 @@ struct InitialDetails {
|
||||
src_cid: ConnectionId,
|
||||
dst_cid: ConnectionId,
|
||||
token: Vec<u8>,
|
||||
version: Version,
|
||||
quic_version: QuicVersion,
|
||||
}
|
||||
|
||||
impl InitialDetails {
|
||||
@ -118,7 +118,7 @@ impl InitialDetails {
|
||||
src_cid: ConnectionId::from(packet.scid()),
|
||||
dst_cid: ConnectionId::from(packet.dcid()),
|
||||
token: packet.token().to_vec(),
|
||||
version: packet.version().unwrap(),
|
||||
quic_version: packet.version().unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -339,7 +339,7 @@ impl Server {
|
||||
};
|
||||
if let Some(new_dcid) = self.cid_generator.borrow_mut().generate_cid() {
|
||||
let packet = PacketBuilder::retry(
|
||||
initial.version,
|
||||
initial.quic_version,
|
||||
&initial.src_cid,
|
||||
&new_dcid,
|
||||
&token,
|
||||
@ -478,13 +478,11 @@ impl Server {
|
||||
saved_cids: Vec::new(),
|
||||
}));
|
||||
|
||||
let mut params = self.conn_params.clone();
|
||||
params.get_versions_mut().set_initial(initial.version);
|
||||
let sconn = Connection::new_server(
|
||||
&self.certs,
|
||||
&self.protocols,
|
||||
Rc::clone(&cid_mgr) as _,
|
||||
params,
|
||||
self.conn_params.quic_version(initial.quic_version),
|
||||
);
|
||||
|
||||
if let Ok(mut c) = sconn {
|
||||
@ -556,29 +554,6 @@ impl Server {
|
||||
return None;
|
||||
}
|
||||
|
||||
if packet.packet_type() == PacketType::OtherVersion
|
||||
|| (packet.packet_type() == PacketType::Initial
|
||||
&& !self
|
||||
.conn_params
|
||||
.get_versions()
|
||||
.all()
|
||||
.contains(&packet.version().unwrap()))
|
||||
{
|
||||
if dgram.len() < MIN_INITIAL_PACKET_SIZE {
|
||||
qdebug!([self], "Unsupported version: too short");
|
||||
return None;
|
||||
}
|
||||
|
||||
qdebug!([self], "Unsupported version: {:x}", packet.wire_version());
|
||||
let vn = PacketBuilder::version_negotiation(
|
||||
packet.scid(),
|
||||
packet.dcid(),
|
||||
packet.wire_version(),
|
||||
self.conn_params.get_versions().all(),
|
||||
);
|
||||
return Some(Datagram::new(dgram.destination(), dgram.source(), vn));
|
||||
}
|
||||
|
||||
match packet.packet_type() {
|
||||
PacketType::Initial => {
|
||||
if dgram.len() < MIN_INITIAL_PACKET_SIZE {
|
||||
@ -593,7 +568,14 @@ impl Server {
|
||||
let dcid = ConnectionId::from(packet.dcid());
|
||||
self.handle_0rtt(dgram, dcid, now)
|
||||
}
|
||||
PacketType::OtherVersion => unreachable!(),
|
||||
PacketType::OtherVersion => {
|
||||
if dgram.len() < MIN_INITIAL_PACKET_SIZE {
|
||||
qdebug!([self], "Unsupported version: too short");
|
||||
return None;
|
||||
}
|
||||
let vn = PacketBuilder::version_negotiation(packet.scid(), packet.dcid());
|
||||
Some(Datagram::new(dgram.destination(), dgram.source(), vn))
|
||||
}
|
||||
_ => {
|
||||
qtrace!([self], "Not an initial packet");
|
||||
None
|
||||
|
299
third_party/rust/neqo-transport/src/tparams.rs
vendored
299
third_party/rust/neqo-transport/src/tparams.rs
vendored
@ -9,13 +9,12 @@
|
||||
use crate::cid::{
|
||||
ConnectionId, ConnectionIdEntry, CONNECTION_ID_SEQNO_PREFERRED, MAX_CONNECTION_ID_LEN,
|
||||
};
|
||||
use crate::version::{Version, VersionConfig, WireVersion};
|
||||
use crate::{Error, Res};
|
||||
|
||||
use neqo_common::{hex, qdebug, qinfo, qtrace, Decoder, Encoder, Role};
|
||||
use neqo_common::{hex, qdebug, qinfo, qtrace, Decoder, Encoder};
|
||||
use neqo_crypto::constants::{TLS_HS_CLIENT_HELLO, TLS_HS_ENCRYPTED_EXTENSIONS};
|
||||
use neqo_crypto::ext::{ExtensionHandler, ExtensionHandlerResult, ExtensionWriterResult};
|
||||
use neqo_crypto::{random, HandshakeMessage, ZeroRttCheckResult, ZeroRttChecker};
|
||||
use neqo_crypto::{HandshakeMessage, ZeroRttCheckResult, ZeroRttChecker};
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
@ -27,10 +26,6 @@ pub type TransportParameterId = u64;
|
||||
macro_rules! tpids {
|
||||
{ $($n:ident = $v:expr),+ $(,)? } => {
|
||||
$(pub const $n: TransportParameterId = $v as TransportParameterId;)+
|
||||
|
||||
/// A complete list of internal transport parameters.
|
||||
#[cfg(not(test))]
|
||||
pub(crate) const INTERNAL_TRANSPORT_PARAMETERS: &[TransportParameterId] = &[ $($n),+ ];
|
||||
};
|
||||
}
|
||||
tpids! {
|
||||
@ -54,7 +49,6 @@ tpids! {
|
||||
GREASE_QUIC_BIT = 0x2ab2,
|
||||
MIN_ACK_DELAY = 0xff02_de1a,
|
||||
MAX_DATAGRAM_FRAME_SIZE = 0x0020,
|
||||
VERSION_NEGOTIATION = 0xff73db,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Copy)]
|
||||
@ -111,10 +105,6 @@ pub enum TransportParameter {
|
||||
cid: ConnectionId,
|
||||
srt: [u8; 16],
|
||||
},
|
||||
Versions {
|
||||
current: WireVersion,
|
||||
other: Vec<WireVersion>,
|
||||
},
|
||||
}
|
||||
|
||||
impl TransportParameter {
|
||||
@ -161,14 +151,6 @@ impl TransportParameter {
|
||||
enc_inner.encode(&srt[..]);
|
||||
});
|
||||
}
|
||||
Self::Versions { current, other } => {
|
||||
enc.encode_vvec_with(|enc_inner| {
|
||||
enc_inner.encode_uint(4, *current);
|
||||
for v in other {
|
||||
enc_inner.encode_uint(4, *v);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -217,26 +199,6 @@ impl TransportParameter {
|
||||
Ok(Self::PreferredAddress { v4, v6, cid, srt })
|
||||
}
|
||||
|
||||
fn decode_versions(dec: &mut Decoder) -> Res<Self> {
|
||||
fn dv(dec: &mut Decoder) -> Res<WireVersion> {
|
||||
let v = dec.decode_uint(4).ok_or(Error::NoMoreData)?;
|
||||
if v == 0 {
|
||||
Err(Error::TransportParameterError)
|
||||
} else {
|
||||
Ok(v as WireVersion)
|
||||
}
|
||||
}
|
||||
|
||||
let current = dv(dec)?;
|
||||
// This rounding down is OK because `decode` checks for left over data.
|
||||
let count = dec.remaining() / 4;
|
||||
let mut other = Vec::with_capacity(count);
|
||||
for _ in 0..count {
|
||||
other.push(dv(dec)?);
|
||||
}
|
||||
Ok(Self::Versions { current, other })
|
||||
}
|
||||
|
||||
fn decode(dec: &mut Decoder) -> Res<Option<(TransportParameterId, Self)>> {
|
||||
let tp = dec.decode_varint().ok_or(Error::NoMoreData)?;
|
||||
let content = dec.decode_vvec().ok_or(Error::NoMoreData)?;
|
||||
@ -291,8 +253,6 @@ impl TransportParameter {
|
||||
_ => return Err(Error::TransportParameterError),
|
||||
},
|
||||
|
||||
VERSION_NEGOTIATION => Self::decode_versions(&mut d)?,
|
||||
|
||||
// Skip.
|
||||
_ => return Ok(None),
|
||||
};
|
||||
@ -428,37 +388,6 @@ impl TransportParameters {
|
||||
}
|
||||
}
|
||||
|
||||
/// Set version information.
|
||||
pub fn set_versions(&mut self, role: Role, versions: &VersionConfig) {
|
||||
let rbuf = random(4);
|
||||
let mut other = Vec::with_capacity(versions.all().len() + 1);
|
||||
let mut dec = Decoder::new(&rbuf);
|
||||
let grease = (dec.decode_uint(4).unwrap() as u32) & 0xf0f0_f0f0 | 0x0a0a0a0a;
|
||||
other.push(grease);
|
||||
for &v in versions.all() {
|
||||
if role == Role::Client && !versions.initial().is_compatible(v) {
|
||||
continue;
|
||||
}
|
||||
other.push(v.wire_version());
|
||||
}
|
||||
let current = versions.initial().wire_version();
|
||||
self.set(
|
||||
VERSION_NEGOTIATION,
|
||||
TransportParameter::Versions { current, other },
|
||||
);
|
||||
}
|
||||
|
||||
fn compatible_upgrade(&mut self, v: Version) {
|
||||
if let Some(TransportParameter::Versions {
|
||||
ref mut current, ..
|
||||
}) = self.params.get_mut(&VERSION_NEGOTIATION)
|
||||
{
|
||||
*current = v.wire_version();
|
||||
} else {
|
||||
unreachable!("Compatible upgrade without transport parameters set!");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_empty(&self, tipe: TransportParameterId) -> bool {
|
||||
match self.params.get(&tipe) {
|
||||
None => false,
|
||||
@ -487,30 +416,23 @@ impl TransportParameters {
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
let ok = if let Some(v_self) = self.params.get(k) {
|
||||
if let Some(v_self) = self.params.get(k) {
|
||||
match (v_self, v_rem) {
|
||||
(TransportParameter::Integer(i_self), TransportParameter::Integer(i_rem)) => {
|
||||
if *k == MIN_ACK_DELAY {
|
||||
// MIN_ACK_DELAY is backwards:
|
||||
// it can only be reduced safely.
|
||||
*i_self <= *i_rem
|
||||
} else {
|
||||
*i_self >= *i_rem
|
||||
if *i_self > *i_rem {
|
||||
return false;
|
||||
}
|
||||
} else if *i_self < *i_rem {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
(TransportParameter::Empty, TransportParameter::Empty) => true,
|
||||
(
|
||||
TransportParameter::Versions {
|
||||
current: v_self, ..
|
||||
},
|
||||
TransportParameter::Versions { current: v_rem, .. },
|
||||
) => v_self == v_rem,
|
||||
_ => false,
|
||||
(TransportParameter::Empty, TransportParameter::Empty) => {}
|
||||
_ => return false,
|
||||
}
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if !ok {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -532,117 +454,26 @@ impl TransportParameters {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the version negotiation values for validation.
|
||||
#[must_use]
|
||||
pub fn get_versions(&self) -> Option<(WireVersion, &[WireVersion])> {
|
||||
if let Some(TransportParameter::Versions { current, other }) =
|
||||
self.params.get(&VERSION_NEGOTIATION)
|
||||
{
|
||||
Some((*current, other))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn has_value(&self, tp: TransportParameterId) -> bool {
|
||||
self.params.contains_key(&tp)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Default, Debug)]
|
||||
pub struct TransportParametersHandler {
|
||||
role: Role,
|
||||
versions: VersionConfig,
|
||||
pub(crate) local: TransportParameters,
|
||||
pub(crate) remote: Option<TransportParameters>,
|
||||
pub(crate) remote_0rtt: Option<TransportParameters>,
|
||||
}
|
||||
|
||||
impl TransportParametersHandler {
|
||||
pub fn new(role: Role, versions: VersionConfig) -> Self {
|
||||
let mut local = TransportParameters::default();
|
||||
local.set_versions(role, &versions);
|
||||
Self {
|
||||
role,
|
||||
versions,
|
||||
local,
|
||||
remote: None,
|
||||
remote_0rtt: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// When resuming, the version is set based on the ticket.
|
||||
/// That needs to be done to override the default choice from configuration.
|
||||
pub fn set_version(&mut self, version: Version) {
|
||||
debug_assert_eq!(self.role, Role::Client);
|
||||
self.versions.set_initial(version);
|
||||
self.local.set_versions(self.role, &self.versions)
|
||||
}
|
||||
|
||||
pub fn remote(&self) -> &TransportParameters {
|
||||
match (self.remote.as_ref(), self.remote_0rtt.as_ref()) {
|
||||
(Some(tp), _) | (_, Some(tp)) => tp,
|
||||
_ => panic!("no transport parameters from peer"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the version as set (or as determined by a compatible upgrade).
|
||||
pub fn version(&self) -> Version {
|
||||
self.versions.initial()
|
||||
}
|
||||
|
||||
fn compatible_upgrade(&mut self, remote_tp: &TransportParameters) -> Res<()> {
|
||||
if let Some((current, other)) = remote_tp.get_versions() {
|
||||
qtrace!(
|
||||
"Peer versions: {:x} {:x?}; config {:?}",
|
||||
current,
|
||||
other,
|
||||
self.versions,
|
||||
);
|
||||
|
||||
if self.role == Role::Client {
|
||||
let chosen = Version::try_from(current)?;
|
||||
if self.versions.compatible().any(|&v| v == chosen) {
|
||||
Ok(())
|
||||
} else {
|
||||
qinfo!(
|
||||
"Chosen version {:x} is not compatible with initial version {:x}",
|
||||
current,
|
||||
self.versions.initial().wire_version(),
|
||||
);
|
||||
Err(Error::TransportParameterError)
|
||||
}
|
||||
} else {
|
||||
if current != self.versions.initial().wire_version() {
|
||||
qinfo!(
|
||||
"Current version {:x} != own version {:x}",
|
||||
current,
|
||||
self.versions.initial().wire_version(),
|
||||
);
|
||||
return Err(Error::TransportParameterError);
|
||||
}
|
||||
|
||||
if let Some(preferred) = self.versions.preferred_compatible(other) {
|
||||
if preferred != self.versions.initial() {
|
||||
qinfo!(
|
||||
"Compatible upgrade {:?} ==> {:?}",
|
||||
self.versions.initial(),
|
||||
preferred
|
||||
);
|
||||
self.versions.set_initial(preferred);
|
||||
self.local.compatible_upgrade(preferred);
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
qinfo!("Unable to find any compatible version");
|
||||
Err(Error::TransportParameterError)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtensionHandler for TransportParametersHandler {
|
||||
@ -657,7 +488,7 @@ impl ExtensionHandler for TransportParametersHandler {
|
||||
let mut enc = Encoder::default();
|
||||
self.local.encode(&mut enc);
|
||||
assert!(enc.len() <= d.len());
|
||||
d[..enc.len()].copy_from_slice(enc.as_ref());
|
||||
d[..enc.len()].copy_from_slice(&enc);
|
||||
ExtensionWriterResult::Write(enc.len())
|
||||
}
|
||||
|
||||
@ -675,12 +506,8 @@ impl ExtensionHandler for TransportParametersHandler {
|
||||
let mut dec = Decoder::from(d);
|
||||
match TransportParameters::decode(&mut dec) {
|
||||
Ok(tp) => {
|
||||
if self.compatible_upgrade(&tp).is_ok() {
|
||||
self.remote = Some(tp);
|
||||
ExtensionHandlerResult::Ok
|
||||
} else {
|
||||
ExtensionHandlerResult::Alert(47)
|
||||
}
|
||||
self.remote = Some(tp);
|
||||
ExtensionHandlerResult::Ok
|
||||
}
|
||||
_ => ExtensionHandlerResult::Alert(47), // illegal_parameter
|
||||
}
|
||||
@ -742,6 +569,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(ekr@rtfm.com): Need to write more TP unit tests.
|
||||
#[cfg(test)]
|
||||
#[allow(unused_variables)]
|
||||
mod tests {
|
||||
@ -811,7 +639,7 @@ mod tests {
|
||||
let spa = make_spa();
|
||||
let mut enc = Encoder::new();
|
||||
spa.encode(&mut enc, PREFERRED_ADDRESS);
|
||||
assert_eq!(enc.as_ref(), ENCODED);
|
||||
assert_eq!(&enc[..], ENCODED);
|
||||
|
||||
let mut dec = enc.as_decoder();
|
||||
let (id, decoded) = TransportParameter::decode(&mut dec).unwrap().unwrap();
|
||||
@ -905,7 +733,7 @@ mod tests {
|
||||
let spa = make_spa();
|
||||
let mut enc = Encoder::new();
|
||||
spa.encode(&mut enc, PREFERRED_ADDRESS);
|
||||
let mut dec = Decoder::from(&enc.as_ref()[..enc.len() - 1]);
|
||||
let mut dec = Decoder::from(&enc[..enc.len() - 1]);
|
||||
assert_eq!(
|
||||
TransportParameter::decode(&mut dec).unwrap_err(),
|
||||
Error::NoMoreData
|
||||
@ -1083,97 +911,4 @@ mod tests {
|
||||
let invalid_decode_result = TransportParameters::decode(&mut enc.as_decoder());
|
||||
assert!(invalid_decode_result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn versions_encode_decode() {
|
||||
const ENCODED: &[u8] = &[
|
||||
0x80, 0xff, 0x73, 0xdb, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a,
|
||||
0x6a, 0x7a, 0x8a,
|
||||
];
|
||||
let vn = TransportParameter::Versions {
|
||||
current: Version::Version1.wire_version(),
|
||||
other: vec![0x1a2a_3a4a, 0x5a6a_7a8a],
|
||||
};
|
||||
|
||||
let mut enc = Encoder::new();
|
||||
vn.encode(&mut enc, VERSION_NEGOTIATION);
|
||||
assert_eq!(enc.as_ref(), ENCODED);
|
||||
|
||||
let mut dec = enc.as_decoder();
|
||||
let (id, decoded) = TransportParameter::decode(&mut dec).unwrap().unwrap();
|
||||
assert_eq!(id, VERSION_NEGOTIATION);
|
||||
assert_eq!(decoded, vn);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn versions_truncated() {
|
||||
const TRUNCATED: &[u8] = &[
|
||||
0x80, 0xff, 0x73, 0xdb, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a,
|
||||
0x6a, 0x7a,
|
||||
];
|
||||
let mut dec = Decoder::from(&TRUNCATED);
|
||||
assert_eq!(
|
||||
TransportParameter::decode(&mut dec).unwrap_err(),
|
||||
Error::NoMoreData
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn versions_zero() {
|
||||
const ZERO1: &[u8] = &[0x80, 0xff, 0x73, 0xdb, 0x04, 0x00, 0x00, 0x00, 0x00];
|
||||
const ZERO2: &[u8] = &[
|
||||
0x80, 0xff, 0x73, 0xdb, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
];
|
||||
|
||||
let mut dec = Decoder::from(&ZERO1);
|
||||
assert_eq!(
|
||||
TransportParameter::decode(&mut dec).unwrap_err(),
|
||||
Error::TransportParameterError
|
||||
);
|
||||
let mut dec = Decoder::from(&ZERO2);
|
||||
assert_eq!(
|
||||
TransportParameter::decode(&mut dec).unwrap_err(),
|
||||
Error::TransportParameterError
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn versions_equal_0rtt() {
|
||||
let mut current = TransportParameters::default();
|
||||
current.set(
|
||||
VERSION_NEGOTIATION,
|
||||
TransportParameter::Versions {
|
||||
current: Version::Version1.wire_version(),
|
||||
other: vec![0x1a2a_3a4a],
|
||||
},
|
||||
);
|
||||
|
||||
let mut remembered = TransportParameters::default();
|
||||
// It's OK to not remember having versions.
|
||||
assert!(current.ok_for_0rtt(&remembered));
|
||||
// But it is bad in the opposite direction.
|
||||
assert!(!remembered.ok_for_0rtt(¤t));
|
||||
|
||||
// If the version matches, it's OK to use 0-RTT.
|
||||
remembered.set(
|
||||
VERSION_NEGOTIATION,
|
||||
TransportParameter::Versions {
|
||||
current: Version::Version1.wire_version(),
|
||||
other: vec![0x5a6a_7a8a, 0x9aaa_baca],
|
||||
},
|
||||
);
|
||||
assert!(current.ok_for_0rtt(&remembered));
|
||||
assert!(remembered.ok_for_0rtt(¤t));
|
||||
|
||||
// An apparent "upgrade" is still cause to reject 0-RTT.
|
||||
remembered.set(
|
||||
VERSION_NEGOTIATION,
|
||||
TransportParameter::Versions {
|
||||
current: Version::Version1.wire_version() + 1,
|
||||
other: vec![],
|
||||
},
|
||||
);
|
||||
assert!(!current.ok_for_0rtt(&remembered));
|
||||
assert!(!remembered.ok_for_0rtt(¤t));
|
||||
}
|
||||
}
|
||||
|
@ -26,8 +26,8 @@ use std::mem;
|
||||
use std::ops::Range;
|
||||
use std::rc::Rc;
|
||||
|
||||
/// Create a server. This is different than the one in the fixture, which is a single connection.
|
||||
pub fn new_server(params: ConnectionParameters) -> Server {
|
||||
// Different than the one in the fixture, which is a single connection.
|
||||
pub fn default_server() -> Server {
|
||||
Server::new(
|
||||
now(),
|
||||
test_fixture::DEFAULT_KEYS,
|
||||
@ -35,16 +35,11 @@ pub fn new_server(params: ConnectionParameters) -> Server {
|
||||
test_fixture::anti_replay(),
|
||||
Box::new(AllowZeroRtt {}),
|
||||
Rc::new(RefCell::new(CountingConnectionIdGenerator::default())),
|
||||
params,
|
||||
ConnectionParameters::default(),
|
||||
)
|
||||
.expect("should create a server")
|
||||
}
|
||||
|
||||
/// Create a server. This is different than the one in the fixture, which is a single connection.
|
||||
pub fn default_server() -> Server {
|
||||
new_server(ConnectionParameters::default())
|
||||
}
|
||||
|
||||
// Check that there is at least one connection. Returns a ref to the first confirmed connection.
|
||||
pub fn connected_server(server: &mut Server) -> ActiveConnectionRef {
|
||||
let server_connections = server.active_connections();
|
||||
@ -115,8 +110,7 @@ pub fn decode_initial_header(dgram: &Datagram) -> (&[u8], &[u8], &[u8], &[u8]) {
|
||||
)
|
||||
}
|
||||
|
||||
/// Generate an AEAD and header protection object for a client Initial.
|
||||
/// Note that this works for QUIC version 1 only.
|
||||
// Generate an AEAD and header protection object for a client Initial.
|
||||
#[must_use]
|
||||
pub fn client_initial_aead_and_hp(dcid: &[u8]) -> (Aead, HpKey) {
|
||||
const INITIAL_SALT: &[u8] = &[
|
||||
@ -190,9 +184,15 @@ pub fn apply_header_protection(hp: &HpKey, packet: &mut [u8], pn_bytes: Range<us
|
||||
}
|
||||
}
|
||||
|
||||
/// Scrub through client events to find a resumption token.
|
||||
pub fn find_ticket(client: &mut Connection) -> ResumptionToken {
|
||||
client
|
||||
pub fn get_ticket(server: &mut Server) -> ResumptionToken {
|
||||
let mut client = default_client();
|
||||
let mut server_conn = connect(&mut client, server);
|
||||
|
||||
server_conn.borrow_mut().send_ticket(now(), &[]).unwrap();
|
||||
let dgram = server.process(None, now()).dgram();
|
||||
client.process_input(dgram.unwrap(), now()); // Consume ticket, ignore output.
|
||||
|
||||
let ticket = client
|
||||
.events()
|
||||
.find_map(|e| {
|
||||
if let ConnectionEvent::ResumptionToken(token) = e {
|
||||
@ -201,18 +201,7 @@ pub fn find_ticket(client: &mut Connection) -> ResumptionToken {
|
||||
None
|
||||
}
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Connect to the server and have it generate a ticket.
|
||||
pub fn generate_ticket(server: &mut Server) -> ResumptionToken {
|
||||
let mut client = default_client();
|
||||
let mut server_conn = connect(&mut client, server);
|
||||
|
||||
server_conn.borrow_mut().send_ticket(now(), &[]).unwrap();
|
||||
let dgram = server.process(None, now()).dgram();
|
||||
client.process_input(dgram.unwrap(), now()); // Consume ticket, ignore output.
|
||||
let ticket = find_ticket(&mut client);
|
||||
.unwrap();
|
||||
|
||||
// Have the client close the connection and then let the server clean up.
|
||||
client.close(now(), 0, "got a ticket");
|
||||
|
@ -10,91 +10,13 @@
|
||||
|
||||
use neqo_common::Datagram;
|
||||
use neqo_transport::{
|
||||
Connection, ConnectionParameters, RandomConnectionIdGenerator, State, Version,
|
||||
Connection, ConnectionParameters, QuicVersion, RandomConnectionIdGenerator, State,
|
||||
};
|
||||
use test_fixture::{self, addr, now};
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
const INITIAL_PACKET_V2: &[u8] = &[
|
||||
0xdd, 0x70, 0x9a, 0x50, 0xc4, 0x08, 0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08, 0x00, 0x00,
|
||||
0x44, 0x9e, 0x43, 0x91, 0xd8, 0x48, 0x23, 0xb8, 0xe6, 0x10, 0x58, 0x9c, 0x83, 0xc9, 0x2d, 0x0e,
|
||||
0x97, 0xeb, 0x7a, 0x6e, 0x50, 0x03, 0xf5, 0x77, 0x64, 0xc5, 0xc7, 0xf0, 0x09, 0x5b, 0xa5, 0x4b,
|
||||
0x90, 0x81, 0x8f, 0x1b, 0xfe, 0xec, 0xc1, 0xc9, 0x7c, 0x54, 0xfc, 0x73, 0x1e, 0xdb, 0xd2, 0xa2,
|
||||
0x44, 0xe3, 0xb1, 0xe6, 0x39, 0xa9, 0xbc, 0x75, 0xed, 0x54, 0x5b, 0x98, 0x64, 0x93, 0x43, 0xb2,
|
||||
0x53, 0x61, 0x5e, 0xc6, 0xb3, 0xe4, 0xdf, 0x0f, 0xd2, 0xe7, 0xfe, 0x9d, 0x69, 0x1a, 0x09, 0xe6,
|
||||
0xa1, 0x44, 0xb4, 0x36, 0xd8, 0xa2, 0xc0, 0x88, 0xa4, 0x04, 0x26, 0x23, 0x40, 0xdf, 0xd9, 0x95,
|
||||
0xec, 0x38, 0x65, 0x69, 0x4e, 0x30, 0x26, 0xec, 0xd8, 0xc6, 0xd2, 0x56, 0x1a, 0x5a, 0x36, 0x67,
|
||||
0x2a, 0x10, 0x05, 0x01, 0x81, 0x68, 0xc0, 0xf0, 0x81, 0xc1, 0x0e, 0x2b, 0xf1, 0x4d, 0x55, 0x0c,
|
||||
0x97, 0x7e, 0x28, 0xbb, 0x9a, 0x75, 0x9c, 0x57, 0xd0, 0xf7, 0xff, 0xb1, 0xcd, 0xfb, 0x40, 0xbd,
|
||||
0x77, 0x4d, 0xec, 0x58, 0x96, 0x57, 0x54, 0x20, 0x47, 0xdf, 0xfe, 0xfa, 0x56, 0xfc, 0x80, 0x89,
|
||||
0xa4, 0xd1, 0xef, 0x37, 0x9c, 0x81, 0xba, 0x3d, 0xf7, 0x1a, 0x05, 0xdd, 0xc7, 0x92, 0x83, 0x40,
|
||||
0x77, 0x59, 0x10, 0xfe, 0xb3, 0xce, 0x4c, 0xbc, 0xfd, 0x8d, 0x25, 0x3e, 0xdd, 0x05, 0xf1, 0x61,
|
||||
0x45, 0x8f, 0x9d, 0xc4, 0x4b, 0xea, 0x01, 0x7c, 0x31, 0x17, 0xcc, 0xa7, 0x06, 0x5a, 0x31, 0x5d,
|
||||
0xed, 0xa9, 0x46, 0x4e, 0x67, 0x2e, 0xc8, 0x0c, 0x3f, 0x79, 0xac, 0x99, 0x34, 0x37, 0xb4, 0x41,
|
||||
0xef, 0x74, 0x22, 0x7e, 0xcc, 0x4d, 0xc9, 0xd5, 0x97, 0xf6, 0x6a, 0xb0, 0xab, 0x8d, 0x21, 0x4b,
|
||||
0x55, 0x84, 0x0c, 0x70, 0x34, 0x9d, 0x76, 0x16, 0xcb, 0xe3, 0x8e, 0x5e, 0x1d, 0x05, 0x2d, 0x07,
|
||||
0xf1, 0xfe, 0xdb, 0x3d, 0xd3, 0xc4, 0xd8, 0xce, 0x29, 0x57, 0x24, 0x94, 0x5e, 0x67, 0xed, 0x2e,
|
||||
0xef, 0xcd, 0x9f, 0xb5, 0x24, 0x72, 0x38, 0x7f, 0x31, 0x8e, 0x3d, 0x9d, 0x23, 0x3b, 0xe7, 0xdf,
|
||||
0xc7, 0x9d, 0x6b, 0xf6, 0x08, 0x0d, 0xcb, 0xbb, 0x41, 0xfe, 0xb1, 0x80, 0xd7, 0x85, 0x88, 0x49,
|
||||
0x7c, 0x3e, 0x43, 0x9d, 0x38, 0xc3, 0x34, 0x74, 0x8d, 0x2b, 0x56, 0xfd, 0x19, 0xab, 0x36, 0x4d,
|
||||
0x05, 0x7a, 0x9b, 0xd5, 0xa6, 0x99, 0xae, 0x14, 0x5d, 0x7f, 0xdb, 0xc8, 0xf5, 0x77, 0x75, 0x18,
|
||||
0x1b, 0x0a, 0x97, 0xc3, 0xbd, 0xed, 0xc9, 0x1a, 0x55, 0x5d, 0x6c, 0x9b, 0x86, 0x34, 0xe1, 0x06,
|
||||
0xd8, 0xc9, 0xca, 0x45, 0xa9, 0xd5, 0x45, 0x0a, 0x76, 0x79, 0xed, 0xc5, 0x45, 0xda, 0x91, 0x02,
|
||||
0x5b, 0xc9, 0x3a, 0x7c, 0xf9, 0xa0, 0x23, 0xa0, 0x66, 0xff, 0xad, 0xb9, 0x71, 0x7f, 0xfa, 0xf3,
|
||||
0x41, 0x4c, 0x3b, 0x64, 0x6b, 0x57, 0x38, 0xb3, 0xcc, 0x41, 0x16, 0x50, 0x2d, 0x18, 0xd7, 0x9d,
|
||||
0x82, 0x27, 0x43, 0x63, 0x06, 0xd9, 0xb2, 0xb3, 0xaf, 0xc6, 0xc7, 0x85, 0xce, 0x3c, 0x81, 0x7f,
|
||||
0xeb, 0x70, 0x3a, 0x42, 0xb9, 0xc8, 0x3b, 0x59, 0xf0, 0xdc, 0xef, 0x12, 0x45, 0xd0, 0xb3, 0xe4,
|
||||
0x02, 0x99, 0x82, 0x1e, 0xc1, 0x95, 0x49, 0xce, 0x48, 0x97, 0x14, 0xfe, 0x26, 0x11, 0xe7, 0x2c,
|
||||
0xd8, 0x82, 0xf4, 0xf7, 0x0d, 0xce, 0x7d, 0x36, 0x71, 0x29, 0x6f, 0xc0, 0x45, 0xaf, 0x5c, 0x9f,
|
||||
0x63, 0x0d, 0x7b, 0x49, 0xa3, 0xeb, 0x82, 0x1b, 0xbc, 0xa6, 0x0f, 0x19, 0x84, 0xdc, 0xe6, 0x64,
|
||||
0x91, 0x71, 0x3b, 0xfe, 0x06, 0x00, 0x1a, 0x56, 0xf5, 0x1b, 0xb3, 0xab, 0xe9, 0x2f, 0x79, 0x60,
|
||||
0x54, 0x7c, 0x4d, 0x0a, 0x70, 0xf4, 0xa9, 0x62, 0xb3, 0xf0, 0x5d, 0xc2, 0x5a, 0x34, 0xbb, 0xe8,
|
||||
0x30, 0xa7, 0xea, 0x47, 0x36, 0xd3, 0xb0, 0x16, 0x17, 0x23, 0x50, 0x0d, 0x82, 0xbe, 0xda, 0x9b,
|
||||
0xe3, 0x32, 0x7a, 0xf2, 0xaa, 0x41, 0x38, 0x21, 0xff, 0x67, 0x8b, 0x2a, 0x87, 0x6e, 0xc4, 0xb0,
|
||||
0x0b, 0xb6, 0x05, 0xff, 0xcc, 0x39, 0x17, 0xff, 0xdc, 0x27, 0x9f, 0x18, 0x7d, 0xaa, 0x2f, 0xce,
|
||||
0x8c, 0xde, 0x12, 0x19, 0x80, 0xbb, 0xa8, 0xec, 0x8f, 0x44, 0xca, 0x56, 0x2b, 0x0f, 0x13, 0x19,
|
||||
0x14, 0xc9, 0x01, 0xcf, 0xbd, 0x84, 0x74, 0x08, 0xb7, 0x78, 0xe6, 0x73, 0x8c, 0x7b, 0xb5, 0xb1,
|
||||
0xb3, 0xf9, 0x7d, 0x01, 0xb0, 0xa2, 0x4d, 0xcc, 0xa4, 0x0e, 0x3b, 0xed, 0x29, 0x41, 0x1b, 0x1b,
|
||||
0xa8, 0xf6, 0x08, 0x43, 0xc4, 0xa2, 0x41, 0x02, 0x1b, 0x23, 0x13, 0x2b, 0x95, 0x00, 0x50, 0x9b,
|
||||
0x9a, 0x35, 0x16, 0xd4, 0xa9, 0xdd, 0x41, 0xd3, 0xba, 0xcb, 0xcd, 0x42, 0x6b, 0x45, 0x13, 0x93,
|
||||
0x52, 0x18, 0x28, 0xaf, 0xed, 0xcf, 0x20, 0xfa, 0x46, 0xac, 0x24, 0xf4, 0x4a, 0x8e, 0x29, 0x73,
|
||||
0x30, 0xb1, 0x67, 0x05, 0xd5, 0xd5, 0xf7, 0x98, 0xef, 0xf9, 0xe9, 0x13, 0x4a, 0x06, 0x59, 0x79,
|
||||
0x87, 0xa1, 0xdb, 0x46, 0x17, 0xca, 0xa2, 0xd9, 0x38, 0x37, 0x73, 0x08, 0x29, 0xd4, 0xd8, 0x9e,
|
||||
0x16, 0x41, 0x3b, 0xe4, 0xd8, 0xa8, 0xa3, 0x8a, 0x7e, 0x62, 0x26, 0x62, 0x3b, 0x64, 0xa8, 0x20,
|
||||
0x17, 0x8e, 0xc3, 0xa6, 0x69, 0x54, 0xe1, 0x07, 0x10, 0xe0, 0x43, 0xae, 0x73, 0xdd, 0x3f, 0xb2,
|
||||
0x71, 0x5a, 0x05, 0x25, 0xa4, 0x63, 0x43, 0xfb, 0x75, 0x90, 0xe5, 0xea, 0xc7, 0xee, 0x55, 0xfc,
|
||||
0x81, 0x0e, 0x0d, 0x8b, 0x4b, 0x8f, 0x7b, 0xe8, 0x2c, 0xd5, 0xa2, 0x14, 0x57, 0x5a, 0x1b, 0x99,
|
||||
0x62, 0x9d, 0x47, 0xa9, 0xb2, 0x81, 0xb6, 0x13, 0x48, 0xc8, 0x62, 0x7c, 0xab, 0x38, 0xe2, 0xa6,
|
||||
0x4d, 0xb6, 0x62, 0x6e, 0x97, 0xbb, 0x8f, 0x77, 0xbd, 0xcb, 0x0f, 0xee, 0x47, 0x6a, 0xed, 0xd7,
|
||||
0xba, 0x8f, 0x54, 0x41, 0xac, 0xaa, 0xb0, 0x0f, 0x44, 0x32, 0xed, 0xab, 0x37, 0x91, 0x04, 0x7d,
|
||||
0x90, 0x91, 0xb2, 0xa7, 0x53, 0xf0, 0x35, 0x64, 0x84, 0x31, 0xf6, 0xd1, 0x2f, 0x7d, 0x6a, 0x68,
|
||||
0x1e, 0x64, 0xc8, 0x61, 0xf4, 0xac, 0x91, 0x1a, 0x0f, 0x7d, 0x6e, 0xc0, 0x49, 0x1a, 0x78, 0xc9,
|
||||
0xf1, 0x92, 0xf9, 0x6b, 0x3a, 0x5e, 0x75, 0x60, 0xa3, 0xf0, 0x56, 0xbc, 0x1c, 0xa8, 0x59, 0x83,
|
||||
0x67, 0xad, 0x6a, 0xcb, 0x6f, 0x2e, 0x03, 0x4c, 0x7f, 0x37, 0xbe, 0xeb, 0x9e, 0xd4, 0x70, 0xc4,
|
||||
0x30, 0x4a, 0xf0, 0x10, 0x7f, 0x0e, 0xb9, 0x19, 0xbe, 0x36, 0xa8, 0x6f, 0x68, 0xf3, 0x7f, 0xa6,
|
||||
0x1d, 0xae, 0x7a, 0xff, 0x14, 0xde, 0xcd, 0x67, 0xec, 0x31, 0x57, 0xa1, 0x14, 0x88, 0xa1, 0x4f,
|
||||
0xed, 0x01, 0x42, 0x82, 0x83, 0x48, 0xf5, 0xf6, 0x08, 0xb0, 0xfe, 0x03, 0xe1, 0xf3, 0xc0, 0xaf,
|
||||
0x3a, 0xcc, 0xa0, 0xce, 0x36, 0x85, 0x2e, 0xd4, 0x2e, 0x22, 0x0a, 0xe9, 0xab, 0xf8, 0xf8, 0x90,
|
||||
0x6f, 0x00, 0xf1, 0xb8, 0x6b, 0xff, 0x85, 0x04, 0xc8, 0xf1, 0x6c, 0x78, 0x4f, 0xd5, 0x2d, 0x25,
|
||||
0xe0, 0x13, 0xff, 0x4f, 0xda, 0x90, 0x3e, 0x9e, 0x1e, 0xb4, 0x53, 0xc1, 0x46, 0x4b, 0x11, 0x96,
|
||||
0x6d, 0xb9, 0xb2, 0x8e, 0x8f, 0x26, 0xa3, 0xfc, 0x41, 0x9e, 0x6a, 0x60, 0xa4, 0x8d, 0x4c, 0x72,
|
||||
0x14, 0xee, 0x9c, 0x6c, 0x6a, 0x12, 0xb6, 0x8a, 0x32, 0xca, 0xc8, 0xf6, 0x15, 0x80, 0xc6, 0x4f,
|
||||
0x29, 0xcb, 0x69, 0x22, 0x40, 0x87, 0x83, 0xc6, 0xd1, 0x2e, 0x72, 0x5b, 0x01, 0x4f, 0xe4, 0x85,
|
||||
0xcd, 0x17, 0xe4, 0x84, 0xc5, 0x95, 0x2b, 0xf9, 0x9b, 0xc9, 0x49, 0x41, 0xd4, 0xb1, 0x91, 0x9d,
|
||||
0x04, 0x31, 0x7b, 0x8a, 0xa1, 0xbd, 0x37, 0x54, 0xec, 0xba, 0xa1, 0x0e, 0xc2, 0x27, 0xde, 0x85,
|
||||
0x40, 0x69, 0x5b, 0xf2, 0xfb, 0x8e, 0xe5, 0x6f, 0x6d, 0xc5, 0x26, 0xef, 0x36, 0x66, 0x25, 0xb9,
|
||||
0x1a, 0xa4, 0x97, 0x0b, 0x6f, 0xfa, 0x5c, 0x82, 0x84, 0xb9, 0xb5, 0xab, 0x85, 0x2b, 0x90, 0x5f,
|
||||
0x9d, 0x83, 0xf5, 0x66, 0x9c, 0x05, 0x35, 0xbc, 0x37, 0x7b, 0xcc, 0x05, 0xad, 0x5e, 0x48, 0xe2,
|
||||
0x81, 0xec, 0x0e, 0x19, 0x17, 0xca, 0x3c, 0x6a, 0x47, 0x1f, 0x8d, 0xa0, 0x89, 0x4b, 0xc8, 0x2a,
|
||||
0xc2, 0xa8, 0x96, 0x54, 0x05, 0xd6, 0xee, 0xf3, 0xb5, 0xe2, 0x93, 0xa8, 0x8f, 0xda, 0x20, 0x3f,
|
||||
0x09, 0xbd, 0xc7, 0x27, 0x57, 0xb1, 0x07, 0xab, 0x14, 0x88, 0x0e, 0xaa, 0x3e, 0xf7, 0x04, 0x5b,
|
||||
0x58, 0x0f, 0x48, 0x21, 0xce, 0x6d, 0xd3, 0x25, 0xb5, 0xa9, 0x06, 0x55, 0xd8, 0xc5, 0xb5, 0x5f,
|
||||
0x76, 0xfb, 0x84, 0x62, 0x79, 0xa9, 0xb5, 0x18, 0xc5, 0xe9, 0xb9, 0xa2, 0x11, 0x65, 0xc5, 0x09,
|
||||
0x3e, 0xd4, 0x9b, 0xaa, 0xac, 0xad, 0xf1, 0xf2, 0x18, 0x73, 0x26, 0x6c, 0x76, 0x7f, 0x67, 0x69,
|
||||
];
|
||||
|
||||
const INITIAL_PACKET_V1: &[u8] = &[
|
||||
0xc0, 0x00, 0x00, 0x00, 0x01, 0x08, 0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08, 0x00, 0x00,
|
||||
0x44, 0x9e, 0x7b, 0x9a, 0xec, 0x34, 0xd1, 0xb1, 0xc9, 0x8d, 0xd7, 0x68, 0x9f, 0xb8, 0xec, 0x11,
|
||||
@ -251,19 +173,19 @@ const INITIAL_PACKET_29: &[u8] = &[
|
||||
0x18, 0x02, 0x77, 0x1a, 0x44, 0x9b, 0x30, 0xf3, 0xfa, 0x22, 0x89, 0x85, 0x26, 0x07, 0xb6, 0x60,
|
||||
];
|
||||
|
||||
fn make_server(v: Version) -> Connection {
|
||||
fn make_server(quic_version: QuicVersion) -> Connection {
|
||||
test_fixture::fixture_init();
|
||||
Connection::new_server(
|
||||
test_fixture::DEFAULT_KEYS,
|
||||
test_fixture::DEFAULT_ALPN,
|
||||
Rc::new(RefCell::new(RandomConnectionIdGenerator::new(5))),
|
||||
ConnectionParameters::default().versions(v, vec![v]),
|
||||
ConnectionParameters::default().quic_version(quic_version),
|
||||
)
|
||||
.expect("create a default server")
|
||||
}
|
||||
|
||||
fn process_client_initial(v: Version, packet: &[u8]) {
|
||||
let mut server = make_server(v);
|
||||
fn process_client_initial(quic_version: QuicVersion, packet: &[u8]) {
|
||||
let mut server = make_server(quic_version);
|
||||
|
||||
let dgram = Datagram::new(addr(), addr(), packet);
|
||||
assert_eq!(*server.state(), State::Init);
|
||||
@ -272,17 +194,12 @@ fn process_client_initial(v: Version, packet: &[u8]) {
|
||||
assert!(out.dgram().is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn process_client_initial_v2() {
|
||||
process_client_initial(Version::Version2, INITIAL_PACKET_V2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn process_client_initial_v1() {
|
||||
process_client_initial(Version::Version1, INITIAL_PACKET_V1);
|
||||
process_client_initial(QuicVersion::Version1, INITIAL_PACKET_V1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn process_client_initial_29() {
|
||||
process_client_initial(Version::Draft29, INITIAL_PACKET_29);
|
||||
process_client_initial(QuicVersion::Draft29, INITIAL_PACKET_29);
|
||||
}
|
||||
|
@ -34,8 +34,8 @@ fn truncate_long_packet() {
|
||||
dupe.destination(),
|
||||
&dupe[..(dupe.len() - tail)],
|
||||
);
|
||||
let hs_probe = client.process(Some(truncated), now()).dgram();
|
||||
assert!(hs_probe.is_some());
|
||||
let dupe_ack = client.process(Some(truncated), now()).dgram();
|
||||
assert!(dupe_ack.is_some());
|
||||
|
||||
// Now feed in the untruncated packet.
|
||||
let dgram = client.process(dgram, now()).dgram();
|
||||
|
31
third_party/rust/neqo-transport/tests/retry.rs
vendored
31
third_party/rust/neqo-transport/tests/retry.rs
vendored
@ -12,7 +12,7 @@ mod common;
|
||||
|
||||
use common::{
|
||||
apply_header_protection, client_initial_aead_and_hp, connected_server, decode_initial_header,
|
||||
default_server, generate_ticket, remove_header_protection,
|
||||
default_server, get_ticket, remove_header_protection,
|
||||
};
|
||||
use neqo_common::{hex_with_len, qdebug, qtrace, Datagram, Encoder};
|
||||
use neqo_crypto::AuthenticationStatus;
|
||||
@ -50,26 +50,6 @@ fn retry_basic() {
|
||||
connected_server(&mut server);
|
||||
}
|
||||
|
||||
/// Receiving a Retry is enough to infer something about the RTT.
|
||||
/// Probably.
|
||||
#[test]
|
||||
fn implicit_rtt_retry() {
|
||||
const RTT: Duration = Duration::from_secs(2);
|
||||
let mut server = default_server();
|
||||
server.set_validation(ValidateAddress::Always);
|
||||
let mut client = default_client();
|
||||
let mut now = now();
|
||||
|
||||
let dgram = client.process(None, now).dgram();
|
||||
now += RTT / 2;
|
||||
let dgram = server.process(dgram, now).dgram();
|
||||
assertions::assert_retry(dgram.as_ref().unwrap());
|
||||
now += RTT / 2;
|
||||
client.process_input(dgram.unwrap(), now);
|
||||
|
||||
assert_eq!(client.stats().rtt, RTT);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn retry_expired() {
|
||||
let mut server = default_server();
|
||||
@ -96,7 +76,7 @@ fn retry_expired() {
|
||||
#[test]
|
||||
fn retry_0rtt() {
|
||||
let mut server = default_server();
|
||||
let token = generate_ticket(&mut server);
|
||||
let token = get_ticket(&mut server);
|
||||
server.set_validation(ValidateAddress::Always);
|
||||
|
||||
let mut client = default_client();
|
||||
@ -158,7 +138,7 @@ fn retry_different_ip() {
|
||||
#[test]
|
||||
fn new_token_different_ip() {
|
||||
let mut server = default_server();
|
||||
let token = generate_ticket(&mut server);
|
||||
let token = get_ticket(&mut server);
|
||||
server.set_validation(ValidateAddress::NoToken);
|
||||
|
||||
let mut client = default_client();
|
||||
@ -180,7 +160,7 @@ fn new_token_different_ip() {
|
||||
#[test]
|
||||
fn new_token_expired() {
|
||||
let mut server = default_server();
|
||||
let token = generate_ticket(&mut server);
|
||||
let token = get_ticket(&mut server);
|
||||
server.set_validation(ValidateAddress::NoToken);
|
||||
|
||||
let mut client = default_client();
|
||||
@ -395,13 +375,12 @@ fn mitm_retry() {
|
||||
.encode_vvec(&[])
|
||||
.encode_varint(u64::try_from(payload.len()).unwrap());
|
||||
let pn_offset = enc.len();
|
||||
let notoken_header = enc.encode_uint(pn_len, pn).as_ref().to_vec();
|
||||
let notoken_header = enc.encode_uint(pn_len, pn).to_vec();
|
||||
qtrace!("notoken_header={}", hex_with_len(¬oken_header));
|
||||
|
||||
// Encrypt.
|
||||
let mut notoken_packet = Encoder::with_capacity(1200)
|
||||
.encode(¬oken_header)
|
||||
.as_ref()
|
||||
.to_vec();
|
||||
notoken_packet.resize_with(1200, u8::default);
|
||||
aead.encrypt(
|
||||
|
223
third_party/rust/neqo-transport/tests/server.rs
vendored
223
third_party/rust/neqo-transport/tests/server.rs
vendored
@ -11,21 +11,18 @@ mod common;
|
||||
|
||||
use common::{
|
||||
apply_header_protection, client_initial_aead_and_hp, connect, connected_server,
|
||||
decode_initial_header, default_server, find_ticket, generate_ticket, new_server,
|
||||
remove_header_protection,
|
||||
decode_initial_header, default_server, get_ticket, remove_header_protection,
|
||||
};
|
||||
|
||||
use neqo_common::{qtrace, Datagram, Decoder, Encoder};
|
||||
use neqo_crypto::{
|
||||
generate_ech_keys, AllowZeroRtt, AuthenticationStatus, ZeroRttCheckResult, ZeroRttChecker,
|
||||
};
|
||||
use neqo_crypto::{generate_ech_keys, AllowZeroRtt, ZeroRttCheckResult, ZeroRttChecker};
|
||||
use neqo_transport::{
|
||||
server::{ActiveConnectionRef, Server, ValidateAddress},
|
||||
Connection, ConnectionError, ConnectionParameters, Error, Output, State, StreamType, Version,
|
||||
Connection, ConnectionError, ConnectionParameters, Error, Output, QuicVersion, State,
|
||||
StreamType,
|
||||
};
|
||||
use test_fixture::{
|
||||
self, assertions, default_client, new_client, now, split_datagram,
|
||||
CountingConnectionIdGenerator,
|
||||
self, assertions, default_client, now, split_datagram, CountingConnectionIdGenerator,
|
||||
};
|
||||
|
||||
use std::cell::RefCell;
|
||||
@ -69,70 +66,6 @@ fn single_client() {
|
||||
connect(&mut client, &mut server);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn connect_single_version_both() {
|
||||
fn connect_one_version(version: Version) {
|
||||
let params = ConnectionParameters::default().versions(version, vec![version]);
|
||||
let mut server = new_server(params.clone());
|
||||
|
||||
let mut client = new_client(params);
|
||||
let server_conn = connect(&mut client, &mut server);
|
||||
assert_eq!(client.version(), version);
|
||||
assert_eq!(server_conn.borrow().version(), version);
|
||||
}
|
||||
|
||||
for v in Version::all() {
|
||||
println!("Connecting with {:?}", v);
|
||||
connect_one_version(v);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn connect_single_version_client() {
|
||||
fn connect_one_version(version: Version) {
|
||||
let mut server = default_server();
|
||||
|
||||
let mut client =
|
||||
new_client(ConnectionParameters::default().versions(version, vec![version]));
|
||||
let server_conn = connect(&mut client, &mut server);
|
||||
assert_eq!(client.version(), version);
|
||||
assert_eq!(server_conn.borrow().version(), version);
|
||||
}
|
||||
|
||||
for v in Version::all() {
|
||||
println!("Connecting with {:?}", v);
|
||||
connect_one_version(v);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn connect_single_version_server() {
|
||||
fn connect_one_version(version: Version) {
|
||||
let mut server =
|
||||
new_server(ConnectionParameters::default().versions(version, vec![version]));
|
||||
|
||||
let mut client = default_client();
|
||||
|
||||
if client.version() != version {
|
||||
// Run the version negotiation exchange if necessary.
|
||||
let dgram = client.process_output(now()).dgram();
|
||||
assert!(dgram.is_some());
|
||||
let dgram = server.process(dgram, now()).dgram();
|
||||
assertions::assert_vn(dgram.as_ref().unwrap());
|
||||
client.process_input(dgram.unwrap(), now());
|
||||
}
|
||||
|
||||
let server_conn = connect(&mut client, &mut server);
|
||||
assert_eq!(client.version(), version);
|
||||
assert_eq!(server_conn.borrow().version(), version);
|
||||
}
|
||||
|
||||
for v in Version::all() {
|
||||
println!("Connecting with {:?}", v);
|
||||
connect_one_version(v);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duplicate_initial() {
|
||||
let mut server = default_server();
|
||||
@ -231,7 +164,7 @@ fn drop_non_initial() {
|
||||
let mut header = neqo_common::Encoder::with_capacity(1200);
|
||||
header
|
||||
.encode_byte(0xfa)
|
||||
.encode_uint(4, Version::default().wire_version())
|
||||
.encode_uint(4, QuicVersion::default().as_u32())
|
||||
.encode_vec(1, CID)
|
||||
.encode_vec(1, CID);
|
||||
let mut bogus_data: Vec<u8> = header.into();
|
||||
@ -250,7 +183,7 @@ fn drop_short_initial() {
|
||||
let mut header = neqo_common::Encoder::with_capacity(1199);
|
||||
header
|
||||
.encode_byte(0xca)
|
||||
.encode_uint(4, Version::default().wire_version())
|
||||
.encode_uint(4, QuicVersion::default().as_u32())
|
||||
.encode_vec(1, CID)
|
||||
.encode_vec(1, CID);
|
||||
let mut bogus_data: Vec<u8> = header.into();
|
||||
@ -267,7 +200,7 @@ fn drop_short_initial() {
|
||||
#[test]
|
||||
fn zero_rtt() {
|
||||
let mut server = default_server();
|
||||
let token = generate_ticket(&mut server);
|
||||
let token = get_ticket(&mut server);
|
||||
|
||||
// Discharge the old connection so that we don't have to worry about it.
|
||||
let mut now = now();
|
||||
@ -329,7 +262,7 @@ fn zero_rtt() {
|
||||
#[test]
|
||||
fn new_token_0rtt() {
|
||||
let mut server = default_server();
|
||||
let token = generate_ticket(&mut server);
|
||||
let token = get_ticket(&mut server);
|
||||
server.set_validation(ValidateAddress::NoToken);
|
||||
|
||||
let mut client = default_client();
|
||||
@ -360,7 +293,7 @@ fn new_token_0rtt() {
|
||||
#[test]
|
||||
fn new_token_different_port() {
|
||||
let mut server = default_server();
|
||||
let token = generate_ticket(&mut server);
|
||||
let token = get_ticket(&mut server);
|
||||
server.set_validation(ValidateAddress::NoToken);
|
||||
|
||||
let mut client = default_client();
|
||||
@ -402,20 +335,20 @@ fn bad_client_initial() {
|
||||
let mut header_enc = Encoder::new();
|
||||
header_enc
|
||||
.encode_byte(0xc0) // Initial with 1 byte packet number.
|
||||
.encode_uint(4, Version::default().wire_version())
|
||||
.encode_uint(4, QuicVersion::default().as_u32())
|
||||
.encode_vec(1, d_cid)
|
||||
.encode_vec(1, s_cid)
|
||||
.encode_vvec(&[])
|
||||
.encode_varint(u64::try_from(payload_enc.len() + aead.expansion() + 1).unwrap())
|
||||
.encode_byte(u8::try_from(pn).unwrap());
|
||||
|
||||
let mut ciphertext = header_enc.as_ref().to_vec();
|
||||
let mut ciphertext = header_enc.to_vec();
|
||||
ciphertext.resize(header_enc.len() + payload_enc.len() + aead.expansion(), 0);
|
||||
let v = aead
|
||||
.encrypt(
|
||||
pn,
|
||||
header_enc.as_ref(),
|
||||
payload_enc.as_ref(),
|
||||
&header_enc,
|
||||
&payload_enc,
|
||||
&mut ciphertext[header_enc.len()..],
|
||||
)
|
||||
.unwrap();
|
||||
@ -468,7 +401,7 @@ fn bad_client_initial() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn version_negotiation_ignored() {
|
||||
fn version_negotiation() {
|
||||
let mut server = default_server();
|
||||
let mut client = default_client();
|
||||
|
||||
@ -493,7 +426,7 @@ fn version_negotiation_ignored() {
|
||||
let mut found = false;
|
||||
while dec.remaining() > 0 {
|
||||
let v = dec.decode_uint(4).expect("supported version");
|
||||
found |= v == u64::from(Version::default().wire_version());
|
||||
found |= v == u64::from(QuicVersion::default().as_u32());
|
||||
}
|
||||
assert!(found, "valid version not found");
|
||||
|
||||
@ -503,128 +436,6 @@ fn version_negotiation_ignored() {
|
||||
assert_eq!(client.state(), &State::WaitInitial);
|
||||
}
|
||||
|
||||
/// Test that if the server doesn't support a version it will signal with a
|
||||
/// Version Negotiation packet and the client will use that version.
|
||||
#[test]
|
||||
fn version_negotiation() {
|
||||
const VN_VERSION: Version = Version::Draft29;
|
||||
assert_ne!(VN_VERSION, Version::default());
|
||||
assert!(!Version::default().is_compatible(VN_VERSION));
|
||||
|
||||
let mut server =
|
||||
new_server(ConnectionParameters::default().versions(VN_VERSION, vec![VN_VERSION]));
|
||||
let mut client = default_client();
|
||||
|
||||
// `connect()` runs a fixed exchange, so manually run the Version Negotiation.
|
||||
let dgram = client.process_output(now()).dgram();
|
||||
assert!(dgram.is_some());
|
||||
let dgram = server.process(dgram, now()).dgram();
|
||||
assertions::assert_vn(dgram.as_ref().unwrap());
|
||||
client.process_input(dgram.unwrap(), now());
|
||||
|
||||
let sconn = connect(&mut client, &mut server);
|
||||
assert_eq!(client.version(), VN_VERSION);
|
||||
assert_eq!(sconn.borrow().version(), VN_VERSION);
|
||||
}
|
||||
|
||||
/// Test that the client can pick a version from a Version Negotiation packet,
|
||||
/// which is then subsequently upgraded to a compatible version by the server.
|
||||
#[test]
|
||||
fn version_negotiation_and_compatible() {
|
||||
const ORIG_VERSION: Version = Version::Draft29;
|
||||
const VN_VERSION: Version = Version::Version1;
|
||||
const COMPAT_VERSION: Version = Version::Version2;
|
||||
assert!(!ORIG_VERSION.is_compatible(VN_VERSION));
|
||||
assert!(!ORIG_VERSION.is_compatible(COMPAT_VERSION));
|
||||
assert!(VN_VERSION.is_compatible(COMPAT_VERSION));
|
||||
|
||||
let mut server = new_server(
|
||||
ConnectionParameters::default().versions(VN_VERSION, vec![COMPAT_VERSION, VN_VERSION]),
|
||||
);
|
||||
// Note that the order of versions at the client only determines what it tries first.
|
||||
// The server will pick between VN_VERSION and COMPAT_VERSION.
|
||||
let mut client = new_client(
|
||||
ConnectionParameters::default()
|
||||
.versions(ORIG_VERSION, vec![ORIG_VERSION, VN_VERSION, COMPAT_VERSION]),
|
||||
);
|
||||
|
||||
// Run the full exchange so that we can observe the versions in use.
|
||||
|
||||
// Version Negotiation
|
||||
let dgram = client.process_output(now()).dgram();
|
||||
assert!(dgram.is_some());
|
||||
assertions::assert_version(dgram.as_ref().unwrap(), ORIG_VERSION.wire_version());
|
||||
let dgram = server.process(dgram, now()).dgram();
|
||||
assertions::assert_vn(dgram.as_ref().unwrap());
|
||||
client.process_input(dgram.unwrap(), now());
|
||||
|
||||
let dgram = client.process(None, now()).dgram(); // ClientHello
|
||||
assertions::assert_version(dgram.as_ref().unwrap(), VN_VERSION.wire_version());
|
||||
let dgram = server.process(dgram, now()).dgram(); // ServerHello...
|
||||
assertions::assert_version(dgram.as_ref().unwrap(), COMPAT_VERSION.wire_version());
|
||||
client.process_input(dgram.unwrap(), now());
|
||||
|
||||
client.authenticated(AuthenticationStatus::Ok, now());
|
||||
let dgram = client.process_output(now()).dgram();
|
||||
assertions::assert_version(dgram.as_ref().unwrap(), COMPAT_VERSION.wire_version());
|
||||
assert_eq!(*client.state(), State::Connected);
|
||||
let dgram = server.process(dgram, now()).dgram(); // ACK + HANDSHAKE_DONE + NST
|
||||
client.process_input(dgram.unwrap(), now());
|
||||
assert_eq!(*client.state(), State::Confirmed);
|
||||
|
||||
let sconn = connected_server(&mut server);
|
||||
assert_eq!(client.version(), COMPAT_VERSION);
|
||||
assert_eq!(sconn.borrow().version(), COMPAT_VERSION);
|
||||
}
|
||||
|
||||
/// When a client resumes it remembers the version that the connection last used.
|
||||
/// A subsequent connection will use that version, but if it then receives
|
||||
/// a version negotiation packet, it should validate based on what it attempted
|
||||
/// not what it was originally configured for.
|
||||
#[test]
|
||||
fn compatible_upgrade_resumption_and_vn() {
|
||||
// Start at v1, compatible upgrade to v2.
|
||||
const ORIG_VERSION: Version = Version::Version1;
|
||||
const COMPAT_VERSION: Version = Version::Version2;
|
||||
const RESUMPTION_VERSION: Version = Version::Draft29;
|
||||
|
||||
let client_params = ConnectionParameters::default().versions(
|
||||
ORIG_VERSION,
|
||||
vec![COMPAT_VERSION, ORIG_VERSION, RESUMPTION_VERSION],
|
||||
);
|
||||
let mut client = new_client(client_params.clone());
|
||||
assert_eq!(client.version(), ORIG_VERSION);
|
||||
|
||||
let mut server = default_server();
|
||||
let mut server_conn = connect(&mut client, &mut server);
|
||||
assert_eq!(client.version(), COMPAT_VERSION);
|
||||
assert_eq!(server_conn.borrow().version(), COMPAT_VERSION);
|
||||
|
||||
server_conn.borrow_mut().send_ticket(now(), &[]).unwrap();
|
||||
let dgram = server.process(None, now()).dgram();
|
||||
client.process_input(dgram.unwrap(), now()); // Consume ticket, ignore output.
|
||||
let ticket = find_ticket(&mut client);
|
||||
|
||||
// This new server will reject the ticket, but it will also generate a VN packet.
|
||||
let mut client = new_client(client_params);
|
||||
let mut server = new_server(
|
||||
ConnectionParameters::default().versions(RESUMPTION_VERSION, vec![RESUMPTION_VERSION]),
|
||||
);
|
||||
client.enable_resumption(now(), ticket).unwrap();
|
||||
|
||||
// The version negotiation exchange.
|
||||
let dgram = client.process_output(now()).dgram();
|
||||
assert!(dgram.is_some());
|
||||
assertions::assert_version(dgram.as_ref().unwrap(), COMPAT_VERSION.wire_version());
|
||||
let dgram = server.process(dgram, now()).dgram();
|
||||
assertions::assert_vn(dgram.as_ref().unwrap());
|
||||
client.process_input(dgram.unwrap(), now());
|
||||
|
||||
let server_conn = connect(&mut client, &mut server);
|
||||
assert_eq!(client.version(), RESUMPTION_VERSION);
|
||||
assert_eq!(server_conn.borrow().version(), RESUMPTION_VERSION);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn closed() {
|
||||
// Let a server connection idle and it should be removed.
|
||||
@ -722,7 +533,7 @@ fn max_streams_after_0rtt_rejection() {
|
||||
.max_streams(StreamType::UniDi, MAX_STREAMS_UNIDI),
|
||||
)
|
||||
.expect("should create a server");
|
||||
let token = generate_ticket(&mut server);
|
||||
let token = get_ticket(&mut server);
|
||||
|
||||
let mut client = default_client();
|
||||
client.enable_resumption(now(), &token).unwrap();
|
||||
|
@ -149,7 +149,7 @@ impl Simulator {
|
||||
/// Though this is convenient, it panics if this isn't a 64 character hex string.
|
||||
pub fn seed_str(&mut self, seed: impl AsRef<str>) {
|
||||
let seed = Encoder::from_hex(seed);
|
||||
self.seed(<[u8; 32]>::try_from(seed.as_ref()).unwrap());
|
||||
self.seed(<[u8; 32]>::try_from(&seed[..]).unwrap());
|
||||
}
|
||||
|
||||
fn next_time(&self, now: Instant) -> Instant {
|
||||
|
Loading…
x
Reference in New Issue
Block a user