Struct PingMultiplexer

Source
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

Source

pub fn new( icmpv4_config: SocketConfig<Icmpv4>, icmpv6_config: SocketConfig<Icmpv6>, ) -> Result<Self>

Create a new multiplexer with the provided socket configs.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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

Source§

fn clone(&self) -> PingMultiplexer

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for PingMultiplexer

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V