Bug 1882863 - Neqo v0.7.2, r=necko-reviewers,valentin

Differential Revision: https://phabricator.services.mozilla.com/D204488
This commit is contained in:
Kershaw Chang 2024-03-13 16:18:45 +00:00
parent 7ebfa77507
commit 16a0b5bd72
136 changed files with 1275 additions and 744 deletions

View file

@ -85,9 +85,9 @@ git = "https://github.com/mozilla/mp4parse-rust"
rev = "a138e40ec1c603615873e524b5b22e11c0ec4820"
replace-with = "vendored-sources"
[source."git+https://github.com/mozilla/neqo?tag=v0.7.1"]
[source."git+https://github.com/mozilla/neqo?tag=v0.7.2"]
git = "https://github.com/mozilla/neqo"
tag = "v0.7.1"
tag = "v0.7.2"
replace-with = "vendored-sources"
[source."git+https://github.com/mozilla/uniffi-rs.git?rev=afb29ebdc1d9edf15021b1c5332fc9f285bbe13b"]

20
Cargo.lock generated
View file

@ -3880,8 +3880,8 @@ dependencies = [
[[package]]
name = "neqo-common"
version = "0.7.1"
source = "git+https://github.com/mozilla/neqo?tag=v0.7.1#721a1eff430f644e23a3e06ef4c5a248a0cbf592"
version = "0.7.2"
source = "git+https://github.com/mozilla/neqo?tag=v0.7.2#ce5cbe4dfc2e38b238abb022c39eee4215058221"
dependencies = [
"enum-map",
"env_logger",
@ -3893,8 +3893,8 @@ dependencies = [
[[package]]
name = "neqo-crypto"
version = "0.7.1"
source = "git+https://github.com/mozilla/neqo?tag=v0.7.1#721a1eff430f644e23a3e06ef4c5a248a0cbf592"
version = "0.7.2"
source = "git+https://github.com/mozilla/neqo?tag=v0.7.2#ce5cbe4dfc2e38b238abb022c39eee4215058221"
dependencies = [
"bindgen 0.69.4",
"log",
@ -3907,8 +3907,8 @@ dependencies = [
[[package]]
name = "neqo-http3"
version = "0.7.1"
source = "git+https://github.com/mozilla/neqo?tag=v0.7.1#721a1eff430f644e23a3e06ef4c5a248a0cbf592"
version = "0.7.2"
source = "git+https://github.com/mozilla/neqo?tag=v0.7.2#ce5cbe4dfc2e38b238abb022c39eee4215058221"
dependencies = [
"enumset",
"log",
@ -3924,8 +3924,8 @@ dependencies = [
[[package]]
name = "neqo-qpack"
version = "0.7.1"
source = "git+https://github.com/mozilla/neqo?tag=v0.7.1#721a1eff430f644e23a3e06ef4c5a248a0cbf592"
version = "0.7.2"
source = "git+https://github.com/mozilla/neqo?tag=v0.7.2#ce5cbe4dfc2e38b238abb022c39eee4215058221"
dependencies = [
"log",
"neqo-common",
@ -3937,8 +3937,8 @@ dependencies = [
[[package]]
name = "neqo-transport"
version = "0.7.1"
source = "git+https://github.com/mozilla/neqo?tag=v0.7.1#721a1eff430f644e23a3e06ef4c5a248a0cbf592"
version = "0.7.2"
source = "git+https://github.com/mozilla/neqo?tag=v0.7.2#ce5cbe4dfc2e38b238abb022c39eee4215058221"
dependencies = [
"indexmap 1.9.3",
"log",

View file

@ -9,10 +9,10 @@ license = "MPL-2.0"
name = "neqo_glue"
[dependencies]
neqo-http3 = { tag = "v0.7.1", git = "https://github.com/mozilla/neqo" }
neqo-transport = { tag = "v0.7.1", git = "https://github.com/mozilla/neqo" }
neqo-common = { tag = "v0.7.1", git = "https://github.com/mozilla/neqo" }
neqo-qpack = { tag = "v0.7.1", git = "https://github.com/mozilla/neqo" }
neqo-http3 = { tag = "v0.7.2", git = "https://github.com/mozilla/neqo" }
neqo-transport = { tag = "v0.7.2", git = "https://github.com/mozilla/neqo" }
neqo-common = { tag = "v0.7.2", git = "https://github.com/mozilla/neqo" }
neqo-qpack = { tag = "v0.7.2", git = "https://github.com/mozilla/neqo" }
nserror = { path = "../../../xpcom/rust/nserror" }
nsstring = { path = "../../../xpcom/rust/nsstring" }
xpcom = { path = "../../../xpcom/rust/xpcom" }
@ -27,7 +27,7 @@ uuid = { version = "1.0", features = ["v4"] }
winapi = {version = "0.3", features = ["ws2def"] }
[dependencies.neqo-crypto]
tag = "v0.7.1"
tag = "v0.7.2"
git = "https://github.com/mozilla/neqo"
default-features = false
features = ["gecko"]

View file

@ -6,10 +6,10 @@ edition = "2018"
license = "MPL-2.0"
[dependencies]
neqo-transport = { tag = "v0.7.1", git = "https://github.com/mozilla/neqo" }
neqo-common = { tag = "v0.7.1", git = "https://github.com/mozilla/neqo" }
neqo-http3 = { tag = "v0.7.1", git = "https://github.com/mozilla/neqo" }
neqo-qpack = { tag = "v0.7.1", git = "https://github.com/mozilla/neqo" }
neqo-transport = { tag = "v0.7.2", git = "https://github.com/mozilla/neqo" }
neqo-common = { tag = "v0.7.2", git = "https://github.com/mozilla/neqo" }
neqo-http3 = { tag = "v0.7.2", git = "https://github.com/mozilla/neqo" }
neqo-qpack = { tag = "v0.7.2", git = "https://github.com/mozilla/neqo" }
mio = "0.6.17"
mio-extras = "2.0.5"
log = "0.4.0"
@ -21,7 +21,7 @@ tokio = { version = "1", features = ["rt-multi-thread"] }
mozilla-central-workspace-hack = { version = "0.1", features = ["http3server"], optional = true }
[dependencies.neqo-crypto]
tag = "v0.7.1"
tag = "v0.7.2"
git = "https://github.com/mozilla/neqo"
default-features = false
features = ["gecko"]

View file

@ -735,6 +735,7 @@ run-sequentially = "http3server"
skip-if = [
"os == 'android'",
"os == 'win' && msix", # https://bugzilla.mozilla.org/show_bug.cgi?id=1807931
"true", # Will be reenabled in bug 1865394
]
run-sequentially = "http3server"

View file

@ -153,6 +153,7 @@ run-sequentially = "http3server"
skip-if = [
"os == 'android'",
"os == 'win' && msix",
"true", # Will be reenabled in bug 1865394
] # https://bugzilla.mozilla.org/show_bug.cgi?id=1807925
run-sequentially = "http3server"

View file

@ -1 +1 @@
{"files":{"Cargo.toml":"a5d8880c97023af584bb1116bf480ff957395e4e744c97aa52051b60b0bc5f80","build.rs":"a17b1bb1bd3de3fc958f72d4d1357f7bc4432faa26640c95b5fbfccf40579d67","src/codec.rs":"c652182a23ada920e55d6c73c5ede3ed3d01696db0b1826136585cfa926370b4","src/datagram.rs":"1a7028d96a2e7385e94265de53189eb824b7cf12e0e2de5d67c3f3f8751b6043","src/event.rs":"4ef9e6f3f5168f2eacb7be982e062e743c64a64e809765d2139122839aa407e5","src/header.rs":"467b947f78bfe354d8bb51e8df0c2be69e75a45e2be688d81f0d268aa77c89ef","src/hrtime.rs":"d7c8849e9ec7a312878ea2bc28939717fa03969fb9aee259a4a516351ee37643","src/incrdecoder.rs":"577c32b9ace51f2daaf940be6d0c391c4f55cd42ef6848c68c1ffc970d8c57b5","src/lib.rs":"47c14084c6d475ebb855f3ed9302b31fa42780b93a816bf098c96987ffe33572","src/log.rs":"8b8e12f4317892fd130c6d021a00d5125c535dea4c1b2c94c1a48d6a65b3aa84","src/qlog.rs":"3f43dc4e5fdccb9d6ee74d9e7b3ff29da63e4eb9f631e4e35446e452d8ec7af6","src/timer.rs":"d5d0e1ae7cc96f06fb2a8a53ef9236e11c4e1b0be2e9312f16c64e48c76acad2","src/tos.rs":"5b5a61c699266716afce2f5bda7c98151db3223ede41ce451c390863198e30a2","tests/log.rs":"480b165b7907ec642c508b303d63005eee1427115d6973a349eaf6b2242ed18d"},"package":null}
{"files":{"Cargo.toml":"b49758e5e8f0a6955d761e689be39530f193f7089de07f2295a7a3aef4df5898","build.rs":"306b2f909a25ae38daf5404a4e128d2a94e8975b70870864c2a71cafec9717c7","src/codec.rs":"fd239f75d374db6ff744211344c82bcd19ecf753e07410e1fe37732bbb81dfe9","src/datagram.rs":"f2ff56faa0e513edbf4331b6ee2c9e6d6111483bda7aff08d16b9f05bce5c320","src/event.rs":"106ca6c4afb107fa49a1bc72f5eb4ae95f4baa1ba19736aa38c8ba973774c160","src/header.rs":"467b947f78bfe354d8bb51e8df0c2be69e75a45e2be688d81f0d268aa77c89ef","src/hrtime.rs":"112dc758e65301b8a7a508b125d3d61063180d432bffaec566a050d4f907ab18","src/incrdecoder.rs":"577c32b9ace51f2daaf940be6d0c391c4f55cd42ef6848c68c1ffc970d8c57b5","src/lib.rs":"a86aae69900933bf83044fa96166ee51216277415eafcdb15c04a907bb2dd10e","src/log.rs":"7246053bffd704b264d42fc82f986b9d62079472a76a9fc3749c25cfc7698532","src/qlog.rs":"9b081f32bf158fd340300693acc97fe0554b617ae664eba86e4d3572e2b1e16e","src/timer.rs":"350a730cc5a159dfdac5d78ec8e8a34c5172a476d827a566703edec24c791842","src/tos.rs":"440616cb0aee9082abe00623b33e68dbe80eda47aec889ac5f4145b1566bf692","src/udp.rs":"2b92132e078791e35b66f68d99d79ff5df55efd03e788474f7781a00403a5533","tests/log.rs":"a11e21fb570258ca93bb40e3923817d381e1e605accbc3aed1df5a0a9918b41d"},"package":null}

View file

@ -10,19 +10,22 @@
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
edition = "2021"
rust-version = "1.74.0"
name = "neqo-common"
version = "0.7.1"
version = "0.7.2"
authors = ["The Neqo Authors <necko@mozilla.com>"]
build = "build.rs"
homepage = "https://github.com/mozilla/neqo/"
license = "MIT OR Apache-2.0"
repository = "https://github.com/mozilla/neqo/"
[dependencies]
enum-map = "2.7"
qlog = "0.12"
[lib]
bench = false
[dependencies.enum-map]
version = "2.7"
default-features = false
[dependencies.env_logger]
version = "0.10"
@ -32,17 +35,46 @@ default-features = false
version = "0.4"
default-features = false
[dependencies.qlog]
version = "0.12"
default-features = false
[dependencies.quinn-udp]
git = "https://github.com/quinn-rs/quinn/"
rev = "a947962131aba8a6521253d03cc948b20098a2d6"
optional = true
[dependencies.time]
version = "0.3"
features = ["formatting"]
default-features = false
[dependencies.tokio]
version = "1"
features = [
"net",
"time",
"macros",
"rt",
"rt-multi-thread",
]
optional = true
default-features = false
[dev-dependencies.test-fixture]
path = "../test-fixture"
[features]
ci = []
deny-warnings = []
udp = [
"dep:quinn-udp",
"dep:tokio",
]
[target."cfg(windows)".dependencies.winapi]
version = "0.3"
features = ["timeapi"]
[lints.clippy.pedantic]
level = "warn"
priority = -1

View file

@ -1,3 +1,9 @@
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::env;
fn main() {

View file

@ -4,7 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{convert::TryFrom, fmt::Debug};
use std::fmt::Debug;
use crate::hex_with_len;

View file

@ -53,6 +53,12 @@ impl Datagram {
pub fn ttl(&self) -> Option<u8> {
self.ttl
}
#[cfg(feature = "udp")]
#[must_use]
pub(crate) fn into_data(self) -> Vec<u8> {
self.d
}
}
impl Deref for Datagram {

View file

@ -4,7 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{iter::Iterator, marker::PhantomData};
use std::marker::PhantomData;
/// An event provider is able to generate a stream of events.
pub trait Provider {

View file

@ -6,7 +6,6 @@
use std::{
cell::RefCell,
convert::TryFrom,
rc::{Rc, Weak},
time::Duration,
};
@ -340,9 +339,7 @@ impl Time {
/// The handle can also be used to update the resolution.
#[must_use]
pub fn get(period: Duration) -> Handle {
thread_local! {
static HR_TIME: RefCell<Weak<RefCell<Time>>> = RefCell::default();
}
thread_local!(static HR_TIME: RefCell<Weak<RefCell<Time>>> = RefCell::default());
HR_TIME.with(|r| {
let mut b = r.borrow_mut();

View file

@ -4,8 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions)] // This lint doesn't work here.
mod codec;
mod datagram;
@ -17,6 +16,8 @@ pub mod log;
pub mod qlog;
pub mod timer;
pub mod tos;
#[cfg(feature = "udp")]
pub mod udp;
use std::fmt::Write;

View file

@ -18,7 +18,7 @@ use env_logger::Builder;
macro_rules! do_log {
(target: $target:expr, $lvl:expr, $($arg:tt)+) => ({
let lvl = $lvl;
if lvl <= ::log::max_level() {
if lvl <= ::log::STATIC_MAX_LEVEL && lvl <= ::log::max_level() {
::log::logger().log(
&::log::Record::builder()
.args(format_args!($($arg)+))
@ -52,6 +52,11 @@ fn since_start() -> Duration {
pub fn init() {
static INIT_ONCE: Once = Once::new();
if ::log::STATIC_MAX_LEVEL == ::log::LevelFilter::Off {
return;
}
INIT_ONCE.call_once(|| {
let mut builder = Builder::from_env("RUST_LOG");
builder.format(|buf, record| {

View file

@ -12,8 +12,7 @@ use std::{
};
use qlog::{
self, streamer::QlogStreamer, CommonFields, Configuration, TraceSeq, VantagePoint,
VantagePointType,
streamer::QlogStreamer, CommonFields, Configuration, TraceSeq, VantagePoint, VantagePointType,
};
use crate::Role;

View file

@ -5,7 +5,6 @@
// except according to those terms.
use std::{
convert::TryFrom,
mem,
time::{Duration, Instant},
};

View file

@ -46,6 +46,12 @@ impl From<u8> for IpTosEcn {
}
}
impl From<IpTos> for IpTosEcn {
fn from(value: IpTos) -> Self {
IpTosEcn::from(value.0 & 0x3)
}
}
/// Diffserv Codepoints, mapped to the upper six bits of the TOS field.
/// <https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml>
#[derive(Copy, Clone, PartialEq, Eq, Enum, Default, Debug)]
@ -159,6 +165,12 @@ impl From<u8> for IpTosDscp {
}
}
impl From<IpTos> for IpTosDscp {
fn from(value: IpTos) -> Self {
IpTosDscp::from(value.0 & 0xfc)
}
}
/// The type-of-service field in an IP packet.
#[allow(clippy::module_name_repetitions)]
#[derive(Copy, Clone, PartialEq, Eq)]
@ -169,22 +181,37 @@ impl From<IpTosEcn> for IpTos {
Self(u8::from(v))
}
}
impl From<IpTosDscp> for IpTos {
fn from(v: IpTosDscp) -> Self {
Self(u8::from(v))
}
}
impl From<(IpTosDscp, IpTosEcn)> for IpTos {
fn from(v: (IpTosDscp, IpTosEcn)) -> Self {
Self(u8::from(v.0) | u8::from(v.1))
}
}
impl From<(IpTosEcn, IpTosDscp)> for IpTos {
fn from(v: (IpTosEcn, IpTosDscp)) -> Self {
Self(u8::from(v.0) | u8::from(v.1))
}
}
impl From<IpTos> for u8 {
fn from(v: IpTos) -> Self {
v.0
}
}
impl From<u8> for IpTos {
fn from(v: u8) -> Self {
Self(v)
}
}
impl Debug for IpTos {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("IpTos")
@ -202,7 +229,7 @@ impl Default for IpTos {
#[cfg(test)]
mod tests {
use super::*;
use crate::{IpTos, IpTosDscp, IpTosEcn};
#[test]
fn iptosecn_into_u8() {
@ -287,4 +314,12 @@ mod tests {
let iptos_dscp: IpTos = dscp.into();
assert_eq!(u8::from(iptos_dscp), dscp as u8);
}
#[test]
fn u8_to_iptos() {
let tos = 0x8b;
let iptos: IpTos = (IpTosEcn::Ce, IpTosDscp::Af41).into();
assert_eq!(tos, u8::from(iptos));
assert_eq!(IpTos::from(tos), iptos);
}
}

222
third_party/rust/neqo-common/src/udp.rs vendored Normal file
View file

@ -0,0 +1,222 @@
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(clippy::missing_errors_doc)] // Functions simply delegate to tokio and quinn-udp.
#![allow(clippy::missing_panics_doc)] // Functions simply delegate to tokio and quinn-udp.
use std::{
io::{self, IoSliceMut},
net::{SocketAddr, ToSocketAddrs},
slice,
};
use quinn_udp::{EcnCodepoint, RecvMeta, Transmit, UdpSocketState};
use tokio::io::Interest;
use crate::{Datagram, IpTos};
/// Socket receive buffer size.
///
/// Allows reading multiple datagrams in a single [`Socket::recv`] call.
const RECV_BUF_SIZE: usize = u16::MAX as usize;
pub struct Socket {
socket: tokio::net::UdpSocket,
state: UdpSocketState,
recv_buf: Vec<u8>,
}
impl Socket {
/// Calls [`std::net::UdpSocket::bind`] and instantiates [`quinn_udp::UdpSocketState`].
pub fn bind<A: ToSocketAddrs>(addr: A) -> Result<Self, io::Error> {
let socket = std::net::UdpSocket::bind(addr)?;
Ok(Self {
state: quinn_udp::UdpSocketState::new((&socket).into())?,
socket: tokio::net::UdpSocket::from_std(socket)?,
recv_buf: vec![0; RECV_BUF_SIZE],
})
}
/// See [`tokio::net::UdpSocket::local_addr`].
pub fn local_addr(&self) -> io::Result<SocketAddr> {
self.socket.local_addr()
}
/// See [`tokio::net::UdpSocket::writable`].
pub async fn writable(&self) -> Result<(), io::Error> {
self.socket.writable().await
}
/// See [`tokio::net::UdpSocket::readable`].
pub async fn readable(&self) -> Result<(), io::Error> {
self.socket.readable().await
}
/// Send the UDP datagram on the specified socket.
pub fn send(&self, d: Datagram) -> io::Result<usize> {
let transmit = Transmit {
destination: d.destination(),
ecn: EcnCodepoint::from_bits(Into::<u8>::into(d.tos())),
contents: d.into_data().into(),
segment_size: None,
src_ip: None,
};
let n = self.socket.try_io(Interest::WRITABLE, || {
self.state
.send((&self.socket).into(), slice::from_ref(&transmit))
})?;
assert_eq!(n, 1, "only passed one slice");
Ok(n)
}
/// Receive a UDP datagram on the specified socket.
pub fn recv(&mut self, local_address: &SocketAddr) -> Result<Vec<Datagram>, io::Error> {
let mut meta = RecvMeta::default();
match self.socket.try_io(Interest::READABLE, || {
self.state.recv(
(&self.socket).into(),
&mut [IoSliceMut::new(&mut self.recv_buf)],
slice::from_mut(&mut meta),
)
}) {
Ok(n) => {
assert_eq!(n, 1, "only passed one slice");
}
Err(ref err)
if err.kind() == io::ErrorKind::WouldBlock
|| err.kind() == io::ErrorKind::Interrupted =>
{
return Ok(vec![])
}
Err(err) => {
return Err(err);
}
};
if meta.len == 0 {
eprintln!("zero length datagram received?");
return Ok(vec![]);
}
if meta.len == self.recv_buf.len() {
eprintln!(
"Might have received more than {} bytes",
self.recv_buf.len()
);
}
Ok(self.recv_buf[0..meta.len]
.chunks(meta.stride.min(self.recv_buf.len()))
.map(|d| {
Datagram::new(
meta.addr,
*local_address,
meta.ecn.map(|n| IpTos::from(n as u8)).unwrap_or_default(),
None, // TODO: get the real TTL https://github.com/quinn-rs/quinn/issues/1749
d,
)
})
.collect())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{IpTosDscp, IpTosEcn};
#[tokio::test]
async fn datagram_tos() -> Result<(), io::Error> {
let sender = Socket::bind("127.0.0.1:0")?;
let receiver_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let mut receiver = Socket::bind(receiver_addr)?;
let datagram = Datagram::new(
sender.local_addr()?,
receiver.local_addr()?,
IpTos::from((IpTosDscp::Le, IpTosEcn::Ect1)),
None,
"Hello, world!".as_bytes().to_vec(),
);
sender.writable().await?;
sender.send(datagram.clone())?;
receiver.readable().await?;
let received_datagram = receiver
.recv(&receiver_addr)
.expect("receive to succeed")
.into_iter()
.next()
.expect("receive to yield datagram");
// Assert that the ECN is correct.
assert_eq!(
IpTosEcn::from(datagram.tos()),
IpTosEcn::from(received_datagram.tos())
);
Ok(())
}
/// Expect [`Socket::recv`] to handle multiple [`Datagram`]s on GRO read.
#[tokio::test]
#[cfg_attr(not(any(target_os = "linux", target_os = "windows")), ignore)]
async fn many_datagrams_through_gro() -> Result<(), io::Error> {
const SEGMENT_SIZE: usize = 128;
let sender = Socket::bind("127.0.0.1:0")?;
let receiver_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let mut receiver = Socket::bind(receiver_addr)?;
// `neqo_common::udp::Socket::send` does not yet
// (https://github.com/mozilla/neqo/issues/1693) support GSO. Use
// `quinn_udp` directly.
let max_gso_segments = sender.state.max_gso_segments();
let msg = vec![0xAB; SEGMENT_SIZE * max_gso_segments];
let transmit = Transmit {
destination: receiver.local_addr()?,
ecn: EcnCodepoint::from_bits(Into::<u8>::into(IpTos::from((
IpTosDscp::Le,
IpTosEcn::Ect1,
)))),
contents: msg.clone().into(),
segment_size: Some(SEGMENT_SIZE),
src_ip: None,
};
sender.writable().await?;
let n = sender.socket.try_io(Interest::WRITABLE, || {
sender
.state
.send((&sender.socket).into(), slice::from_ref(&transmit))
})?;
assert_eq!(n, 1, "only passed one slice");
// Allow for one GSO sendmmsg to result in multiple GRO recvmmsg.
let mut num_received = 0;
while num_received < max_gso_segments {
receiver.readable().await?;
receiver
.recv(&receiver_addr)
.expect("receive to succeed")
.into_iter()
.for_each(|d| {
assert_eq!(
SEGMENT_SIZE,
d.len(),
"Expect received datagrams to have same length as sent datagrams."
);
num_received += 1;
});
}
Ok(())
}
}

View file

@ -4,9 +4,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(clippy::use_self)]
use neqo_common::{qdebug, qerror, qinfo, qtrace, qwarn};
#[test]

View file

@ -1 +1 @@
{"files":{"Cargo.toml":"780c81b4f5abd5d90126084127f22b61fb82773c175db6f3c4ec9d97a6a01aa2","bindings/bindings.toml":"0660c1661318b8a5094834c2f1bb12266287ef467307f66947eff7762528f70a","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":"e712c16cb830a83eb4ea1f50dd341a4c30e1cce95d8c45af97030bc8ad0ae829","src/aead.rs":"b7cda4b89298cfd122cd2e1e94c462840e966c60f4832eb441106563ac332e00","src/aead_fuzzing.rs":"c3e590572314e0bb3fafa13dac3c831358b8a7b5570fe9cfe592752fce8cbdee","src/agent.rs":"f1f570913afb6f7b2cedebd69c387e1f80eb49f48feac05f8b06108c8ff66a8a","src/agentio.rs":"34342094ce2de9bea7cfee8c61ef314e44c0f1a127a73ea22df1a7b84a9c51e4","src/auth.rs":"ced1a18f691894984244088020ea25dc1ee678603317f0c7dfc8b8842fa750b4","src/cert.rs":"ee40428e9f49ff9eacc30be499cb512e1fd846620f270bd93a97802c80a0514a","src/constants.rs":"f22bf16bd8cb539862cb1e47138dbba79e93fe738f4b907e465891326f98883c","src/ech.rs":"d43ee1df69ae0864eb38f322c5c6b1f7d7ec5f2b3a9c88be875cebdb543c29d7","src/err.rs":"fca0222167883231a5e0a569a593f44214501819adf5aadf814be27891c87c24","src/exp.rs":"cec59d61fc95914f9703d2fb6490a8507af993c9db710dde894f2f8fd38123c7","src/ext.rs":"663f56ff1f2dd471117f22005ba4663be146858ee78165d9f684eafe213cd633","src/hkdf.rs":"364d9bdd57edf0e2e1ca38b5067e0c34ac6fda53f9182b77307708477ab785f9","src/hp.rs":"0c0196f2def1b8429915c6559219414a70ff7326177aa11c127c97e2fd09152e","src/lib.rs":"61ae448c8de034eb6fd2970b81b01a573849c9c15ec739c639c90880b1bbca74","src/p11.rs":"d31464782b44b3b4be4616b1224af40e27a1e0e8a37973aaeb509902b1d71679","src/prio.rs":"e5e169296c0ac69919c59fb6c1f8bd6bf079452eaa13d75da0edd41d435d3f6f","src/replay.rs":"1ff4a12f6135ef2c42aef2b0947e26fd6241cd4b359020245608046452a7fcb0","src/result.rs":"0587cbb6aace71a7f9765ef7c01dcd9f73a49dcc6331e1d8fe4de2aef6ca65b6","src/secrets.rs":"4ffaa66f25df47dadf042063bff5953effa7bf2f4920cafe827757d6a659cb58","src/selfencrypt.rs":"ac65b13f5bade9d03ab4709364f9ec937fa4ca009965c77ca73b481534a0a470","src/ssl.rs":"c83baa5518b81dd06f2e4072ea3c2d666ccdeb8b1ff6e3746eea9f1af47023a6","src/time.rs":"9a617965cd4d926368838e7af9536030f294071c0e1dd0f1d0c4831d29d3274c","tests/aead.rs":"efdb92a060ca1957d890da1604513369559cb43195ee54149ed3ab47958dad59","tests/agent.rs":"0e55354595ae5f0e1ab83731564da57ba88a296e00692147c47df7067a0f416a","tests/ext.rs":"54657b45bd86d2561bb0f548736bc6f141bb664a5b043506f428422919ab95d4","tests/handshake.rs":"40701bc22f16d1ba9b9bd9683738e52b96faafee4119f7057437dae705f7867a","tests/hkdf.rs":"4160978b96505c1f1b7d6c4b5f43536ff7bd791c8746f9546c9fbc0fce5cf1c7","tests/hp.rs":"8eeee21a439e0f991145dff07b01283ae39ccd4b8dac4d011d43a464f73db670","tests/init.rs":"fc9e392b1efa0d8efb28952f73ffc05e5348e7b2b69207b60e375c3888a252a2","tests/selfencrypt.rs":"6edd0914b8466d79ecfb569c6d86995fd364b0dc71be2a0554e82f736ebd6b7c"},"package":null}
{"files":{"Cargo.toml":"6f1917fbd4cbf53cb4883c30e8fcb9c20f8ebe15e19576c7d37cb6ba0ab9e42b","bindings/bindings.toml":"0660c1661318b8a5094834c2f1bb12266287ef467307f66947eff7762528f70a","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":"21d9a0140b2afd708583f58f2af0a4ba93ab07ec088680b4cbf0e184aeb8785b","src/aead.rs":"8f50e4557b7829edb67f57c80c777c6ae23c868e2b2eeaaae0736af04dc0d298","src/aead_fuzzing.rs":"c3e590572314e0bb3fafa13dac3c831358b8a7b5570fe9cfe592752fce8cbdee","src/agent.rs":"e995e9cc5108470594bae1b0d4e4bc6b7a8ac2b66488f71ea99e2836c0edbd7e","src/agentio.rs":"c4cb1b3cd92ef53eb0b4fb0b34a597068d82d78ba470dae5821670a0f06c9cda","src/auth.rs":"ced1a18f691894984244088020ea25dc1ee678603317f0c7dfc8b8842fa750b4","src/cert.rs":"8942cb3ce25a61f92b6ffc30fb286052ed6f56eeda3be12fd46ea76ceba6c1cf","src/constants.rs":"f22bf16bd8cb539862cb1e47138dbba79e93fe738f4b907e465891326f98883c","src/ech.rs":"9d322fcc01c0886f1dfe9bb6273cb9f88a746452ac9a802761b1816a05930c1f","src/err.rs":"fca0222167883231a5e0a569a593f44214501819adf5aadf814be27891c87c24","src/exp.rs":"cec59d61fc95914f9703d2fb6490a8507af993c9db710dde894f2f8fd38123c7","src/ext.rs":"cbf7d9f5ecabf4b8c9efd6c334637ab1596ec5266d38ab8d2d6ceae305283deb","src/hkdf.rs":"ef32f20e30a9bd7f094199536d19c87c4231b7fbbe4a9c54c70e84ca9c6575be","src/hp.rs":"644f1bed67f1c6189a67c8d02ab3358aaa7f63af4b913dd7395becbc01a84291","src/lib.rs":"23732c7799be038c0e0835b54e7c40cf6c6536113e0adb6ae3b41b216a6e5220","src/p11.rs":"e8c366def0df470101f3d120dcc4391f74f921fe59e2f3db2a56832e2852b855","src/prio.rs":"e5e169296c0ac69919c59fb6c1f8bd6bf079452eaa13d75da0edd41d435d3f6f","src/replay.rs":"96b7af8eff9e14313e79303092018b12e8834f780c96b8e247c497fdc680c696","src/result.rs":"0587cbb6aace71a7f9765ef7c01dcd9f73a49dcc6331e1d8fe4de2aef6ca65b6","src/secrets.rs":"4ffaa66f25df47dadf042063bff5953effa7bf2f4920cafe827757d6a659cb58","src/selfencrypt.rs":"ac65b13f5bade9d03ab4709364f9ec937fa4ca009965c77ca73b481534a0a470","src/ssl.rs":"c83baa5518b81dd06f2e4072ea3c2d666ccdeb8b1ff6e3746eea9f1af47023a6","src/time.rs":"3b2829a98a1648eb052db19bb470808b6b015a1eca27ab7be64b5d196c0271c0","tests/aead.rs":"3ac4fe4ab79922b5d0191a9717058fc8d0710380ce9b25448095f870f511844f","tests/agent.rs":"824735f88e487a3748200844e9481e81a72163ad74d82faa9aa16594d9b9bb25","tests/ext.rs":"1b047d23d9b224ad06eb65d8f3a7b351e263774e404c79bbcbe8f43790e29c18","tests/handshake.rs":"e892a2839b31414be16e96cdf3b1a65978716094700c1a4989229f7edbf578a0","tests/hkdf.rs":"1d2098dc8398395864baf13e4886cfd1da6d36118727c3b264f457ee3da6b048","tests/hp.rs":"b24fec53771c169be788772532d2617a5349196cf87d6444dc74214f7c73e92c","tests/init.rs":"44fe7626b75ab8c57adfee361bb70a83d5958797e1eb6c4531bb74988ba3a990","tests/selfencrypt.rs":"25813b0c6f32fc8383bb7685745feb750eb3fdc0a6a172a50d961c68d39f2a46"},"package":null}

View file

@ -10,16 +10,19 @@
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
edition = "2021"
rust-version = "1.74.0"
name = "neqo-crypto"
version = "0.7.1"
version = "0.7.2"
authors = ["The Neqo Authors <necko@mozilla.com>"]
build = "build.rs"
homepage = "https://github.com/mozilla/neqo/"
license = "MIT OR Apache-2.0"
repository = "https://github.com/mozilla/neqo/"
[lib]
bench = false
[dependencies.log]
version = "0.4"
default-features = false
@ -30,11 +33,6 @@ path = "../neqo-common"
[dev-dependencies.test-fixture]
path = "../test-fixture"
[build-dependencies]
serde = "1.0"
serde_derive = "1.0"
toml = "0.5"
[build-dependencies.bindgen]
version = "0.69"
features = ["runtime"]
@ -43,8 +41,24 @@ default-features = false
[build-dependencies.mozbuild]
version = "0.1"
optional = true
default-features = false
[build-dependencies.serde]
version = "1.0"
default-features = false
[build-dependencies.serde_derive]
version = "1.0"
default-features = false
[build-dependencies.toml]
version = "0.5"
default-features = false
[features]
deny-warnings = []
fuzzing = []
gecko = ["mozbuild"]
[lints.clippy.pedantic]
level = "warn"
priority = -1

View file

@ -4,9 +4,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(clippy::pedantic)]
use std::{
collections::HashMap,
env, fs,
@ -37,7 +34,7 @@ struct Bindings {
opaque: Vec<String>,
/// enumerations that are turned into a module (without this, the enum is
/// mapped using the default, which means that the individual values are
/// formed with an underscore as <enum_type>_<enum_value_name>).
/// formed with an underscore as <`enum_type`>_<`enum_value_name`>).
#[serde(default)]
enums: Vec<String>,
@ -53,9 +50,10 @@ struct Bindings {
}
fn is_debug() -> bool {
env::var("DEBUG")
.map(|d| d.parse::<bool>().unwrap_or(false))
.unwrap_or(false)
// Check the build profile and not whether debug symbols are enabled (i.e.,
// `env::var("DEBUG")`), because we enable those for benchmarking/profiling and still want
// to build NSS in release mode.
env::var("PROFILE").unwrap_or_default() == "debug"
}
// bindgen needs access to libclang.
@ -126,7 +124,7 @@ fn nss_dir() -> PathBuf {
}
dir
};
assert!(dir.is_dir(), "NSS_DIR {:?} doesn't exist", dir);
assert!(dir.is_dir(), "NSS_DIR {dir:?} doesn't exist");
// Note that this returns a relative path because UNC
// paths on windows cause certain tools to explode.
dir
@ -150,10 +148,10 @@ fn build_nss(dir: PathBuf) {
let mut build_nss = vec![
String::from("./build.sh"),
String::from("-Ddisable_tests=1"),
// Generate static libraries in addition to shared libraries.
String::from("--static"),
];
if is_debug() {
build_nss.push(String::from("--static"));
} else {
if !is_debug() {
build_nss.push(String::from("-o"));
}
if let Ok(d) = env::var("NSS_JOBS") {
@ -318,7 +316,7 @@ fn setup_standalone() -> Vec<String> {
"cargo:rustc-link-search=native={}",
nsslibdir.to_str().unwrap()
);
if is_debug() {
if is_debug() || env::consts::OS == "windows" {
static_link();
} else {
dynamic_link();

View file

@ -5,7 +5,6 @@
// except according to those terms.
use std::{
convert::{TryFrom, TryInto},
fmt,
ops::{Deref, DerefMut},
os::raw::{c_char, c_uint},

View file

@ -6,7 +6,6 @@
use std::{
cell::RefCell,
convert::TryFrom,
ffi::{CStr, CString},
mem::{self, MaybeUninit},
ops::{Deref, DerefMut},
@ -1016,7 +1015,7 @@ pub enum ZeroRttCheckResult {
Accept,
/// Reject 0-RTT, but continue the handshake normally.
Reject,
/// Send HelloRetryRequest (probably not needed for QUIC).
/// Send `HelloRetryRequest` (probably not needed for QUIC).
HelloRetryRequest(Vec<u8>),
/// Fail the handshake.
Fail,

View file

@ -6,13 +6,11 @@
use std::{
cmp::min,
convert::{TryFrom, TryInto},
fmt, mem,
ops::Deref,
os::raw::{c_uint, c_void},
pin::Pin,
ptr::{null, null_mut},
vec::Vec,
};
use neqo_common::{hex, hex_with_len, qtrace};

View file

@ -4,10 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{
convert::TryFrom,
ptr::{addr_of, NonNull},
};
use std::ptr::{addr_of, NonNull};
use neqo_common::qerror;
@ -24,7 +21,7 @@ use crate::{
pub struct CertificateInfo {
certs: CertList,
cursor: *const CERTCertListNode,
/// stapled_ocsp_responses and signed_cert_timestamp are properties
/// `stapled_ocsp_responses` and `signed_cert_timestamp` are properties
/// associated with each of the certificates. Right now, NSS only
/// reports the value for the end-entity certificate (the first).
stapled_ocsp_responses: Option<Vec<Vec<u8>>>,

View file

@ -5,7 +5,6 @@
// except according to those terms.
use std::{
convert::TryFrom,
ffi::CString,
os::raw::{c_char, c_uint},
ptr::{addr_of_mut, null_mut},

View file

@ -6,7 +6,6 @@
use std::{
cell::RefCell,
convert::TryFrom,
os::raw::{c_uint, c_void},
pin::Pin,
rc::Rc,

View file

@ -5,7 +5,6 @@
// except according to those terms.
use std::{
convert::TryFrom,
os::raw::{c_char, c_uint},
ptr::null_mut,
};

View file

@ -6,7 +6,6 @@
use std::{
cell::RefCell,
convert::TryFrom,
fmt::{self, Debug},
os::raw::{c_char, c_int, c_uint},
ptr::{addr_of_mut, null, null_mut},
@ -46,7 +45,7 @@ pub enum HpKey {
/// 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
/// 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),
}

View file

@ -4,13 +4,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(clippy::pedantic)]
// Bindgen auto generated code
// won't adhere to the clippy rules below
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::unseparated_literal_suffix)]
#![allow(clippy::used_underscore_binding)]
#![allow(clippy::module_name_repetitions)] // This lint doesn't work here.
#![allow(clippy::unseparated_literal_suffix, clippy::used_underscore_binding)] // For bindgen code.
mod aead;
#[cfg(feature = "fuzzing")]
@ -36,13 +31,7 @@ pub mod selfencrypt;
mod ssl;
mod time;
use std::{
convert::TryFrom,
ffi::CString,
path::{Path, PathBuf},
ptr::null,
sync::OnceLock,
};
use std::{ffi::CString, path::PathBuf, ptr::null, sync::OnceLock};
#[cfg(not(feature = "fuzzing"))]
pub use self::aead::RealAead as Aead;
@ -87,7 +76,7 @@ fn secstatus_to_res(code: nss::SECStatus) -> Res<()> {
enum NssLoaded {
External,
NoDb,
Db(Box<Path>),
Db,
}
impl Drop for NssLoaded {
@ -189,7 +178,7 @@ pub fn init_db<P: Into<PathBuf>>(dir: P) {
#[cfg(debug_assertions)]
enable_ssl_trace();
NssLoaded::Db(path.into_boxed_path())
NssLoaded::Db
});
}

View file

@ -11,7 +11,6 @@
use std::{
cell::RefCell,
convert::TryFrom,
mem,
ops::{Deref, DerefMut},
os::raw::{c_int, c_uint},
@ -345,7 +344,7 @@ impl RandomCache {
/// When `size` is too large or NSS fails.
#[must_use]
pub fn random<const N: usize>() -> [u8; N] {
thread_local! { static CACHE: RefCell<RandomCache> = RefCell::new(RandomCache::new()) };
thread_local!(static CACHE: RefCell<RandomCache> = RefCell::new(RandomCache::new()));
let buf = [0; N];
if N <= RandomCache::CUTOFF {

View file

@ -5,7 +5,6 @@
// except according to those terms.
use std::{
convert::{TryFrom, TryInto},
ops::{Deref, DerefMut},
os::raw::c_uint,
ptr::null_mut,

View file

@ -7,8 +7,6 @@
#![allow(clippy::upper_case_acronyms)]
use std::{
boxed::Box,
convert::{TryFrom, TryInto},
ops::Deref,
os::raw::c_void,
pin::Pin,
@ -215,10 +213,7 @@ impl Default for TimeHolder {
#[cfg(test)]
mod test {
use std::{
convert::{TryFrom, TryInto},
time::{Duration, Instant},
};
use std::time::{Duration, Instant};
use super::{get_base, init, Interval, PRTime, Time};
use crate::err::Res;

View file

@ -1,4 +1,9 @@
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![warn(clippy::pedantic)]
#![cfg(not(feature = "fuzzing"))]

View file

@ -1,7 +1,8 @@
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(clippy::pedantic)]
use std::boxed::Box;
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use neqo_crypto::{
generate_ech_keys, AuthenticationStatus, Client, Error, HandshakeState, SecretAgentPreInfo,

View file

@ -1,5 +1,8 @@
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(clippy::pedantic)]
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{cell::RefCell, rc::Rc};

View file

@ -1,4 +1,12 @@
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(dead_code)]
#![allow(clippy::missing_panics_doc)]
#![allow(clippy::missing_errors_doc)]
use std::{mem, time::Instant};
@ -127,6 +135,7 @@ fn zero_rtt_setup(
}
}
#[must_use]
pub fn resumption_setup(mode: Resumption) -> (Option<AntiReplay>, ResumptionToken) {
fixture_init();

View file

@ -1,5 +1,8 @@
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(clippy::pedantic)]
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use neqo_crypto::{
constants::{

View file

@ -1,5 +1,8 @@
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(clippy::pedantic)]
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::mem;

View file

@ -1,5 +1,8 @@
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(clippy::pedantic)]
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// This uses external interfaces to neqo_crypto rather than being a module
// inside of lib.rs. Because all other code uses the test_fixture module,

View file

@ -1,5 +1,9 @@
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(clippy::pedantic)]
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![cfg(not(feature = "fuzzing"))]
use neqo_crypto::{

View file

@ -1 +1 @@
{"files":{"Cargo.toml":"d91d814a49a77d19195fbeaed449de6730802ad429b2f6a7e06524e599fcf0e2","src/buffered_send_stream.rs":"f45bdf9ad2a04b3828c74ff5440681d3c9d1af39b55470e4f729842dc2412295","src/client_events.rs":"e1392e7bbb62fb0505a4d8bcd27559699bbf38f3c94e7d8cae7291db82e6334c","src/conn_params.rs":"224a8ea6ef632930a7788a1cabf47ce69ad41bd4bc8dcf3053fbd998fdb38e82","src/connection.rs":"09aeb123f8dc6b903dd7d30579e5bb09ed8f70bfae563fb2fcc1871c67d604d4","src/connection_client.rs":"c38ebb402ce410e872866e4093f806f6c1bae25b1de320e22a0f99efb847ac5e","src/connection_server.rs":"ca33b50650bd1ca2a952851b72712d55ec2e48b48f1f06e4184c808b8e1e009a","src/control_stream_local.rs":"d6ecc0adc926e1d5cec9a378317f9dfcfeeb9840a0873a2afb380c2d252d8c54","src/control_stream_remote.rs":"59eb4041e366d92f9f294e8446755caa5e91fd943bba7b79b726698ba13be248","src/features/extended_connect/mod.rs":"3b02f6b18627f3855465a81b1d9b285e6f13839e75a8a6db648ed9082908d7f0","src/features/extended_connect/tests/mod.rs":"fd6aee37243713e80fc526552f21f0222338cec9890409b6575a2a637b17ec1f","src/features/extended_connect/tests/webtransport/datagrams.rs":"7e3bdd591b9c7d02f69954629f889d52bd54f13dbca11d555e614138c2a55107","src/features/extended_connect/tests/webtransport/mod.rs":"a30ea715f5271a826a739278b18e145964dedbce7026eed45f1b7d0355c407d5","src/features/extended_connect/tests/webtransport/negotiation.rs":"98254ef8446581ec520026b04ef9549645602181b61602c9936f6660141edf0b","src/features/extended_connect/tests/webtransport/sessions.rs":"de3d836f666c2bec31e70b33bdc2669572cabbe17df2225db7282613a224a364","src/features/extended_connect/tests/webtransport/streams.rs":"8b3c34cac1b2171252a4bb53d420ac2098549a20309c327bf56e2e9ba9e33538","src/features/extended_connect/webtransport_session.rs":"a6472eca50a2d097aa6ba8a76b45ae69fe2edd2696b2953945faa3ce6e7417f9","src/features/extended_connect/webtransport_streams.rs":"a9a106eefc93a9f6e9e1c246df64904353de1c4fbcd394b338e6b117f6c677f5","src/features/mod.rs":"925aae4427ad82e4d019354802b223d53db5e5585d4a940f5417a24a9503d7ee","src/frames/hframe.rs":"56c36ac597504f28c73cf2370acd82104f8c7a7b9ffc0f6d222378abc524482d","src/frames/mod.rs":"7d0a46ca147336d14781edb8dbee8b03c2e4bcd6646f5473a9d93d31fe73fecb","src/frames/reader.rs":"4883e25064da1fb3a6ae46b5d15e6bcfec9c5bbea55a1937ecdb9465b62a93b2","src/frames/tests/hframe.rs":"01ec74eb3eb25d95042aa0263f9267f89535e6b7b8c1161fab4ba9ee5352d4a7","src/frames/tests/mod.rs":"0610609b316767a6a022837d32ee0452e37ea296fde37e51bec87e7c77e923a3","src/frames/tests/reader.rs":"2bfadc7afbc41bff9f5f930b31550259a8a92484d35f6c5d8dd8fd9acfb88f5b","src/frames/tests/wtframe.rs":"589ebe1e62ce4da63b37b7d22cde7ba572ddbf29336fdcdbbcd0a745f79dacd8","src/frames/wtframe.rs":"c80518d1569de277767c7ccb7441898aadbfc5fb2afb968c1d5105f8d175ccff","src/headers_checks.rs":"44891c16dda6b7ef742058ecb0a8d34e219c51cae1216c09c661cf72d9a5e7d5","src/lib.rs":"ed8da14e573cc5a97afb012a78af7f076eb83b5cc20cb4fe432eb7136a3ffe52","src/priority.rs":"10d9dcfcd4585f2ca256daf254c78a428297c41976c6548f19cd3ed2222b7cd2","src/push_controller.rs":"eb27c7c2a52c6108c0e4d040b021775a2b573f32d78b7ac8652ff46fd549f780","src/qlog.rs":"b1e6108b018abb077f218d1806e0a83370afa87709e26b3d51f482ae5d9b9c82","src/qpack_decoder_receiver.rs":"c927dfc3e58c71d282210ba79280f6f03e789733bc3bedc247e68bab516b9e9e","src/qpack_encoder_receiver.rs":"d0ac03cc111b6e1c555a8654d3234116f2b135b5b040edac23cefe2d640beba9","src/recv_message.rs":"06666c22101cda41de14682dc7e2e6721f2821bd45baefc22caceae4ccfcf2e0","src/request_target.rs":"6041a69a0a74969ec08bc164509c055e9bad99f53bbeb16c0aa17d108dd68b8c","src/send_message.rs":"70f8a91d85515f42a64a88bd2a9480175b12596bc082f77587cc5bcff9ce996c","src/server.rs":"ab6d4c80cb5f6c070f74d8df27e7bd62d5c8a8e7756ff9d1a31d3f9ff91327a1","src/server_connection_events.rs":"12d353ca6301467f6d475dde3b789951a5716c89ddd7dbf1383efef8082361f3","src/server_events.rs":"c96cff96d5893a9ab7165d17e3d1afaafc5492418b30003c1c26ca8f489ab7ca","src/settings.rs":"476b154b5eea4c8d69a4a790fee3e527cef4d375df1cfb5eed04ec56406fe15a","src/stream_type_reader.rs":"7a7226b7911d69f7e00ec4987c2a32a5e8a33463203398cbee1e6645d2691478","tests/httpconn.rs":"bb6927801a8c75e4f05eb6cdb1e7f2d57be69b74e68ddad2a1614f2aeed04369","tests/priority.rs":"3418be17fbdfdbcfd80dc4532f9365f405925442fabc916f2b22f90aee89629f","tests/send_message.rs":"b5435045b16429d9e626ea94a8f10e2937e1a5a878af0035763a4f5ec09bf53c","tests/webtransport.rs":"25794305017ff58e57dc3c3b9b078e5bfc1814ea82a521b7b7156228e613c092"},"package":null}
{"files":{"Cargo.toml":"458f04261cda071d61402c52cf64062ad7cfc24f3f312bfaa5d52cae47409010","src/buffered_send_stream.rs":"f45bdf9ad2a04b3828c74ff5440681d3c9d1af39b55470e4f729842dc2412295","src/client_events.rs":"77fedca72ce54956eaba3fb7103085d196a631b764662584ea2629224c5c234e","src/conn_params.rs":"224a8ea6ef632930a7788a1cabf47ce69ad41bd4bc8dcf3053fbd998fdb38e82","src/connection.rs":"9384cdfd8481a30a0cd13f56f590188ccfa47b4472f35f7a4978537bab19adc1","src/connection_client.rs":"8db29409f3a265f7dff7c7a7eaf2ac607d6923e4b3238e82eab6dc22854e4303","src/connection_server.rs":"ca33b50650bd1ca2a952851b72712d55ec2e48b48f1f06e4184c808b8e1e009a","src/control_stream_local.rs":"ae52e3286f1686ca1265e7de841392addd42616db02799bb967a59feb6039cb5","src/control_stream_remote.rs":"59eb4041e366d92f9f294e8446755caa5e91fd943bba7b79b726698ba13be248","src/features/extended_connect/mod.rs":"3b02f6b18627f3855465a81b1d9b285e6f13839e75a8a6db648ed9082908d7f0","src/features/extended_connect/tests/mod.rs":"fd6aee37243713e80fc526552f21f0222338cec9890409b6575a2a637b17ec1f","src/features/extended_connect/tests/webtransport/datagrams.rs":"4c85a90afb753ce588e3fdeb773669bc49c013aebc28912340359eb01b74fd70","src/features/extended_connect/tests/webtransport/mod.rs":"a30ea715f5271a826a739278b18e145964dedbce7026eed45f1b7d0355c407d5","src/features/extended_connect/tests/webtransport/negotiation.rs":"98254ef8446581ec520026b04ef9549645602181b61602c9936f6660141edf0b","src/features/extended_connect/tests/webtransport/sessions.rs":"de3d836f666c2bec31e70b33bdc2669572cabbe17df2225db7282613a224a364","src/features/extended_connect/tests/webtransport/streams.rs":"8b3c34cac1b2171252a4bb53d420ac2098549a20309c327bf56e2e9ba9e33538","src/features/extended_connect/webtransport_session.rs":"239d92c06fbc5f6226078bb411a803f57b555dea0077349d49d7f57671cf2eab","src/features/extended_connect/webtransport_streams.rs":"5d7507aaf6a819d266fbea9b7a415c8324329df0f6936d9045b73e17a5b844ee","src/features/mod.rs":"925aae4427ad82e4d019354802b223d53db5e5585d4a940f5417a24a9503d7ee","src/frames/hframe.rs":"56c36ac597504f28c73cf2370acd82104f8c7a7b9ffc0f6d222378abc524482d","src/frames/mod.rs":"7d0a46ca147336d14781edb8dbee8b03c2e4bcd6646f5473a9d93d31fe73fecb","src/frames/reader.rs":"e07ee9de74bc499c10afcda592fefd9a7eef3381c045aa14f6596d67313546ca","src/frames/tests/hframe.rs":"01ec74eb3eb25d95042aa0263f9267f89535e6b7b8c1161fab4ba9ee5352d4a7","src/frames/tests/mod.rs":"0610609b316767a6a022837d32ee0452e37ea296fde37e51bec87e7c77e923a3","src/frames/tests/reader.rs":"2bfadc7afbc41bff9f5f930b31550259a8a92484d35f6c5d8dd8fd9acfb88f5b","src/frames/tests/wtframe.rs":"589ebe1e62ce4da63b37b7d22cde7ba572ddbf29336fdcdbbcd0a745f79dacd8","src/frames/wtframe.rs":"1d9d0256ace2ba7262343ed035df795f21a4d45065792d3fd45b3391b6916b2f","src/headers_checks.rs":"be0f0109298dcc3a40350b7c0950076ddfe20617d195b305e3ffc8582557ab18","src/lib.rs":"4f908a021222bcc79b9d569bc3759a493379a20b47dfa228fddf51600bf6e446","src/priority.rs":"f3b77c208962e44a4e2d13138c6998b703d40e7bcf8f73ea84d8ef5b556e0aee","src/push_controller.rs":"13bccf2834ae19109504cf695a5948c3b2d03fd101bc032a92bb77a033423854","src/qlog.rs":"2debd75c7ea103c95ff79e44412f1408c3e496e324976100c55d5a833912b6c3","src/qpack_decoder_receiver.rs":"c927dfc3e58c71d282210ba79280f6f03e789733bc3bedc247e68bab516b9e9e","src/qpack_encoder_receiver.rs":"d0ac03cc111b6e1c555a8654d3234116f2b135b5b040edac23cefe2d640beba9","src/recv_message.rs":"eb711dbc6b3371373c26b75333ac5858edf0d30184b0e05d67ab02c656eb6619","src/request_target.rs":"6041a69a0a74969ec08bc164509c055e9bad99f53bbeb16c0aa17d108dd68b8c","src/send_message.rs":"7785af11b77cee398faf3f7a2875b41e251ed7a1b272c23f81a48334596ab836","src/server.rs":"b9e6060da36cfb467478f5b78b17e22a123214ad2d64c919ce688ea2bc0e24bb","src/server_connection_events.rs":"12d353ca6301467f6d475dde3b789951a5716c89ddd7dbf1383efef8082361f3","src/server_events.rs":"463dd2cb6f97a800bac32c93c4aa2a6289f71e33a89f3b33152460cb941fc378","src/settings.rs":"476b154b5eea4c8d69a4a790fee3e527cef4d375df1cfb5eed04ec56406fe15a","src/stream_type_reader.rs":"7a7226b7911d69f7e00ec4987c2a32a5e8a33463203398cbee1e6645d2691478","tests/httpconn.rs":"bb6927801a8c75e4f05eb6cdb1e7f2d57be69b74e68ddad2a1614f2aeed04369","tests/priority.rs":"364754507873298612ad12e8d1d106d26d993712142d0be4cbf056da5338854c","tests/send_message.rs":"b5435045b16429d9e626ea94a8f10e2937e1a5a878af0035763a4f5ec09bf53c","tests/webtransport.rs":"25794305017ff58e57dc3c3b9b078e5bfc1814ea82a521b7b7156228e613c092"},"package":null}

View file

@ -10,21 +10,21 @@
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
edition = "2021"
rust-version = "1.74.0"
name = "neqo-http3"
version = "0.7.1"
version = "0.7.2"
authors = ["The Neqo Authors <necko@mozilla.com>"]
homepage = "https://github.com/mozilla/neqo/"
license = "MIT OR Apache-2.0"
repository = "https://github.com/mozilla/neqo/"
[dependencies]
enumset = "1.1"
qlog = "0.12"
sfv = "0.9"
smallvec = "1.11"
url = "2.5"
[lib]
bench = false
[dependencies.enumset]
version = "1.1"
default-features = false
[dependencies.log]
version = "0.4"
@ -42,12 +42,31 @@ path = "./../neqo-qpack"
[dependencies.neqo-transport]
path = "./../neqo-transport"
[dependencies.qlog]
version = "0.12"
default-features = false
[dependencies.sfv]
version = "0.9"
default-features = false
[dependencies.smallvec]
version = "1.11"
default-features = false
[dependencies.url]
version = "2.5"
default-features = false
[dev-dependencies.test-fixture]
path = "../test-fixture"
[features]
deny-warnings = []
fuzzing = [
"neqo-transport/fuzzing",
"neqo-crypto/fuzzing",
]
[lints.clippy.pedantic]
level = "warn"
priority = -1

View file

@ -61,7 +61,7 @@ pub enum Http3ClientEvent {
error: AppError,
local: bool,
},
/// Peer has sent a STOP_SENDING.
/// Peer has sent a `STOP_SENDING`.
StopSending {
stream_id: StreamId,
error: AppError,
@ -83,7 +83,7 @@ pub enum Http3ClientEvent {
PushDataReadable { push_id: u64 },
/// A push has been canceled.
PushCanceled { push_id: u64 },
/// A push stream was been reset due to a HttpGeneralProtocol error.
/// A push stream was been reset due to a `HttpGeneralProtocol` error.
/// Most common case are malformed response headers.
PushReset { push_id: u64, error: AppError },
/// New stream can be created
@ -102,7 +102,7 @@ pub enum Http3ClientEvent {
GoawayReceived,
/// Connection state change.
StateChange(Http3State),
/// WebTransport events
/// `WebTransport` events
WebTransport(WebTransportEvent),
}

View file

@ -835,9 +835,6 @@ impl Http3Connection {
final_headers.push(Header::new(":protocol", conn_type.string()));
}
if let Some(priority_header) = request.priority.header() {
final_headers.push(priority_header);
}
final_headers.extend_from_slice(request.headers);
Ok(final_headers)
}

View file

@ -6,7 +6,6 @@
use std::{
cell::RefCell,
convert::TryFrom,
fmt::{Debug, Display},
mem,
net::SocketAddr,
@ -894,13 +893,6 @@ impl Http3Client {
self.process_http3(now);
}
/// This should not be used because it gives access to functionalities that may disrupt the
/// proper functioning of the HTTP/3 session.
/// Only used by `neqo-interop`.
pub fn conn(&mut self) -> &mut Connection {
&mut self.conn
}
/// Process HTTP3 layer.
/// When `process_output`, `process_input`, or `process` is called we must call this function
/// as well. The functions calls `Http3Client::check_connection_events` to handle events from
@ -943,12 +935,12 @@ impl Http3Client {
/// returned. After that, the application should call the function again if a new UDP packet is
/// received and processed or the timer value expires.
///
/// The HTTP/3 neqo implementation drives the HTTP/3 and QUC layers, therefore this function
/// The HTTP/3 neqo implementation drives the HTTP/3 and QUIC layers, therefore this function
/// will call both layers:
/// - First it calls HTTP/3 layer processing (`process_http3`) to make sure the layer writes
/// data to QUIC layer or cancels streams if needed.
/// - Then QUIC layer processing is called - [`Connection::process_output`][3]. This produces a
/// packet or a timer value. It may also produce ned [`ConnectionEvent`][2]s, e.g. connection
/// packet or a timer value. It may also produce new [`ConnectionEvent`][2]s, e.g. connection
/// state-change event.
/// - Therefore the HTTP/3 layer processing (`process_http3`) is called again.
///
@ -1296,7 +1288,7 @@ impl EventProvider for Http3Client {
#[cfg(test)]
mod tests {
use std::{convert::TryFrom, mem, time::Duration};
use std::{mem, time::Duration};
use neqo_common::{event::Provider, qtrace, Datagram, Decoder, Encoder};
use neqo_crypto::{AllowZeroRtt, AntiReplay, ResumptionToken};
@ -1997,7 +1989,7 @@ mod tests {
// The response header from PUSH_DATA (0x01, 0x06, 0x00, 0x00, 0xd9, 0x54, 0x01, 0x34) are
// decoded into:
fn check_push_response_header(header: &[Header]) {
let expected_push_response_header = vec![
let expected_push_response_header = [
Header::new(":status", "200"),
Header::new("content-length", "4"),
];
@ -3953,7 +3945,7 @@ mod tests {
);
}
x => {
panic!("event {:?}", x);
panic!("event {x:?}");
}
}
@ -3999,7 +3991,7 @@ mod tests {
assert!(fin);
}
x => {
panic!("event {:?}", x);
panic!("event {x:?}");
}
}
// Stream should now be closed and gone
@ -4072,7 +4064,7 @@ mod tests {
assert_eq!(stream_id, request_stream_id);
}
x => {
panic!("event {:?}", x);
panic!("event {x:?}");
}
}
}
@ -4136,7 +4128,7 @@ mod tests {
assert!(!interim);
recv_header = true;
} else {
panic!("event {:?}", e);
panic!("event {e:?}");
}
}
assert!(recv_header);

View file

@ -4,10 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{
collections::{HashMap, VecDeque},
convert::TryFrom,
};
use std::collections::{HashMap, VecDeque};
use neqo_common::{qtrace, Encoder};
use neqo_transport::{Connection, StreamId, StreamType};

View file

@ -4,8 +4,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::convert::TryFrom;
use neqo_common::Encoder;
use neqo_transport::Error as TransportError;

View file

@ -4,13 +4,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(clippy::module_name_repetitions)]
use std::{any::Any, cell::RefCell, collections::BTreeSet, mem, rc::Rc};
use std::{cell::RefCell, collections::BTreeSet, mem, rc::Rc};
use neqo_common::{qtrace, Encoder, Header, MessageType, Role};
use neqo_qpack::{QPackDecoder, QPackEncoder};
use neqo_transport::{streams::SendOrder, Connection, DatagramTracking, StreamId};
use neqo_transport::{Connection, DatagramTracking, StreamId};
use super::{ExtendedConnectEvents, ExtendedConnectType, SessionCloseReason};
use crate::{
@ -473,10 +471,6 @@ impl HttpRecvStream for Rc<RefCell<WebTransportSession>> {
fn priority_update_sent(&mut self) {
self.borrow_mut().priority_update_sent();
}
fn any(&self) -> &dyn Any {
self
}
}
impl SendStream for Rc<RefCell<WebTransportSession>> {
@ -492,16 +486,6 @@ impl SendStream for Rc<RefCell<WebTransportSession>> {
self.borrow_mut().has_data_to_send()
}
fn set_sendorder(&mut self, _conn: &mut Connection, _sendorder: Option<SendOrder>) -> Res<()> {
// Not relevant on session
Ok(())
}
fn set_fairness(&mut self, _conn: &mut Connection, _fairness: bool) -> Res<()> {
// Not relevant on session
Ok(())
}
fn stream_writable(&self) {}
fn done(&self) -> bool {

View file

@ -215,16 +215,6 @@ impl SendStream for WebTransportSendStream {
}
}
fn set_sendorder(&mut self, conn: &mut Connection, sendorder: Option<i64>) -> Res<()> {
conn.stream_sendorder(self.stream_id, sendorder)
.map_err(|_| crate::Error::InvalidStreamId)
}
fn set_fairness(&mut self, conn: &mut Connection, fairness: bool) -> Res<()> {
conn.stream_fairness(self.stream_id, fairness)
.map_err(|_| crate::Error::InvalidStreamId)
}
fn handle_stop_sending(&mut self, close_type: CloseType) {
self.set_done(close_type);
}

View file

@ -6,7 +6,7 @@
#![allow(clippy::module_name_repetitions)]
use std::{convert::TryFrom, fmt::Debug};
use std::fmt::Debug;
use neqo_common::{
hex_with_len, qtrace, Decoder, IncrementalDecoderBuffer, IncrementalDecoderIgnore,

View file

@ -4,8 +4,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::convert::TryFrom;
use neqo_common::{Decoder, Encoder};
use crate::{frames::reader::FrameDecoder, Error, Res};

View file

@ -6,8 +6,6 @@
#![allow(clippy::unused_unit)] // see https://github.com/Lymia/enumset/issues/44
use std::convert::TryFrom;
use enumset::{enum_set, EnumSet, EnumSetType};
use neqo_common::Header;

View file

@ -4,8 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions)] // This lint doesn't work here.
/*!
@ -160,7 +159,7 @@ mod server_events;
mod settings;
mod stream_type_reader;
use std::{any::Any, cell::RefCell, fmt::Debug, rc::Rc};
use std::{cell::RefCell, fmt::Debug, rc::Rc};
use buffered_send_stream::BufferedStream;
pub use client_events::{Http3ClientEvent, WebTransportEvent};
@ -433,20 +432,15 @@ pub enum Http3StreamType {
}
#[must_use]
#[derive(PartialEq, Eq, Debug)]
#[derive(Default, PartialEq, Eq, Debug)]
enum ReceiveOutput {
#[default]
NoOutput,
ControlFrames(Vec<HFrame>),
UnblockedStreams(Vec<StreamId>),
NewStream(NewStreamType),
}
impl Default for ReceiveOutput {
fn default() -> Self {
Self::NoOutput
}
}
trait Stream: Debug {
fn stream_type(&self) -> Http3StreamType;
}
@ -509,8 +503,6 @@ trait HttpRecvStream: RecvStream {
fn extended_connect_wait_for_response(&self) -> bool {
false
}
fn any(&self) -> &dyn Any;
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
@ -567,27 +559,25 @@ trait HttpRecvStreamEvents: RecvStreamEvents {
trait SendStream: Stream {
/// # Errors
///
/// Error my occur during sending data, e.g. protocol error, etc.
/// Error may occur during sending data, e.g. protocol error, etc.
fn send(&mut self, conn: &mut Connection) -> Res<()>;
fn has_data_to_send(&self) -> bool;
fn stream_writable(&self);
fn done(&self) -> bool;
fn set_sendorder(&mut self, conn: &mut Connection, sendorder: Option<SendOrder>) -> Res<()>;
fn set_fairness(&mut self, conn: &mut Connection, fairness: bool) -> Res<()>;
/// # Errors
///
/// Error my occur during sending data, e.g. protocol error, etc.
/// Error may occur during sending data, e.g. protocol error, etc.
fn send_data(&mut self, _conn: &mut Connection, _buf: &[u8]) -> Res<usize>;
/// # Errors
///
/// It may happen that the transport stream is already close. This is unlikely.
/// It may happen that the transport stream is already closed. This is unlikely.
fn close(&mut self, conn: &mut Connection) -> Res<()>;
/// # Errors
///
/// It may happen that the transport stream is already close. This is unlikely.
/// It may happen that the transport stream is already closed. This is unlikely.
fn close_with_message(
&mut self,
_conn: &mut Connection,
@ -606,7 +596,7 @@ trait SendStream: Stream {
/// # Errors
///
/// It may happen that the transport stream is already close. This is unlikely.
/// It may happen that the transport stream is already closed. This is unlikely.
fn send_data_atomic(&mut self, _conn: &mut Connection, _buf: &[u8]) -> Res<()> {
Err(Error::InvalidStreamId)
}
@ -627,7 +617,6 @@ trait HttpSendStream: SendStream {
/// This can also return an error if the underlying stream is closed.
fn send_headers(&mut self, headers: &[Header], conn: &mut Connection) -> Res<()>;
fn set_new_listener(&mut self, _conn_events: Box<dyn SendStreamEvents>) {}
fn any(&self) -> &dyn Any;
}
trait SendStreamEvents: Debug {

View file

@ -1,4 +1,10 @@
use std::{convert::TryFrom, fmt};
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt;
use neqo_transport::StreamId;
use sfv::{BareItem, Item, ListEntry, Parser};

View file

@ -1,3 +1,4 @@
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
@ -6,7 +7,6 @@
use std::{
cell::RefCell,
collections::VecDeque,
convert::TryFrom,
fmt::{Debug, Display},
mem,
rc::Rc,

View file

@ -6,14 +6,9 @@
// Functions that handle capturing QLOG traces.
use std::convert::TryFrom;
use neqo_common::qlog::NeqoQlog;
use neqo_transport::StreamId;
use qlog::{
self,
events::{DataRecipient, EventData},
};
use qlog::events::{DataRecipient, EventData};
pub fn h3_data_moved_up(qlog: &mut NeqoQlog, stream_id: StreamId, amount: usize) {
qlog.add_event_data(|| {

View file

@ -4,9 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{
any::Any, cell::RefCell, cmp::min, collections::VecDeque, convert::TryFrom, fmt::Debug, rc::Rc,
};
use std::{cell::RefCell, cmp::min, collections::VecDeque, fmt::Debug, rc::Rc};
use neqo_common::{qdebug, qinfo, qtrace, Header};
use neqo_qpack::decoder::QPackDecoder;
@ -494,8 +492,4 @@ impl HttpRecvStream for RecvMessage {
fn extended_connect_wait_for_response(&self) -> bool {
matches!(self.state, RecvMessageState::ExtendedConnect)
}
fn any(&self) -> &dyn Any {
self
}
}

View file

@ -4,11 +4,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{any::Any, cell::RefCell, cmp::min, fmt::Debug, rc::Rc};
use std::{cell::RefCell, cmp::min, fmt::Debug, rc::Rc};
use neqo_common::{qdebug, qinfo, qtrace, Encoder, Header, MessageType};
use neqo_qpack::encoder::QPackEncoder;
use neqo_transport::{streams::SendOrder, Connection, StreamId};
use neqo_transport::{Connection, StreamId};
use crate::{
frames::HFrame,
@ -270,16 +270,6 @@ impl SendStream for SendMessage {
self.stream.has_buffered_data()
}
fn set_sendorder(&mut self, _conn: &mut Connection, _sendorder: Option<SendOrder>) -> Res<()> {
// Not relevant for SendMessage
Ok(())
}
fn set_fairness(&mut self, _conn: &mut Connection, _fairness: bool) -> Res<()> {
// Not relevant for SendMessage
Ok(())
}
fn close(&mut self, conn: &mut Connection) -> Res<()> {
self.state.fin()?;
if !self.stream.has_buffered_data() {
@ -332,10 +322,6 @@ impl HttpSendStream for SendMessage {
self.stream_type = Http3StreamType::ExtendedConnect;
self.conn_events = conn_events;
}
fn any(&self) -> &dyn Any {
self
}
}
impl ::std::fmt::Display for SendMessage {

View file

@ -151,7 +151,7 @@ impl Http3Server {
active_conns.dedup();
active_conns
.iter()
.for_each(|conn| self.server.add_to_waiting(conn.clone()));
.for_each(|conn| self.server.add_to_waiting(conn));
for mut conn in active_conns {
self.process_events(&mut conn, now);
}
@ -1271,11 +1271,11 @@ mod tests {
while let Some(event) = hconn.next_event() {
match event {
Http3ServerEvent::Headers { stream, .. } => {
assert!(requests.get(&stream).is_none());
assert!(!requests.contains_key(&stream));
requests.insert(stream, 0);
}
Http3ServerEvent::Data { stream, .. } => {
assert!(requests.get(&stream).is_some());
assert!(requests.contains_key(&stream));
}
Http3ServerEvent::DataWritable { .. }
| Http3ServerEvent::StreamReset { .. }

View file

@ -9,7 +9,6 @@
use std::{
cell::RefCell,
collections::VecDeque,
convert::TryFrom,
ops::{Deref, DerefMut},
rc::Rc,
};

View file

@ -68,7 +68,7 @@ fn priority_update() {
Instant::now(),
"GET",
&("https", "something.com", "/"),
&[],
&[Header::new("priority", "u=4,i")],
Priority::new(4, true),
)
.unwrap();
@ -98,7 +98,7 @@ fn priority_update() {
assert_eq!(&headers, expected_headers);
assert!(!fin);
}
other => panic!("unexpected server event: {:?}", other),
other => panic!("unexpected server event: {other:?}"),
}
let update_priority = Priority::new(3, false);
@ -129,7 +129,7 @@ fn priority_update_dont_send_for_cancelled_stream() {
Instant::now(),
"GET",
&("https", "something.com", "/"),
&[],
&[Header::new("priority", "u=5")],
Priority::new(5, false),
)
.unwrap();

View file

@ -1 +1 @@
{"files":{"Cargo.toml":"385fb0450ea02925108585a1d4e48ad6ef304a5f3c5f4385ee5f8b829bc85393","src/decoder.rs":"7e468d59adff1fa9373cbb703d13a7503f721a89bebafd049feaf0308a39b606","src/decoder_instructions.rs":"d991d70e51f079bc5b30d3982fd0176edfa9bb7ba14c17a20ec3eea878c56206","src/encoder.rs":"e026da38c2c3410a4e9aa330cda09ac411008772dd66d262d6c375601cebf481","src/encoder_instructions.rs":"86e3abbd9cf94332041326ac6cf806ed64623e3fd38dbc0385b1f63c37e73fd9","src/header_block.rs":"3925476df69b90d950594faadc5cb24c374d46de8c75a374a235f0d27323a7d8","src/huffman.rs":"4b3308ed71da233181d99101bc2eeb30eca7ec30ba776f055f01e94f10974a24","src/huffman_decode_helper.rs":"e9d405f00327a124d1751481077c31fb6348daeee7032ea3b0fa5cf6d5d8add1","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"196114397c2b1bf6ef154206018f519b012789cf712e89b069a7616d7278ef3a","src/prefix.rs":"fb4a9acbcf6fd3178f4474404cd3d3b131abca934f69fe14a9d744bc7e636dc5","src/qlog.rs":"e320007ea8309546b26f9c0019ab8722da80dbd38fa976233fd8ae19a0af637c","src/qpack_send_buf.rs":"14d71310c260ee15ea40a783998b507c968eef12db2892b47c689e872b5242a5","src/reader.rs":"b9a7dccd726f471fc24f1d3304f03ac0a039c0828aac7b33c927be07d395c655","src/static_table.rs":"fda9d5c6f38f94b0bf92d3afdf8432dce6e27e189736596e16727090c77b78ec","src/stats.rs":"624dfa3b40858c304097bb0ce5b1be1bb4d7916b1abfc222f1aa705907009730","src/table.rs":"05dbec6483bb24c9fc8d721b70fdfefc2df53b458488b55104147f13c386a47d"},"package":null}
{"files":{"Cargo.toml":"c2152600379c3961ba79e661e164630a63531744f79e082fce39cdf1cbe75ddd","src/decoder.rs":"0675444129e074e9d5d56f0d45d2eaed614c85e22cfe9f2d28cdee912c15b420","src/decoder_instructions.rs":"d991d70e51f079bc5b30d3982fd0176edfa9bb7ba14c17a20ec3eea878c56206","src/encoder.rs":"84649cbee81e050f55d7ea691ac871e072741abd8bbf96303eb2e98aa8ee0aea","src/encoder_instructions.rs":"86e3abbd9cf94332041326ac6cf806ed64623e3fd38dbc0385b1f63c37e73fd9","src/header_block.rs":"3925476df69b90d950594faadc5cb24c374d46de8c75a374a235f0d27323a7d8","src/huffman.rs":"71ec740426eee0abb6205104e504f5b97f525a76c4a5f5827b78034d28ce1876","src/huffman_decode_helper.rs":"9ce470e318b3664f58aa109bed483ab15bfd9e0b17d261ea2b609668a42a9d80","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"fd673630b5ed64197851c9a9758685096d3c0aa04f4994290733a38057004ee6","src/prefix.rs":"fb4a9acbcf6fd3178f4474404cd3d3b131abca934f69fe14a9d744bc7e636dc5","src/qlog.rs":"e320007ea8309546b26f9c0019ab8722da80dbd38fa976233fd8ae19a0af637c","src/qpack_send_buf.rs":"755af90fe077b1bcca34a1a2a1bdce5ce601ea490b2ca3f1313e0107d13e67e2","src/reader.rs":"1581261741a0922b147a6975cc8b1a3503846f6dbfdb771d254760c298996982","src/static_table.rs":"fda9d5c6f38f94b0bf92d3afdf8432dce6e27e189736596e16727090c77b78ec","src/stats.rs":"624dfa3b40858c304097bb0ce5b1be1bb4d7916b1abfc222f1aa705907009730","src/table.rs":"6e16debdceadc453546f247f8316883af9eeeedd12f2070219d8484a0a131d46"},"package":null}

View file

@ -10,18 +10,17 @@
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
edition = "2021"
rust-version = "1.74.0"
name = "neqo-qpack"
version = "0.7.1"
version = "0.7.2"
authors = ["The Neqo Authors <necko@mozilla.com>"]
homepage = "https://github.com/mozilla/neqo/"
license = "MIT OR Apache-2.0"
repository = "https://github.com/mozilla/neqo/"
[dependencies]
qlog = "0.12"
static_assertions = "1.1"
[lib]
bench = false
[dependencies.log]
version = "0.4"
@ -36,8 +35,17 @@ path = "./../neqo-crypto"
[dependencies.neqo-transport]
path = "./../neqo-transport"
[dependencies.qlog]
version = "0.12"
default-features = false
[dependencies.static_assertions]
version = "1.1"
default-features = false
[dev-dependencies.test-fixture]
path = "../test-fixture"
[features]
deny-warnings = []
[lints.clippy.pedantic]
level = "warn"
priority = -1

View file

@ -4,8 +4,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::convert::TryFrom;
use neqo_common::{qdebug, Header};
use neqo_transport::{Connection, StreamId};
@ -287,7 +285,7 @@ fn map_error(err: &Error) -> Error {
#[cfg(test)]
mod tests {
use std::{convert::TryFrom, mem};
use std::mem;
use neqo_common::Header;
use neqo_transport::{StreamId, StreamType};

View file

@ -4,10 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{
collections::{HashMap, HashSet, VecDeque},
convert::TryFrom,
};
use std::collections::{HashMap, HashSet, VecDeque};
use neqo_common::{qdebug, qerror, qlog::NeqoQlog, qtrace, Header};
use neqo_transport::{Connection, Error as TransportError, StreamId};

View file

@ -4,8 +4,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::convert::TryFrom;
use crate::{
huffman_decode_helper::{huffman_decoder_root, HuffmanDecoderNode},
huffman_table::HUFFMAN_TABLE,

View file

@ -4,7 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{convert::TryFrom, sync::OnceLock};
use std::sync::OnceLock;
use crate::huffman_table::HUFFMAN_TABLE;

View file

@ -4,11 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(clippy::pedantic)]
// This is because of Encoder and Decoder structs. TODO: think about a better namings for crate and
// structs.
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::module_name_repetitions)] // This lint doesn't work here.
pub mod decoder;
mod decoder_instructions;

View file

@ -4,7 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{convert::TryFrom, ops::Deref};
use std::ops::Deref;
use neqo_common::Encoder;

View file

@ -4,7 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{convert::TryInto, mem, str};
use std::{mem, str};
use neqo_common::{qdebug, qerror};
use neqo_transport::{Connection, StreamId};
@ -223,20 +223,19 @@ impl IntReader {
}
}
#[derive(Debug)]
#[derive(Debug, Default)]
enum LiteralReaderState {
#[default]
ReadHuffman,
ReadLength { reader: IntReader },
ReadLiteral { offset: usize },
ReadLength {
reader: IntReader,
},
ReadLiteral {
offset: usize,
},
Done,
}
impl Default for LiteralReaderState {
fn default() -> Self {
Self::ReadHuffman
}
}
/// This is decoder of a literal with a prefix:
/// 1) ignores `prefix_len` bits of the first byte,
/// 2) reads "huffman bit"

View file

@ -4,7 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{collections::VecDeque, convert::TryFrom};
use std::collections::VecDeque;
use neqo_common::qtrace;

File diff suppressed because one or more lines are too long

View file

@ -10,15 +10,18 @@
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
edition = "2021"
rust-version = "1.74.0"
name = "neqo-transport"
version = "0.7.1"
version = "0.7.2"
authors = ["The Neqo Authors <necko@mozilla.com>"]
homepage = "https://github.com/mozilla/neqo/"
license = "MIT OR Apache-2.0"
repository = "https://github.com/mozilla/neqo/"
[lib]
bench = false
[[bench]]
name = "transfer"
harness = false
@ -34,10 +37,9 @@ name = "range_tracker"
harness = false
required-features = ["bench"]
[dependencies]
indexmap = "1.9"
qlog = "0.12"
smallvec = "1.11"
[dependencies.indexmap]
version = "1.9"
default-features = false
[dependencies.log]
version = "0.4"
@ -49,17 +51,30 @@ path = "../neqo-common"
[dependencies.neqo-crypto]
path = "../neqo-crypto"
[dev-dependencies]
enum-map = "2.7"
[dependencies.qlog]
version = "0.12"
default-features = false
[dependencies.smallvec]
version = "1.11"
default-features = false
[dev-dependencies.criterion]
version = "0.5"
features = ["html_reports"]
default-features = false
[dev-dependencies.enum-map]
version = "2.7"
default-features = false
[dev-dependencies.test-fixture]
path = "../test-fixture"
[features]
bench = []
deny-warnings = []
fuzzing = ["neqo-crypto/fuzzing"]
[lints.clippy.pedantic]
level = "warn"
priority = -1

View file

@ -1,3 +1,9 @@
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use criterion::{criterion_group, criterion_main, Criterion}; // black_box
use neqo_transport::send_stream::RangeTracker;

View file

@ -1,3 +1,9 @@
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use criterion::{criterion_group, criterion_main, Criterion};
use neqo_transport::recv_stream::RxStreamOrderer;

View file

@ -1,3 +1,9 @@
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::time::Duration;
use criterion::{criterion_group, criterion_main, BatchSize::SmallInput, Criterion};

View file

@ -5,9 +5,8 @@
// except according to those terms.
// Management of the peer's ack rate.
#![deny(clippy::pedantic)]
use std::{cmp::max, convert::TryFrom, time::Duration};
use std::{cmp::max, time::Duration};
use neqo_common::qtrace;

View file

@ -7,7 +7,6 @@
// This file implements functions necessary for address validation.
use std::{
convert::TryFrom,
net::{IpAddr, SocketAddr},
time::{Duration, Instant},
};
@ -23,15 +22,15 @@ use crate::{
cid::ConnectionId, packet::PacketBuilder, recovery::RecoveryToken, stats::FrameStats, Res,
};
/// A prefix we add to Retry tokens to distinguish them from NEW_TOKEN tokens.
/// A prefix we add to Retry tokens to distinguish them from `NEW_TOKEN` tokens.
const TOKEN_IDENTIFIER_RETRY: &[u8] = &[0x52, 0x65, 0x74, 0x72, 0x79];
/// A prefix on NEW_TOKEN tokens, that is maximally Hamming distant from NEW_TOKEN.
/// A prefix on `NEW_TOKEN` tokens, that is maximally Hamming distant from `NEW_TOKEN`.
/// Together, these need to have a low probability of collision, even if there is
/// corruption of individual bits in transit.
const TOKEN_IDENTIFIER_NEW_TOKEN: &[u8] = &[0xad, 0x9a, 0x8b, 0x8d, 0x86];
/// The maximum number of tokens we'll save from NEW_TOKEN frames.
/// This should be the same as the value of MAX_TICKETS in neqo-crypto.
/// The maximum number of tokens we'll save from `NEW_TOKEN` frames.
/// This should be the same as the value of `MAX_TICKETS` in neqo-crypto.
const MAX_NEW_TOKEN: usize = 4;
/// The number of tokens we'll track for the purposes of looking for duplicates.
/// This is based on how many might be received over a period where could be
@ -44,9 +43,9 @@ const MAX_SAVED_TOKENS: usize = 8;
pub enum ValidateAddress {
/// Require address validation never.
Never,
/// Require address validation unless a NEW_TOKEN token is provided.
/// Require address validation unless a `NEW_TOKEN` token is provided.
NoToken,
/// Require address validation even if a NEW_TOKEN token is provided.
/// Require address validation even if a `NEW_TOKEN` token is provided.
Always,
}
@ -143,7 +142,7 @@ impl AddressValidation {
self.generate_token(Some(dcid), peer_address, now)
}
/// This generates a token for use with NEW_TOKEN.
/// This generates a token for use with `NEW_TOKEN`.
pub fn generate_new_token(&self, peer_address: SocketAddr, now: Instant) -> Res<Vec<u8>> {
self.generate_token(None, peer_address, now)
}
@ -184,7 +183,7 @@ impl AddressValidation {
/// Less than one difference per byte indicates that it is likely not a Retry.
/// This generous interpretation allows for a lot of damage in transit.
/// Note that if this check fails, then the token will be treated like it came
/// from NEW_TOKEN instead. If there truly is corruption of packets that causes
/// from `NEW_TOKEN` instead. If there truly is corruption of packets that causes
/// validation failure, it will be a failure that we try to recover from.
fn is_likely_retry(token: &[u8]) -> bool {
let mut difference = 0;
@ -210,10 +209,9 @@ impl AddressValidation {
if self.validation == ValidateAddress::Never {
qinfo!("AddressValidation: no token; accepting");
return AddressValidationResult::Pass;
} else {
qinfo!("AddressValidation: no token; validating");
return AddressValidationResult::Validate;
}
qinfo!("AddressValidation: no token; validating");
return AddressValidationResult::Validate;
}
if token.len() <= TOKEN_IDENTIFIER_RETRY.len() {
// Treat bad tokens strictly.
@ -231,7 +229,7 @@ impl AddressValidation {
qinfo!("AddressValidation: valid Retry token for {}", cid);
AddressValidationResult::ValidRetry(cid)
} else {
panic!("AddressValidation: Retry token with small CID {}", cid);
panic!("AddressValidation: Retry token with small CID {cid}");
}
} else if cid.is_empty() {
// An empty connection ID means NEW_TOKEN.
@ -243,7 +241,7 @@ impl AddressValidation {
AddressValidationResult::Pass
}
} else {
panic!("AddressValidation: NEW_TOKEN token with CID {}", cid);
panic!("AddressValidation: NEW_TOKEN token with CID {cid}");
}
} else {
// From here on, we have a token that we couldn't decrypt.
@ -351,14 +349,13 @@ impl NewTokenState {
builder: &mut PacketBuilder,
tokens: &mut Vec<RecoveryToken>,
stats: &mut FrameStats,
) -> Res<()> {
) {
if let Self::Server(ref mut sender) = self {
sender.write_frames(builder, tokens, stats)?;
sender.write_frames(builder, tokens, stats);
}
Ok(())
}
/// If this a server, buffer a NEW_TOKEN for sending.
/// If this a server, buffer a `NEW_TOKEN` for sending.
/// If this is a client, panic.
pub fn send_new_token(&mut self, token: Vec<u8>) {
if let Self::Server(ref mut sender) = self {
@ -368,7 +365,7 @@ impl NewTokenState {
}
}
/// If this a server, process a lost signal for a NEW_TOKEN frame.
/// If this a server, process a lost signal for a `NEW_TOKEN` frame.
/// If this is a client, panic.
pub fn lost(&mut self, seqno: usize) {
if let Self::Server(ref mut sender) = self {
@ -378,7 +375,7 @@ impl NewTokenState {
}
}
/// If this a server, process remove the acknowledged NEW_TOKEN frame.
/// If this a server, process remove the acknowledged `NEW_TOKEN` frame.
/// If this is a client, panic.
pub fn acked(&mut self, seqno: usize) {
if let Self::Server(ref mut sender) = self {
@ -403,7 +400,7 @@ impl NewTokenFrameStatus {
#[derive(Default)]
pub struct NewTokenSender {
/// The unacknowledged NEW_TOKEN frames we are yet to send.
/// The unacknowledged `NEW_TOKEN` frames we are yet to send.
tokens: Vec<NewTokenFrameStatus>,
/// A sequence number that is used to track individual tokens
/// by reference (so that recovery tokens can be simple).
@ -426,8 +423,8 @@ impl NewTokenSender {
builder: &mut PacketBuilder,
tokens: &mut Vec<RecoveryToken>,
stats: &mut FrameStats,
) -> Res<()> {
for t in self.tokens.iter_mut() {
) {
for t in &mut self.tokens {
if t.needs_sending && t.len() <= builder.remaining() {
t.needs_sending = false;
@ -438,11 +435,10 @@ impl NewTokenSender {
stats.new_token += 1;
}
}
Ok(())
}
pub fn lost(&mut self, seqno: usize) {
for t in self.tokens.iter_mut() {
for t in &mut self.tokens {
if t.seqno == seqno {
t.needs_sending = true;
break;

View file

@ -5,7 +5,6 @@
// except according to those terms.
// Congestion control
#![deny(clippy::pedantic)]
use std::{
cmp::{max, min},
@ -536,10 +535,7 @@ impl<T: WindowAdjustment> ClassicCongestionControl<T> {
#[cfg(test)]
mod tests {
use std::{
convert::TryFrom,
time::{Duration, Instant},
};
use std::time::{Duration, Instant};
use neqo_common::qinfo;
use test_fixture::now;

View file

@ -4,10 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![deny(clippy::pedantic)]
use std::{
convert::TryFrom,
fmt::{self, Display},
time::{Duration, Instant},
};

View file

@ -5,7 +5,6 @@
// except according to those terms.
// Congestion control
#![deny(clippy::pedantic)]
use std::{
fmt::{Debug, Display},

View file

@ -5,7 +5,6 @@
// except according to those terms.
// Congestion control
#![deny(clippy::pedantic)]
use std::{
fmt::{self, Display},

View file

@ -8,7 +8,6 @@
#![allow(clippy::cast_sign_loss)]
use std::{
convert::TryFrom,
ops::Sub,
time::{Duration, Instant},
};

View file

@ -1,3 +1,4 @@
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed

View file

@ -5,7 +5,6 @@
// except according to those terms.
// Congestion control
#![deny(clippy::pedantic)]
use std::time::Duration;

View file

@ -10,7 +10,6 @@ use std::{
borrow::Borrow,
cell::{Ref, RefCell},
cmp::{max, min},
convert::{AsRef, TryFrom},
ops::Deref,
rc::Rc,
};
@ -39,6 +38,9 @@ pub struct ConnectionId {
}
impl ConnectionId {
/// # Panics
/// When `len` is larger than `MAX_CONNECTION_ID_LEN`.
#[must_use]
pub fn generate(len: usize) -> Self {
assert!(matches!(len, 0..=MAX_CONNECTION_ID_LEN));
let mut cid = smallvec![0; len];
@ -47,6 +49,7 @@ impl ConnectionId {
}
// Apply a wee bit of greasing here in picking a length between 8 and 20 bytes long.
#[must_use]
pub fn generate_initial() -> Self {
let v = random::<1>()[0];
// Bias selection toward picking 8 (>50% of the time).
@ -54,6 +57,7 @@ impl ConnectionId {
Self::generate(len)
}
#[must_use]
pub fn as_cid_ref(&self) -> ConnectionIdRef {
ConnectionIdRef::from(&self.cid[..])
}
@ -197,7 +201,7 @@ impl ConnectionIdGenerator for EmptyConnectionIdGenerator {
}
}
/// An RandomConnectionIdGenerator produces connection IDs of
/// An `RandomConnectionIdGenerator` produces connection IDs of
/// a fixed length and random content. No effort is made to
/// prevent collisions.
pub struct RandomConnectionIdGenerator {
@ -205,6 +209,7 @@ pub struct RandomConnectionIdGenerator {
}
impl RandomConnectionIdGenerator {
#[must_use]
pub fn new(len: usize) -> Self {
Self { len }
}
@ -232,7 +237,7 @@ impl ConnectionIdGenerator for RandomConnectionIdGenerator {
}
}
/// A single connection ID, as saved from NEW_CONNECTION_ID.
/// A single connection ID, as saved from `NEW_CONNECTION_ID`.
/// This is templated so that the connection ID entries from a peer can be
/// saved with a stateless reset token. Local entries don't need that.
#[derive(Debug, PartialEq, Eq, Clone)]
@ -292,6 +297,23 @@ impl ConnectionIdEntry<[u8; 16]> {
pub fn sequence_number(&self) -> u64 {
self.seqno
}
/// Write the entry out in a `NEW_CONNECTION_ID` frame.
/// Returns `true` if the frame was written, `false` if there is insufficient space.
pub fn write(&self, builder: &mut PacketBuilder, stats: &mut FrameStats) -> bool {
let len = 1 + Encoder::varint_len(self.seqno) + 1 + 1 + self.cid.len() + 16;
if builder.remaining() < len {
return false;
}
builder.encode_varint(FRAME_TYPE_NEW_CONNECTION_ID);
builder.encode_varint(self.seqno);
builder.encode_varint(0u64);
builder.encode_vec(1, &self.cid);
builder.encode(&self.srt);
stats.new_connection_id += 1;
true
}
}
impl ConnectionIdEntry<()> {
@ -428,7 +450,7 @@ pub struct ConnectionIdManager {
limit: usize,
/// The next sequence number that will be used for sending `NEW_CONNECTION_ID` frames.
next_seqno: u64,
/// Outstanding, but lost NEW_CONNECTION_ID frames will be stored here.
/// Outstanding, but lost `NEW_CONNECTION_ID` frames will be stored here.
lost_new_connection_id: Vec<ConnectionIdEntry<[u8; 16]>>,
}
@ -514,39 +536,19 @@ impl ConnectionIdManager {
);
}
fn write_entry(
&mut self,
entry: &ConnectionIdEntry<[u8; 16]>,
builder: &mut PacketBuilder,
stats: &mut FrameStats,
) -> Res<bool> {
let len = 1 + Encoder::varint_len(entry.seqno) + 1 + 1 + entry.cid.len() + 16;
if builder.remaining() < len {
return Ok(false);
}
builder.encode_varint(FRAME_TYPE_NEW_CONNECTION_ID);
builder.encode_varint(entry.seqno);
builder.encode_varint(0u64);
builder.encode_vec(1, &entry.cid);
builder.encode(&entry.srt);
stats.new_connection_id += 1;
Ok(true)
}
pub fn write_frames(
&mut self,
builder: &mut PacketBuilder,
tokens: &mut Vec<RecoveryToken>,
stats: &mut FrameStats,
) -> Res<()> {
) {
if self.generator.deref().borrow().generates_empty_cids() {
debug_assert_eq!(self.generator.borrow_mut().generate_cid().unwrap().len(), 0);
return Ok(());
return;
}
while let Some(entry) = self.lost_new_connection_id.pop() {
if self.write_entry(&entry, builder, stats)? {
if entry.write(builder, stats) {
tokens.push(RecoveryToken::NewConnectionId(entry));
} else {
// This shouldn't happen often.
@ -571,11 +573,10 @@ impl ConnectionIdManager {
.add_local(ConnectionIdEntry::new(seqno, cid.clone(), ()));
let entry = ConnectionIdEntry::new(seqno, cid, srt);
self.write_entry(&entry, builder, stats)?;
entry.write(builder, stats);
tokens.push(RecoveryToken::NewConnectionId(entry));
}
}
Ok(())
}
pub fn lost(&mut self, entry: &ConnectionIdEntry<[u8; 16]>) {
@ -592,16 +593,17 @@ impl ConnectionIdManager {
mod tests {
use test_fixture::fixture_init;
use super::*;
use crate::{cid::MAX_CONNECTION_ID_LEN, ConnectionId};
#[test]
fn generate_initial_cid() {
fixture_init();
for _ in 0..100 {
let cid = ConnectionId::generate_initial();
if !matches!(cid.len(), 8..=MAX_CONNECTION_ID_LEN) {
panic!("connection ID {:?}", cid);
}
assert!(
matches!(cid.len(), 8..=MAX_CONNECTION_ID_LEN),
"connection ID length {cid:?}",
);
}
}
}

View file

@ -27,11 +27,11 @@ pub fn dump_packet(
pn: PacketNumber,
payload: &[u8],
) {
if !log::log_enabled!(log::Level::Debug) {
if log::STATIC_MAX_LEVEL == log::LevelFilter::Off || !log::log_enabled!(log::Level::Debug) {
return;
}
let mut s = String::from("");
let mut s = String::new();
let mut d = Decoder::from(payload);
while d.remaining() > 0 {
let Ok(f) = Frame::decode(&mut d) else {

View file

@ -9,7 +9,6 @@
use std::{
cell::RefCell,
cmp::{max, min},
convert::TryFrom,
fmt::{self, Debug},
mem,
net::{IpAddr, SocketAddr},
@ -48,6 +47,7 @@ use crate::{
recovery::{LossRecovery, RecoveryToken, SendProfile},
recv_stream::RecvStreamStats,
rtt::GRANULARITY,
send_stream::SendStream,
stats::{Stats, StatsCell},
stream_id::StreamType,
streams::{SendOrder, Streams},
@ -95,7 +95,7 @@ pub enum ZeroRttState {
}
#[derive(Clone, Debug, PartialEq, Eq)]
/// Type returned from process() and `process_output()`. Users are required to
/// Type returned from `process()` and `process_output()`. Users are required to
/// call these repeatedly until `Callback` or `None` is returned.
pub enum Output {
/// Connection requires no action.
@ -118,6 +118,7 @@ impl Output {
}
/// Get a reference to the Datagram, if any.
#[must_use]
pub fn as_dgram_ref(&self) -> Option<&Datagram> {
match self {
Self::Datagram(dg) => Some(dg),
@ -135,7 +136,7 @@ impl Output {
}
}
/// Used by inner functions like Connection::output.
/// Used by inner functions like `Connection::output`.
enum SendOption {
/// Yes, please send this datagram.
Yes(Datagram),
@ -256,7 +257,7 @@ pub struct Connection {
/// Some packets were received, but not tracked.
received_untracked: bool,
/// This is responsible for the QuicDatagrams' handling:
/// This is responsible for the `QuicDatagrams`' handling:
/// <https://datatracker.ietf.org/doc/html/draft-ietf-quic-datagram>
quic_datagrams: QuicDatagrams,
@ -270,8 +271,8 @@ pub struct Connection {
new_token: NewTokenState,
stats: StatsCell,
qlog: NeqoQlog,
/// A session ticket was received without NEW_TOKEN,
/// this is when that turns into an event without NEW_TOKEN.
/// A session ticket was received without `NEW_TOKEN`,
/// this is when that turns into an event without `NEW_TOKEN`.
release_resumption_token_timer: Option<Instant>,
conn_params: ConnectionParameters,
hrtime: hrtime::Handle,
@ -301,6 +302,8 @@ impl Connection {
const LOOSE_TIMER_RESOLUTION: Duration = Duration::from_millis(50);
/// Create a new QUIC connection with Client role.
/// # Errors
/// When NSS fails and an agent cannot be created.
pub fn new_client(
server_name: impl Into<String>,
protocols: &[impl AsRef<str>],
@ -337,6 +340,8 @@ impl Connection {
}
/// Create a new QUIC connection with Server role.
/// # Errors
/// When NSS fails and an agent cannot be created.
pub fn new_server(
certs: &[impl AsRef<str>],
protocols: &[impl AsRef<str>],
@ -426,6 +431,8 @@ impl Connection {
Ok(c)
}
/// # Errors
/// When the operation fails.
pub fn server_enable_0rtt(
&mut self,
anti_replay: &AntiReplay,
@ -435,6 +442,8 @@ impl Connection {
.server_enable_0rtt(self.tps.clone(), anti_replay, zero_rtt_checker)
}
/// # Errors
/// When the operation fails.
pub fn server_enable_ech(
&mut self,
config: u8,
@ -446,10 +455,13 @@ impl Connection {
}
/// Get the active ECH configuration, which is empty if ECH is disabled.
#[must_use]
pub fn ech_config(&self) -> &[u8] {
self.crypto.ech_config()
}
/// # Errors
/// When the operation fails.
pub fn client_enable_ech(&mut self, ech_config_list: impl AsRef<[u8]>) -> Res<()> {
self.crypto.client_enable_ech(ech_config_list)
}
@ -467,8 +479,9 @@ impl Connection {
}
/// Get the original destination connection id for this connection. This
/// will always be present for Role::Client but not if Role::Server is in
/// State::Init.
/// will always be present for `Role::Client` but not if `Role::Server` is in
/// `State::Init`.
#[must_use]
pub fn odcid(&self) -> Option<&ConnectionId> {
self.original_destination_cid.as_ref()
}
@ -477,8 +490,9 @@ impl Connection {
/// This only sets transport parameters without dealing with other aspects of
/// setting the value.
///
/// # Errors
/// When the transport parameter is invalid.
/// # 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))]
@ -501,9 +515,9 @@ impl Connection {
/// Retry.
pub(crate) fn set_retry_cids(
&mut self,
odcid: ConnectionId,
odcid: &ConnectionId,
remote_cid: ConnectionId,
retry_cid: ConnectionId,
retry_cid: &ConnectionId,
) {
debug_assert_eq!(self.role, Role::Server);
qtrace!(
@ -532,12 +546,16 @@ impl Connection {
/// Set ALPN preferences. Strings that appear earlier in the list are given
/// higher preference.
/// # Errors
/// When the operation fails, which is usually due to bad inputs or bad connection state.
pub fn set_alpn(&mut self, protocols: &[impl AsRef<str>]) -> Res<()> {
self.crypto.tls.set_alpn(protocols)?;
Ok(())
}
/// Enable a set of ciphers.
/// # Errors
/// When the operation fails, which is usually due to bad inputs or bad connection state.
pub fn set_ciphers(&mut self, ciphers: &[Cipher]) -> Res<()> {
if self.state != State::Init {
qerror!([self], "Cannot enable ciphers in state {:?}", self.state);
@ -548,6 +566,8 @@ impl Connection {
}
/// Enable a set of key exchange groups.
/// # Errors
/// When the operation fails, which is usually due to bad inputs or bad connection state.
pub fn set_groups(&mut self, groups: &[Group]) -> Res<()> {
if self.state != State::Init {
qerror!([self], "Cannot enable groups in state {:?}", self.state);
@ -558,6 +578,8 @@ impl Connection {
}
/// Set the number of additional key shares to send in the client hello.
/// # Errors
/// When the operation fails, which is usually due to bad inputs or bad connection state.
pub fn send_additional_key_shares(&mut self, count: usize) -> Res<()> {
if self.state != State::Init {
qerror!([self], "Cannot enable groups in state {:?}", self.state);
@ -666,6 +688,8 @@ impl Connection {
/// This can only be called once and only on the client.
/// After calling the function, it should be possible to attempt 0-RTT
/// if the token supports that.
/// # Errors
/// When the operation fails, which is usually due to bad inputs or bad connection state.
pub fn enable_resumption(&mut self, now: Instant, token: impl AsRef<[u8]>) -> Res<()> {
if self.state != State::Init {
qerror!([self], "set token in state {:?}", self.state);
@ -682,8 +706,9 @@ 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)?;
let version = Version::try_from(u32::try_from(
dec.decode_uint(4).ok_or(Error::InvalidResumptionToken)?,
)?)?;
qtrace!([self], " version {:?}", version);
if !self.conn_params.get_versions().all().contains(&version) {
return Err(Error::DisabledVersion);
@ -731,13 +756,15 @@ impl Connection {
Ok(())
}
pub(crate) fn set_validation(&mut self, validation: Rc<RefCell<AddressValidation>>) {
pub(crate) fn set_validation(&mut self, validation: &Rc<RefCell<AddressValidation>>) {
qtrace!([self], "Enabling NEW_TOKEN");
assert_eq!(self.role, Role::Server);
self.address_validation = AddressValidationInfo::Server(Rc::downgrade(&validation));
self.address_validation = AddressValidationInfo::Server(Rc::downgrade(validation));
}
/// Send a TLS session ticket AND a NEW_TOKEN frame (if possible).
/// Send a TLS session ticket AND a `NEW_TOKEN` frame (if possible).
/// # Errors
/// When the operation fails, which is usually due to bad inputs or bad connection state.
pub fn send_ticket(&mut self, now: Instant, extra: &[u8]) -> Res<()> {
if self.role == Role::Client {
return Err(Error::WrongRole);
@ -773,15 +800,19 @@ impl Connection {
}
}
#[must_use]
pub fn tls_info(&self) -> Option<&SecretAgentInfo> {
self.crypto.tls.info()
}
/// # Errors
/// When there is no information to obtain.
pub fn tls_preinfo(&self) -> Res<SecretAgentPreInfo> {
Ok(self.crypto.tls.preinfo()?)
}
/// Get the peer's certificate chain and other info.
#[must_use]
pub fn peer_certificate(&self) -> Option<CertificateInfo> {
self.crypto.tls.peer_certificate()
}
@ -801,26 +832,31 @@ impl Connection {
}
/// Get the role of the connection.
#[must_use]
pub fn role(&self) -> Role {
self.role
}
/// Get the state of the connection.
#[must_use]
pub fn state(&self) -> &State {
&self.state
}
/// The QUIC version in use.
#[must_use]
pub fn version(&self) -> Version {
self.version
}
/// Get the 0-RTT state of the connection.
#[must_use]
pub fn zero_rtt_state(&self) -> ZeroRttState {
self.zero_rtt_state
}
/// Get a snapshot of collected statistics.
#[must_use]
pub fn stats(&self) -> Stats {
let mut v = self.stats.borrow().clone();
if let Some(p) = self.paths.primary_fallible() {
@ -887,7 +923,7 @@ impl Connection {
res
}
/// For use with process_input(). Errors there can be ignored, but this
/// For use with `process_input()`. Errors there can be ignored, but this
/// needs to ensure that the state is updated.
fn absorb_error<T>(&mut self, now: Instant, res: Res<T>) -> Option<T> {
self.capture_error(None, now, 0, res).ok()
@ -1233,6 +1269,7 @@ impl Connection {
/// Perform any processing that we might have to do on packets prior to
/// attempting to remove protection.
#[allow(clippy::too_many_lines)] // Yeah, it's a work in progress.
fn preprocess_packet(
&mut self,
packet: &PublicPacket,
@ -1345,17 +1382,17 @@ impl Connection {
}
State::WaitInitial => PreprocessResult::Continue,
State::WaitVersion | State::Handshaking | State::Connected | State::Confirmed => {
if !self.cid_manager.is_valid(packet.dcid()) {
self.stats
.borrow_mut()
.pkt_dropped(format!("Invalid DCID {:?}", packet.dcid()));
PreprocessResult::Next
} else {
if self.cid_manager.is_valid(packet.dcid()) {
if self.role == Role::Server && packet.packet_type() == PacketType::Handshake {
// Server has received a Handshake packet -> discard Initial keys and states
self.discard_keys(PacketNumberSpace::Initial, now);
}
PreprocessResult::Continue
} else {
self.stats
.borrow_mut()
.pkt_dropped(format!("Invalid DCID {:?}", packet.dcid()));
PreprocessResult::Next
}
}
State::Closing { .. } => {
@ -1375,7 +1412,7 @@ impl Connection {
Ok(res)
}
/// After a Initial, Handshake, ZeroRtt, or Short packet is successfully processed.
/// After a Initial, Handshake, `ZeroRtt`, or Short packet is successfully processed.
fn postprocess_packet(
&mut self,
path: &PathRef,
@ -1614,7 +1651,7 @@ impl Connection {
}
}
/// After an error, a permanent path is needed to send the CONNECTION_CLOSE.
/// After an error, a permanent path is needed to send the `CONNECTION_CLOSE`.
/// This attempts to ensure that this exists. As the connection is now
/// temporary, there is no reason to do anything special here.
fn ensure_error_path(&mut self, path: &PathRef, packet: &PublicPacket, now: Instant) {
@ -1813,7 +1850,7 @@ impl Connection {
State::Closing { .. } | State::Draining { .. } | State::Closed(_) => {
if let Some(details) = self.state_signaling.close_frame() {
let path = Rc::clone(details.path());
let res = self.output_close(details);
let res = self.output_close(&details);
self.capture_error(Some(path), now, 0, res)
} else {
Ok(SendOption::default())
@ -1890,7 +1927,7 @@ impl Connection {
}
}
fn output_close(&mut self, close: ClosingFrame) -> Res<SendOption> {
fn output_close(&mut self, close: &ClosingFrame) -> Res<SendOption> {
let mut encoder = Encoder::with_capacity(256);
let grease_quic_bit = self.can_grease_quic_bit();
let version = self.version();
@ -1900,6 +1937,14 @@ impl Connection {
};
let path = close.path().borrow();
// In some error cases, we will not be able to make a new, permanent path.
// For example, if we run out of connection IDs and the error results from
// a packet on a new path, we avoid sending (and the privacy risk) rather
// than reuse a connection ID.
if path.is_temporary() {
assert!(!cfg!(test), "attempting to close with a temporary path");
return Err(Error::InternalError);
}
let (_, mut builder) = Self::build_packet_header(
&path,
cspace,
@ -1930,7 +1975,7 @@ impl Connection {
};
sanitized
.as_ref()
.unwrap_or(&close)
.unwrap_or(close)
.write_frame(&mut builder);
encoder = builder.build(tx)?;
}
@ -1944,11 +1989,11 @@ impl Connection {
&mut self,
builder: &mut PacketBuilder,
tokens: &mut Vec<RecoveryToken>,
) -> Res<()> {
) {
let stats = &mut self.stats.borrow_mut();
let frame_stats = &mut stats.frame_tx;
if self.role == Role::Server {
if let Some(t) = self.state_signaling.write_done(builder)? {
if let Some(t) = self.state_signaling.write_done(builder) {
tokens.push(t);
frame_stats.handshake_done += 1;
}
@ -1957,7 +2002,7 @@ impl Connection {
self.streams
.write_frames(TransmissionPriority::Critical, builder, tokens, frame_stats);
if builder.is_full() {
return Ok(());
return;
}
self.streams.write_frames(
@ -1967,36 +2012,35 @@ impl Connection {
frame_stats,
);
if builder.is_full() {
return Ok(());
return;
}
// NEW_CONNECTION_ID, RETIRE_CONNECTION_ID, and ACK_FREQUENCY.
self.cid_manager
.write_frames(builder, tokens, frame_stats)?;
self.cid_manager.write_frames(builder, tokens, frame_stats);
if builder.is_full() {
return Ok(());
return;
}
self.paths.write_frames(builder, tokens, frame_stats);
if builder.is_full() {
return Ok(());
return;
}
self.streams
.write_frames(TransmissionPriority::High, builder, tokens, frame_stats);
if builder.is_full() {
return Ok(());
return;
}
self.streams
.write_frames(TransmissionPriority::Normal, builder, tokens, frame_stats);
if builder.is_full() {
return Ok(());
return;
}
// Datagrams are best-effort and unreliable. Let streams starve them for now.
self.quic_datagrams.write_frames(builder, tokens, stats);
if builder.is_full() {
return Ok(());
return;
}
let frame_stats = &mut stats.frame_tx;
@ -2007,13 +2051,13 @@ impl Connection {
builder,
tokens,
frame_stats,
)?;
);
if builder.is_full() {
return Ok(());
return;
}
self.new_token.write_frames(builder, tokens, frame_stats)?;
self.new_token.write_frames(builder, tokens, frame_stats);
if builder.is_full() {
return Ok(());
return;
}
self.streams
@ -2025,8 +2069,6 @@ impl Connection {
w.write_frames(builder);
}
}
Ok(())
}
// Maybe send a probe. Return true if the packet was ack-eliciting.
@ -2087,7 +2129,7 @@ impl Connection {
profile: &SendProfile,
builder: &mut PacketBuilder,
now: Instant,
) -> Res<(Vec<RecoveryToken>, bool, bool)> {
) -> (Vec<RecoveryToken>, bool, bool) {
let mut tokens = Vec::new();
let primary = path.borrow().is_primary();
let mut ack_eliciting = false;
@ -2123,16 +2165,15 @@ impl Connection {
if profile.ack_only(space) {
// If we are CC limited we can only send acks!
return Ok((tokens, false, false));
return (tokens, false, false);
}
if primary {
if space == PacketNumberSpace::ApplicationData {
self.write_appdata_frames(builder, &mut tokens)?;
self.write_appdata_frames(builder, &mut tokens);
} else {
let stats = &mut self.stats.borrow_mut().frame_tx;
self.crypto
.write_frame(space, builder, &mut tokens, stats)?;
self.crypto.write_frame(space, builder, &mut tokens, stats);
}
}
@ -2156,11 +2197,12 @@ impl Connection {
};
stats.all += tokens.len();
Ok((tokens, ack_eliciting, padded))
(tokens, ack_eliciting, padded)
}
/// Build a datagram, possibly from multiple packets (for different PN
/// spaces) and each containing 1+ frames.
#[allow(clippy::too_many_lines)] // Yeah, that's just the way it is.
fn output_path(&mut self, path: &PathRef, now: Instant) -> Res<SendOption> {
let mut initial_sent = None;
let mut needs_padding = false;
@ -2215,7 +2257,7 @@ impl Connection {
// Add frames to the packet.
let payload_start = builder.len();
let (tokens, ack_eliciting, padded) =
self.write_frames(path, *space, &profile, &mut builder, now)?;
self.write_frames(path, *space, &profile, &mut builder, now);
if builder.packet_empty() {
// Nothing to include in this packet.
encoder = builder.abort();
@ -2304,6 +2346,8 @@ impl Connection {
}
}
/// # Errors
/// When connection state is not valid.
pub fn initiate_key_update(&mut self) -> Res<()> {
if self.state == State::Confirmed {
let la = self
@ -2317,6 +2361,7 @@ impl Connection {
}
#[cfg(test)]
#[must_use]
pub fn get_epochs(&self) -> (Option<usize>, Option<usize>) {
self.crypto.states.get_epochs()
}
@ -2375,6 +2420,7 @@ impl Connection {
);
}
#[must_use]
pub fn is_stream_id_allowed(&self, stream_id: StreamId) -> bool {
self.streams.is_stream_id_allowed(stream_id)
}
@ -2590,7 +2636,7 @@ impl Connection {
HandshakeState::Authenticated(_) | HandshakeState::InProgress => (),
HandshakeState::AuthenticationPending => {
if !was_authentication_pending {
self.events.authentication_needed()
self.events.authentication_needed();
}
}
HandshakeState::EchFallbackAuthenticationPending(public_name) => self
@ -2627,6 +2673,7 @@ impl Connection {
Ok(())
}
#[allow(clippy::too_many_lines)] // Yep, but it's a nice big match, which is basically lots of little functions.
fn input_frame(
&mut self,
path: &PathRef,
@ -2644,7 +2691,7 @@ impl Connection {
if frame.is_stream() {
return self
.streams
.input_frame(frame, &mut self.stats.borrow_mut().frame_rx);
.input_frame(&frame, &mut self.stats.borrow_mut().frame_rx);
}
match frame {
Frame::Padding => {
@ -3009,11 +3056,10 @@ impl Connection {
Ok(())
}
/// Set the SendOrder of a stream. Re-enqueues to keep the ordering correct
/// Set the `SendOrder` of a stream. Re-enqueues to keep the ordering correct
///
/// # Errors
///
/// Returns InvalidStreamId if the stream id doesn't exist
/// When the stream does not exist.
pub fn stream_sendorder(
&mut self,
stream_id: StreamId,
@ -3025,16 +3071,21 @@ impl Connection {
/// Set the Fairness of a stream
///
/// # Errors
///
/// Returns InvalidStreamId if the stream id doesn't exist
/// When the stream does not exist.
pub fn stream_fairness(&mut self, stream_id: StreamId, fairness: bool) -> Res<()> {
self.streams.set_fairness(stream_id, fairness)
}
/// # Errors
/// When the stream does not exist.
pub fn send_stream_stats(&self, stream_id: StreamId) -> Res<SendStreamStats> {
self.streams.get_send_stream(stream_id).map(|s| s.stats())
self.streams
.get_send_stream(stream_id)
.map(SendStream::stats)
}
/// # Errors
/// When the stream does not exist.
pub fn recv_stream_stats(&mut self, stream_id: StreamId) -> Res<RecvStreamStats> {
let stream = self.streams.get_recv_stream_mut(stream_id)?;
@ -3054,8 +3105,8 @@ impl Connection {
self.streams.get_send_stream_mut(stream_id)?.send(data)
}
/// Send all data or nothing on a stream. May cause DATA_BLOCKED or
/// STREAM_DATA_BLOCKED frames to be sent.
/// Send all data or nothing on a stream. May cause `DATA_BLOCKED` or
/// `STREAM_DATA_BLOCKED` frames to be sent.
/// Returns true if data was successfully sent, otherwise false.
///
/// # Errors
@ -3079,20 +3130,26 @@ impl Connection {
val.map(|v| v == data.len())
}
/// Bytes that stream_send() is guaranteed to accept for sending.
/// Bytes that `stream_send()` is guaranteed to accept for sending.
/// i.e. that will not be blocked by flow credits or send buffer max
/// capacity.
/// # Errors
/// When the stream ID is invalid.
pub fn stream_avail_send_space(&self, stream_id: StreamId) -> Res<usize> {
Ok(self.streams.get_send_stream(stream_id)?.avail())
}
/// Close the stream. Enqueued data will be sent.
/// # Errors
/// When the stream ID is invalid.
pub fn stream_close_send(&mut self, stream_id: StreamId) -> Res<()> {
self.streams.get_send_stream_mut(stream_id)?.close();
Ok(())
}
/// Abandon transmission of in-flight and future stream data.
/// # Errors
/// When the stream ID is invalid.
pub fn stream_reset_send(&mut self, stream_id: StreamId, err: AppError) -> Res<()> {
self.streams.get_send_stream_mut(stream_id)?.reset(err);
Ok(())
@ -3113,6 +3170,8 @@ impl Connection {
}
/// Application is no longer interested in this stream.
/// # Errors
/// When the stream ID is invalid.
pub fn stream_stop_sending(&mut self, stream_id: StreamId, err: AppError) -> Res<()> {
let stream = self.streams.get_recv_stream_mut(stream_id)?;
@ -3146,6 +3205,7 @@ impl Connection {
self.streams.keep_alive(stream_id, keep)
}
#[must_use]
pub fn remote_datagram_size(&self) -> u64 {
self.quic_datagrams.remote_datagram_size()
}
@ -3154,9 +3214,10 @@ impl Connection {
/// The value will change over time depending on the encoded size of the
/// packet number, ack frames, etc.
///
/// # Error
///
/// # Errors
/// The function returns `NotAvailable` if datagrams are not enabled.
/// # Panics
/// Basically never, because that unwrap won't fail.
pub fn max_datagram_size(&self) -> Res<u64> {
let max_dgram_size = self.quic_datagrams.remote_datagram_size();
if max_dgram_size == 0 {
@ -3197,7 +3258,7 @@ impl Connection {
/// Queue a datagram for sending.
///
/// # Error
/// # Errors
///
/// The function returns `TooMuchData` if the supply buffer is bigger than
/// the allowed remote datagram size. The funcion does not check if the
@ -3207,7 +3268,6 @@ impl Connection {
/// to check the estimated max datagram size and to use smaller datagrams.
/// `max_datagram_size` is just a current estimate and will change over
/// time depending on the encoded size of the packet number, ack frames, etc.
pub fn send_datagram(&mut self, buf: &[u8], id: impl Into<DatagramTracking>) -> Res<()> {
self.quic_datagrams
.add_datagram(buf, id.into(), &mut self.stats.borrow_mut())

View file

@ -4,7 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{cmp::max, convert::TryFrom, time::Duration};
use std::{cmp::max, time::Duration};
pub use crate::recovery::FAST_PTO_SCALE;
use crate::{
@ -41,7 +41,7 @@ pub enum PreferredAddressConfig {
Address(PreferredAddress),
}
/// ConnectionParameters use for setting intitial value for QUIC parameters.
/// `ConnectionParameters` use for setting intitial value for QUIC parameters.
/// This collects configuration like initial limits, protocol version, and
/// congestion control algorithm.
#[derive(Debug, Clone)]
@ -108,6 +108,7 @@ impl Default for ConnectionParameters {
}
impl ConnectionParameters {
#[must_use]
pub fn get_versions(&self) -> &VersionConfig {
&self.versions
}
@ -120,29 +121,35 @@ impl ConnectionParameters {
/// 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.
#[must_use]
pub fn versions(mut self, initial: Version, all: Vec<Version>) -> Self {
self.versions = VersionConfig::new(initial, all);
self
}
#[must_use]
pub fn get_cc_algorithm(&self) -> CongestionControlAlgorithm {
self.cc_algorithm
}
#[must_use]
pub fn cc_algorithm(mut self, v: CongestionControlAlgorithm) -> Self {
self.cc_algorithm = v;
self
}
#[must_use]
pub fn get_max_data(&self) -> u64 {
self.max_data
}
#[must_use]
pub fn max_data(mut self, v: u64) -> Self {
self.max_data = v;
self
}
#[must_use]
pub fn get_max_streams(&self, stream_type: StreamType) -> u64 {
match stream_type {
StreamType::BiDi => self.max_streams_bidi,
@ -153,6 +160,7 @@ impl ConnectionParameters {
/// # Panics
///
/// If v > 2^60 (the maximum allowed by the protocol).
#[must_use]
pub fn max_streams(mut self, stream_type: StreamType, v: u64) -> Self {
assert!(v <= (1 << 60), "max_streams is too large");
match stream_type {
@ -171,6 +179,7 @@ impl ConnectionParameters {
/// # Panics
///
/// If `StreamType::UniDi` and `false` are passed as that is not a valid combination.
#[must_use]
pub fn get_max_stream_data(&self, stream_type: StreamType, remote: bool) -> u64 {
match (stream_type, remote) {
(StreamType::BiDi, false) => self.max_stream_data_bidi_local,
@ -188,6 +197,7 @@ impl ConnectionParameters {
///
/// If `StreamType::UniDi` and `false` are passed as that is not a valid combination
/// or if v >= 62 (the maximum allowed by the protocol).
#[must_use]
pub fn max_stream_data(mut self, stream_type: StreamType, remote: bool, v: u64) -> Self {
assert!(v < (1 << 62), "max stream data is too large");
match (stream_type, remote) {
@ -208,26 +218,31 @@ impl ConnectionParameters {
}
/// Set a preferred address (which only has an effect for a server).
#[must_use]
pub fn preferred_address(mut self, preferred: PreferredAddress) -> Self {
self.preferred_address = PreferredAddressConfig::Address(preferred);
self
}
/// Disable the use of preferred addresses.
#[must_use]
pub fn disable_preferred_address(mut self) -> Self {
self.preferred_address = PreferredAddressConfig::Disabled;
self
}
#[must_use]
pub fn get_preferred_address(&self) -> &PreferredAddressConfig {
&self.preferred_address
}
#[must_use]
pub fn ack_ratio(mut self, ack_ratio: u8) -> Self {
self.ack_ratio = ack_ratio;
self
}
#[must_use]
pub fn get_ack_ratio(&self) -> u8 {
self.ack_ratio
}
@ -235,45 +250,54 @@ impl ConnectionParameters {
/// # Panics
///
/// If `timeout` is 2^62 milliseconds or more.
#[must_use]
pub fn idle_timeout(mut self, timeout: Duration) -> Self {
assert!(timeout.as_millis() < (1 << 62), "idle timeout is too long");
self.idle_timeout = timeout;
self
}
#[must_use]
pub fn get_idle_timeout(&self) -> Duration {
self.idle_timeout
}
#[must_use]
pub fn get_datagram_size(&self) -> u64 {
self.datagram_size
}
#[must_use]
pub fn datagram_size(mut self, v: u64) -> Self {
self.datagram_size = v;
self
}
#[must_use]
pub fn get_outgoing_datagram_queue(&self) -> usize {
self.outgoing_datagram_queue
}
#[must_use]
pub fn outgoing_datagram_queue(mut self, v: usize) -> Self {
// The max queue length must be at least 1.
self.outgoing_datagram_queue = max(v, 1);
self
}
#[must_use]
pub fn get_incoming_datagram_queue(&self) -> usize {
self.incoming_datagram_queue
}
#[must_use]
pub fn incoming_datagram_queue(mut self, v: usize) -> Self {
// The max queue length must be at least 1.
self.incoming_datagram_queue = max(v, 1);
self
}
#[must_use]
pub fn get_fast_pto(&self) -> u8 {
self.fast_pto
}
@ -293,39 +317,50 @@ impl ConnectionParameters {
/// # Panics
///
/// A value of 0 is invalid and will cause a panic.
#[must_use]
pub fn fast_pto(mut self, scale: u8) -> Self {
assert_ne!(scale, 0);
self.fast_pto = scale;
self
}
#[must_use]
pub fn is_fuzzing(&self) -> bool {
self.fuzzing
}
#[must_use]
pub fn fuzzing(mut self, enable: bool) -> Self {
self.fuzzing = enable;
self
}
#[must_use]
pub fn is_greasing(&self) -> bool {
self.grease
}
#[must_use]
pub fn grease(mut self, grease: bool) -> Self {
self.grease = grease;
self
}
#[must_use]
pub fn pacing_enabled(&self) -> bool {
self.pacing
}
#[must_use]
pub fn pacing(mut self, pacing: bool) -> Self {
self.pacing = pacing;
self
}
/// # Errors
/// When a connection ID cannot be obtained.
/// # Panics
/// Only when this code includes a transport parameter that is invalid.
pub fn create_transport_parameter(
&self,
role: Role,

View file

@ -21,7 +21,7 @@ use crate::{
packet::PacketBuilder,
path::PathRef,
recovery::RecoveryToken,
ConnectionError, Error, Res,
ConnectionError, Error,
};
#[derive(Clone, Debug, PartialEq, Eq)]
@ -66,6 +66,7 @@ impl State {
)
}
#[must_use]
pub fn error(&self) -> Option<&ConnectionError> {
if let Self::Closing { error, .. } | Self::Draining { error, .. } | Self::Closed(error) =
self
@ -184,13 +185,13 @@ impl ClosingFrame {
}
}
/// `StateSignaling` manages whether we need to send HANDSHAKE_DONE and CONNECTION_CLOSE.
/// `StateSignaling` manages whether we need to send `HANDSHAKE_DONE` and `CONNECTION_CLOSE`.
/// Valid state transitions are:
/// * Idle -> HandshakeDone: at the server when the handshake completes
/// * HandshakeDone -> Idle: when a HANDSHAKE_DONE frame is sent
/// * Idle -> `HandshakeDone`: at the server when the handshake completes
/// * `HandshakeDone` -> Idle: when a `HANDSHAKE_DONE` frame is sent
/// * Idle/HandshakeDone -> Closing/Draining: when closing or draining
/// * Closing/Draining -> CloseSent: after sending CONNECTION_CLOSE
/// * CloseSent -> Closing: any time a new CONNECTION_CLOSE is needed
/// * Closing/Draining -> `CloseSent`: after sending `CONNECTION_CLOSE`
/// * `CloseSent` -> Closing: any time a new `CONNECTION_CLOSE` is needed
/// * -> Reset: from any state in case of a stateless reset
#[derive(Debug, Clone)]
pub enum StateSignaling {
@ -214,13 +215,13 @@ impl StateSignaling {
*self = Self::HandshakeDone;
}
pub fn write_done(&mut self, builder: &mut PacketBuilder) -> Res<Option<RecoveryToken>> {
pub fn write_done(&mut self, builder: &mut PacketBuilder) -> Option<RecoveryToken> {
if matches!(self, Self::HandshakeDone) && builder.remaining() >= 1 {
*self = Self::Idle;
builder.encode_varint(FRAME_TYPE_HANDSHAKE_DONE);
Ok(Some(RecoveryToken::HandshakeDone))
Some(RecoveryToken::HandshakeDone)
} else {
Ok(None)
None
}
}

View file

@ -4,7 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{convert::TryFrom, mem, time::Duration};
use std::{mem, time::Duration};
use neqo_common::{qdebug, qinfo, Datagram};
@ -71,6 +71,7 @@ fn cc_slow_start_to_cong_avoidance_recovery_period() {
client.stats().frame_rx.largest_acknowledged,
flight1_largest
);
let cwnd_before_cong = cwnd(&client);
// Client: send more
let (mut c_tx_dgrams, mut now) = fill_cwnd(&mut client, stream_id, now);
@ -93,6 +94,7 @@ fn cc_slow_start_to_cong_avoidance_recovery_period() {
client.stats().frame_rx.largest_acknowledged,
flight2_largest
);
assert!(cwnd(&client) < cwnd_before_cong);
}
#[test]

View file

@ -6,7 +6,7 @@
use std::time::Duration;
use test_fixture::{self, datagram, now};
use test_fixture::{datagram, now};
use super::{
super::{Connection, Output, State},

View file

@ -4,7 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{cell::RefCell, convert::TryFrom, rc::Rc};
use std::{cell::RefCell, rc::Rc};
use neqo_common::event::Provider;
use test_fixture::now;

View file

@ -4,8 +4,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(clippy::pedantic)]
#![cfg(feature = "fuzzing")]
use neqo_crypto::FIXED_TAG_FUZZING;

View file

@ -6,7 +6,6 @@
use std::{
cell::RefCell,
convert::TryFrom,
mem,
net::{IpAddr, Ipv6Addr, SocketAddr},
rc::Rc,
@ -18,8 +17,8 @@ use neqo_crypto::{
constants::TLS_CHACHA20_POLY1305_SHA256, generate_ech_keys, AuthenticationStatus,
};
use test_fixture::{
self, assertions, assertions::assert_coalesced_0rtt, datagram, fixture_init, now,
split_datagram, DEFAULT_ADDR,
assertions, assertions::assert_coalesced_0rtt, datagram, fixture_init, now, split_datagram,
DEFAULT_ADDR,
};
use super::{
@ -347,7 +346,7 @@ fn reorder_05rtt_with_0rtt() {
let mut server = default_server();
let validation = AddressValidation::new(now(), ValidateAddress::NoToken).unwrap();
let validation = Rc::new(RefCell::new(validation));
server.set_validation(Rc::clone(&validation));
server.set_validation(&validation);
let mut now = connect_with_rtt(&mut client, &mut server, now(), RTT);
// Include RTT in sending the ticket or the ticket age reported by the

View file

@ -10,7 +10,7 @@ use std::{
};
use neqo_common::{qtrace, Encoder};
use test_fixture::{self, now, split_datagram};
use test_fixture::{now, split_datagram};
use super::{
super::{Connection, ConnectionParameters, IdleTimeout, Output, State},
@ -310,28 +310,20 @@ fn idle_caching() {
server.process_input(&dgram.unwrap(), middle);
assert_eq!(server.stats().frame_rx.ping, ping_before_s + 1);
let mut tokens = Vec::new();
server
.crypto
.streams
.write_frame(
PacketNumberSpace::Initial,
&mut builder,
&mut tokens,
&mut FrameStats::default(),
)
.unwrap();
server.crypto.streams.write_frame(
PacketNumberSpace::Initial,
&mut builder,
&mut tokens,
&mut FrameStats::default(),
);
assert_eq!(tokens.len(), 1);
tokens.clear();
server
.crypto
.streams
.write_frame(
PacketNumberSpace::Initial,
&mut builder,
&mut tokens,
&mut FrameStats::default(),
)
.unwrap();
server.crypto.streams.write_frame(
PacketNumberSpace::Initial,
&mut builder,
&mut tokens,
&mut FrameStats::default(),
);
assert!(tokens.is_empty());
let dgram = server.process_output(middle).dgram();

View file

@ -7,7 +7,7 @@
use std::mem;
use neqo_common::{qdebug, Datagram};
use test_fixture::{self, now};
use test_fixture::now;
use super::{
super::{

Some files were not shown because too many files have changed in this diff Show more