use std::time::{Duration, Instant};
use irtt_client::{Client, ClientConfig, ClientEvent, OpenOutcome, OpenPolicy, SessionRequest};
const RUN_DURATION: Duration = Duration::from_secs(2);
fn main() {
let config = ClientConfig {
open: OpenPolicy {
timeouts: vec![Duration::from_millis(300)],
..Default::default()
},
request: SessionRequest {
duration: Some(RUN_DURATION),
interval: Duration::from_millis(200),
..Default::default()
},
..Default::default()
};
let mut client = match Client::connect("127.0.0.1:2112", config) {
Ok(client) => client,
Err(err) => {
eprintln!("failed to prepare client socket: {err}");
return;
}
};
if let Err(err) = client.set_recv_timeout(Some(Duration::from_millis(100))) {
eprintln!("failed to configure receive timeout: {err}");
return;
}
let negotiated = match client.open() {
Ok(OpenOutcome::Started(started)) => {
println!("session opened: {started:?}");
started.negotiation
}
Ok(OpenOutcome::NoTestCompleted(completed)) => {
println!("{completed:?}");
return;
}
Err(err) => {
eprintln!("open failed (is a server running at 127.0.0.1:2112?): {err}");
return;
}
};
let interval = negotiated.accepted.interval;
let start = Instant::now();
let end = start
+ negotiated
.accepted
.duration
.expect("example requests a finite run");
let deadline = end + client.probe_timeout();
let mut next_send = start;
while Instant::now() < deadline && !client.is_peer_closed() {
let now = Instant::now();
if now >= end && !client.has_pending_probes() {
break;
}
if now < end && now >= next_send {
match client.send_probe() {
Ok(receipt) => {
print_event(&receipt.into());
while next_send <= Instant::now() {
next_send += interval;
}
}
Err(err) => {
if let irtt_client::SendProbeError::AfterCommit { receipt, .. } = &err {
print_event(&(*receipt).into());
}
eprintln!("send failed: {err}");
break;
}
}
}
match client.recv_once() {
Ok(events) => events.iter().for_each(print_event),
Err(err) => {
eprintln!("receive failed: {err}");
break;
}
}
match client.poll_timeouts() {
Ok(events) => events.iter().for_each(print_event),
Err(err) => {
eprintln!("timeout polling failed: {err}");
break;
}
}
}
if client.is_peer_closed() {
return;
}
match client.close() {
Ok(events) => events.iter().for_each(print_event),
Err(err) => eprintln!("close failed: {err}"),
}
}
fn print_event(event: &ClientEvent) {
match event {
ClientEvent::EchoReply { seq, rtt, .. } => {
println!("seq {seq}: rtt {:?}", rtt.effective);
}
ClientEvent::EchoLoss { seq, .. } => println!("seq {seq}: lost"),
other => println!("{other:?}"),
}
}