icmp_client/
impl_async_io.rs

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