autonatv2_client/
autonatv2_client.rs1use std::{error::Error, net::Ipv4Addr, time::Duration};
2
3use clap::Parser;
4use libp2p::{
5 autonat,
6 futures::StreamExt,
7 identify, identity,
8 multiaddr::Protocol,
9 noise,
10 swarm::{dial_opts::DialOpts, NetworkBehaviour, SwarmEvent},
11 tcp, yamux, Multiaddr, SwarmBuilder,
12};
13use rand::rngs::OsRng;
14use tracing_subscriber::EnvFilter;
15
16#[derive(Debug, Parser)]
17#[command(name = "libp2p autonatv2 client")]
18struct Opt {
19 #[arg(short = 'p', long, default_value_t = 0)]
21 listen_port: u16,
22
23 #[arg(short = 'a', long)]
25 server_address: Multiaddr,
26
27 #[arg(short = 't', long, default_value = "2")]
29 probe_interval: u64,
30}
31
32#[tokio::main]
33async fn main() -> Result<(), Box<dyn Error>> {
34 let _ = tracing_subscriber::fmt()
35 .with_env_filter(EnvFilter::from_default_env())
36 .try_init();
37
38 let opt = Opt::parse();
39
40 let mut swarm = SwarmBuilder::with_new_identity()
41 .with_tokio()
42 .with_tcp(
43 tcp::Config::default(),
44 noise::Config::new,
45 yamux::Config::default,
46 )?
47 .with_quic()
48 .with_dns()?
49 .with_behaviour(|key| Behaviour::new(key.public(), opt.probe_interval))?
50 .with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(10)))
51 .build();
52
53 swarm.listen_on(
54 Multiaddr::empty()
55 .with(Protocol::Ip4(Ipv4Addr::UNSPECIFIED))
56 .with(Protocol::Tcp(opt.listen_port)),
57 )?;
58
59 swarm.dial(
60 DialOpts::unknown_peer_id()
61 .address(opt.server_address)
62 .build(),
63 )?;
64
65 loop {
66 match swarm.select_next_some().await {
67 SwarmEvent::NewListenAddr { address, .. } => {
68 println!("Listening on {address:?}");
69 }
70 SwarmEvent::Behaviour(BehaviourEvent::Autonat(autonat::v2::client::Event {
71 server,
72 tested_addr,
73 bytes_sent,
74 result: Ok(()),
75 })) => {
76 println!("Tested {tested_addr} with {server}. Sent {bytes_sent} bytes for verification. Everything Ok and verified.");
77 }
78 SwarmEvent::Behaviour(BehaviourEvent::Autonat(autonat::v2::client::Event {
79 server,
80 tested_addr,
81 bytes_sent,
82 result: Err(e),
83 })) => {
84 println!("Tested {tested_addr} with {server}. Sent {bytes_sent} bytes for verification. Failed with {e:?}.");
85 }
86 SwarmEvent::ExternalAddrConfirmed { address } => {
87 println!("External address confirmed: {address}");
88 }
89 _ => {}
90 }
91 }
92}
93
94#[derive(NetworkBehaviour)]
95pub struct Behaviour {
96 autonat: autonat::v2::client::Behaviour,
97 identify: identify::Behaviour,
98}
99
100impl Behaviour {
101 pub fn new(key: identity::PublicKey, probe_interval: u64) -> Self {
102 Self {
103 autonat: autonat::v2::client::Behaviour::new(
104 OsRng,
105 autonat::v2::client::Config::default()
106 .with_probe_interval(Duration::from_secs(probe_interval)),
107 ),
108 identify: identify::Behaviour::new(identify::Config::new("/ipfs/0.1.0".into(), key)),
109 }
110 }
111}