1#![allow(clippy::std_instead_of_core)]
2
3use std::env;
4use std::time::{Duration, Instant};
5
6use msrt_udp::{EngineConfig, UdpServer, UdpServerEvent};
7use tokio::time::sleep;
8
9const DEFAULT_BIND: &str = "127.0.0.1:9000";
10const IDLE_TIMEOUT: Duration = Duration::from_secs(30);
11const LOOP_SLEEP: Duration = Duration::from_millis(10);
12
13#[tokio::main]
14async fn main() -> msrt_udp::Result<()> {
15 let bind = env::args()
16 .nth(1)
17 .unwrap_or_else(|| DEFAULT_BIND.to_string());
18 let mut server = UdpServer::<16>::bind_with_config(&bind, demo_config()).await?;
19 println!("server listening on {}", server.local_addr()?);
20
21 let mut next_idle_sweep = Instant::now() + Duration::from_secs(1);
22
23 loop {
24 match server.tick().await? {
25 UdpServerEvent::Message { peer, message } if message.as_bytes() != [0] => {
26 let text = String::from_utf8_lossy(message.as_bytes());
27 println!("{peer}: {text}");
28 let reply = format!("echo from server: {text}");
29 let _ = server.send_to(peer, reply.as_bytes())?;
30 }
31 UdpServerEvent::Message { .. } | UdpServerEvent::Idle => {}
32 UdpServerEvent::SendFailed { peer, failed } => {
33 println!("{peer}: send failed: {failed:?}; disconnecting peer");
34 server.disconnect(peer);
35 }
36 }
37
38 if next_idle_sweep <= Instant::now() {
39 let disconnected = server.disconnect_idle(IDLE_TIMEOUT.as_millis() as u64);
40 if disconnected > 0 {
41 println!("disconnected {disconnected} idle peer(s)");
42 }
43 next_idle_sweep = Instant::now() + Duration::from_secs(1);
44 }
45
46 sleep(LOOP_SLEEP).await;
47 }
48}
49
50fn demo_config() -> EngineConfig {
51 EngineConfig {
52 retransmit_timeout_ms: 250,
53 max_retransmit_attempts: 8,
54 ..EngineConfig::default()
55 }
56}