refactor(client): make configuration reusable across endpoints
This commit is contained in:
43 files changed
+1012
-723
No files matched your search
@@ -1,6 +1,8 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use irtt_client::{AsyncClient, ClientConfig, ClientEvent, OpenOutcome, SocketConfig};
|
||||
use irtt_client::{
|
||||
AsyncClient, ClientConfig, ClientEvent, OpenOutcome, OpenPolicy, SessionRequest,
|
||||
};
|
||||
use irtt_proto::{Clock, ReceivedStats, StampAt};
|
||||
use irtt_server::{Server, ServerConfig};
|
||||
use tokio::{sync::oneshot, time::timeout};
|
||||
@@ -27,22 +29,26 @@ async fn exercise_client_server() {
|
||||
});
|
||||
|
||||
let config = ClientConfig {
|
||||
server_addr: server_addr.to_string(),
|
||||
duration: Some(Duration::from_secs(1)),
|
||||
interval: Duration::from_millis(100),
|
||||
length: 64,
|
||||
received_stats: ReceivedStats::Both,
|
||||
stamp_at: StampAt::Both,
|
||||
clock: Clock::Both,
|
||||
open_timeouts: vec![Duration::from_millis(200)],
|
||||
socket_config: SocketConfig {
|
||||
recv_timeout: Some(Duration::from_millis(200)),
|
||||
..SocketConfig::default()
|
||||
open: OpenPolicy {
|
||||
timeouts: vec![Duration::from_millis(200)],
|
||||
..Default::default()
|
||||
},
|
||||
request: SessionRequest {
|
||||
duration: Some(Duration::from_secs(1)),
|
||||
interval: Duration::from_millis(100),
|
||||
length: 64,
|
||||
received_stats: ReceivedStats::Both,
|
||||
stamp_at: StampAt::Both,
|
||||
clock: Clock::Both,
|
||||
..Default::default()
|
||||
},
|
||||
|
||||
probe_timeout: Duration::from_millis(200),
|
||||
..ClientConfig::default()
|
||||
};
|
||||
let mut client = AsyncClient::connect(config).await.unwrap();
|
||||
let mut client = AsyncClient::connect(server_addr.to_string(), config)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let opened = client.open().await.unwrap();
|
||||
match &opened {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use irtt_client::{Authentication, HmacKey};
|
||||
use irtt_client::{Authentication, HmacKey, OpenPolicy, SessionRequest};
|
||||
use std::{
|
||||
future::Future,
|
||||
net::UdpSocket,
|
||||
@@ -17,7 +17,7 @@ use tokio::runtime::{Builder, Runtime};
|
||||
mod support;
|
||||
|
||||
use irtt_client::{AsyncClient, ClientConfig, ClientError, ClientEvent, OpenOutcome};
|
||||
use irtt_client::{Client, RunMode, SocketConfig};
|
||||
use irtt_client::{Client, RunMode};
|
||||
use irtt_server::ServerConfig;
|
||||
use std::{
|
||||
io,
|
||||
@@ -49,26 +49,27 @@ fn runtime() -> Runtime {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn config(addr: SocketAddr, key: Option<Vec<u8>>, dscp: u8) -> ClientConfig {
|
||||
fn config(key: Option<Vec<u8>>, dscp: u8) -> ClientConfig {
|
||||
ClientConfig {
|
||||
server_addr: addr.to_string(),
|
||||
received_stats: ReceivedStats::None,
|
||||
stamp_at: StampAt::None,
|
||||
dscp,
|
||||
open: OpenPolicy {
|
||||
timeouts: vec![Duration::from_millis(200)],
|
||||
..Default::default()
|
||||
},
|
||||
request: SessionRequest {
|
||||
received_stats: ReceivedStats::None,
|
||||
stamp_at: StampAt::None,
|
||||
dscp,
|
||||
..Default::default()
|
||||
},
|
||||
auth: key.map_or(Authentication::Unauthenticated, |key| {
|
||||
Authentication::Hmac(HmacKey::new(key))
|
||||
}),
|
||||
open_timeouts: vec![Duration::from_millis(200)],
|
||||
socket_config: SocketConfig {
|
||||
recv_timeout: Some(Duration::from_millis(200)),
|
||||
..SocketConfig::default()
|
||||
},
|
||||
..ClientConfig::default()
|
||||
}
|
||||
}
|
||||
|
||||
async fn opened_client(addr: SocketAddr, dscp: u8) -> AsyncClient {
|
||||
let mut client = AsyncClient::connect(config(addr, None, dscp))
|
||||
let mut client = AsyncClient::connect(addr.to_string(), config(None, dscp))
|
||||
.await
|
||||
.unwrap();
|
||||
client.open().await.unwrap();
|
||||
@@ -251,7 +252,10 @@ fn poll_recv_once(client: &mut AsyncClient) -> Poll<Result<Vec<ClientEvent>, Cli
|
||||
|
||||
#[test]
|
||||
fn connect_requires_current_runtime_when_polled() {
|
||||
let mut future = Box::pin(AsyncClient::connect(ClientConfig::default()));
|
||||
let mut future = Box::pin(AsyncClient::connect(
|
||||
"127.0.0.1:2112",
|
||||
ClientConfig::default(),
|
||||
));
|
||||
assert!(matches!(
|
||||
poll_once(Pin::as_mut(&mut future)),
|
||||
Poll::Ready(Err(ClientError::NoTokioRuntime))
|
||||
@@ -262,7 +266,9 @@ fn connect_requires_current_runtime_when_polled() {
|
||||
fn recv_before_open_fails_on_first_poll_without_socket_readiness() {
|
||||
runtime().block_on(async {
|
||||
let remote = SocketAddr::from(([127, 0, 0, 1], 2112));
|
||||
let mut client = AsyncClient::connect(config(remote, None, 0)).await.unwrap();
|
||||
let mut client = AsyncClient::connect(remote.to_string(), config(None, 0))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert!(matches!(
|
||||
poll_recv_once(&mut client),
|
||||
@@ -312,11 +318,13 @@ fn ignored_open_traffic_cannot_extend_the_absolute_attempt_deadline() {
|
||||
}
|
||||
panic!("second open request did not arrive after the first absolute deadline");
|
||||
});
|
||||
let mut client_config = config(server.addr, None, 0);
|
||||
client_config.open_timeouts = vec![Duration::from_millis(200), Duration::from_millis(200)];
|
||||
let mut client_config = config(None, 0);
|
||||
client_config.open.timeouts = vec![Duration::from_millis(200), Duration::from_millis(200)];
|
||||
|
||||
runtime().block_on(async {
|
||||
let mut client = AsyncClient::connect(client_config).await.unwrap();
|
||||
let mut client = AsyncClient::connect(server.addr.to_string(), client_config)
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(matches!(
|
||||
client.open().await.unwrap(),
|
||||
OpenOutcome::Started { .. }
|
||||
@@ -339,11 +347,13 @@ fn authenticated_rejection_is_terminal_without_retry() {
|
||||
0,
|
||||
);
|
||||
});
|
||||
let mut client_config = config(server.addr, None, 0);
|
||||
client_config.open_timeouts = vec![Duration::from_millis(200), Duration::from_millis(200)];
|
||||
let mut client_config = config(None, 0);
|
||||
client_config.open.timeouts = vec![Duration::from_millis(200), Duration::from_millis(200)];
|
||||
|
||||
runtime().block_on(async {
|
||||
let mut client = AsyncClient::connect(client_config).await.unwrap();
|
||||
let mut client = AsyncClient::connect(server.addr.to_string(), client_config)
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(matches!(
|
||||
client.open().await,
|
||||
Err(ClientError::ServerRejected)
|
||||
@@ -371,9 +381,11 @@ fn recv_after_local_close_and_no_test_fails_on_first_poll() {
|
||||
|
||||
let no_test_server = start_no_test_server();
|
||||
runtime().block_on(async {
|
||||
let mut client_config = config(no_test_server.addr, None, 0);
|
||||
client_config.run_mode = RunMode::NoTest;
|
||||
let mut client = AsyncClient::connect(client_config).await.unwrap();
|
||||
let mut client_config = config(None, 0);
|
||||
client_config.request.run_mode = RunMode::NoTest;
|
||||
let mut client = AsyncClient::connect(no_test_server.addr.to_string(), client_config)
|
||||
.await
|
||||
.unwrap();
|
||||
client.open().await.unwrap();
|
||||
assert!(matches!(
|
||||
poll_recv_once(&mut client),
|
||||
@@ -388,7 +400,7 @@ fn authenticated_async_lifecycle_negotiates_dscp() {
|
||||
let key = b"async-lifecycle-key".to_vec();
|
||||
let server = InTreeServer::start(ServerConfig::default().with_hmac_key(key.clone()));
|
||||
runtime().block_on(async {
|
||||
let mut client = AsyncClient::connect(config(server.addr, Some(key), 46))
|
||||
let mut client = AsyncClient::connect(server.addr.to_string(), config(Some(key), 46))
|
||||
.await
|
||||
.unwrap();
|
||||
let opened = client.open().await.unwrap();
|
||||
@@ -403,7 +415,10 @@ fn authenticated_async_lifecycle_negotiates_dscp() {
|
||||
fn blocking_and_async_peer_close_are_semantically_equivalent() {
|
||||
let blocking_peer_close_server = start_peer_close_server();
|
||||
let mut blocking_peer_close =
|
||||
Client::connect(config(blocking_peer_close_server.addr, None, 0)).unwrap();
|
||||
Client::connect(blocking_peer_close_server.addr.to_string(), config(None, 0)).unwrap();
|
||||
blocking_peer_close
|
||||
.set_recv_timeout(Some(Duration::from_millis(200)))
|
||||
.unwrap();
|
||||
blocking_peer_close.open().unwrap();
|
||||
blocking_peer_close.send_probe().unwrap();
|
||||
let blocking_peer_close_events = blocking_peer_close.recv_once().unwrap();
|
||||
@@ -412,9 +427,10 @@ fn blocking_and_async_peer_close_are_semantically_equivalent() {
|
||||
|
||||
let async_peer_close_server = start_peer_close_server();
|
||||
let async_peer_close_events = runtime().block_on(async {
|
||||
let mut client = AsyncClient::connect(config(async_peer_close_server.addr, None, 0))
|
||||
.await
|
||||
.unwrap();
|
||||
let mut client =
|
||||
AsyncClient::connect(async_peer_close_server.addr.to_string(), config(None, 0))
|
||||
.await
|
||||
.unwrap();
|
||||
client.open().await.unwrap();
|
||||
client.send_probe().await.unwrap();
|
||||
let events = client.recv().await.unwrap();
|
||||
@@ -525,7 +541,10 @@ fn blocking_and_async_roll_back_a_failed_open_and_accept_a_retry() {
|
||||
// One open attempt is ignored, so the first open times out and the second
|
||||
// must be able to open the same connected client.
|
||||
let blocking_server = start_silent_then_open_server(1);
|
||||
let mut blocking = Client::connect(config(blocking_server.addr, None, 0)).unwrap();
|
||||
let mut blocking = Client::connect(blocking_server.addr.to_string(), config(None, 0)).unwrap();
|
||||
blocking
|
||||
.set_recv_timeout(Some(Duration::from_millis(200)))
|
||||
.unwrap();
|
||||
assert!(!blocking.has_pending_probes());
|
||||
let blocking_first = blocking.open().unwrap_err();
|
||||
assert!(!blocking.has_pending_probes());
|
||||
@@ -539,7 +558,7 @@ fn blocking_and_async_roll_back_a_failed_open_and_accept_a_retry() {
|
||||
let async_server = start_silent_then_open_server(1);
|
||||
let (async_first, async_second, async_sent, async_reply, async_close) =
|
||||
runtime().block_on(async {
|
||||
let mut client = AsyncClient::connect(config(async_server.addr, None, 0))
|
||||
let mut client = AsyncClient::connect(async_server.addr.to_string(), config(None, 0))
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(!client.has_pending_probes());
|
||||
@@ -580,16 +599,16 @@ fn blocking_and_async_roll_back_a_failed_open_and_accept_a_retry() {
|
||||
#[test]
|
||||
fn blocking_and_async_complete_every_caller_paced_probe() {
|
||||
const PROBES: u32 = 3;
|
||||
fn caller_config(addr: SocketAddr) -> ClientConfig {
|
||||
ClientConfig {
|
||||
duration: Some(Duration::from_millis(1)),
|
||||
interval: Duration::from_secs(1),
|
||||
..config(addr, None, 0)
|
||||
}
|
||||
}
|
||||
let mut caller_config = config(None, 0);
|
||||
caller_config.request.duration = Some(Duration::from_millis(1));
|
||||
caller_config.request.interval = Duration::from_secs(1);
|
||||
|
||||
let blocking_server = InTreeServer::start(ServerConfig::default());
|
||||
let mut blocking = Client::connect(caller_config(blocking_server.addr)).unwrap();
|
||||
let mut blocking =
|
||||
Client::connect(blocking_server.addr.to_string(), caller_config.clone()).unwrap();
|
||||
blocking
|
||||
.set_recv_timeout(Some(Duration::from_millis(200)))
|
||||
.unwrap();
|
||||
let outcome = blocking.open().unwrap();
|
||||
assert_eq!(
|
||||
blocking.negotiated_params(),
|
||||
@@ -613,7 +632,7 @@ fn blocking_and_async_complete_every_caller_paced_probe() {
|
||||
|
||||
let async_server = InTreeServer::start(ServerConfig::default());
|
||||
let (async_sent, async_replies) = runtime().block_on(async {
|
||||
let mut client = AsyncClient::connect(caller_config(async_server.addr))
|
||||
let mut client = AsyncClient::connect(async_server.addr.to_string(), caller_config)
|
||||
.await
|
||||
.unwrap();
|
||||
let outcome = client.open().await.unwrap();
|
||||
@@ -670,11 +689,13 @@ fn ignored_open_traffic_uses_one_request_and_deadline_per_attempt() {
|
||||
}
|
||||
}
|
||||
});
|
||||
let mut client_config = config(server.addr, None, 0);
|
||||
client_config.open_timeouts = vec![Duration::from_millis(200), Duration::from_millis(200)];
|
||||
let mut client_config = config(None, 0);
|
||||
client_config.open.timeouts = vec![Duration::from_millis(200), Duration::from_millis(200)];
|
||||
|
||||
runtime().block_on(async {
|
||||
let mut client = AsyncClient::connect(client_config).await.unwrap();
|
||||
let mut client = AsyncClient::connect(server.addr.to_string(), client_config)
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(matches!(client.open().await, Err(ClientError::OpenTimeout)));
|
||||
});
|
||||
assert_eq!(server.finish().len(), 2);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use irtt_client::{OpenPolicy, SessionRequest};
|
||||
use std::{
|
||||
net::{SocketAddr, UdpSocket},
|
||||
sync::{Arc, Condvar, Mutex},
|
||||
@@ -146,12 +147,18 @@ fn test_runtime() -> tokio::runtime::Runtime {
|
||||
fn config(completion: ManagedCompletionPolicy) -> ManagedClientConfig {
|
||||
ManagedClientConfig {
|
||||
client: ClientConfig {
|
||||
duration: Some(Duration::from_millis(120)),
|
||||
interval: Duration::from_millis(20),
|
||||
open: OpenPolicy {
|
||||
timeouts: vec![Duration::from_millis(200)],
|
||||
..Default::default()
|
||||
},
|
||||
request: SessionRequest {
|
||||
duration: Some(Duration::from_millis(120)),
|
||||
interval: Duration::from_millis(20),
|
||||
received_stats: ReceivedStats::None,
|
||||
stamp_at: StampAt::None,
|
||||
..Default::default()
|
||||
},
|
||||
probe_timeout: Duration::from_millis(40),
|
||||
open_timeouts: vec![Duration::from_millis(200)],
|
||||
received_stats: ReceivedStats::None,
|
||||
stamp_at: StampAt::None,
|
||||
..ClientConfig::default()
|
||||
},
|
||||
pacing: ManagedPacing::Burst,
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
use std::time::Duration;
|
||||
mod support;
|
||||
|
||||
use irtt_client::{Client, ClientConfig, ClientError, NegotiationPolicy};
|
||||
use irtt_client::{
|
||||
Client, ClientConfig, ClientError, NegotiationPolicy, OpenPolicy, SessionRequest,
|
||||
};
|
||||
use irtt_proto::{Params, TimestampFields};
|
||||
|
||||
use support::{
|
||||
@@ -52,11 +55,14 @@ fn server_fill_none_short_and_max_map_into_open_params() {
|
||||
fn server_fill_empty_and_oversized_values_are_rejected_at_config_boundary() {
|
||||
for fill in ["", "0123456789abcdef0123456789abcdefx"] {
|
||||
let config = ClientConfig {
|
||||
server_fill: Some(fill.to_owned()),
|
||||
request: SessionRequest {
|
||||
server_fill: Some(fill.to_owned()),
|
||||
..Default::default()
|
||||
},
|
||||
..ClientConfig::default()
|
||||
};
|
||||
assert!(matches!(
|
||||
Client::connect(config),
|
||||
Client::connect("127.0.0.1:2112", config),
|
||||
Err(ClientError::InvalidConfig { .. })
|
||||
));
|
||||
}
|
||||
@@ -69,7 +75,10 @@ fn server_fill_negotiated_params_reflect_accepted_value() {
|
||||
let mut params = default_params();
|
||||
params.server_fill = server_fill("rand");
|
||||
let server = InTreeServer::start(irtt_server::ServerConfig::default());
|
||||
let mut client = Client::connect(config_for_params(server.addr, ¶ms)).unwrap();
|
||||
let mut client = Client::connect(server.addr.to_string(), config_for_params(¶ms)).unwrap();
|
||||
client
|
||||
.set_recv_timeout(Some(Duration::from_millis(500)))
|
||||
.unwrap();
|
||||
let outcome = client.open().unwrap();
|
||||
let negotiated = match outcome {
|
||||
irtt_client::OpenOutcome::Started { negotiated, .. } => negotiated,
|
||||
@@ -99,7 +108,11 @@ fn server_fill_strict_rejects_removed_changed_or_unexpected_fill() {
|
||||
returned.server_fill = returned_fill.and_then(server_fill);
|
||||
|
||||
let server = start_open_server(returned, None);
|
||||
let mut client = Client::connect(config_for_params(server.addr, &requested)).unwrap();
|
||||
let mut client =
|
||||
Client::connect(server.addr.to_string(), config_for_params(&requested)).unwrap();
|
||||
client
|
||||
.set_recv_timeout(Some(Duration::from_millis(500)))
|
||||
.unwrap();
|
||||
assert!(matches!(
|
||||
client.open(),
|
||||
Err(ClientError::NegotiationRejected { .. })
|
||||
@@ -117,10 +130,13 @@ fn server_fill_loose_allows_server_to_remove_fill() {
|
||||
returned.server_fill = None;
|
||||
|
||||
let requested_for_config = requested.clone();
|
||||
let run = run_one_probe_with_config(returned, TimestampFields::default(), None, |addr| {
|
||||
let run = run_one_probe_with_config(returned, TimestampFields::default(), None, || {
|
||||
ClientConfig {
|
||||
negotiation_policy: NegotiationPolicy::Loose,
|
||||
..config_for_params(addr, &requested_for_config)
|
||||
open: OpenPolicy {
|
||||
negotiation: NegotiationPolicy::Loose,
|
||||
..config_for_params(&requested_for_config).open
|
||||
},
|
||||
..config_for_params(&requested_for_config)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use irtt_client::{
|
||||
AsyncClient, ClientConfig, NegotiationPolicy, NegotiationRestriction, OpenOutcome, SocketConfig,
|
||||
AsyncClient, ClientConfig, NegotiationPolicy, NegotiationRestriction, OpenOutcome, OpenPolicy,
|
||||
SessionRequest,
|
||||
};
|
||||
use irtt_proto::{
|
||||
decode_echo_reply, decode_open_reply, echo_header_len, encode_request, Clock, Params,
|
||||
@@ -132,24 +133,26 @@ async fn exercise_fallback_negotiation() {
|
||||
// `ClientConfig` accepts any non-empty descriptor within the wire bound, so
|
||||
// an unknown one genuinely reaches the server.
|
||||
let config = |policy| ClientConfig {
|
||||
server_addr: server_addr.to_string(),
|
||||
duration: Some(Duration::from_secs(1)),
|
||||
interval: Duration::from_millis(100),
|
||||
length: 64,
|
||||
server_fill: Some("bogus".to_owned()),
|
||||
negotiation_policy: policy,
|
||||
open_timeouts: vec![Duration::from_millis(200)],
|
||||
socket_config: SocketConfig {
|
||||
recv_timeout: Some(Duration::from_millis(200)),
|
||||
..SocketConfig::default()
|
||||
open: OpenPolicy {
|
||||
negotiation: policy,
|
||||
timeouts: vec![Duration::from_millis(200)],
|
||||
},
|
||||
request: SessionRequest {
|
||||
duration: Some(Duration::from_secs(1)),
|
||||
interval: Duration::from_millis(100),
|
||||
length: 64,
|
||||
server_fill: Some("bogus".to_owned()),
|
||||
..Default::default()
|
||||
},
|
||||
|
||||
probe_timeout: Duration::from_millis(200),
|
||||
..ClientConfig::default()
|
||||
};
|
||||
|
||||
let mut strict = AsyncClient::connect(config(NegotiationPolicy::Strict))
|
||||
.await
|
||||
.unwrap();
|
||||
let mut strict =
|
||||
AsyncClient::connect(server_addr.to_string(), config(NegotiationPolicy::Strict))
|
||||
.await
|
||||
.unwrap();
|
||||
let rejected = strict
|
||||
.open()
|
||||
.await
|
||||
@@ -159,7 +162,7 @@ async fn exercise_fallback_negotiation() {
|
||||
"the restriction names the fill: {rejected}"
|
||||
);
|
||||
|
||||
let mut loose = AsyncClient::connect(config(NegotiationPolicy::Loose))
|
||||
let mut loose = AsyncClient::connect(server_addr.to_string(), config(NegotiationPolicy::Loose))
|
||||
.await
|
||||
.unwrap();
|
||||
match loose.open().await.unwrap() {
|
||||
|
||||
@@ -3,9 +3,7 @@ mod support;
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use irtt_client::{
|
||||
Client, ClientConfig, ClientError, ClientEvent, OpenOutcome, SocketConfig, WarningKind,
|
||||
};
|
||||
use irtt_client::{Client, ClientConfig, ClientError, ClientEvent, OpenOutcome, WarningKind};
|
||||
use irtt_proto::TimestampFields;
|
||||
|
||||
use support::{
|
||||
@@ -27,9 +25,9 @@ fn hmac_open_success_negotiates_without_warnings() {
|
||||
params.clone(),
|
||||
TimestampFields::default(),
|
||||
Some(key),
|
||||
|addr| ClientConfig {
|
||||
|| ClientConfig {
|
||||
auth: Authentication::Hmac(HmacKey::new(config_key)),
|
||||
..config_for_params(addr, &config_params)
|
||||
..config_for_params(&config_params)
|
||||
},
|
||||
);
|
||||
|
||||
@@ -51,10 +49,10 @@ fn hmac_echo_success_verifies_request_and_accepts_reply() {
|
||||
let config_params = params.clone();
|
||||
let config_key = key.clone();
|
||||
|
||||
let run = run_one_probe_with_config(params.clone(), standard_timestamps(), Some(key), |addr| {
|
||||
let run = run_one_probe_with_config(params.clone(), standard_timestamps(), Some(key), || {
|
||||
ClientConfig {
|
||||
auth: Authentication::Hmac(HmacKey::new(config_key)),
|
||||
..config_for_params(addr, &config_params)
|
||||
..config_for_params(&config_params)
|
||||
}
|
||||
});
|
||||
|
||||
@@ -94,10 +92,13 @@ fn hmac_close_success_sends_authenticated_close_and_closes_session() {
|
||||
let key = b"compat-secret".to_vec();
|
||||
let params = default_params();
|
||||
let server = start_hmac_close_server(params.clone(), key.clone());
|
||||
let mut config = config_for_params(server.addr, ¶ms);
|
||||
let mut config = config_for_params(¶ms);
|
||||
config.auth = Authentication::Hmac(HmacKey::new(key));
|
||||
|
||||
let mut client = Client::connect(config).unwrap();
|
||||
let mut client = Client::connect(server.addr.to_string(), config).unwrap();
|
||||
client
|
||||
.set_recv_timeout(Some(Duration::from_millis(500)))
|
||||
.unwrap();
|
||||
let outcome = client.open().unwrap();
|
||||
assert_started(outcome, ¶ms);
|
||||
|
||||
@@ -134,13 +135,16 @@ fn hmac_required_server_rejects_missing_or_wrong_client_key() {
|
||||
] {
|
||||
let server_key = b"compat-secret".to_vec();
|
||||
let server = start_hmac_required_open_drop_server(server_key, Duration::from_millis(250));
|
||||
let mut config = config_for_params(server.addr, &default_params());
|
||||
config.open_timeouts = vec![Duration::from_millis(200)];
|
||||
let mut config = config_for_params(&default_params());
|
||||
config.open.timeouts = vec![Duration::from_millis(200)];
|
||||
config.auth = hmac_key.map_or(Authentication::Unauthenticated, |key| {
|
||||
Authentication::Hmac(HmacKey::new(key))
|
||||
});
|
||||
|
||||
let mut client = Client::connect(config).unwrap();
|
||||
let mut client = Client::connect(server.addr.to_string(), config).unwrap();
|
||||
client
|
||||
.set_recv_timeout(Some(Duration::from_millis(500)))
|
||||
.unwrap();
|
||||
assert!(matches!(client.open(), Err(ClientError::OpenTimeout)));
|
||||
|
||||
let observations = server.observations(1);
|
||||
@@ -160,14 +164,13 @@ fn bad_hmac_echo_reply_is_rejected_without_echo_reply_event() {
|
||||
let key = b"compat-secret".to_vec();
|
||||
let params = default_params();
|
||||
let server = start_bad_hmac_echo_reply_server(params.clone(), key.clone());
|
||||
let mut config = config_for_params(server.addr, ¶ms);
|
||||
let mut config = config_for_params(¶ms);
|
||||
config.auth = Authentication::Hmac(HmacKey::new(key));
|
||||
config.socket_config = SocketConfig {
|
||||
recv_timeout: Some(Duration::from_millis(500)),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut client = Client::connect(config).unwrap();
|
||||
let mut client = Client::connect(server.addr.to_string(), config).unwrap();
|
||||
client
|
||||
.set_recv_timeout(Some(Duration::from_millis(500)))
|
||||
.unwrap();
|
||||
let outcome = client.open().unwrap();
|
||||
assert_started(outcome, ¶ms);
|
||||
|
||||
@@ -207,10 +210,13 @@ fn hmac_open_reply_with_bad_hmac_is_ignored_until_timeout() {
|
||||
let wrong_key = b"wrong-secret".to_vec();
|
||||
let params = default_params();
|
||||
let server = support::start_bad_hmac_open_reply_server(params.clone(), key.clone(), wrong_key);
|
||||
let mut config = config_for_params(server.addr, ¶ms);
|
||||
let mut config = config_for_params(¶ms);
|
||||
config.auth = Authentication::Hmac(HmacKey::new(key));
|
||||
|
||||
let mut client = Client::connect(config).unwrap();
|
||||
let mut client = Client::connect(server.addr.to_string(), config).unwrap();
|
||||
client
|
||||
.set_recv_timeout(Some(Duration::from_millis(500)))
|
||||
.unwrap();
|
||||
assert!(matches!(client.open(), Err(ClientError::OpenTimeout)));
|
||||
server.join();
|
||||
}
|
||||
@@ -223,10 +229,13 @@ fn non_hmac_client_open_does_not_set_hmac_flag() {
|
||||
irtt_proto::Clock::Both,
|
||||
);
|
||||
let server = support::start_open_server(params.clone(), None);
|
||||
let mut config = config_for_params(server.addr, ¶ms);
|
||||
let mut config = config_for_params(¶ms);
|
||||
config.auth = Authentication::Unauthenticated;
|
||||
|
||||
let mut client = Client::connect(config).unwrap();
|
||||
let mut client = Client::connect(server.addr.to_string(), config).unwrap();
|
||||
client
|
||||
.set_recv_timeout(Some(Duration::from_millis(500)))
|
||||
.unwrap();
|
||||
let outcome = client.open().unwrap();
|
||||
assert_started(outcome, ¶ms);
|
||||
|
||||
@@ -280,10 +289,13 @@ fn backend_hmac_correct_key_succeeds() {
|
||||
let key = b"compat-secret".to_vec();
|
||||
let params = default_params();
|
||||
let peer = BackendPeer::start_open_echo(Some(key.clone()));
|
||||
let mut config = config_for_params(peer.addr(), ¶ms);
|
||||
let mut config = config_for_params(¶ms);
|
||||
config.auth = Authentication::Hmac(HmacKey::new(key));
|
||||
|
||||
let mut client = Client::connect(config).unwrap();
|
||||
let mut client = Client::connect(peer.addr().to_string(), config).unwrap();
|
||||
client
|
||||
.set_recv_timeout(Some(Duration::from_millis(500)))
|
||||
.unwrap();
|
||||
let outcome = client.open().unwrap();
|
||||
assert!(matches!(outcome, OpenOutcome::Started { .. }));
|
||||
|
||||
@@ -302,13 +314,16 @@ fn backend_hmac_required_rejects_missing_or_wrong_client_key() {
|
||||
for hmac_key in [None, Some(b"wrong-secret".to_vec())] {
|
||||
let server_key = b"compat-secret".to_vec();
|
||||
let peer = BackendPeer::start_hmac_required(server_key);
|
||||
let mut config = config_for_params(peer.addr(), &default_params());
|
||||
config.open_timeouts = vec![Duration::from_millis(200)];
|
||||
let mut config = config_for_params(&default_params());
|
||||
config.open.timeouts = vec![Duration::from_millis(200)];
|
||||
config.auth = hmac_key.map_or(Authentication::Unauthenticated, |key| {
|
||||
Authentication::Hmac(HmacKey::new(key))
|
||||
});
|
||||
|
||||
let mut client = Client::connect(config).unwrap();
|
||||
let mut client = Client::connect(peer.addr().to_string(), config).unwrap();
|
||||
client
|
||||
.set_recv_timeout(Some(Duration::from_millis(500)))
|
||||
.unwrap();
|
||||
assert!(matches!(client.open(), Err(ClientError::OpenTimeout)));
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
mod support;
|
||||
|
||||
use irtt_client::{Client, ClientConfig, ClientEvent, NegotiationPolicy};
|
||||
use irtt_client::{Client, ClientEvent, NegotiationPolicy};
|
||||
use irtt_proto::{echo_header_len, Params, TimestampFields};
|
||||
|
||||
use support::{config_for_params, default_params, run_one_probe, BackendPeer, ServerObservation};
|
||||
@@ -84,12 +84,13 @@ fn echo_reply_bytes_consistent_with_echo_packet_len_for_various_lengths() {
|
||||
fn backend_large_packet_smoke() {
|
||||
let params = params_with_length(1472);
|
||||
let peer = BackendPeer::start_open_echo(None);
|
||||
let mut client = Client::connect(ClientConfig {
|
||||
negotiation_policy: NegotiationPolicy::Loose,
|
||||
length: 1472,
|
||||
..config_for_params(peer.addr(), ¶ms)
|
||||
})
|
||||
.unwrap();
|
||||
let mut config = config_for_params(¶ms);
|
||||
config.open.negotiation = NegotiationPolicy::Loose;
|
||||
config.request.length = 1472;
|
||||
let mut client = Client::connect(peer.addr().to_string(), config).unwrap();
|
||||
client
|
||||
.set_recv_timeout(Some(std::time::Duration::from_millis(500)))
|
||||
.unwrap();
|
||||
|
||||
let outcome = client.open().unwrap();
|
||||
assert!(matches!(outcome, irtt_client::OpenOutcome::Started { .. }));
|
||||
|
||||
@@ -2,7 +2,7 @@ mod support;
|
||||
|
||||
use std::{collections::HashMap, time::Duration};
|
||||
|
||||
use irtt_client::{managed::*, ClientConfig, ClientEvent};
|
||||
use irtt_client::{managed::*, ClientConfig, ClientEvent, OpenPolicy, SessionRequest};
|
||||
use irtt_server::ServerConfig;
|
||||
use support::InTreeServer;
|
||||
use tokio::time::timeout;
|
||||
@@ -18,10 +18,16 @@ async fn both_pacing_modes_serve_every_target_on_its_negotiated_grid() {
|
||||
for _ in 0..3 {
|
||||
let config = ManagedClientConfig {
|
||||
client: ClientConfig {
|
||||
duration: Some(Duration::from_millis(600)),
|
||||
interval: Duration::from_millis(100),
|
||||
open: OpenPolicy {
|
||||
timeouts: vec![Duration::from_millis(200)],
|
||||
..Default::default()
|
||||
},
|
||||
request: SessionRequest {
|
||||
duration: Some(Duration::from_millis(600)),
|
||||
interval: Duration::from_millis(100),
|
||||
..Default::default()
|
||||
},
|
||||
probe_timeout: Duration::from_millis(100),
|
||||
open_timeouts: vec![Duration::from_millis(200)],
|
||||
..ClientConfig::default()
|
||||
},
|
||||
pacing,
|
||||
@@ -111,10 +117,16 @@ async fn target_updates_preserve_identical_sessions_and_retire_removed_generatio
|
||||
let server = InTreeServer::start(ServerConfig::default());
|
||||
let config = ManagedClientConfig {
|
||||
client: ClientConfig {
|
||||
duration: None,
|
||||
interval: Duration::from_millis(20),
|
||||
open: OpenPolicy {
|
||||
timeouts: vec![Duration::from_millis(200)],
|
||||
..Default::default()
|
||||
},
|
||||
request: SessionRequest {
|
||||
duration: None,
|
||||
interval: Duration::from_millis(20),
|
||||
..Default::default()
|
||||
},
|
||||
probe_timeout: Duration::from_millis(100),
|
||||
open_timeouts: vec![Duration::from_millis(200)],
|
||||
..ClientConfig::default()
|
||||
},
|
||||
completion: ManagedCompletionPolicy::ExplicitStop,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use irtt_client::{Authentication, HmacKey};
|
||||
use irtt_client::{Authentication, HmacKey, OpenPolicy, SessionRequest};
|
||||
use std::{
|
||||
future::Future,
|
||||
net::{SocketAddr, UdpSocket},
|
||||
@@ -176,12 +176,18 @@ fn runtime() -> Runtime {
|
||||
fn config(pacing: ManagedPacing) -> ManagedClientConfig {
|
||||
ManagedClientConfig {
|
||||
client: ClientConfig {
|
||||
duration: Some(Duration::from_millis(130)),
|
||||
interval: Duration::from_millis(60),
|
||||
open: OpenPolicy {
|
||||
timeouts: vec![Duration::from_millis(200)],
|
||||
..Default::default()
|
||||
},
|
||||
request: SessionRequest {
|
||||
duration: Some(Duration::from_millis(130)),
|
||||
interval: Duration::from_millis(60),
|
||||
received_stats: ReceivedStats::None,
|
||||
stamp_at: StampAt::None,
|
||||
..Default::default()
|
||||
},
|
||||
probe_timeout: Duration::from_millis(35),
|
||||
open_timeouts: vec![Duration::from_millis(200)],
|
||||
received_stats: ReceivedStats::None,
|
||||
stamp_at: StampAt::None,
|
||||
..ClientConfig::default()
|
||||
},
|
||||
pacing,
|
||||
@@ -340,7 +346,7 @@ fn finite_immediate_replies_use_retained_drain_deadline() {
|
||||
fn no_test_target_completion() {
|
||||
let server = start_server(ServerBehavior::NoTest, None);
|
||||
let mut config = config(ManagedPacing::Staggered);
|
||||
config.client.run_mode = RunMode::NoTest;
|
||||
config.client.request.run_mode = RunMode::NoTest;
|
||||
let (task, _) = ManagedClient::task(config, vec![target("no-test", server.addr)]).unwrap();
|
||||
let outcome = runtime().block_on(task);
|
||||
let records = server.finish();
|
||||
@@ -411,8 +417,8 @@ fn pending_limit_failure_drains_reply_and_closes_session() {
|
||||
Some(key.clone()),
|
||||
);
|
||||
let mut managed = config(ManagedPacing::Staggered);
|
||||
managed.client.duration = Some(Duration::from_millis(250));
|
||||
managed.client.interval = Duration::from_millis(20);
|
||||
managed.client.request.duration = Some(Duration::from_millis(250));
|
||||
managed.client.request.interval = Duration::from_millis(20);
|
||||
managed.client.probe_timeout = Duration::from_secs(2);
|
||||
managed.client.max_pending_probes = 1;
|
||||
managed.final_drain = Duration::from_millis(50);
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use irtt_client::{
|
||||
AsyncClient, ClientConfig, NegotiationPolicy, NegotiationRestriction, OpenOutcome, SocketConfig,
|
||||
AsyncClient, ClientConfig, NegotiationPolicy, NegotiationRestriction, OpenOutcome, OpenPolicy,
|
||||
SessionRequest,
|
||||
};
|
||||
use irtt_proto::{Clock, ReceivedStats, StampAt};
|
||||
use irtt_server::{Server, ServerConfig, TimestampAllowance};
|
||||
@@ -84,13 +85,19 @@ async fn exercise_dscp_restriction() {
|
||||
// The client's configuration is a DSCP codepoint; 46 (EF) is raw byte 184 on
|
||||
// the wire, and this test does not change either convention.
|
||||
let with_dscp = |policy| ClientConfig {
|
||||
dscp: 46,
|
||||
..test_config(server_addr, policy)
|
||||
request: SessionRequest {
|
||||
dscp: 46,
|
||||
..test_config(policy).request
|
||||
},
|
||||
..test_config(policy)
|
||||
};
|
||||
|
||||
let mut strict = AsyncClient::connect(with_dscp(NegotiationPolicy::Strict))
|
||||
.await
|
||||
.unwrap();
|
||||
let mut strict = AsyncClient::connect(
|
||||
server_addr.to_string(),
|
||||
with_dscp(NegotiationPolicy::Strict),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let rejected = strict
|
||||
.open()
|
||||
.await
|
||||
@@ -100,9 +107,10 @@ async fn exercise_dscp_restriction() {
|
||||
"the restriction names DSCP: {rejected}"
|
||||
);
|
||||
|
||||
let mut loose = AsyncClient::connect(with_dscp(NegotiationPolicy::Loose))
|
||||
.await
|
||||
.unwrap();
|
||||
let mut loose =
|
||||
AsyncClient::connect(server_addr.to_string(), with_dscp(NegotiationPolicy::Loose))
|
||||
.await
|
||||
.unwrap();
|
||||
let negotiated = match loose.open().await.unwrap() {
|
||||
OpenOutcome::Started { negotiated, .. } => negotiated,
|
||||
OpenOutcome::NoTestCompleted { .. } => panic!("normal client unexpectedly ran no-test"),
|
||||
@@ -138,10 +146,16 @@ async fn a_default_server_restricts_nothing_an_ordinary_client_asks_for() {
|
||||
async fn exercise_default_policy() {
|
||||
let (server_addr, shutdown_tx, server_task) = serve(ServerConfig::default()).await;
|
||||
|
||||
let mut client = AsyncClient::connect(ClientConfig {
|
||||
dscp: 46,
|
||||
..test_config(server_addr, NegotiationPolicy::Strict)
|
||||
})
|
||||
let mut client = AsyncClient::connect(
|
||||
server_addr.to_string(),
|
||||
ClientConfig {
|
||||
request: SessionRequest {
|
||||
dscp: 46,
|
||||
..test_config(NegotiationPolicy::Strict).request
|
||||
},
|
||||
..test_config(NegotiationPolicy::Strict)
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let negotiated = match client.open().await.unwrap() {
|
||||
@@ -186,28 +200,29 @@ async fn serve(
|
||||
}
|
||||
|
||||
/// A short deterministic client requesting both timestamps from both clocks.
|
||||
fn test_config(server_addr: std::net::SocketAddr, policy: NegotiationPolicy) -> ClientConfig {
|
||||
fn test_config(policy: NegotiationPolicy) -> ClientConfig {
|
||||
ClientConfig {
|
||||
server_addr: server_addr.to_string(),
|
||||
duration: Some(Duration::from_secs(1)),
|
||||
interval: Duration::from_millis(100),
|
||||
length: 64,
|
||||
received_stats: ReceivedStats::Both,
|
||||
stamp_at: StampAt::Both,
|
||||
clock: Clock::Both,
|
||||
negotiation_policy: policy,
|
||||
open_timeouts: vec![Duration::from_millis(200)],
|
||||
socket_config: SocketConfig {
|
||||
recv_timeout: Some(Duration::from_millis(200)),
|
||||
..SocketConfig::default()
|
||||
open: OpenPolicy {
|
||||
negotiation: policy,
|
||||
timeouts: vec![Duration::from_millis(200)],
|
||||
},
|
||||
request: SessionRequest {
|
||||
duration: Some(Duration::from_secs(1)),
|
||||
interval: Duration::from_millis(100),
|
||||
length: 64,
|
||||
received_stats: ReceivedStats::Both,
|
||||
stamp_at: StampAt::Both,
|
||||
clock: Clock::Both,
|
||||
..Default::default()
|
||||
},
|
||||
|
||||
probe_timeout: Duration::from_millis(200),
|
||||
..ClientConfig::default()
|
||||
}
|
||||
}
|
||||
|
||||
async fn client(server_addr: std::net::SocketAddr, policy: NegotiationPolicy) -> AsyncClient {
|
||||
AsyncClient::connect(test_config(server_addr, policy))
|
||||
AsyncClient::connect(server_addr.to_string(), test_config(policy))
|
||||
.await
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use irtt_client::{Authentication, HmacKey};
|
||||
use irtt_client::{Authentication, HmacKey, OpenPolicy};
|
||||
mod support;
|
||||
mod protocol_options {
|
||||
pub mod backend_smoke;
|
||||
@@ -147,10 +147,10 @@ fn hmac_rich_mode_uses_negotiated_echo_layout_and_decodes_reply() {
|
||||
let params = params_for_modes(ReceivedStats::Both, StampAt::Both, Clock::Both);
|
||||
let config_params = params.clone();
|
||||
let config_key = key.clone();
|
||||
let run = run_one_probe_with_config(params.clone(), standard_timestamps(), Some(key), |addr| {
|
||||
let run = run_one_probe_with_config(params.clone(), standard_timestamps(), Some(key), || {
|
||||
ClientConfig {
|
||||
auth: Authentication::Hmac(HmacKey::new(config_key)),
|
||||
..config_for_params(addr, &config_params)
|
||||
..config_for_params(&config_params)
|
||||
}
|
||||
});
|
||||
assert_negotiated_echo_use(&run, ¶ms, true);
|
||||
@@ -171,9 +171,11 @@ fn strict_open_rejects_changed_compatibility_params_from_server() {
|
||||
|
||||
for returned in changed_compatibility_params(&requested) {
|
||||
let server = start_open_server(returned, None);
|
||||
let mut config = config_for_params(server.addr, &requested);
|
||||
config.server_addr = server.addr.to_string();
|
||||
let mut client = Client::connect(config).unwrap();
|
||||
let config = config_for_params(&requested);
|
||||
let mut client = Client::connect(server.addr.to_string(), config).unwrap();
|
||||
client
|
||||
.set_recv_timeout(Some(Duration::from_millis(500)))
|
||||
.unwrap();
|
||||
assert!(matches!(
|
||||
client.open(),
|
||||
Err(ClientError::NegotiationRejected { .. })
|
||||
@@ -199,10 +201,13 @@ fn loose_open_uses_returned_params_for_echo_layout_and_reply_parsing() {
|
||||
returned.server_fill = None;
|
||||
|
||||
let requested_for_config = requested.clone();
|
||||
let run = run_one_probe_with_config(returned.clone(), standard_timestamps(), None, |addr| {
|
||||
let run = run_one_probe_with_config(returned.clone(), standard_timestamps(), None, || {
|
||||
ClientConfig {
|
||||
negotiation_policy: irtt_client::NegotiationPolicy::Loose,
|
||||
..config_for_params(addr, &requested_for_config)
|
||||
open: OpenPolicy {
|
||||
negotiation: irtt_client::NegotiationPolicy::Loose,
|
||||
..config_for_params(&requested_for_config).open
|
||||
},
|
||||
..config_for_params(&requested_for_config)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use irtt_client::{Client, ClientEvent};
|
||||
use irtt_proto::{Clock, ReceivedStats, StampAt};
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::support::{config_for_params, default_params, params_for_modes, BackendPeer};
|
||||
|
||||
@@ -7,7 +8,10 @@ use crate::support::{config_for_params, default_params, params_for_modes, Backen
|
||||
fn backend_basic_open_echo_close() {
|
||||
let params = default_params();
|
||||
let peer = BackendPeer::start_open_echo(None);
|
||||
let mut client = Client::connect(config_for_params(peer.addr(), ¶ms)).unwrap();
|
||||
let mut client = Client::connect(peer.addr().to_string(), config_for_params(¶ms)).unwrap();
|
||||
client
|
||||
.set_recv_timeout(Some(Duration::from_millis(500)))
|
||||
.unwrap();
|
||||
|
||||
let outcome = client.open().unwrap();
|
||||
assert!(matches!(outcome, irtt_client::OpenOutcome::Started { .. }));
|
||||
@@ -32,7 +36,11 @@ fn backend_received_stats_smoke() {
|
||||
] {
|
||||
let params = params_for_modes(mode, StampAt::None, Clock::Both);
|
||||
let peer = BackendPeer::start_open_echo(None);
|
||||
let mut client = Client::connect(config_for_params(peer.addr(), ¶ms)).unwrap();
|
||||
let mut client =
|
||||
Client::connect(peer.addr().to_string(), config_for_params(¶ms)).unwrap();
|
||||
client
|
||||
.set_recv_timeout(Some(Duration::from_millis(500)))
|
||||
.unwrap();
|
||||
|
||||
client.open().unwrap();
|
||||
client.send_probe().unwrap();
|
||||
@@ -55,7 +63,11 @@ fn backend_timestamp_smoke() {
|
||||
] {
|
||||
let params = params_for_modes(ReceivedStats::None, mode, Clock::Both);
|
||||
let peer = BackendPeer::start_open_echo(None);
|
||||
let mut client = Client::connect(config_for_params(peer.addr(), ¶ms)).unwrap();
|
||||
let mut client =
|
||||
Client::connect(peer.addr().to_string(), config_for_params(¶ms)).unwrap();
|
||||
client
|
||||
.set_recv_timeout(Some(Duration::from_millis(500)))
|
||||
.unwrap();
|
||||
|
||||
client.open().unwrap();
|
||||
client.send_probe().unwrap();
|
||||
@@ -102,7 +114,11 @@ fn backend_clock_smoke() {
|
||||
for clock in [Clock::Wall, Clock::Monotonic, Clock::Both] {
|
||||
let params = params_for_modes(ReceivedStats::None, StampAt::Both, clock);
|
||||
let peer = BackendPeer::start_open_echo(None);
|
||||
let mut client = Client::connect(config_for_params(peer.addr(), ¶ms)).unwrap();
|
||||
let mut client =
|
||||
Client::connect(peer.addr().to_string(), config_for_params(¶ms)).unwrap();
|
||||
client
|
||||
.set_recv_timeout(Some(Duration::from_millis(500)))
|
||||
.unwrap();
|
||||
|
||||
client.open().unwrap();
|
||||
client.send_probe().unwrap();
|
||||
|
||||
@@ -12,7 +12,9 @@ use std::{
|
||||
time::{Duration, Instant, SystemTime},
|
||||
};
|
||||
|
||||
use irtt_client::{Client, ClientConfig, ClientEvent, NegotiatedParams, OpenOutcome, SocketConfig};
|
||||
use irtt_client::{
|
||||
Client, ClientConfig, ClientEvent, NegotiatedParams, OpenOutcome, OpenPolicy, SessionRequest,
|
||||
};
|
||||
use irtt_proto::{
|
||||
compute_hmac_in_place, decode_request, echo_packet_len, encode_echo_reply, encode_open_reply,
|
||||
flags, verify_packet_hmac, Clock, DecodedRequest, DecodedRequestKind, EchoReply, OpenReply,
|
||||
@@ -166,12 +168,12 @@ pub fn params_for_modes(received_stats: ReceivedStats, stamp_at: StampAt, clock:
|
||||
/// Builds a [`ClientConfig`] whose negotiated `Params` will match `params`.
|
||||
///
|
||||
/// `params.dscp` is the raw IP TOS / Traffic Class byte, while
|
||||
/// [`ClientConfig::dscp`] is the six-bit codepoint that produces it; shift
|
||||
/// [`SessionRequest::dscp`] is the six-bit codepoint that produces it; shift
|
||||
/// right by two to recover the codepoint the resulting config must request.
|
||||
/// Panics if `params.dscp` has any ECN bits set, since those cannot be
|
||||
/// recovered from a codepoint and this helper's contract would silently stop
|
||||
/// holding otherwise.
|
||||
pub fn config_for_params(addr: SocketAddr, params: &Params) -> ClientConfig {
|
||||
pub fn config_for_params(params: &Params) -> ClientConfig {
|
||||
let traffic_class =
|
||||
u8::try_from(params.dscp).expect("test DSCP must fit the raw traffic-class byte");
|
||||
assert_eq!(
|
||||
@@ -180,26 +182,27 @@ pub fn config_for_params(addr: SocketAddr, params: &Params) -> ClientConfig {
|
||||
"test Params::dscp must be representable by ClientConfig's DSCP codepoint"
|
||||
);
|
||||
ClientConfig {
|
||||
server_addr: addr.to_string(),
|
||||
duration: if params.duration_ns == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(Duration::from_nanos(
|
||||
u64::try_from(params.duration_ns).expect("test duration must be non-negative"),
|
||||
))
|
||||
open: OpenPolicy {
|
||||
timeouts: vec![Duration::from_millis(200)],
|
||||
..Default::default()
|
||||
},
|
||||
interval: Duration::from_nanos(
|
||||
u64::try_from(params.interval_ns).expect("test interval must be non-negative"),
|
||||
),
|
||||
length: u32::try_from(params.length).unwrap(),
|
||||
received_stats: params.received_stats,
|
||||
stamp_at: params.stamp_at,
|
||||
clock: params.clock,
|
||||
dscp: traffic_class >> 2,
|
||||
server_fill: params.server_fill.as_ref().map(|fill| fill.value.clone()),
|
||||
open_timeouts: vec![Duration::from_millis(200)],
|
||||
socket_config: SocketConfig {
|
||||
recv_timeout: Some(Duration::from_millis(500)),
|
||||
request: SessionRequest {
|
||||
duration: if params.duration_ns == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(Duration::from_nanos(
|
||||
u64::try_from(params.duration_ns).expect("test duration must be non-negative"),
|
||||
))
|
||||
},
|
||||
interval: Duration::from_nanos(
|
||||
u64::try_from(params.interval_ns).expect("test interval must be non-negative"),
|
||||
),
|
||||
length: u32::try_from(params.length).unwrap(),
|
||||
received_stats: params.received_stats,
|
||||
stamp_at: params.stamp_at,
|
||||
clock: params.clock,
|
||||
dscp: traffic_class >> 2,
|
||||
server_fill: params.server_fill.as_ref().map(|fill| fill.value.clone()),
|
||||
..Default::default()
|
||||
},
|
||||
..ClientConfig::default()
|
||||
@@ -219,8 +222,8 @@ pub fn standard_timestamps() -> TimestampFields {
|
||||
|
||||
pub fn run_one_probe(params: Params, timestamps: TimestampFields) -> OneProbeRun {
|
||||
let config_params = params.clone();
|
||||
run_one_probe_with_config(params, timestamps, None, |addr| {
|
||||
config_for_params(addr, &config_params)
|
||||
run_one_probe_with_config(params, timestamps, None, || {
|
||||
config_for_params(&config_params)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -231,10 +234,13 @@ pub fn run_one_probe_with_config<F>(
|
||||
build_config: F,
|
||||
) -> OneProbeRun
|
||||
where
|
||||
F: FnOnce(SocketAddr) -> ClientConfig,
|
||||
F: FnOnce() -> ClientConfig,
|
||||
{
|
||||
let server = start_one_probe_server(server_params, timestamps, hmac_key);
|
||||
let mut client = Client::connect(build_config(server.addr)).unwrap();
|
||||
let mut client = Client::connect(server.addr.to_string(), build_config()).unwrap();
|
||||
client
|
||||
.set_recv_timeout(Some(Duration::from_millis(500)))
|
||||
.unwrap();
|
||||
let negotiated = assert_started(client.open().unwrap());
|
||||
|
||||
let sent_events = client.send_probe().unwrap();
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
|
||||
use std::{io, net::SocketAddr, time::Duration};
|
||||
|
||||
use irtt_client::{AsyncClient, ClientConfig, ClientEvent, OpenOutcome, PacketMeta, SocketConfig};
|
||||
use irtt_client::{
|
||||
AsyncClient, ClientConfig, ClientEvent, OpenOutcome, OpenPolicy, PacketMeta, SessionRequest,
|
||||
};
|
||||
use irtt_proto::{Clock, ReceivedStats, StampAt};
|
||||
use irtt_server::{Server, ServerConfig, ServerRuntimeError};
|
||||
use tokio::{sync::oneshot, task::JoinHandle, time::timeout};
|
||||
@@ -193,23 +195,27 @@ impl OpenSession {
|
||||
/// A client with an open session requesting `dscp` as a codepoint.
|
||||
async fn opened_session(server_addr: SocketAddr, dscp: u8) -> OpenSession {
|
||||
let config = ClientConfig {
|
||||
server_addr: server_addr.to_string(),
|
||||
duration: Some(Duration::from_secs(30)),
|
||||
interval: Duration::from_millis(10),
|
||||
length: 64,
|
||||
dscp,
|
||||
received_stats: ReceivedStats::Both,
|
||||
stamp_at: StampAt::Both,
|
||||
clock: Clock::Both,
|
||||
open_timeouts: vec![Duration::from_millis(500)],
|
||||
socket_config: SocketConfig {
|
||||
recv_timeout: Some(Duration::from_millis(500)),
|
||||
..SocketConfig::default()
|
||||
open: OpenPolicy {
|
||||
timeouts: vec![Duration::from_millis(500)],
|
||||
..Default::default()
|
||||
},
|
||||
request: SessionRequest {
|
||||
duration: Some(Duration::from_secs(30)),
|
||||
interval: Duration::from_millis(10),
|
||||
length: 64,
|
||||
dscp,
|
||||
received_stats: ReceivedStats::Both,
|
||||
stamp_at: StampAt::Both,
|
||||
clock: Clock::Both,
|
||||
..Default::default()
|
||||
},
|
||||
|
||||
probe_timeout: Duration::from_millis(500),
|
||||
..ClientConfig::default()
|
||||
};
|
||||
let mut client = AsyncClient::connect(config).await.unwrap();
|
||||
let mut client = AsyncClient::connect(server_addr.to_string(), config)
|
||||
.await
|
||||
.unwrap();
|
||||
match client.open().await.unwrap() {
|
||||
OpenOutcome::Started { negotiated, .. } => assert_eq!(
|
||||
negotiated.params.dscp,
|
||||
|
||||
@@ -18,7 +18,9 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use irtt_client::{AsyncClient, ClientConfig, ClientEvent, OpenOutcome, PacketMeta, SocketConfig};
|
||||
use irtt_client::{
|
||||
AsyncClient, ClientConfig, ClientEvent, OpenOutcome, OpenPolicy, PacketMeta, SessionRequest,
|
||||
};
|
||||
use irtt_proto::{Clock, ReceivedStats, StampAt};
|
||||
use irtt_server::{Server, ServerConfig, ServerRuntimeError};
|
||||
use tokio::{sync::oneshot, task::JoinHandle, time::timeout};
|
||||
@@ -193,23 +195,27 @@ fn unthrottled() -> ServerConfig {
|
||||
|
||||
async fn connected_client(server_addr: SocketAddr) -> AsyncClient {
|
||||
let config = ClientConfig {
|
||||
server_addr: server_addr.to_string(),
|
||||
duration: Some(Duration::from_secs(30)),
|
||||
interval: Duration::from_millis(10),
|
||||
length: 64,
|
||||
dscp: EF_DSCP,
|
||||
received_stats: ReceivedStats::Both,
|
||||
stamp_at: StampAt::Both,
|
||||
clock: Clock::Both,
|
||||
open_timeouts: vec![Duration::from_millis(500)],
|
||||
socket_config: SocketConfig {
|
||||
recv_timeout: Some(Duration::from_millis(500)),
|
||||
..SocketConfig::default()
|
||||
open: OpenPolicy {
|
||||
timeouts: vec![Duration::from_millis(500)],
|
||||
..Default::default()
|
||||
},
|
||||
request: SessionRequest {
|
||||
duration: Some(Duration::from_secs(30)),
|
||||
interval: Duration::from_millis(10),
|
||||
length: 64,
|
||||
dscp: EF_DSCP,
|
||||
received_stats: ReceivedStats::Both,
|
||||
stamp_at: StampAt::Both,
|
||||
clock: Clock::Both,
|
||||
..Default::default()
|
||||
},
|
||||
|
||||
probe_timeout: Duration::from_millis(500),
|
||||
..ClientConfig::default()
|
||||
};
|
||||
AsyncClient::connect(config).await.unwrap()
|
||||
AsyncClient::connect(server_addr.to_string(), config)
|
||||
.await
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
async fn assert_started(client: &mut AsyncClient, server_addr: SocketAddr) {
|
||||
|
||||
Reference in new issue
Block a user