ping_async/
lib.rs

1// lib.rs
2
3mod 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}