blocking_client/
blocking_client.rs1use std::time::{Duration, Instant};
20
21use irtt_client::{Client, ClientConfig, ClientEvent, OpenOutcome, OpenPolicy, SessionRequest};
22
23const RUN_DURATION: Duration = Duration::from_secs(2);
24
25fn main() {
26 let config = ClientConfig {
27 open: OpenPolicy {
28 timeouts: vec![Duration::from_millis(300)],
31 ..Default::default()
32 },
33 request: SessionRequest {
34 duration: Some(RUN_DURATION),
35 interval: Duration::from_millis(200),
36 ..Default::default()
37 },
38 ..Default::default()
39 };
40
41 let mut client = match Client::connect("127.0.0.1:2112", config) {
42 Ok(client) => client,
43 Err(err) => {
44 eprintln!("failed to prepare client socket: {err}");
45 return;
46 }
47 };
48
49 if let Err(err) = client.set_recv_timeout(Some(Duration::from_millis(100))) {
50 eprintln!("failed to configure receive timeout: {err}");
51 return;
52 }
53
54 let negotiated = match client.open() {
55 Ok(OpenOutcome::Started(started)) => {
56 println!("session opened: {started:?}");
57 started.negotiation
58 }
59 Ok(OpenOutcome::NoTestCompleted(completed)) => {
60 println!("{completed:?}");
61 return;
62 }
63 Err(err) => {
64 eprintln!("open failed (is a server running at 127.0.0.1:2112?): {err}");
65 return;
66 }
67 };
68
69 let interval = negotiated.accepted.interval;
71 let start = Instant::now();
72 let end = start
73 + negotiated
74 .accepted
75 .duration
76 .expect("example requests a finite run");
77 let deadline = end + client.probe_timeout();
78 let mut next_send = start;
79 while Instant::now() < deadline && !client.is_peer_closed() {
80 let now = Instant::now();
81 if now >= end && !client.has_pending_probes() {
82 break;
83 }
84 if now < end && now >= next_send {
85 match client.send_probe() {
86 Ok(receipt) => {
87 print_event(&receipt.into());
88 while next_send <= Instant::now() {
89 next_send += interval;
90 }
91 }
92 Err(err) => {
93 if let irtt_client::SendProbeError::AfterCommit { receipt, .. } = &err {
94 print_event(&(*receipt).into());
95 }
96 eprintln!("send failed: {err}");
97 break;
98 }
99 }
100 }
101 match client.recv_once() {
102 Ok(events) => events.iter().for_each(print_event),
103 Err(err) => {
104 eprintln!("receive failed: {err}");
105 break;
106 }
107 }
108 match client.poll_timeouts() {
109 Ok(events) => events.iter().for_each(print_event),
110 Err(err) => {
111 eprintln!("timeout polling failed: {err}");
112 break;
113 }
114 }
115 }
116
117 if client.is_peer_closed() {
118 return;
119 }
120 match client.close() {
121 Ok(events) => events.iter().for_each(print_event),
122 Err(err) => eprintln!("close failed: {err}"),
123 }
124}
125
126fn print_event(event: &ClientEvent) {
127 match event {
128 ClientEvent::EchoReply { seq, rtt, .. } => {
129 println!("seq {seq}: rtt {:?}", rtt.effective);
130 }
131 ClientEvent::EchoLoss { seq, .. } => println!("seq {seq}: lost"),
132 other => println!("{other:?}"),
133 }
134}