1use std::net::IpAddr;
2use std::time::{Duration, Instant};
3
4#[derive(Debug)]
5pub struct HostEntry {
6 pub display: String,
7 pub addr: IpAddr,
8 pub is_ipv6: bool,
9
10 pub num_sent: u32,
11 pub num_recv: u32,
12 pub max_reply: Option<Duration>,
13 pub min_reply: Option<Duration>,
14 pub total_time: Duration,
15
16 pub resp_times: Vec<Option<Duration>>,
17
18 pub last_send: Option<Instant>,
19 pub next_send: Instant,
20 pub retries_left: u32,
21 pub current_ping_index: u32,
22 pub done: bool,
23}
24
25impl HostEntry {
26 pub fn new(name: String, addr: IpAddr, is_ipv6: bool, count: u32) -> Self {
27 let display = name.clone();
28 HostEntry {
29 display,
30 addr,
31 is_ipv6,
32 num_sent: 0,
33 num_recv: 0,
34 max_reply: None,
35 min_reply: None,
36 total_time: Duration::ZERO,
37 resp_times: if count > 0 {
38 vec![None; count as usize]
39 } else {
40 Vec::new()
41 },
42 last_send: None,
43 next_send: Instant::now(),
44 retries_left: 0,
45 current_ping_index: 0,
46 done: false,
47 }
48 }
49
50 pub fn record_reply(&mut self, rtt: Duration, ping_index: u32) {
51 self.num_recv += 1;
52 self.total_time += rtt;
53 self.max_reply = Some(self.max_reply.map_or(rtt, |m| m.max(rtt)));
54 self.min_reply = Some(self.min_reply.map_or(rtt, |m| m.min(rtt)));
55 let idx = ping_index as usize;
56 if idx < self.resp_times.len() {
57 self.resp_times[idx] = Some(rtt);
59 } else {
60 self.resp_times.push(Some(rtt));
62 }
63 }
64
65 pub fn avg_reply(&self) -> Option<Duration> {
66 (self.num_recv > 0).then(|| self.total_time / self.num_recv)
67 }
68
69 pub fn loss_pct(&self) -> u32 {
70 if self.num_sent == 0 {
71 0
72 } else {
73 ((self.num_sent - self.num_recv) * 100) / self.num_sent
74 }
75 }
76}
77
78pub struct PendingPing {
79 pub host_index: usize,
80 pub ping_index: u32,
81 pub sent_at: Instant,
82}