icmp_client/
impl_tokio.rs

1use std::{io::Error as IoError, net::SocketAddr, sync::Arc};
2
3use async_trait::async_trait;
4use tokio::net::UdpSocket;
5
6use crate::{config::Config, utils::new_std_udp_socket, AsyncClient, AsyncClientWithConfigError};
7
8//
9#[derive(Debug, Clone)]
10pub struct Client {
11    inner: Arc<UdpSocket>,
12}
13
14impl Client {
15    pub fn new(config: &Config) -> Result<Self, AsyncClientWithConfigError> {
16        let udp_socket = new_std_udp_socket(config)?;
17        let inner = UdpSocket::from_std(udp_socket)?;
18        Ok(Self {
19            inner: Arc::new(inner),
20        })
21    }
22}
23
24#[async_trait]
25impl AsyncClient for Client {
26    fn with_config(config: &Config) -> Result<Self, AsyncClientWithConfigError> {
27        Client::new(config)
28    }
29
30    async fn send_to<A: Into<SocketAddr> + Send>(
31        &self,
32        buf: &[u8],
33        addr: A,
34    ) -> Result<usize, IoError> {
35        self.inner.send_to(buf, addr.into()).await
36    }
37    async fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr), IoError> {
38        self.inner.recv_from(buf).await
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45
46    #[tokio::test]
47    async fn test_client() -> Result<(), Box<dyn std::error::Error>> {
48        crate::tests_helper::ping_ipv4::<Client>("127.0.0.1".parse().expect("Never")).await?;
49
50        match crate::tests_helper::ping_ipv6::<Client>("::1".parse().expect("Never")).await {
51            Ok(_) => {}
52            Err(err) => {
53                if let Some(AsyncClientWithConfigError::IcmpV6ProtocolNotSupported(_)) =
54                    err.downcast_ref::<AsyncClientWithConfigError>()
55                {
56                    let info = os_info::get();
57                    if info.os_type() == os_info::Type::CentOS
58                        && matches!(info.version(), os_info::Version::Semantic(7, 0, 0))
59                    {
60                        eprintln!("CentOS 7 doesn't support IcmpV6");
61                    } else {
62                        panic!("{err:?}")
63                    }
64                } else {
65                    panic!("{err:?}")
66                }
67            }
68        }
69
70        Ok(())
71    }
72}