autonat_server/
autonat_server.rs

1// Copyright 2021 Protocol Labs.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the "Software"),
5// to deal in the Software without restriction, including without limitation
6// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7// and/or sell copies of the Software, and to permit persons to whom the
8// Software is furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19// DEALINGS IN THE SOFTWARE.
20
21#![doc = include_str!("../../README.md")]
22
23use std::{error::Error, net::Ipv4Addr};
24
25use clap::Parser;
26use futures::StreamExt;
27use libp2p::{
28    autonat,
29    core::{multiaddr::Protocol, Multiaddr},
30    identify, identity, noise,
31    swarm::{NetworkBehaviour, SwarmEvent},
32    tcp, yamux,
33};
34use tracing_subscriber::EnvFilter;
35
36#[derive(Debug, Parser)]
37#[command(name = "libp2p autonat")]
38struct Opt {
39    #[arg(long)]
40    listen_port: Option<u16>,
41}
42
43#[tokio::main]
44async fn main() -> Result<(), Box<dyn Error>> {
45    let _ = tracing_subscriber::fmt()
46        .with_env_filter(EnvFilter::from_default_env())
47        .try_init();
48
49    let opt = Opt::parse();
50
51    let mut swarm = libp2p::SwarmBuilder::with_new_identity()
52        .with_tokio()
53        .with_tcp(
54            tcp::Config::default(),
55            noise::Config::new,
56            yamux::Config::default,
57        )?
58        .with_behaviour(|key| Behaviour::new(key.public()))?
59        .build();
60
61    swarm.listen_on(
62        Multiaddr::empty()
63            .with(Protocol::Ip4(Ipv4Addr::UNSPECIFIED))
64            .with(Protocol::Tcp(opt.listen_port.unwrap_or(0))),
65    )?;
66
67    loop {
68        match swarm.select_next_some().await {
69            SwarmEvent::NewListenAddr { address, .. } => println!("Listening on {address:?}"),
70            SwarmEvent::Behaviour(event) => println!("{event:?}"),
71            e => println!("{e:?}"),
72        }
73    }
74}
75
76#[derive(NetworkBehaviour)]
77struct Behaviour {
78    identify: identify::Behaviour,
79    auto_nat: autonat::Behaviour,
80}
81
82impl Behaviour {
83    fn new(local_public_key: identity::PublicKey) -> Self {
84        Self {
85            identify: identify::Behaviour::new(identify::Config::new(
86                "/ipfs/0.1.0".into(),
87                local_public_key.clone(),
88            )),
89            auto_nat: autonat::Behaviour::new(
90                local_public_key.to_peer_id(),
91                autonat::Config {
92                    only_global_ips: false,
93                    ..Default::default()
94                },
95            ),
96        }
97    }
98}