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