1#![allow(clippy::std_instead_of_core)]
2
3use std::env;
4use std::io::ErrorKind;
5use std::time::{Duration, Instant};
6
7use msrt_udp::{EngineConfig, UdpClient, UdpClientEvent};
8use tokio::time::sleep;
9
10const DEFAULT_SERVER: &str = "127.0.0.1:9000";
11const SEND_INTERVAL: Duration = Duration::from_secs(1);
12const LOOP_SLEEP: Duration = Duration::from_millis(10);
13
14#[tokio::main]
15async fn main() -> msrt_udp::Result<()> {
16 let server = env::args()
17 .nth(1)
18 .unwrap_or_else(|| DEFAULT_SERVER.to_string());
19
20 let mut client = UdpClient::bind_with_config("127.0.0.1:0", &server, demo_config()).await?;
21 println!(
22 "frontend local={} remote={}",
23 client.local_addr()?,
24 client.peer_addr()?
25 );
26
27 reconnect(&mut client)?;
28 let mut sequence = 0_u64;
29 let mut next_send = Instant::now();
30
31 loop {
32 if next_send <= Instant::now() {
33 let payload = format!("hello udp {sequence}");
34 if client.send(payload.as_bytes())? {
35 println!("queued: {payload}");
36 sequence = sequence.wrapping_add(1);
37 }
38 next_send = Instant::now() + SEND_INTERVAL;
39 }
40
41 match client.tick().await? {
42 UdpClientEvent::Message(message) if message.as_bytes() != [0] => {
43 println!("message: {}", String::from_utf8_lossy(message.as_bytes()));
44 }
45 UdpClientEvent::Message(_) | UdpClientEvent::Idle => {}
46 UdpClientEvent::SendFailed(failed) => {
47 println!("send failed: {failed:?}; reconnecting");
48 client.disconnect();
49 reconnect(&mut client)?;
50 next_send = Instant::now();
51 }
52 UdpClientEvent::TransportUnavailable { kind } => {
53 println!("transport unavailable: {kind:?}; reconnecting");
54 client.disconnect();
55 reconnect(&mut client)?;
56 next_send = Instant::now() + reconnect_delay(kind);
57 }
58 }
59
60 sleep(LOOP_SLEEP).await;
61 }
62}
63
64fn reconnect_delay(kind: ErrorKind) -> Duration {
65 match kind {
66 ErrorKind::ConnectionRefused | ErrorKind::ConnectionReset => Duration::from_millis(250),
67 _ => Duration::from_secs(1),
68 }
69}
70
71fn reconnect(client: &mut UdpClient) -> msrt_udp::Result<()> {
72 client.connect()?;
73 println!("session started");
74 Ok(())
75}
76
77fn demo_config() -> EngineConfig {
78 EngineConfig {
79 retransmit_timeout_ms: 250,
80 max_retransmit_attempts: 8,
81 ..EngineConfig::default()
82 }
83}