Skip to content

Commit

Permalink
fix(manager): use default nat detection server list if none is provided
Browse files Browse the repository at this point in the history
  • Loading branch information
RolandSherwin authored and b-zee committed Jul 1, 2024
1 parent bf6695a commit c813442
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 45 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions node-launchpad/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ libc = "0.2.148"
log = "0.4.20"
pretty_assertions = "1.4.0"
prometheus-parse = "0.2.5"
rand = "0.8.5"
ratatui = { version = "0.26.0", features = ["serde", "macros", "unstable-widget-ref"] }
reqwest = { version = "0.12.2", default-features = false, features = [
"rustls-tls-manual-roots",
Expand All @@ -51,7 +50,7 @@ serde = { version = "1.0.188", features = ["derive"] }
serde_json = "1.0.107"
signal-hook = "0.3.17"
sn-node-manager = { version = "0.9.7", path = "../sn_node_manager" }
sn_peers_acquisition = { version = "0.3.5", path = "../sn_peers_acquisition", features = ["network-contacts"]}
sn_peers_acquisition = { version = "0.3.5", path = "../sn_peers_acquisition" }
sn-releases = "~0.2.6"
sn_service_management = { version = "0.3.7", path = "../sn_service_management" }
strip-ansi-escapes = "0.2.0"
Expand Down
13 changes: 2 additions & 11 deletions node-launchpad/src/components/home.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ use crate::{
},
};
use color_eyre::eyre::{OptionExt, Result};
use rand::seq::SliceRandom;
use ratatui::{prelude::*, widgets::*};
use sn_node_manager::{config::get_node_registry_path, VerbosityLevel};
use sn_peers_acquisition::{get_bootstrap_peers_from_url, PeersArgs};
use sn_peers_acquisition::PeersArgs;
use sn_service_management::{
control::ServiceController, NodeRegistry, NodeServiceData, ServiceStatus,
};
Expand All @@ -34,8 +33,6 @@ use tokio::sync::mpsc::UnboundedSender;

const NODE_START_INTERVAL: usize = 10;
const NODE_STAT_UPDATE_INTERVAL: Duration = Duration::from_secs(5);
const NAT_DETECTION_SERVERS_LIST_URL: &str =
"https://sn-testnet.s3.eu-west-2.amazonaws.com/nat-detection-servers";
/// If nat detection fails for more than 3 times, we don't want to waste time running during every node start.
const MAX_ERRORS_WHILE_RUNNING_NAT_DETECTION: usize = 3;

Expand Down Expand Up @@ -613,14 +610,8 @@ fn stop_nodes(services: Vec<String>, action_sender: UnboundedSender<Action>) {
}

async fn run_nat_detection_process() -> Result<()> {
let servers = get_bootstrap_peers_from_url(NAT_DETECTION_SERVERS_LIST_URL.parse()?).await?;
let servers = servers
.choose_multiple(&mut rand::thread_rng(), 10)
.cloned()
.collect::<Vec<_>>();
info!("Running nat detection with servers: {servers:?}");
sn_node_manager::cmd::nat_detection::run_nat_detection(
servers,
None,
true,
None,
None,
Expand Down
1 change: 1 addition & 0 deletions sn_node_manager/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ indicatif = { version = "0.17.5", features = ["tokio"] }
libp2p = { version = "0.53", features = [] }
libp2p-identity = { version = "0.2.7", features = ["rand"] }
prost = { version = "0.9" }
rand = "0.8.5"
semver = "1.0.20"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
Expand Down
7 changes: 4 additions & 3 deletions sn_node_manager/src/bin/cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -673,13 +673,14 @@ pub enum NatDetectionSubCmd {
/// Useful for running NAT detection using a custom built binary.
#[clap(long)]
path: Option<PathBuf>,
/// Provide NAT servers in the form of a multiaddr or an address/port pair.
/// Provide NAT servers in the form of a multiaddr or an address/port pair. If no servers are provided,
/// the default servers will be used.
///
/// We attempt to establish connections to these servers to determine our own NAT status.
///
/// The argument can be used multiple times.
#[clap(long, required = true, value_delimiter = ',')]
servers: Vec<Multiaddr>,
#[clap(long, value_delimiter = ',')]
servers: Option<Vec<Multiaddr>>,
/// Provide a NAT detection binary using a URL.
///
/// The binary must be inside a zip or gzipped tar archive.
Expand Down
18 changes: 17 additions & 1 deletion sn_node_manager/src/cmd/nat_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ use crate::{
};
use color_eyre::eyre::{bail, OptionExt, Result};
use libp2p::Multiaddr;
use rand::seq::SliceRandom;
use sn_peers_acquisition::get_peers_from_url;
use sn_releases::{ReleaseType, SafeReleaseRepoActions};
use sn_service_management::{NatDetectionStatus, NodeRegistry};
use std::{
Expand All @@ -19,14 +21,28 @@ use std::{
process::{Command, Stdio},
};

const NAT_DETECTION_SERVERS_LIST_URL: &str =
"https://sn-testnet.s3.eu-west-2.amazonaws.com/nat-detection-servers";

pub async fn run_nat_detection(
servers: Vec<Multiaddr>,
servers: Option<Vec<Multiaddr>>,
force_run: bool,
path: Option<PathBuf>,
url: Option<String>,
version: Option<String>,
verbosity: VerbosityLevel,
) -> Result<()> {
let servers = match servers {
Some(servers) => servers,
None => {
let servers = get_peers_from_url(NAT_DETECTION_SERVERS_LIST_URL.parse()?).await?;

servers
.choose_multiple(&mut rand::thread_rng(), 10)
.cloned()
.collect::<Vec<_>>()
}
};
info!("Running nat detection with servers: {servers:?}");
let mut node_registry = NodeRegistry::load(&get_node_registry_path()?)?;

Expand Down
10 changes: 5 additions & 5 deletions sn_peers_acquisition/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,20 @@ version = "0.3.5"

[features]
local-discovery = []
network-contacts = ["reqwest", "tokio", "url"]
network-contacts = ["sn_networking"]
websockets = []

[dependencies]
clap = { version = "4.2.1", features = ["derive", "env"] }
lazy_static = "~1.4.0"
libp2p = { version="0.53", features = [] }
rand = "0.8.5"
reqwest = { version="0.12.2", default-features=false, features = ["rustls-tls"], optional = true }
sn_networking = { path = "../sn_networking", version = "0.16.6" }
reqwest = { version="0.12.2", default-features=false, features = ["rustls-tls"] }
sn_networking = { path = "../sn_networking", version = "0.16.6", optional = true}
thiserror = "1.0.23"
tokio = { version = "1.32.0", optional = true, default-features = false}
tokio = { version = "1.32.0", default-features = false}
tracing = { version = "~0.1.26" }
url = { version = "2.4.0", optional = true }
url = { version = "2.4.0" }

[lints]
workspace = true
4 changes: 1 addition & 3 deletions sn_peers_acquisition/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@ pub enum Error {
#[error("Could not parse the supplied multiaddr or socket address")]
InvalidPeerAddr,
#[error("Could not obtain network contacts from {0} after {1} retries")]
NetworkContactsUnretrievable(String, usize),
FailedToObtainPeersFromUrl(String, usize),
#[error("No valid multaddr was present in the contacts file at {0}")]
NoMultiAddrObtainedFromNetworkContacts(String),
#[error("Could not obtain peers through any available options")]
PeersNotObtained,
#[cfg(feature = "network-contacts")]
#[error(transparent)]
ReqwestError(#[from] reqwest::Error),
#[cfg(feature = "network-contacts")]
#[error(transparent)]
UrlParseError(#[from] url::ParseError),
}
35 changes: 16 additions & 19 deletions sn_peers_acquisition/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use rand::{seq::SliceRandom, thread_rng};
#[cfg(feature = "network-contacts")]
use sn_networking::version::get_network_version;
use tracing::*;
#[cfg(feature = "network-contacts")]
use url::Url;

#[cfg(feature = "network-contacts")]
Expand All @@ -30,9 +29,8 @@ lazy_static! {
};
}

#[cfg(feature = "network-contacts")]
// The maximum number of retries to be performed while trying to fetch the network contacts file.
const MAX_NETWORK_CONTACTS_GET_RETRIES: usize = 3;
// The maximum number of retries to be performed while trying to get peers from a URL.
const MAX_RETRIES_ON_GET_PEERS_FROM_URL: usize = 3;

/// The name of the environment variable that can be used to pass peers to the node.
pub const SAFE_PEERS_ENV: &str = "SAFE_PEERS";
Expand Down Expand Up @@ -154,7 +152,7 @@ impl PeersArgs {

info!("Trying to fetch the bootstrap peers from {url}");

get_bootstrap_peers_from_url(url).await
get_peers_from_url(url).await
}
}

Expand Down Expand Up @@ -188,11 +186,8 @@ pub fn parse_peer_addr(addr: &str) -> Result<Multiaddr> {
Err(Error::InvalidPeerAddr)
}

#[cfg(feature = "network-contacts")]
/// Get bootstrap peers from the Network contacts file stored in the given URL.
///
/// If URL is not provided, the addresses are fetched from the default NETWORK_CONTACTS_URL
pub async fn get_bootstrap_peers_from_url(url: Url) -> Result<Vec<Multiaddr>> {
/// Get and parse a list of peers from a URL. The URL should contain one multiaddr per line.
pub async fn get_peers_from_url(url: Url) -> Result<Vec<Multiaddr>> {
let mut retries = 0;

loop {
Expand All @@ -203,7 +198,7 @@ pub async fn get_bootstrap_peers_from_url(url: Url) -> Result<Vec<Multiaddr>> {
let mut multi_addresses = Vec::new();
if response.status().is_success() {
let text = response.text().await?;
trace!("Got bootstrap peers from {url}: {text}");
trace!("Got peers from url: {url}: {text}");
// example of contacts file exists in resources/network-contacts-examples
for addr in text.split('\n') {
// ignore empty/last lines
Expand All @@ -215,7 +210,7 @@ pub async fn get_bootstrap_peers_from_url(url: Url) -> Result<Vec<Multiaddr>> {
multi_addresses.push(parse_peer_addr(addr)?);
}
if !multi_addresses.is_empty() {
trace!("Successfully got bootstrap peers from URL {multi_addresses:?}");
trace!("Successfully got peers from URL {multi_addresses:?}");
return Ok(multi_addresses);
} else {
return Err(Error::NoMultiAddrObtainedFromNetworkContacts(
Expand All @@ -224,25 +219,27 @@ pub async fn get_bootstrap_peers_from_url(url: Url) -> Result<Vec<Multiaddr>> {
}
} else {
retries += 1;
if retries >= MAX_NETWORK_CONTACTS_GET_RETRIES {
return Err(Error::NetworkContactsUnretrievable(
if retries >= MAX_RETRIES_ON_GET_PEERS_FROM_URL {
return Err(Error::FailedToObtainPeersFromUrl(
url.to_string(),
MAX_NETWORK_CONTACTS_GET_RETRIES,
MAX_RETRIES_ON_GET_PEERS_FROM_URL,
));
}
}
}
Err(_) => {
retries += 1;
if retries >= MAX_NETWORK_CONTACTS_GET_RETRIES {
return Err(Error::NetworkContactsUnretrievable(
if retries >= MAX_RETRIES_ON_GET_PEERS_FROM_URL {
return Err(Error::FailedToObtainPeersFromUrl(
url.to_string(),
MAX_NETWORK_CONTACTS_GET_RETRIES,
MAX_RETRIES_ON_GET_PEERS_FROM_URL,
));
}
}
}
trace!("Failed to get bootstrap peers from URL, retrying {retries}/{MAX_NETWORK_CONTACTS_GET_RETRIES}");
trace!(
"Failed to get peers from URL, retrying {retries}/{MAX_RETRIES_ON_GET_PEERS_FROM_URL}"
);
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
}
}

0 comments on commit c813442

Please sign in to comment.