use std::net::UdpSocket;
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
use badnet::{BadNet, BadNetConfig};
fn main() -> std::io::Result<()> {
let net = BadNet::builder().loss(1.0).build()?;
let left = net.left_addr();
let right = net.right_addr();
let net = Arc::new(Mutex::new(net));
let rx_sock = UdpSocket::bind(format!("{right}:9100"))?;
rx_sock.set_read_timeout(Some(Duration::from_millis(50)))?;
let received_before = Arc::new(Mutex::new(0u32));
let received_after = Arc::new(Mutex::new(0u32));
let start = Instant::now();
let reconfigure_at = Arc::new(Mutex::new(None::<Duration>));
let rb = Arc::clone(&received_before);
let ra = Arc::clone(&received_after);
let rat = Arc::clone(&reconfigure_at);
let rx_thread = std::thread::spawn(move || {
let mut buf = [0u8; 64];
while start.elapsed() < Duration::from_millis(2500) {
if rx_sock.recv(&mut buf).is_ok() {
let elapsed = start.elapsed();
let phase_switch = *rat.lock().unwrap();
match phase_switch {
None => *rb.lock().unwrap() += 1,
Some(t) if elapsed >= t => *ra.lock().unwrap() += 1,
_ => *rb.lock().unwrap() += 1,
}
}
}
});
let net_ctrl = Arc::clone(&net);
let rat2 = Arc::clone(&reconfigure_at);
let ctrl_thread = std::thread::spawn(move || -> std::io::Result<()> {
std::thread::sleep(Duration::from_millis(500));
let mut net = net_ctrl.lock().unwrap();
net.reconfigure(BadNetConfig::default())?;
*rat2.lock().unwrap() = Some(start.elapsed());
println!("reconfigured at {:.0} ms — loss cleared", start.elapsed().as_secs_f64() * 1000.0);
Ok(())
});
let tx_sock = UdpSocket::bind(format!("{left}:0"))?;
let dest = format!("{right}:9100");
for i in 0u32..200 {
tx_sock.send_to(&i.to_le_bytes(), &dest)?;
std::thread::sleep(Duration::from_millis(10));
}
rx_thread.join().ok();
ctrl_thread.join().ok().transpose()?;
let before = *received_before.lock().unwrap();
let after = *received_after.lock().unwrap();
println!("packets received BEFORE reconfigure (~500 ms, 100% loss): {before}");
println!("packets received AFTER reconfigure (~1500 ms, 0% loss): {after}");
Ok(())
}