pub struct PingMultiplexer { /* private fields */ }
Expand description
A high-level ping (ICMP echo / echo reply) API.
This addresses the common case of handling one or more ping “sessions”: for a given IP address, ICMP Echo ID, and ICMP Echo Data, you send one or more pings (ICMP Echo).
Each session has its own channel for responses (ICMP Echo Reply).
Because this is designed to be used from many tasks simultaneously, it is safe to clone()
as it uses Arc
internally.
§Examples
Create two ping sessions on one socket, and send one ping with each.
use std::net;
use async_icmp::{
message::echo::EchoSeq,
IpVersion,
ping::PingMultiplexer,
socket::SocketConfig
};
async fn ping_demo() -> anyhow::Result<()> {
let multiplexer = PingMultiplexer::new(SocketConfig::default(), SocketConfig::default())?;
// Two sessions with distinct `data` (and possibly id, platform permitting)
let (handle1, mut rx1) = multiplexer
.add_session(
net::Ipv4Addr::LOCALHOST.into(),
multiplexer.platform_echo_id(IpVersion::V4).unwrap_or_else(rand::random),
rand::random::<[u8; 32]>().to_vec(),
)
.await?;
let (handle2, mut rx2) = multiplexer
.add_session(
net::Ipv4Addr::LOCALHOST.into(),
multiplexer.platform_echo_id(IpVersion::V4).unwrap_or_else(rand::random),
rand::random::<[u8; 32]>().to_vec(),
)
.await?;
// Using distinct `seq` just to show that sessions are disambiguated.
// Typically you would start at 0 and increment for multiple pings.
let seq1 = EchoSeq::from_be(3);
let seq2 = EchoSeq::from_be(7);
// Receiver task waiting in the background
let receiver = tokio::spawn(async move {
assert_eq!(seq1, rx1.recv().await.unwrap().seq);
assert_eq!(seq2, rx2.recv().await.unwrap().seq);
});
multiplexer.send_ping(handle1, seq1).await?;
multiplexer.send_ping(handle2, seq2).await?;
// Make sure receiver got expected results
receiver.await?;
Ok(())
}
Implementations§
Source§impl PingMultiplexer
impl PingMultiplexer
Sourcepub fn new(
icmpv4_config: SocketConfig<Icmpv4>,
icmpv6_config: SocketConfig<Icmpv6>,
) -> Result<Self>
pub fn new( icmpv4_config: SocketConfig<Icmpv4>, icmpv6_config: SocketConfig<Icmpv6>, ) -> Result<Self>
Create a new multiplexer with the provided socket configs.
Sourcepub async fn add_session(
&self,
ip: IpAddr,
id: EchoId,
data: Vec<u8>,
) -> Result<(SessionHandle, Receiver<ReplyTimestamp>), AddSessionError>
pub async fn add_session( &self, ip: IpAddr, id: EchoId, data: Vec<u8>, ) -> Result<(SessionHandle, Receiver<ReplyTimestamp>), AddSessionError>
Add a session to the multiplexer.
Echo Reply messages with the provided id
and data
will cause a ReplyTimestamp
to be
sent to the returned channel receiver. Timestamps will be sent as they are received from the
socket, including duplicates, etc.
If the receiver is not drained fast enough, timestamps will be dropped.
If the receiver is dropped, the session may be closed at some point in the future, but to
reliably release resources, call Self::close_session
.
On some platforms (for which platform::icmp_send_overwrite_echo_id_with_local_port
returns true),
the provided id
will be overwritten in the kernel by the local port. On such platforms,
id
must be the local port for the relevant socket. If a different id is used, echo reply
messages won’t be matched to this session.
See Self::platform_echo_id
, Self::ipv4_local_port
, and Self::ipv6_local_port
.
Sourcepub async fn send_ping(
&self,
session_handle: SessionHandle,
seq: EchoSeq,
) -> Result<Instant, SendPingError>
pub async fn send_ping( &self, session_handle: SessionHandle, seq: EchoSeq, ) -> Result<Instant, SendPingError>
Send a ping to the IP address specified when the session was created.
Returns the timestamp at which the ICMP message was passed to the socket.
Sourcepub async fn close_session(
&self,
session_handle: SessionHandle,
) -> Result<(), LifecycleError>
pub async fn close_session( &self, session_handle: SessionHandle, ) -> Result<(), LifecycleError>
Close a session, releasing any resources associated with it.
If the session is open, it will be closed. It is not an error to attempt to close an already closed session.
Sourcepub async fn shutdown(&self)
pub async fn shutdown(&self)
Shutdown the multiplexer.
While dropping this value will eventually shut down the background task, if you need to wait until shutdown is complete, this method provides that.
It is not an error to call this multiple times.
Attempts to use the multiplexer (send, etc) after shutdown will result in an error.
Sourcepub fn ipv4_local_port(&self) -> u16
pub fn ipv4_local_port(&self) -> u16
Returns the local port used by the IPv4 listen socket.
See Self::ipv6_local_port
for the IPv6 equivalent, and Self::platform_echo_id
for use as an echo id.
Sourcepub fn ipv6_local_port(&self) -> u16
pub fn ipv6_local_port(&self) -> u16
Returns the local port used by the IPv6 listen socket.
See Self::ipv4_local_port
for the IPv4 equivalent, and Self::platform_echo_id
for use as an echo id.
Sourcepub fn platform_echo_id(&self, ip_version: IpVersion) -> Option<EchoId>
pub fn platform_echo_id(&self, ip_version: IpVersion) -> Option<EchoId>
Returns the local port used by the IPv4 or IPv6 listen socket (per ip_version
) as an
EchoId
, if it required to be used as the id
in ICMP Echo Request messages by the local
platform – that is, when platform::icmp_send_overwrite_echo_id_with_local_port
returns true.
This is just a possibly more convenient way to turn Self::ipv4_local_port
or
Self::ipv6_local_port
into an EchoId
.
§Examples
Get the IPv4 local port as an EchoId, if required by the platform, otherwise use a random one.
use async_icmp::{message::echo::EchoId, ping::PingMultiplexer, platform, IpVersion};
fn get_ipv4_echo_id(multiplexer: &PingMultiplexer) -> EchoId {
multiplexer.platform_echo_id(IpVersion::V4).unwrap_or_else(rand::random)
}
Trait Implementations§
Source§impl Clone for PingMultiplexer
impl Clone for PingMultiplexer
Source§fn clone(&self) -> PingMultiplexer
fn clone(&self) -> PingMultiplexer
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read more