icmp_client/
impl_async_io.rs1use 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#[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}