use anyhow::Error;
use async_trait::async_trait;
use clap::Parser;
use minotari_app_utilities::utilities::UniNodeId;
use tari_comms::peer_manager::NodeId;
use tari_p2p::services::liveness::LivenessEvent;
use tokio::{sync::broadcast::error::RecvError, task};
use super::{CommandContext, HandleCommand};
#[derive(Debug, Parser)]
pub struct Args {
node_id: UniNodeId,
}
#[async_trait]
impl HandleCommand<Args> for CommandContext {
async fn handle_command(&mut self, args: Args) -> Result<(), Error> {
self.ping_peer(args.node_id.into()).await
}
}
impl CommandContext {
pub async fn ping_peer(&mut self, dest_node_id: NodeId) -> Result<(), Error> {
let mut liveness_events = self.liveness.get_event_stream();
let mut liveness = self.liveness.clone();
task::spawn(async move {
match liveness.send_ping(dest_node_id.clone()).await {
Ok(nonce) => {
println!("🏓 Pinging peer {dest_node_id} with nonce {nonce} ...");
loop {
match liveness_events.recv().await {
Ok(event) => {
if let LivenessEvent::ReceivedPong(pong) = &*event &&
pong.node_id == dest_node_id &&
pong.nonce == nonce
{
println!(
"🏓️ Pong: peer {} responded with nonce {}, round-trip-time is {:.2?}!",
pong.node_id,
pong.nonce,
pong.latency.unwrap_or_default()
);
break;
}
},
Err(RecvError::Closed) => {
break;
},
Err(RecvError::Lagged(_)) => {},
}
}
},
Err(e) => {
println!("🏓 Ping failed to send to {dest_node_id}: {e}");
},
}
});
Ok(())
}
}