diff --git a/one/src/lib.rs b/one/src/lib.rs index c788cd238..c01dc479f 100644 --- a/one/src/lib.rs +++ b/one/src/lib.rs @@ -78,7 +78,7 @@ struct DaemonOpts { #[arg( short, long, - default_value = "127.0.0.1:9090", + default_value = "127.0.0.1:9464", env = "CERAMIC_ONE_METRICS_BIND_ADDRESS" )] metrics_bind_address: String, @@ -99,14 +99,19 @@ struct DaemonOpts { #[arg(long, env = "CERAMIC_ONE_LOCAL_NETWORK_ID")] local_network_id: Option, - /// When true mdns will be used to discover peers. + /// When set mdns will be used to discover peers. #[arg(long, default_value_t = false, env = "CERAMIC_ONE_MDNS")] mdns: bool, - /// When true Recon will be used to synchronized events with peers. + /// When set Recon will be used to synchronized events with peers. #[arg(long, default_value_t = false, env = "CERAMIC_ONE_RECON")] recon: bool, + /// When set autonat will not be used to discover external address or allow other peers + /// to directly dial the local peer. + #[arg(long, default_value_t = false, env = "CERAMIC_ONE_DISABLE_AUTONAT")] + disable_autonat: bool, + /// Specify the format of log events. #[arg(long, default_value = "multi-line", env = "CERAMIC_ONE_LOG_FORMAT")] log_format: LogFormat, @@ -348,7 +353,7 @@ impl Daemon { bitswap_server: true, bitswap_client: true, kademlia: true, - autonat: true, + autonat: !opts.disable_autonat, relay_server: true, relay_client: true, gossipsub: true, diff --git a/p2p/src/node.rs b/p2p/src/node.rs index a2d697228..822a23f5d 100644 --- a/p2p/src/node.rs +++ b/p2p/src/node.rs @@ -84,6 +84,8 @@ where listen_addrs: Vec, trust_observed_addrs: bool, + failed_external_addresses: HashSet, + active_address_probe: Option, } impl fmt::Debug for Node @@ -194,6 +196,8 @@ where providers: Providers::new(4), listen_addrs, trust_observed_addrs: libp2p_config.trust_observed_addrs, + failed_external_addresses: Default::default(), + active_address_probe: Default::default(), }) } @@ -629,6 +633,7 @@ where .swarm .external_addresses() .any(|addr| addr == &info.observed_addr) + && !self.failed_external_addresses.contains(&info.observed_addr) { if self.trust_observed_addrs { debug!( @@ -640,14 +645,26 @@ where self.swarm.add_external_address(info.observed_addr.clone()); } else if let Some(autonat) = self.swarm.behaviour_mut().autonat.as_mut() { // Probe the observed addr for external connectivity. - // See OutboundProbeEvent case for - - debug!( - address=%info.observed_addr, - %peer_id, - "probing observed address from peer for external connectivity", - ); - autonat.probe_address(info.observed_addr.clone()); + // Only probe one address at a time. + // + // This logic is run very frequently because any new peer connection + // for a new observed address triggers this path. Its typical to have + // only a few external addresses, in which cases its likely that the + // in-progress address probe is one that will succeed. + // + // In cases where there are lots of different observed addresses its + // likely that NAT hasn't been setup and so the peer doesn't have an + // external address. Therefore we do not want to waste resources on + // probing many different addresses that are likely to fail. + if self.active_address_probe.is_none() { + self.active_address_probe = Some(info.observed_addr.clone()); + debug!( + address=%info.observed_addr, + %peer_id, + "probing observed address from peer for external connectivity", + ); + autonat.probe_address(info.observed_addr.clone()); + } }; }; @@ -765,6 +782,11 @@ where self.swarm.add_external_address(address); } } + Event::Autonat(autonat::Event::OutboundProbe(OutboundProbeEvent::Error { .. })) => { + if let Some(addr) = self.active_address_probe.take() { + self.failed_external_addresses.insert(addr); + } + } _ => { // TODO: check all important events are handled }