use std::{error::Error, time::Duration}; use cll2v0::messages::{MyRequest, MyResponse}; use futures::prelude::*; use libp2p::{ mdns, noise, request_response::{self, ProtocolSupport}, swarm::{NetworkBehaviour, SwarmEvent}, tcp, yamux, StreamProtocol, Swarm, }; use libp2p_identity::ed25519::Keypair; use tracing_subscriber::EnvFilter; // We create a custom network behaviour #[derive(NetworkBehaviour)] struct MyBehaviour { mdns: mdns::tokio::Behaviour, req_res: request_response::cbor::Behaviour, } fn sign(kp: &Keypair, msg: &Vec) -> String { hex::encode(kp.sign(msg)) } fn mk_swarm( kp: &Keypair, protocol_support: ProtocolSupport, ) -> Result, Box> { let swarm = libp2p::SwarmBuilder::with_existing_identity(kp.clone().into()) .with_tokio() .with_tcp( tcp::Config::default(), noise::Config::new, yamux::Config::default, )? .with_behaviour(|key| { let mdns = mdns::tokio::Behaviour::new(mdns::Config::default(), key.public().to_peer_id())?; let protocol = [(StreamProtocol::new("/sign-me/1"), protocol_support)]; let config = request_response::Config::default(); let req_res = request_response::cbor::Behaviour::::new(protocol, config); Ok(MyBehaviour { req_res, mdns }) })? .with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::from_secs(u64::MAX))) .build(); Ok(swarm) } #[tokio::main] pub async fn main() -> Result<(), Box> { let body: Vec = vec![0, 0, 0, 0, 0, 0, 0, 0]; let _ = tracing_subscriber::fmt() .with_env_filter(EnvFilter::from_default_env()) .try_init(); let keypair = libp2p_identity::ed25519::Keypair::generate(); let key = keypair.public().to_bytes(); let is_client = match std::env::args().nth(1) { Some(arg) => { println!("Arg {}", arg); true } _ => false, }; let protocol_support = if is_client { ProtocolSupport::Outbound } else { ProtocolSupport::Inbound }; let mut swarm = mk_swarm(&keypair, protocol_support)?; // Tell the swarm to listen on all interfaces and a random, OS-assigned // port. swarm.listen_on("/ip4/192.168.1.51/tcp/0".parse()?)?; println!("ORISIG : {}", sign(&keypair, &body)); loop { match swarm.select_next_some().await { SwarmEvent::Behaviour(MyBehaviourEvent::Mdns(mdns::Event::Discovered(list))) => { for (peer_id, multiaddr) in list { println!("add peer {:?}, {:?}", peer_id, multiaddr.clone()); if is_client { let _ = swarm.dial(multiaddr); } } } SwarmEvent::Behaviour(MyBehaviourEvent::Mdns(mdns::Event::Expired(list))) => { for (peer_id, _multiaddr) in list { println!("mDNS discover peer has expired: {peer_id}"); // swarm.behaviour_mut().gossipsub.remove_explicit_peer(&peer_id); } } SwarmEvent::Behaviour(MyBehaviourEvent::ReqRes(request_response::Event::Message { peer: _peer, message: libp2p::request_response::Message::Request { request, channel, .. }, })) => { // println!("Req : {:?} {:?} {:?}", peer, channel, hex::encode(request.body.clone()), ); println!("REQSIG : {}", hex::encode(request.sig.clone()),); let _ = swarm.behaviour_mut().req_res.send_response( channel, MyResponse { sig: keypair.sign(&request.body), }, ); } SwarmEvent::Behaviour(MyBehaviourEvent::ReqRes(request_response::Event::Message { peer: _peer, message: libp2p::request_response::Message::Response { response, .. }, })) => { // println!("response : {:?} {:?} {:?}", peer, request_id, "" ); println!("RESSIG : {}", hex::encode(response.sig.clone()),); } SwarmEvent::ConnectionEstablished { peer_id, .. } => { //connection_id, endpoint, num_established, concurrent_dial_errors, established_in } => { println!("ConnectionEstablisted {}", peer_id); if is_client { swarm.behaviour_mut().req_res.send_request( &peer_id, MyRequest { key: key.clone(), body: body.clone(), sig: keypair.sign(&body), }, ); } } e => { println!("OTHER {:?}", e) } } } }