use crate::{
message::{echo::EchoId, EncodeIcmpMessage},
platform,
socket::{IcmpSocket, SocketConfig},
Icmpv4, Icmpv6, IpVersion,
};
use std::{io, net, ops};
pub struct SocketPair {
pub ipv4: IcmpSocket<Icmpv4>,
pub ipv6: IcmpSocket<Icmpv6>,
}
impl SocketPair {
pub fn new(
icmpv4_config: SocketConfig<Icmpv4>,
icmpv6_config: SocketConfig<Icmpv6>,
) -> io::Result<Self> {
Ok(Self {
ipv4: IcmpSocket::new(icmpv4_config)?,
ipv6: IcmpSocket::new(icmpv6_config)?,
})
}
pub async fn send_to_either<M>(&self, msg: &mut M, addr: net::IpAddr) -> io::Result<()>
where
M: EncodeIcmpMessage<Icmpv4> + EncodeIcmpMessage<Icmpv6>,
{
match addr {
net::IpAddr::V4(v4) => self.ipv4.send_to(msg, v4).await,
net::IpAddr::V6(v6) => self.ipv6.send_to(msg, v6).await,
}
}
pub async fn recv_either<'a>(
&self,
ip_version: IpVersion,
buf: &'a mut [u8],
) -> io::Result<(&'a [u8], ops::Range<usize>)> {
match ip_version {
IpVersion::V4 => self.ipv4.recv(buf).await,
IpVersion::V6 => self.ipv6.recv(buf).await,
}
}
pub fn platform_echo_id(&self, ip_version: IpVersion) -> Option<EchoId> {
if platform::icmp_send_overwrite_echo_id_with_local_port() {
let port = match ip_version {
IpVersion::V4 => self.ipv4.local_port(),
IpVersion::V6 => self.ipv6.local_port(),
};
Some(EchoId::from_be(port))
} else {
None
}
}
}