summaryrefslogtreecommitdiffstats
path: root/third_party/rust/neqo-transport/src/connection
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--third_party/rust/neqo-transport/src/connection/dump.rs16
-rw-r--r--third_party/rust/neqo-transport/src/connection/mod.rs160
-rw-r--r--third_party/rust/neqo-transport/src/connection/params.rs13
-rw-r--r--third_party/rust/neqo-transport/src/connection/state.rs5
-rw-r--r--third_party/rust/neqo-transport/src/connection/tests/fuzzing.rs42
-rw-r--r--third_party/rust/neqo-transport/src/connection/tests/handshake.rs11
-rw-r--r--third_party/rust/neqo-transport/src/connection/tests/mod.rs85
-rw-r--r--third_party/rust/neqo-transport/src/connection/tests/null.rs42
-rw-r--r--third_party/rust/neqo-transport/src/connection/tests/stream.rs6
9 files changed, 199 insertions, 181 deletions
diff --git a/third_party/rust/neqo-transport/src/connection/dump.rs b/third_party/rust/neqo-transport/src/connection/dump.rs
index 8a4f34dbb8..12d337c570 100644
--- a/third_party/rust/neqo-transport/src/connection/dump.rs
+++ b/third_party/rust/neqo-transport/src/connection/dump.rs
@@ -9,7 +9,7 @@
use std::fmt::Write;
-use neqo_common::{qdebug, Decoder};
+use neqo_common::{qdebug, Decoder, IpTos};
use crate::{
connection::Connection,
@@ -26,6 +26,7 @@ pub fn dump_packet(
pt: PacketType,
pn: PacketNumber,
payload: &[u8],
+ tos: IpTos,
) {
if log::STATIC_MAX_LEVEL == log::LevelFilter::Off || !log::log_enabled!(log::Level::Debug) {
return;
@@ -38,9 +39,18 @@ pub fn dump_packet(
s.push_str(" [broken]...");
break;
};
- if let Some(x) = f.dump() {
+ let x = f.dump();
+ if !x.is_empty() {
write!(&mut s, "\n {} {}", dir, &x).unwrap();
}
}
- qdebug!([conn], "pn={} type={:?} {}{}", pn, pt, path.borrow(), s);
+ qdebug!(
+ [conn],
+ "pn={} type={:?} {} {:?}{}",
+ pn,
+ pt,
+ path.borrow(),
+ tos,
+ s
+ );
}
diff --git a/third_party/rust/neqo-transport/src/connection/mod.rs b/third_party/rust/neqo-transport/src/connection/mod.rs
index c81a3727c6..8522507a69 100644
--- a/third_party/rust/neqo-transport/src/connection/mod.rs
+++ b/third_party/rust/neqo-transport/src/connection/mod.rs
@@ -10,7 +10,7 @@ use std::{
cell::RefCell,
cmp::{max, min},
fmt::{self, Debug},
- mem,
+ iter, mem,
net::{IpAddr, SocketAddr},
ops::RangeInclusive,
rc::{Rc, Weak},
@@ -19,7 +19,7 @@ use std::{
use neqo_common::{
event::Provider as EventProvider, hex, hex_snip_middle, hrtime, qdebug, qerror, qinfo,
- qlog::NeqoQlog, qtrace, qwarn, Datagram, Decoder, Encoder, Role,
+ qlog::NeqoQlog, qtrace, qwarn, Datagram, Decoder, Encoder, IpTos, Role,
};
use neqo_crypto::{
agent::CertificateInfo, Agent, AntiReplay, AuthenticationStatus, Cipher, Client, Group,
@@ -383,7 +383,6 @@ impl Connection {
agent,
protocols.iter().map(P::as_ref).map(String::from).collect(),
Rc::clone(&tphandler),
- conn_params.is_fuzzing(),
)?;
let stats = StatsCell::default();
@@ -461,7 +460,7 @@ impl Connection {
}
/// # Errors
- /// When the operation fails.
+ /// 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)
}
@@ -778,7 +777,7 @@ impl Connection {
});
enc.encode(extra);
let records = s.send_ticket(now, enc.as_ref())?;
- qinfo!([self], "send session ticket {}", hex(&enc));
+ qdebug!([self], "send session ticket {}", hex(&enc));
self.crypto.buffer_records(records)?;
} else {
unreachable!();
@@ -824,7 +823,7 @@ impl Connection {
/// the connection to fail. However, if no packets have been
/// exchanged, it's not OK.
pub fn authenticated(&mut self, status: AuthenticationStatus, now: Instant) {
- qinfo!([self], "Authenticated {:?}", status);
+ qdebug!([self], "Authenticated {:?}", status);
self.crypto.tls.authenticated(status);
let res = self.handshake(now, self.version, PacketNumberSpace::Handshake, None);
self.absorb_error(now, res);
@@ -979,19 +978,16 @@ impl Connection {
/// Process new input datagrams on the connection.
pub fn process_input(&mut self, d: &Datagram, now: Instant) {
- self.input(d, now, now);
- self.process_saved(now);
- self.streams.cleanup_closed_streams();
+ self.process_multiple_input(iter::once(d), now);
}
/// Process new input datagrams on the connection.
pub fn process_multiple_input<'a, I>(&mut self, dgrams: I, now: Instant)
where
I: IntoIterator<Item = &'a Datagram>,
- I::IntoIter: ExactSizeIterator,
{
- let dgrams = dgrams.into_iter();
- if dgrams.len() == 0 {
+ let mut dgrams = dgrams.into_iter().peekable();
+ if dgrams.peek().is_none() {
return;
}
@@ -1154,7 +1150,7 @@ impl Connection {
fn discard_keys(&mut self, space: PacketNumberSpace, now: Instant) {
if self.crypto.discard(space) {
- qinfo!([self], "Drop packet number space {}", space);
+ qdebug!([self], "Drop packet number space {}", space);
let primary = self.paths.primary();
self.loss_recovery.discard(&primary, space, now);
self.acks.drop_space(space);
@@ -1492,6 +1488,7 @@ impl Connection {
payload.packet_type(),
payload.pn(),
&payload[..],
+ d.tos(),
);
qlog::packet_received(&mut self.qlog, &packet, &payload);
@@ -1552,6 +1549,10 @@ impl Connection {
packet: &DecryptedPacket,
now: Instant,
) -> Res<bool> {
+ (!packet.is_empty())
+ .then_some(())
+ .ok_or(Error::ProtocolViolation)?;
+
// TODO(ekr@rtfm.com): Have the server blow away the initial
// crypto state if this fails? Otherwise, we will get a panic
// on the assert for doesn't exist.
@@ -1560,24 +1561,8 @@ impl Connection {
let mut ack_eliciting = false;
let mut probing = true;
let mut d = Decoder::from(&packet[..]);
- let mut consecutive_padding = 0;
while d.remaining() > 0 {
- let mut f = Frame::decode(&mut d)?;
-
- // Skip padding
- while f == Frame::Padding && d.remaining() > 0 {
- consecutive_padding += 1;
- f = Frame::decode(&mut d)?;
- }
- if consecutive_padding > 0 {
- qdebug!(
- [self],
- "PADDING frame repeated {} times",
- consecutive_padding
- );
- consecutive_padding = 0;
- }
-
+ let f = Frame::decode(&mut d)?;
ack_eliciting |= f.ack_eliciting();
probing &= f.path_probing();
let t = f.get_type();
@@ -1841,7 +1826,7 @@ impl Connection {
| State::Connected
| State::Confirmed => {
if let Some(path) = self.paths.select_path() {
- let res = self.output_path(&path, now);
+ let res = self.output_path(&path, now, &None);
self.capture_error(Some(path), now, 0, res)
} else {
Ok(SendOption::default())
@@ -1850,7 +1835,16 @@ 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);
+ // 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.
+ let res = if path.borrow().is_temporary() {
+ assert!(!cfg!(test), "attempting to close with a temporary path");
+ Err(Error::InternalError)
+ } else {
+ self.output_path(&path, now, &Some(details))
+ };
self.capture_error(Some(path), now, 0, res)
} else {
Ok(SendOption::default())
@@ -1927,62 +1921,6 @@ impl Connection {
}
}
- 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();
- for space in PacketNumberSpace::iter() {
- let Some((cspace, tx)) = self.crypto.states.select_tx_mut(self.version, *space) else {
- continue;
- };
-
- 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,
- encoder,
- tx,
- &AddressValidationInfo::None,
- version,
- grease_quic_bit,
- );
- _ = Self::add_packet_number(
- &mut builder,
- tx,
- self.loss_recovery.largest_acknowledged_pn(*space),
- );
- // The builder will set the limit to 0 if there isn't enough space for the header.
- if builder.is_full() {
- encoder = builder.abort();
- break;
- }
- builder.set_limit(min(path.amplification_limit(), path.mtu()) - tx.expansion());
- debug_assert!(builder.limit() <= 2048);
-
- // ConnectionError::Application is only allowed at 1RTT.
- let sanitized = if *space == PacketNumberSpace::ApplicationData {
- None
- } else {
- close.sanitize()
- };
- sanitized
- .as_ref()
- .unwrap_or(close)
- .write_frame(&mut builder);
- encoder = builder.build(tx)?;
- }
-
- Ok(SendOption::Yes(close.path().borrow().datagram(encoder)))
- }
-
/// Write the frames that are exchanged in the application data space.
/// The order of calls here determines the relative priority of frames.
fn write_appdata_frames(
@@ -2203,7 +2141,12 @@ impl Connection {
/// 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> {
+ fn output_path(
+ &mut self,
+ path: &PathRef,
+ now: Instant,
+ closing_frame: &Option<ClosingFrame>,
+ ) -> Res<SendOption> {
let mut initial_sent = None;
let mut needs_padding = false;
let grease_quic_bit = self.can_grease_quic_bit();
@@ -2256,8 +2199,23 @@ 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);
+ let (mut tokens, mut ack_eliciting, mut padded) = (Vec::new(), false, false);
+ if let Some(ref close) = closing_frame {
+ // ConnectionError::Application is only allowed at 1RTT.
+ let sanitized = if *space == PacketNumberSpace::ApplicationData {
+ None
+ } else {
+ close.sanitize()
+ };
+ sanitized
+ .as_ref()
+ .unwrap_or(close)
+ .write_frame(&mut builder);
+ self.stats.borrow_mut().frame_tx.connection_close += 1;
+ } else {
+ (tokens, ack_eliciting, padded) =
+ self.write_frames(path, *space, &profile, &mut builder, now);
+ }
if builder.packet_empty() {
// Nothing to include in this packet.
encoder = builder.abort();
@@ -2271,6 +2229,7 @@ impl Connection {
pt,
pn,
&builder.as_ref()[payload_start..],
+ IpTos::default(), // TODO: set from path
);
qlog::packet_sent(
&mut self.qlog,
@@ -2323,7 +2282,7 @@ impl Connection {
}
if encoder.is_empty() {
- qinfo!("TX blocked, profile={:?} ", profile);
+ qdebug!("TX blocked, profile={:?} ", profile);
Ok(SendOption::No(profile.paced()))
} else {
// Perform additional padding for Initial packets as necessary.
@@ -2337,6 +2296,8 @@ impl Connection {
mtu
);
initial.size += mtu - packets.len();
+ // These zeros aren't padding frames, they are an invalid all-zero coalesced
+ // packet, which is why we don't increase `frame_tx.padding` count here.
packets.resize(mtu, 0);
}
self.loss_recovery.on_packet_sent(path, initial);
@@ -2367,7 +2328,7 @@ impl Connection {
}
fn client_start(&mut self, now: Instant) -> Res<()> {
- qinfo!([self], "client_start");
+ qdebug!([self], "client_start");
debug_assert_eq!(self.role, Role::Client);
qlog::client_connection_started(&mut self.qlog, &self.paths.primary());
qlog::client_version_information_initiated(&mut self.qlog, self.conn_params.get_versions());
@@ -2599,7 +2560,7 @@ impl Connection {
fn confirm_version(&mut self, v: Version) {
if self.version != v {
- qinfo!([self], "Compatible upgrade {:?} ==> {:?}", self.version, v);
+ qdebug!([self], "Compatible upgrade {:?} ==> {:?}", self.version, v);
}
self.crypto.confirm_version(v);
self.version = v;
@@ -2694,9 +2655,8 @@ impl Connection {
.input_frame(&frame, &mut self.stats.borrow_mut().frame_rx);
}
match frame {
- Frame::Padding => {
- // Note: This counts contiguous padding as a single frame.
- self.stats.borrow_mut().frame_rx.padding += 1;
+ Frame::Padding(length) => {
+ self.stats.borrow_mut().frame_rx.padding += usize::from(length);
}
Frame::Ping => {
// If we get a PING and there are outstanding CRYPTO frames,
@@ -2899,7 +2859,7 @@ impl Connection {
R: IntoIterator<Item = RangeInclusive<u64>> + Debug,
R::IntoIter: ExactSizeIterator,
{
- qinfo!([self], "Rx ACK space={}, ranges={:?}", space, ack_ranges);
+ qdebug!([self], "Rx ACK space={}, ranges={:?}", space, ack_ranges);
let (acked_packets, lost_packets) = self.loss_recovery.on_ack_received(
&self.paths.primary(),
@@ -2953,7 +2913,7 @@ impl Connection {
}
fn set_connected(&mut self, now: Instant) -> Res<()> {
- qinfo!([self], "TLS connection complete");
+ qdebug!([self], "TLS connection complete");
if self.crypto.tls.info().map(SecretAgentInfo::alpn).is_none() {
qwarn!([self], "No ALPN. Closing connection.");
// 120 = no_application_protocol
@@ -2996,7 +2956,7 @@ impl Connection {
fn set_state(&mut self, state: State) {
if state > self.state {
- qinfo!([self], "State change from {:?} -> {:?}", self.state, state);
+ qdebug!([self], "State change from {:?} -> {:?}", self.state, state);
self.state = state.clone();
if self.state.closed() {
self.streams.clear_streams();
diff --git a/third_party/rust/neqo-transport/src/connection/params.rs b/third_party/rust/neqo-transport/src/connection/params.rs
index 72d1efa3ee..d8aa617024 100644
--- a/third_party/rust/neqo-transport/src/connection/params.rs
+++ b/third_party/rust/neqo-transport/src/connection/params.rs
@@ -77,7 +77,6 @@ pub struct ConnectionParameters {
outgoing_datagram_queue: usize,
incoming_datagram_queue: usize,
fast_pto: u8,
- fuzzing: bool,
grease: bool,
pacing: bool,
}
@@ -100,7 +99,6 @@ impl Default for ConnectionParameters {
outgoing_datagram_queue: MAX_QUEUED_DATAGRAMS_DEFAULT,
incoming_datagram_queue: MAX_QUEUED_DATAGRAMS_DEFAULT,
fast_pto: FAST_PTO_SCALE,
- fuzzing: false,
grease: true,
pacing: true,
}
@@ -325,17 +323,6 @@ impl ConnectionParameters {
}
#[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
}
diff --git a/third_party/rust/neqo-transport/src/connection/state.rs b/third_party/rust/neqo-transport/src/connection/state.rs
index 9789151d3f..cc2f6e30d2 100644
--- a/third_party/rust/neqo-transport/src/connection/state.rs
+++ b/third_party/rust/neqo-transport/src/connection/state.rs
@@ -209,7 +209,10 @@ pub enum StateSignaling {
impl StateSignaling {
pub fn handshake_done(&mut self) {
if !matches!(self, Self::Idle) {
- debug_assert!(false, "StateSignaling must be in Idle state.");
+ debug_assert!(
+ false,
+ "StateSignaling must be in Idle state but is in {self:?} state.",
+ );
return;
}
*self = Self::HandshakeDone;
diff --git a/third_party/rust/neqo-transport/src/connection/tests/fuzzing.rs b/third_party/rust/neqo-transport/src/connection/tests/fuzzing.rs
deleted file mode 100644
index 9924c06fa4..0000000000
--- a/third_party/rust/neqo-transport/src/connection/tests/fuzzing.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![cfg(feature = "fuzzing")]
-
-use neqo_crypto::FIXED_TAG_FUZZING;
-use test_fixture::now;
-
-use super::{connect_force_idle, default_client, default_server};
-use crate::StreamType;
-
-#[test]
-fn no_encryption() {
- const DATA_CLIENT: &[u8] = &[2; 40];
- const DATA_SERVER: &[u8] = &[3; 50];
- let mut client = default_client();
- let mut server = default_server();
- connect_force_idle(&mut client, &mut server);
-
- let stream_id = client.stream_create(StreamType::BiDi).unwrap();
-
- client.stream_send(stream_id, DATA_CLIENT).unwrap();
- let client_pkt = client.process_output(now()).dgram().unwrap();
- assert!(client_pkt[..client_pkt.len() - FIXED_TAG_FUZZING.len()].ends_with(DATA_CLIENT));
-
- server.process_input(&client_pkt, now());
- let mut buf = vec![0; 100];
- let (len, _) = server.stream_recv(stream_id, &mut buf).unwrap();
- assert_eq!(len, DATA_CLIENT.len());
- assert_eq!(&buf[..len], DATA_CLIENT);
- server.stream_send(stream_id, DATA_SERVER).unwrap();
- let server_pkt = server.process_output(now()).dgram().unwrap();
- assert!(server_pkt[..server_pkt.len() - FIXED_TAG_FUZZING.len()].ends_with(DATA_SERVER));
-
- client.process_input(&server_pkt, now());
- let (len, _) = client.stream_recv(stream_id, &mut buf).unwrap();
- assert_eq!(len, DATA_SERVER.len());
- assert_eq!(&buf[..len], DATA_SERVER);
-}
diff --git a/third_party/rust/neqo-transport/src/connection/tests/handshake.rs b/third_party/rust/neqo-transport/src/connection/tests/handshake.rs
index af0352ce90..f2103523ec 100644
--- a/third_party/rust/neqo-transport/src/connection/tests/handshake.rs
+++ b/third_party/rust/neqo-transport/src/connection/tests/handshake.rs
@@ -16,9 +16,10 @@ use neqo_common::{event::Provider, qdebug, Datagram};
use neqo_crypto::{
constants::TLS_CHACHA20_POLY1305_SHA256, generate_ech_keys, AuthenticationStatus,
};
+#[cfg(not(feature = "disable-encryption"))]
+use test_fixture::datagram;
use test_fixture::{
- assertions, assertions::assert_coalesced_0rtt, datagram, fixture_init, now, split_datagram,
- DEFAULT_ADDR,
+ assertions, assertions::assert_coalesced_0rtt, fixture_init, now, split_datagram, DEFAULT_ADDR,
};
use super::{
@@ -458,7 +459,7 @@ fn coalesce_05rtt() {
assert_eq!(client.stats().dropped_rx, 0); // No Initial padding.
assert_eq!(client.stats().packets_rx, 4);
assert_eq!(client.stats().saved_datagrams, 1);
- assert_eq!(client.stats().frame_rx.padding, 1); // Padding uses frames.
+ assert!(client.stats().frame_rx.padding > 0); // Padding uses frames.
// Allow the handshake to complete.
now += RTT / 2;
@@ -605,7 +606,7 @@ fn reorder_1rtt() {
}
}
-#[cfg(not(feature = "fuzzing"))]
+#[cfg(not(feature = "disable-encryption"))]
#[test]
fn corrupted_initial() {
let mut client = default_client();
@@ -808,7 +809,7 @@ fn anti_amplification() {
assert_eq!(*server.state(), State::Confirmed);
}
-#[cfg(not(feature = "fuzzing"))]
+#[cfg(not(feature = "disable-encryption"))]
#[test]
fn garbage_initial() {
let mut client = default_client();
diff --git a/third_party/rust/neqo-transport/src/connection/tests/mod.rs b/third_party/rust/neqo-transport/src/connection/tests/mod.rs
index b6ce08f8d1..c8c87a0df0 100644
--- a/third_party/rust/neqo-transport/src/connection/tests/mod.rs
+++ b/third_party/rust/neqo-transport/src/connection/tests/mod.rs
@@ -37,11 +37,11 @@ mod ackrate;
mod cc;
mod close;
mod datagram;
-mod fuzzing;
mod handshake;
mod idle;
mod keys;
mod migration;
+mod null;
mod priority;
mod recovery;
mod resumption;
@@ -170,12 +170,17 @@ impl crate::connection::test_internal::FrameWriter for PingWriter {
}
}
+trait DatagramModifier: FnMut(Datagram) -> Option<Datagram> {}
+
+impl<T> DatagramModifier for T where T: FnMut(Datagram) -> Option<Datagram> {}
+
/// Drive the handshake between the client and server.
-fn handshake(
+fn handshake_with_modifier(
client: &mut Connection,
server: &mut Connection,
now: Instant,
rtt: Duration,
+ mut modifier: impl DatagramModifier,
) -> Instant {
let mut a = client;
let mut b = server;
@@ -212,7 +217,11 @@ fn handshake(
did_ping[a.role()] = true;
}
assert!(had_input || output.is_some());
- input = output;
+ if let Some(d) = output {
+ input = modifier(d);
+ } else {
+ input = output;
+ }
qtrace!("handshake: t += {:?}", rtt / 2);
now += rtt / 2;
mem::swap(&mut a, &mut b);
@@ -223,6 +232,15 @@ fn handshake(
now
}
+fn handshake(
+ client: &mut Connection,
+ server: &mut Connection,
+ now: Instant,
+ rtt: Duration,
+) -> Instant {
+ handshake_with_modifier(client, server, now, rtt, Some)
+}
+
fn connect_fail(
client: &mut Connection,
server: &mut Connection,
@@ -234,11 +252,12 @@ fn connect_fail(
assert_error(server, &ConnectionError::Transport(server_error));
}
-fn connect_with_rtt(
+fn connect_with_rtt_and_modifier(
client: &mut Connection,
server: &mut Connection,
now: Instant,
rtt: Duration,
+ modifier: impl DatagramModifier,
) -> Instant {
fn check_rtt(stats: &Stats, rtt: Duration) {
assert_eq!(stats.rtt, rtt);
@@ -246,7 +265,7 @@ fn connect_with_rtt(
let n = stats.frame_rx.ack + usize::from(stats.rtt_init_guess);
assert_eq!(stats.rttvar, rttvar_after_n_updates(n, rtt));
}
- let now = handshake(client, server, now, rtt);
+ let now = handshake_with_modifier(client, server, now, rtt, modifier);
assert_eq!(*client.state(), State::Confirmed);
assert_eq!(*server.state(), State::Confirmed);
@@ -255,6 +274,15 @@ fn connect_with_rtt(
now
}
+fn connect_with_rtt(
+ client: &mut Connection,
+ server: &mut Connection,
+ now: Instant,
+ rtt: Duration,
+) -> Instant {
+ connect_with_rtt_and_modifier(client, server, now, rtt, Some)
+}
+
fn connect(client: &mut Connection, server: &mut Connection) {
connect_with_rtt(client, server, now(), Duration::new(0, 0));
}
@@ -301,8 +329,13 @@ fn assert_idle(client: &mut Connection, server: &mut Connection, rtt: Duration,
}
/// Connect with an RTT and then force both peers to be idle.
-fn connect_rtt_idle(client: &mut Connection, server: &mut Connection, rtt: Duration) -> Instant {
- let now = connect_with_rtt(client, server, now(), rtt);
+fn connect_rtt_idle_with_modifier(
+ client: &mut Connection,
+ server: &mut Connection,
+ rtt: Duration,
+ modifier: impl DatagramModifier,
+) -> Instant {
+ let now = connect_with_rtt_and_modifier(client, server, now(), rtt, modifier);
assert_idle(client, server, rtt, now);
// Drain events from both as well.
_ = client.events().count();
@@ -311,8 +344,20 @@ fn connect_rtt_idle(client: &mut Connection, server: &mut Connection, rtt: Durat
now
}
+fn connect_rtt_idle(client: &mut Connection, server: &mut Connection, rtt: Duration) -> Instant {
+ connect_rtt_idle_with_modifier(client, server, rtt, Some)
+}
+
+fn connect_force_idle_with_modifier(
+ client: &mut Connection,
+ server: &mut Connection,
+ modifier: impl DatagramModifier,
+) {
+ connect_rtt_idle_with_modifier(client, server, Duration::new(0, 0), modifier);
+}
+
fn connect_force_idle(client: &mut Connection, server: &mut Connection) {
- connect_rtt_idle(client, server, Duration::new(0, 0));
+ connect_force_idle_with_modifier(client, server, Some);
}
fn fill_stream(c: &mut Connection, stream: StreamId) {
@@ -524,12 +569,14 @@ fn assert_full_cwnd(packets: &[Datagram], cwnd: usize) {
}
/// Send something on a stream from `sender` to `receiver`, maybe allowing for pacing.
+/// Takes a modifier function that can be used to modify the datagram before it is sent.
/// Return the resulting datagram and the new time.
#[must_use]
-fn send_something_paced(
+fn send_something_paced_with_modifier(
sender: &mut Connection,
mut now: Instant,
allow_pacing: bool,
+ mut modifier: impl DatagramModifier,
) -> (Datagram, Instant) {
let stream_id = sender.stream_create(StreamType::UniDi).unwrap();
assert!(sender.stream_send(stream_id, DEFAULT_STREAM_DATA).is_ok());
@@ -544,16 +591,32 @@ fn send_something_paced(
.dgram()
.expect("send_something: should have something to send")
}
- Output::Datagram(d) => d,
+ Output::Datagram(d) => modifier(d).unwrap(),
Output::None => panic!("send_something: got Output::None"),
};
(dgram, now)
}
+fn send_something_paced(
+ sender: &mut Connection,
+ now: Instant,
+ allow_pacing: bool,
+) -> (Datagram, Instant) {
+ send_something_paced_with_modifier(sender, now, allow_pacing, Some)
+}
+
+fn send_something_with_modifier(
+ sender: &mut Connection,
+ now: Instant,
+ modifier: impl DatagramModifier,
+) -> Datagram {
+ send_something_paced_with_modifier(sender, now, false, modifier).0
+}
+
/// Send something on a stream from `sender` to `receiver`.
/// Return the resulting datagram.
fn send_something(sender: &mut Connection, now: Instant) -> Datagram {
- send_something_paced(sender, now, false).0
+ send_something_with_modifier(sender, now, Some)
}
/// Send something on a stream from `sender` to `receiver`.
diff --git a/third_party/rust/neqo-transport/src/connection/tests/null.rs b/third_party/rust/neqo-transport/src/connection/tests/null.rs
new file mode 100644
index 0000000000..e4d60445c6
--- /dev/null
+++ b/third_party/rust/neqo-transport/src/connection/tests/null.rs
@@ -0,0 +1,42 @@
+// 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(feature = "disable-encryption")]
+
+use neqo_crypto::aead_null::AEAD_NULL_TAG;
+use test_fixture::now;
+
+use super::{connect_force_idle, default_client, default_server};
+use crate::StreamType;
+
+#[test]
+fn no_encryption() {
+ const DATA_CLIENT: &[u8] = &[2; 40];
+ const DATA_SERVER: &[u8] = &[3; 50];
+ let mut client = default_client();
+ let mut server = default_server();
+ connect_force_idle(&mut client, &mut server);
+
+ let stream_id = client.stream_create(StreamType::BiDi).unwrap();
+
+ client.stream_send(stream_id, DATA_CLIENT).unwrap();
+ let client_pkt = client.process_output(now()).dgram().unwrap();
+ assert!(client_pkt[..client_pkt.len() - AEAD_NULL_TAG.len()].ends_with(DATA_CLIENT));
+
+ server.process_input(&client_pkt, now());
+ let mut buf = vec![0; 100];
+ let (len, _) = server.stream_recv(stream_id, &mut buf).unwrap();
+ assert_eq!(len, DATA_CLIENT.len());
+ assert_eq!(&buf[..len], DATA_CLIENT);
+ server.stream_send(stream_id, DATA_SERVER).unwrap();
+ let server_pkt = server.process_output(now()).dgram().unwrap();
+ assert!(server_pkt[..server_pkt.len() - AEAD_NULL_TAG.len()].ends_with(DATA_SERVER));
+
+ client.process_input(&server_pkt, now());
+ let (len, _) = client.stream_recv(stream_id, &mut buf).unwrap();
+ assert_eq!(len, DATA_SERVER.len());
+ assert_eq!(&buf[..len], DATA_SERVER);
+}
diff --git a/third_party/rust/neqo-transport/src/connection/tests/stream.rs b/third_party/rust/neqo-transport/src/connection/tests/stream.rs
index f469866d50..66d3bf32f3 100644
--- a/third_party/rust/neqo-transport/src/connection/tests/stream.rs
+++ b/third_party/rust/neqo-transport/src/connection/tests/stream.rs
@@ -116,12 +116,6 @@ fn transfer() {
assert!(fin3);
}
-#[derive(PartialEq, Eq, PartialOrd, Ord)]
-struct IdEntry {
- sendorder: StreamOrder,
- stream_id: StreamId,
-}
-
// tests stream sendorder priorization
fn sendorder_test(order_of_sendorder: &[Option<SendOrder>]) {
let mut client = default_client();