1mod platform;
4pub use platform::IcmpEchoRequestor;
5
6use std::net::IpAddr;
7use std::time::Duration;
8
9pub const PING_DEFAULT_TTL: u8 = 128;
10pub const PING_DEFAULT_TIMEOUT: Duration = Duration::from_secs(2);
11pub const PING_DEFAULT_REQUEST_DATA_LENGTH: usize = 32;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum IcmpEchoStatus {
15 Success,
16 TimedOut,
17 Unreachable,
18 Unknown,
19}
20
21impl IcmpEchoStatus {
22 pub fn ok(self) -> Result<(), String> {
23 match self {
24 Self::Success => Ok(()),
25 Self::TimedOut => Err("Timed out".to_string()),
26 Self::Unreachable => Err("Destination unreachable".to_string()),
27 Self::Unknown => Err("Unknown error".to_string()),
28 }
29 }
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33pub struct IcmpEchoReply {
34 destination: IpAddr,
35 status: IcmpEchoStatus,
36 round_trip_time: Duration,
37}
38
39impl IcmpEchoReply {
40 pub fn new(destination: IpAddr, status: IcmpEchoStatus, round_trip_time: Duration) -> Self {
41 Self {
42 destination,
43 status,
44 round_trip_time,
45 }
46 }
47
48 pub fn destination(&self) -> IpAddr {
49 self.destination
50 }
51
52 pub fn status(&self) -> IcmpEchoStatus {
53 self.status
54 }
55
56 pub fn round_trip_time(&self) -> Duration {
57 self.round_trip_time
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use futures::{channel::mpsc, StreamExt};
64 use std::io;
65
66 use super::*;
67
68 #[tokio::test]
69 async fn ping_localhost_v4() -> io::Result<()> {
70 let (tx, mut rx) = mpsc::unbounded();
71
72 let pinger = IcmpEchoRequestor::new(tx, "127.0.0.1".parse().unwrap(), None, None, None)?;
73 pinger.send().await?;
74 rx.next().await;
75
76 Ok(())
77 }
78
79 #[tokio::test]
80 async fn ping_localhost_v6() -> io::Result<()> {
81 let (tx, mut rx) = mpsc::unbounded();
82
83 let pinger = IcmpEchoRequestor::new(tx, "::1".parse().unwrap(), None, None, None)?;
84 pinger.send().await?;
85 rx.next().await;
86
87 Ok(())
88 }
89}