libp2p_server/
behaviour.rs

1use std::{str::FromStr, time::Duration};
2
3use libp2p::{
4    autonat, identify, identity, kad, ping, relay,
5    swarm::{behaviour::toggle::Toggle, NetworkBehaviour, StreamProtocol},
6    Multiaddr, PeerId,
7};
8
9const BOOTNODES: [&str; 4] = [
10    "QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
11    "QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa",
12    "QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb",
13    "QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt",
14];
15
16const IPFS_PROTO_NAME: StreamProtocol = StreamProtocol::new("/ipfs/kad/1.0.0");
17
18#[derive(NetworkBehaviour)]
19pub(crate) struct Behaviour {
20    relay: relay::Behaviour,
21    ping: ping::Behaviour,
22    identify: identify::Behaviour,
23    pub(crate) kademlia: Toggle<kad::Behaviour<kad::store::MemoryStore>>,
24    autonat: Toggle<autonat::Behaviour>,
25}
26
27impl Behaviour {
28    pub(crate) fn new(
29        pub_key: identity::PublicKey,
30        enable_kademlia: bool,
31        enable_autonat: bool,
32    ) -> Self {
33        let kademlia = if enable_kademlia {
34            let mut kademlia_config = kad::Config::new(IPFS_PROTO_NAME);
35            // Instantly remove records and provider records.
36            //
37            // TODO: Replace hack with option to disable both.
38            kademlia_config.set_record_ttl(Some(Duration::from_secs(0)));
39            kademlia_config.set_provider_record_ttl(Some(Duration::from_secs(0)));
40            let mut kademlia = kad::Behaviour::with_config(
41                pub_key.to_peer_id(),
42                kad::store::MemoryStore::new(pub_key.to_peer_id()),
43                kademlia_config,
44            );
45            let bootaddr = Multiaddr::from_str("/dnsaddr/bootstrap.libp2p.io").unwrap();
46            for peer in &BOOTNODES {
47                kademlia.add_address(&PeerId::from_str(peer).unwrap(), bootaddr.clone());
48            }
49            kademlia.bootstrap().unwrap();
50            Some(kademlia)
51        } else {
52            None
53        }
54        .into();
55
56        let autonat = if enable_autonat {
57            Some(autonat::Behaviour::new(
58                PeerId::from(pub_key.clone()),
59                Default::default(),
60            ))
61        } else {
62            None
63        }
64        .into();
65
66        Self {
67            relay: relay::Behaviour::new(PeerId::from(pub_key.clone()), Default::default()),
68            ping: ping::Behaviour::new(ping::Config::new()),
69            identify: identify::Behaviour::new(
70                identify::Config::new("ipfs/0.1.0".to_string(), pub_key).with_agent_version(
71                    format!("rust-libp2p-server/{}", env!("CARGO_PKG_VERSION")),
72                ),
73            ),
74            kademlia,
75            autonat,
76        }
77    }
78}