cll2v0/app/server.rs

140 lines
5.0 KiB
Rust

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<MyRequest, MyResponse>,
}
fn sign(kp: &Keypair, msg: &Vec<u8>) -> String {
hex::encode(kp.sign(msg))
}
fn mk_swarm(
kp: &Keypair,
protocol_support: ProtocolSupport,
) -> Result<Swarm<MyBehaviour>, Box<dyn Error>> {
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::<MyRequest, MyResponse>::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<dyn Error>> {
let body: Vec<u8> = 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)
}
}
}
}