async_icmp/socket/
pair.rs1use crate::{
4 message::{echo::EchoId, EncodeIcmpMessage},
5 platform,
6 socket::{IcmpSocket, SocketConfig},
7 Icmpv4, Icmpv6, IpVersion,
8};
9use std::{io, net, ops};
10
11pub struct SocketPair {
18 pub ipv4: IcmpSocket<Icmpv4>,
20 pub ipv6: IcmpSocket<Icmpv6>,
22}
23impl SocketPair {
24 pub fn new(
26 icmpv4_config: SocketConfig<Icmpv4>,
27 icmpv6_config: SocketConfig<Icmpv6>,
28 ) -> io::Result<Self> {
29 Ok(Self {
30 ipv4: IcmpSocket::new(icmpv4_config)?,
31 ipv6: IcmpSocket::new(icmpv6_config)?,
32 })
33 }
34
35 pub async fn send_to_either<M>(&self, msg: &mut M, addr: net::IpAddr) -> io::Result<()>
37 where
38 M: EncodeIcmpMessage<Icmpv4> + EncodeIcmpMessage<Icmpv6>,
39 {
40 match addr {
41 net::IpAddr::V4(v4) => self.ipv4.send_to(msg, v4).await,
42 net::IpAddr::V6(v6) => self.ipv6.send_to(msg, v6).await,
43 }
44 }
45
46 pub async fn recv_either<'a>(
51 &self,
52 ip_version: IpVersion,
53 buf: &'a mut [u8],
54 ) -> io::Result<(&'a [u8], ops::Range<usize>)> {
55 match ip_version {
56 IpVersion::V4 => self.ipv4.recv(buf).await,
57 IpVersion::V6 => self.ipv6.recv(buf).await,
58 }
59 }
60
61 pub fn platform_echo_id(&self, ip_version: IpVersion) -> Option<EchoId> {
63 if platform::icmp_send_overwrite_echo_id_with_local_port() {
64 let port = match ip_version {
65 IpVersion::V4 => self.ipv4.local_port(),
66 IpVersion::V6 => self.ipv6.local_port(),
67 };
68
69 Some(EchoId::from_be(port))
70 } else {
71 None
72 }
73 }
74}