Ping: Four necessary traits

  • Identity: PeerId and corresponding Keypair
  • Transport: send and receive bytes on the network.
  • NetworkBehaviour: decode or encode the bytes from the Transport.
  • Swarm: drives both a Transport and a NetworkBehaviour forward.
use futures::StreamExt;
use libp2p::ping::{Ping, PingConfig};
use libp2p::{identity, Multiaddr, PeerId, Swarm};
use std::error::Error;

#[async_std::main]
async fn main() -> Result<(), Box<dyn Error>> {
		// First we need to create a network identity.
		let local_key = identity::Keypair::generate_ed25519();
		let local_peer_id = PeerId::from(local_key.public());
		println!("Local peer id: {:?}", local_peer_id);

		// Then construct a transport: defines how to send bytes on the network.
		let transport = libp2p::development_transport(local_key).await?;

		// NetworkBehaviour defines what bytes to send on the network.
		let behaviour = Ping::new(PingConfig::new().with_keep_alive(true));

		// Swarm connects transport and behaviour together:
		//
		// 1. Passing commands from NetworkBehaviour to the Transport.
		// 2. As well ass events from the Transport to the NetworkBehaviour.
		let mut swarm = Swarm::new(transport, behaviour, local_peer_id);
		swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;
		if let Some(addr) = std::env::args().nth(1) {
				let remote: Multiaddr = addr.parse()?;
				swarm.dial(remote)?;
				println!("Dialed {}", addr);
		}

		loop {
				match swarm.select_next_some().await {
						libp2p::swarm::SwarmEvent::NewListenAddr {
								listener_id: _,
								address,
						} => println!("Listening on {:?}", address),
						libp2p::swarm::SwarmEvent::Behaviour(event) => println!("{:?}", event),
						_ => {}
				}
		}

		Ok(())
}