diff --git a/iroh-p2p/src/behaviour.rs b/iroh-p2p/src/behaviour.rs index a7485d4d805..7f89c55cd26 100644 --- a/iroh-p2p/src/behaviour.rs +++ b/iroh-p2p/src/behaviour.rs @@ -7,6 +7,7 @@ use anyhow::Result; use bytes::Bytes; use cid::Cid; use iroh_bitswap::{Bitswap, BitswapConfig, BitswapEvent, Priority, QueryId}; +use libp2p::autonat; use libp2p::core::identity::Keypair; use libp2p::core::PeerId; use libp2p::identify::{Identify, IdentifyConfig, IdentifyEvent}; @@ -34,6 +35,7 @@ pub(crate) struct NodeBehaviour { bitswap: Bitswap, pub(crate) kad: Toggle>, mdns: Toggle, + pub(crate) autonat: Toggle, } /// Event type which is emitted from the [NodeBehaviour] into the libp2p service. @@ -44,6 +46,7 @@ pub(crate) enum Event { Kademlia(KademliaEvent), Mdns(MdnsEvent), Bitswap(BitswapEvent), + Autonat(autonat::Event), } impl From for Event { @@ -76,6 +79,12 @@ impl From for Event { } } +impl From for Event { + fn from(event: autonat::Event) -> Self { + Event::Autonat(event) + } +} + impl NodeBehaviour { pub async fn new( local_key: &Keypair, @@ -127,6 +136,19 @@ impl NodeBehaviour { } .into(); + let autonat = if config.autonat { + let pub_key = local_key.public(); + let config = autonat::Config { + use_connected: true, + ..Default::default() + }; // TODO: configurable + let autonat = autonat::Behaviour::new(pub_key.to_peer_id(), config); + Some(autonat) + } else { + None + } + .into(); + let mut req_res_config = RequestResponseConfig::default(); req_res_config.set_request_timeout(Duration::from_secs(20)); req_res_config.set_connection_keep_alive(Duration::from_secs(20)); @@ -137,6 +159,7 @@ impl NodeBehaviour { bitswap, mdns, kad, + autonat, }) } diff --git a/iroh-p2p/src/config.rs b/iroh-p2p/src/config.rs index 0aed7ba52ee..e5f79c099a0 100644 --- a/iroh-p2p/src/config.rs +++ b/iroh-p2p/src/config.rs @@ -25,6 +25,8 @@ pub struct Libp2pConfig { pub mdns: bool, /// Kademlia discovery enabled. pub kademlia: bool, + /// Autonat holepunching enabled. + pub autonat: bool, /// Target peer count. pub target_peer_count: u32, /// Rpc listening addr @@ -46,6 +48,7 @@ impl Source for Libp2pConfig { // config::Config and the p2p::Config, we need to cast it as a signed int insert_into_config_map(&mut map, "target_peer_count", self.target_peer_count as i64); insert_into_config_map(&mut map, "kademlia", self.kademlia); + insert_into_config_map(&mut map, "autonat", self.autonat); insert_into_config_map(&mut map, "mdns", self.mdns); let peers: Vec = self.bootstrap_peers.iter().map(|b| b.to_string()).collect(); insert_into_config_map(&mut map, "bootstrap_peers", peers); @@ -83,6 +86,7 @@ impl Default for Libp2pConfig { bootstrap_peers, mdns: false, kademlia: true, + autonat: true, target_peer_count: 256, rpc_addr: "0.0.0.0:4401".parse().unwrap(), rpc_client: RpcClientConfig::default(), @@ -120,6 +124,7 @@ mod tests { Value::new(None, default.target_peer_count as i64), ); expect.insert("kademlia".to_string(), Value::new(None, default.kademlia)); + expect.insert("autonat".to_string(), Value::new(None, default.autonat)); expect.insert("mdns".to_string(), Value::new(None, default.mdns)); expect.insert( "bootstrap_peers".to_string(), diff --git a/iroh-p2p/src/service.rs b/iroh-p2p/src/service.rs index 2c75b1c33ad..b732fd5f544 100644 --- a/iroh-p2p/src/service.rs +++ b/iroh-p2p/src/service.rs @@ -293,13 +293,25 @@ impl Libp2pService { if protocols .iter() .any(|p| p.as_bytes() == kad::protocol::DEFAULT_PROTO_NAME) + { + for addr in &listen_addrs { + if let Some(kad) = self.swarm.behaviour_mut().kad.as_mut() { + kad.add_address(&peer_id, addr.clone()); + } + } + } + + // Inform autonat about identified peers + // TODO: expose protocol name on `libp2p::autonat`. + // TODO: should we remove them at some point? + if protocols + .iter() + .any(|p| p.as_bytes() == b"/libp2p/autonat/1.0.0") { for addr in listen_addrs { - self.swarm - .behaviour_mut() - .kad - .as_mut() - .map(|k| k.add_address(&peer_id, addr)); + if let Some(autonat) = self.swarm.behaviour_mut().autonat.as_mut() { + autonat.add_server(peer_id, Some(addr)); + } } } }