use ed25519_dalek::ed25519::signature::SignerMut; use std::error::Error; use tokio::{io, io::AsyncBufReadExt, select}; use futures::prelude::*; use libp2p::{ mdns, request_response::{self, ProtocolSupport}, swarm::SwarmEvent, Multiaddr, }; use tracing_subscriber::EnvFilter; use cll2v0::{ keys, messages::MyRequest, protocol::{mk_swarm, MyBehaviourEvent}, }; use clap::{Parser, Subcommand}; /// cll2v0 is a playground for rust libraries. /// This is signing service. #[derive(Parser)] #[command(arg_required_else_help(true), version, about)] struct Args { #[command(subcommand)] cmd: Option, } #[derive(Subcommand)] enum Command { /// Start server Start(ClientParams), } #[derive(clap::Args, Debug)] pub struct ClientParams { /// Root of the multiaddr #[arg( long, default_value = "/ip4/0.0.0.0/tcp/52321/p2p/12D3KooWPADMrTD3njNGBwyiqFEaDSarki8bQJdiFtofo8sGXs1o" )] pub server_addr: String, // pub listen_on : String, /// If used in prod, this should be an envvar. #[arg( long, default_value = "0000000000000000000000000000000000000000000000000000000000000000" )] pub skey: String, // FIXME :: rust does not like this option /// If turn trace on // pub trace: bool, } fn main() -> Result<(), Box> { match Args::parse().cmd { Some(Command::Start(sp)) => tokio::runtime::Builder::new_multi_thread() .enable_all() .build() .unwrap() .block_on(start(sp)), _ => { panic!("oops") } } } pub async fn start(params: ClientParams) -> Result<(), Box> { println!("params {:?}", params); let ClientParams { server_addr, skey: skey_hex, } = params; if true { let _ = tracing_subscriber::fmt() .with_env_filter(EnvFilter::from_default_env()) .try_init(); } let key = keys::signing_key_from_hex(&skey_hex)?; println!("VERIFYING : {}", keys::to_hex(&key.verifying_key())); let keypair = keys::libp2p_kp_from_hex(skey_hex)?; let mut swarm = mk_swarm(&keypair.clone().into(), ProtocolSupport::Outbound)?; swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?; // Read full lines from stdin let mut stdin = io::BufReader::new(io::stdin()).lines(); let server_addr: libp2p::Multiaddr = server_addr.parse()?; let server_peer_id = match server_addr.clone().pop() { Some(libp2p::multiaddr::Protocol::P2p(peer_id)) => peer_id, _ => panic!("must end in peer"), }; println!("server addr : {:?}, {:?}", server_addr, server_peer_id); let _res = swarm.dial(server_addr)?; loop { select! { Ok(Some(line)) = stdin.next_line() => { println!("MESSAGE: {}", line); let bytes = line.into_bytes(); let req = MyRequest { key: keypair.clone().public().to_bytes(), body: bytes.clone(), sig: keys::sign(&mut key.clone(), bytes).to_vec(), }; println!("REQ : {:?}", req); swarm.behaviour_mut().req_res.send_request( &server_peer_id, req, ); } event = swarm.select_next_some() => match event { // MDNS BEHAVIOR SwarmEvent::Behaviour(MyBehaviourEvent::Mdns(mdns::Event::Discovered(list))) => { for (peer_id, multiaddr) in list { println!("add peer {:?}, {:?}", peer_id, multiaddr.clone()); // 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()),); } e => { println!("OTHER {:?}", e) } } } } }