use std::{
net::{SocketAddr, ToSocketAddrs as _},
path::PathBuf,
time::{Duration, Instant},
};
use clap::{Parser, builder::TypedValueParser as _}; use neqo_transport::{
CongestionControl, ConnectionParameters, DEFAULT_INITIAL_RTT, SlowStart, StreamType, Version,
tparams::PreferredAddress,
}; use strum::VariantNames as _; use thiserror::Error;
pubmod client; mod send_data; pubmod server; pubmod udp;
#[arg(short = 'a', long, default_value = "h3")] /// ALPN labels to negotiate. /// /// This client still only does HTTP/3 no matter what the ALPN says.
alpn: String,
#[arg(name = "qlog-dir", long, value_parser=clap::value_parser!(PathBuf))] /// Enable QLOG logging and QLOG traces to this directory
qlog_dir: Option<PathBuf>,
#[derive(Clone, Debug, Parser)] pubstruct QuicParameters { #[arg(
short = 'Q',
long,
num_args = 1..,
value_delimiter = ' ',
number_of_values = 1,
value_parser = from_str)] /// A list of versions to support, in hex. /// The first is the version to attempt. /// Adding multiple values adds versions in order of preference. /// If the first listed version appears in the list twice, the position /// of the second entry determines the preference order of that version. pub quic_version: Vec<Version>,
#[arg(long, default_value = "16")] /// Set the `MAX_STREAMS_BIDI` limit. pub max_streams_bidi: u64,
#[arg(long, default_value = "16")] /// Set the `MAX_STREAMS_UNI` limit. pub max_streams_uni: u64,
#[arg(long = "idle", default_value = "30")] /// The idle timeout for connections, in seconds. pub idle_timeout: u64,
#[arg(long = "init_rtt", default_value_t = DEFAULT_INITIAL_RTT.as_millis() as u64)] /// The initial round-trip time, in milliseconds. pub initial_rtt_ms: u64,
#[arg(long = "cc", default_value = "cubic",
value_parser = clap::builder::PossibleValuesParser::new(CongestionControl::VARIANTS)
.map(|s| s.parse::<CongestionControl>().unwrap()))] /// The congestion control algorithm to use. pub congestion_control: CongestionControl,
fn from_str(s: &str) -> Result<Version, Error> { let v = u32::from_str_radix(s, 16)
.map_err(|_| Error::Argument("versions need to be specified in hex"))?;
Version::try_from(v).map_err(|_| Error::Argument("unknown version"))
}
/// Wrapper for [`Instant::now()`] to manage the `disallowed_methods` override. fn now() -> Instant { #![expect(clippy::disallowed_methods, reason = "This program uses the time")]
Instant::now()
}
#[cfg(not(target_os = "netbsd"))] // FIXME: Test fails on NetBSD. #[cfg(test)] #[cfg_attr(coverage_nightly, coverage(off))] mod tests { use std::{fs, path::PathBuf, time::SystemTime};
usecrate::{client, server};
struct TempDir {
path: PathBuf,
}
impl TempDir { fn new() -> Self { let dir = std::env::temp_dir().join(format!( "neqo-bin-test-{}",
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs()
));
fs::create_dir_all(&dir).unwrap(); Self { path: dir }
}
fn path(&self) -> PathBuf { self.path.clone()
}
}
impl Drop for TempDir { fn drop(&mutself) { ifself.path.exists() {
fs::remove_dir_all(&self.path).unwrap();
}
}
}
let client = client::client(client_args); let (server, _local_addrs) = server::run(server_args).unwrap();
tokio::select! {
_ = client => {}
res = server => panic!("expect server not to terminate: {res:?}"),
};
// Verify that the directory contains two non-empty files let entries: Vec<_> = fs::read_dir(temp_dir.path())
.unwrap()
.filter_map(Result::ok)
.collect();
assert_eq!(entries.len(), 2, "expect 2 files in the directory");
for entry in entries { let metadata = entry.metadata().unwrap();
assert!(metadata.is_file(), "expect a file, found something else");
assert!(metadata.len() > 0, "expect file not be empty");
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.