iroh_relay/
ping_tracker.rs1use n0_future::time::{self, Duration, Instant};
2use tracing::debug;
3
4pub const PING_TIMEOUT: Duration = Duration::from_secs(5);
6
7#[derive(Debug)]
11pub struct PingTracker {
12 inner: Option<PingInner>,
13 default_timeout: Duration,
14}
15
16#[derive(Debug)]
17struct PingInner {
18 data: [u8; 8],
19 deadline: Instant,
20}
21
22impl Default for PingTracker {
23 fn default() -> Self {
24 Self::new(PING_TIMEOUT)
25 }
26}
27
28impl PingTracker {
29 pub fn new(default_timeout: Duration) -> Self {
31 Self {
32 inner: None,
33 default_timeout,
34 }
35 }
36
37 pub fn default_timeout(&self) -> Duration {
39 self.default_timeout
40 }
41
42 pub fn new_ping(&mut self) -> [u8; 8] {
44 let ping_data = rand::random();
45 debug!(data = ?ping_data, "Sending ping to relay server.");
46 self.inner = Some(PingInner {
47 data: ping_data,
48 deadline: Instant::now() + self.default_timeout,
49 });
50 ping_data
51 }
52
53 pub fn pong_received(&mut self, data: [u8; 8]) {
58 if self.inner.as_ref().map(|inner| inner.data) == Some(data) {
59 debug!(?data, "Pong received from relay server");
60 self.inner = None;
61 }
62 }
63
64 pub async fn timeout(&mut self) {
68 match self.inner {
69 Some(PingInner { deadline, data }) => {
70 time::sleep_until(deadline).await;
71 debug!(?data, "Ping timeout.");
72 self.inner = None;
73 }
74 None => std::future::pending().await,
75 }
76 }
77}