use std::str::FromStr;
use xcli::*;
use libp2prs_core::{Multiaddr, PeerId};
use libp2prs_runtime::task;
use crate::Control;
const SWRM: &str = "swarm";
pub fn swarm_cli_commands<'a>() -> Command<'a> {
Command::new_with_alias(SWRM, "s")
.about("Swarm")
.usage("swarm")
.subcommand(Command::new("close").about("close swarm").usage("close").action(cli_close_swarm))
.subcommand(Command::new("id").about("show id information").usage("id").action(cli_show_id))
.subcommand(
Command::new_with_alias("stats", "st")
.about("dump statistics")
.usage("stats")
.action(cli_dump_statistics),
)
.subcommand(
Command::new_with_alias("connection", "lc")
.about("display connection information")
.usage("connection [PeerId]")
.action(cli_show_connections),
)
.subcommand(
Command::new_with_alias("peer", "pr")
.about("display peer information")
.usage("peer [PeerId]")
.action(cli_show_peers),
)
.subcommand(
Command::new_with_alias("connect", "con")
.about("connect to a peer")
.usage("connect <PeerId> [Multiaddr]")
.action(cli_connect),
)
.subcommand(
Command::new_with_alias("disconnect", "disc")
.about("disconnect a peer")
.usage("disconnect <PeerId>")
.action(cli_disconnect),
)
}
fn handler(app: &App) -> Control {
let value_any = app.get_handler(SWRM).expect(SWRM);
let swarm = value_any.downcast_ref::<Control>().expect("control").clone();
swarm
}
fn cli_show_id(app: &App, _args: &[&str]) -> XcliResult {
let mut swarm = handler(app);
task::block_on(async {
if let Ok(id) = swarm.retrieve_networkinfo().await {
println!("Id : {}", id.id);
println!("Total Peers : {:?}", id.num_peers);
println!("Total Connections : {:?}", id.num_connections);
println!("Total Substreams : {:?}", id.num_active_streams);
}
if let Ok(identify) = swarm.retrieve_identify_info().await {
println!("PublicKey : {:?}", identify.public_key);
println!("Protocol Version : {:?}", identify.protocol_version);
println!("Agent Version : {:?}", identify.agent_version);
println!("Support Protocols : {:?}", identify.protocols);
println!("Listening address : {:?}", identify.listen_addrs);
}
println!(
"Metric: {:?} {:?}",
swarm.get_recv_count_and_size(),
swarm.get_sent_count_and_size()
);
});
Ok(CmdExeCode::Ok)
}
fn cli_close_swarm(app: &App, _args: &[&str]) -> XcliResult {
let mut swarm = handler(app);
swarm.close();
Ok(CmdExeCode::Ok)
}
fn cli_dump_statistics(app: &App, _args: &[&str]) -> XcliResult {
let mut swarm = handler(app);
task::block_on(async {
let stats = swarm.dump_statistics().await.unwrap();
println!("{:?}", stats.base);
println!("{:?}", stats.dialer);
println!("{:?}", stats.listener);
});
Ok(CmdExeCode::Ok)
}
fn cli_show_connections(app: &App, args: &[&str]) -> XcliResult {
let mut swarm = handler(app);
let peer = match args.len() {
0 => None,
1 => Some(PeerId::from_str(args[0]).map_err(|e| XcliError::BadArgument(e.to_string()))?),
_ => return Err(XcliError::MismatchArgument(1, args.len())),
};
task::block_on(async {
let connections = swarm.dump_connections(peer).await.unwrap();
println!("CID DIR Remote-Peer-Id I/O Local-Multiaddr Remote-Multiaddr");
connections.iter().for_each(|v| {
println!(
"{} {} {:52} {}/{} {} {}",
v.id, v.dir, v.info.remote_peer_id, v.info.num_inbound_streams, v.info.num_outbound_streams, v.info.la, v.info.ra
);
if true {
v.substreams.iter().for_each(|s| {
println!(" ({})", s);
});
}
});
});
Ok(CmdExeCode::Ok)
}
fn cli_show_peers(app: &App, args: &[&str]) -> XcliResult {
let swarm = handler(app);
let pid = match args.len() {
0 => None,
1 => Some(PeerId::from_str(args[0]).map_err(|e| XcliError::BadArgument(e.to_string()))?),
_ => return Err(XcliError::MismatchArgument(1, args.len())),
};
if let Some(peer) = pid {
let addrs = swarm.get_addrs(&peer);
let protos = swarm.get_protocols(&peer);
println!("Addrs: {:?}\nProtocols: {:?}", addrs, protos);
} else {
let peers = swarm.get_peers();
println!("Remote-Peer-Id Pin Multiaddrs");
peers.iter().for_each(|v| {
println!("{:52} {:5} {:?}", v, swarm.pinned(v), swarm.get_addrs(v));
});
}
Ok(CmdExeCode::Ok)
}
fn cli_connect(app: &App, args: &[&str]) -> XcliResult {
let mut swarm = handler(app);
let (peer_id, opt_addr) = match args.len() {
0 => return Err(XcliError::MissingArgument),
1 => (PeerId::from_str(args[0]).map_err(|e| XcliError::BadArgument(e.to_string()))?, None),
2 => (
PeerId::from_str(args[0]).map_err(|e| XcliError::BadArgument(e.to_string()))?,
Some(Multiaddr::from_str(args[1]).map_err(|e| XcliError::BadArgument(e.to_string()))?),
),
_ => return Err(XcliError::MismatchArgument(1, args.len())),
};
task::block_on(async {
let r = if let Some(addr) = opt_addr {
swarm.connect_with_addrs(peer_id, vec![addr]).await
} else {
swarm.new_connection(peer_id).await
};
println!("Connecting to {}: {:?}", peer_id, r);
});
Ok(CmdExeCode::Ok)
}
fn cli_disconnect(app: &App, args: &[&str]) -> XcliResult {
let mut swarm = handler(app);
let peer_id = if args.len() == 1 {
PeerId::from_str(args[0]).map_err(|e| XcliError::BadArgument(e.to_string()))?
} else {
return Err(XcliError::MismatchArgument(1, args.len()));
};
task::block_on(async {
let r = swarm.disconnect(peer_id).await;
println!("Disconnecting {}: {:?}", peer_id, r);
});
Ok(CmdExeCode::Ok)
}