1use std::net::{SocketAddr, UdpSocket};
11use std::sync::Mutex;
12use std::time::Duration;
13
14pub struct Prober {
15 sock: UdpSocket,
16 task: Mutex<Option<tokio::task::JoinHandle<()>>>,
17}
18
19impl Prober {
20 pub(crate) fn new(sock: UdpSocket) -> Self {
21 Self {
22 sock,
23 task: Mutex::new(None),
24 }
25 }
26
27 pub fn start(&self, target: SocketAddr, interval: Duration, duration: Duration) {
29 self.stop();
30 let sock = match self.sock.try_clone() {
31 Ok(s) => s,
32 Err(e) => {
33 tracing::warn!("prober: cannot clone socket: {e}");
34 return;
35 }
36 };
37 let handle = tokio::spawn(async move {
38 let deadline = tokio::time::Instant::now() + duration;
39 let mut ticker = tokio::time::interval(interval);
40 let mut sent = 0u32;
41 while tokio::time::Instant::now() < deadline {
42 ticker.tick().await;
43 if sock.send_to(&[0u8], target).is_ok() {
45 sent += 1;
46 }
47 }
48 tracing::debug!(%target, sent, "prober finished");
49 });
50 *self.task.lock().unwrap() = Some(handle);
51 }
52
53 pub fn start_default(&self, target: SocketAddr) {
54 self.start(target, Duration::from_millis(250), Duration::from_secs(12));
55 }
56
57 pub fn stop(&self) {
58 if let Some(t) = self.task.lock().unwrap().take() {
59 t.abort();
60 }
61 }
62}
63
64impl Drop for Prober {
65 fn drop(&mut self) {
66 self.stop();
67 }
68}