#[derive(Debug)] struct PingError; async fn restart_wg() -> Result<(), Box> { tokio::process::Command::new("systemctl") .args(["restart", "wg-quick@wg0"]) .spawn()? .wait() .await?; Ok(()) } async fn ping() -> Result<(), Box> { let pinger = surge_ping::Pinger::new("192.168.5.1".parse()?)?; let mut any_success = false; for i in 0..3 { any_success |= pinger.ping(i).await.is_ok(); } if !any_success { return Err(PingError.into()); } Ok(()) } #[tokio::main(flavor = "current_thread")] async fn main() -> Result<(), Box> { let mut ticker = tokio::time::interval(std::time::Duration::from_secs(15)); loop { ticker.tick().await; match ping().await { Ok(_) => { println!("online"); } Err(e) => { if e.is::() { println!("restarting"); if let Err(e) = restart_wg().await { eprintln!("Failed to restart tunnel: {}", e); } } } } } } impl std::fmt::Display for PingError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "All ping attempts failed") } } impl std::error::Error for PingError {}