Bläddra i källkod

net: DEP-0007: rename allowed_transports and mixed_transports, retrieve outbound_connect_timeout, channel_handshake_timeout, channel_heartbeat_interval from network profiles

oars 1 år sedan
förälder
incheckning
ee33b9de3b

+ 8 - 12
src/net/connector.rs

@@ -63,21 +63,15 @@ impl Connector {
         }
 
         let settings = self.settings.read().await;
-        let transports = settings.allowed_transports.clone();
-        let mixed_transports = settings.mixed_transports.clone();
         let datastore = settings.p2p_datastore.clone();
-        let outbound_connect_timeout = settings.outbound_connect_timeout;
         let i2p_socks5_proxy = settings.i2p_socks5_proxy.clone();
-        let tor_socks5_proxy = settings.tor_socks5_proxy.clone();
-        let nym_socks5_proxy = settings.nym_socks5_proxy.clone();
-        drop(settings);
 
         let (endpoint, mixed_transport) = if let Some(mixed_host) = HostContainer::mix_host(
-            url.clone(),
-            &transports,
-            &mixed_transports,
-            tor_socks5_proxy,
-            nym_socks5_proxy,
+            url,
+            &settings.active_profiles,
+            &settings.mixed_profiles,
+            &settings.tor_socks5_proxy,
+            &settings.nym_socks5_proxy,
         )
         .first()
         {
@@ -86,11 +80,13 @@ impl Connector {
             (url.clone(), false)
         };
 
+        let outbound_connect_timeout = settings.outbound_connect_timeout(endpoint.scheme());
+        drop(settings);
+
         let dialer = match Dialer::new(endpoint.clone(), datastore, Some(i2p_socks5_proxy)).await {
             Ok(dialer) => dialer,
             Err(err) => return Err(Error::ConnectFailed(format!("[{endpoint}]: {err}"))),
         };
-
         let timeout = Duration::from_secs(outbound_connect_timeout);
 
         let stop_fut = async {

+ 21 - 21
src/net/hosts.rs

@@ -806,11 +806,11 @@ impl HostContainer {
     /// to connect to tcp+tls:// or socks5:// to connect to tor://.
     /// However, **do not** mix tor:// and tcp+tls://, nor tor+tls:// and tcp://.
     pub(in crate::net) fn mix_host(
-        addr: Url,
+        addr: &Url,
         transports: &[String],
         mixed_transports: &[String],
-        tor_socks5_proxy: Option<Url>,
-        nym_socks5_proxy: Option<Url>,
+        tor_socks5_proxy: &Option<Url>,
+        nym_socks5_proxy: &Option<Url>,
     ) -> Vec<Url> {
         let mut hosts = vec![];
 
@@ -821,9 +821,9 @@ impl HostContainer {
         macro_rules! mix_transport {
             ($a:expr, $b:expr) => {
                 if transports.contains(&$a.to_string()) && addr.scheme() == $b {
-                    let mut addr = addr.clone();
-                    addr.set_scheme($a).unwrap();
-                    hosts.push(addr.clone());
+                    let mut url = addr.clone();
+                    url.set_scheme($a).unwrap();
+                    hosts.push(url);
                 }
             };
         }
@@ -1383,7 +1383,7 @@ impl Hosts {
             // or if this peer is IPV6 and we do not support IPV6.
             // We will personally ignore this peer but still send it to others in
             // Protocol Addr to ensure all transports get propagated.
-            if !settings.allowed_transports.contains(&addr_.scheme().to_string()) ||
+            if !settings.active_profiles.contains(&addr_.scheme().to_string()) ||
                 (!self.ipv6_available.load(Ordering::SeqCst) && self.is_ipv6(addr_))
             {
                 self.container.store_or_update(HostColor::Dark, addr_.clone(), *last_seen);
@@ -1394,8 +1394,8 @@ impl Hosts {
                 let day = 86400;
                 self.container.refresh(HostColor::Dark, day);
 
-                // If the scheme is not found in mixed_transports we can not connect to this host
-                if !settings.mixed_transports.contains(&addr_.scheme().to_string()) {
+                // If the scheme is not found in mixed_profiles we can not connect to this host
+                if !settings.mixed_profiles.contains(&addr_.scheme().to_string()) {
                     continue;
                 }
             }
@@ -1923,11 +1923,11 @@ mod tests {
     #[test]
     fn test_transport_tor_mixed_with_tcp() {
         let mixed_hosts = HostContainer::mix_host(
-            Url::parse("tcp://dark.fi:28880").unwrap(),
+            &Url::parse("tcp://dark.fi:28880").unwrap(),
             &["tor+tls".to_string(), "tcp".to_string(), "tor".to_string()],
             &["tcp".to_string()],
-            Url::parse("socks5://127.0.0.1:9050").ok(),
-            None,
+            &Url::parse("socks5://127.0.0.1:9050").ok(),
+            &None,
         );
 
         assert_eq!(mixed_hosts.len(), 1);
@@ -1943,11 +1943,11 @@ mod tests {
         let nym_socks5_proxy_url = Url::parse("socks5://127.0.0.1:1080").ok();
 
         let fetched_hosts = HostContainer::mix_host(
-            Url::parse("tcp+tls://dark.fi:28880").unwrap(),
+            &Url::parse("tcp+tls://dark.fi:28880").unwrap(),
             &["socks5".to_string(), "socks5+tls".to_string()],
             &["tcp+tls".to_string()],
-            tor_socks5_proxy_url.clone(),
-            nym_socks5_proxy_url.clone(),
+            &tor_socks5_proxy_url,
+            &nym_socks5_proxy_url,
         );
 
         assert_eq!(fetched_hosts.len(), 2);
@@ -1979,11 +1979,11 @@ mod tests {
         let nym_socks5_proxy_url = Url::parse("socks5://127.0.0.1:1080").ok();
 
         let fetched_hosts = HostContainer::mix_host(
-            Url::parse(&format!("tor://{addr}")).unwrap(),
+            &Url::parse(&format!("tor://{addr}")).unwrap(),
             &["socks5".to_string(), "socks5+tls".to_string(), "tor".to_string()],
             &["tor".to_string()],
-            tor_socks5_proxy_url.clone(),
-            nym_socks5_proxy_url,
+            &tor_socks5_proxy_url,
+            &nym_socks5_proxy_url,
         );
 
         assert_eq!(fetched_hosts.len(), 1);
@@ -1998,7 +1998,7 @@ mod tests {
     #[test]
     fn test_transport_tor_and_socks5_mixed_with_tcp() {
         let fetched_hosts = HostContainer::mix_host(
-            Url::parse("tcp://dark.fi:28880").unwrap(),
+            &Url::parse("tcp://dark.fi:28880").unwrap(),
             &[
                 "tor".to_string(),
                 "tor+tls".to_string(),
@@ -2006,8 +2006,8 @@ mod tests {
                 "socks5+tls".to_string(),
             ],
             &["tcp".to_string()],
-            Url::parse("socks5://127.0.0.1:9050").ok(),
-            None,
+            &Url::parse("socks5://127.0.0.1:9050").ok(),
+            &None,
         );
 
         assert_eq!(fetched_hosts.len(), 2);

+ 2 - 2
src/net/protocol/protocol_address.rs

@@ -279,8 +279,8 @@ impl ProtocolBase for ProtocolAddress {
 
         let settings = self.settings.read().await;
         let outbound_connections = settings.outbound_connections;
+        let active_profiles = settings.active_profiles.clone();
         let getaddrs_max = settings.getaddrs_max;
-        let allowed_transports = settings.allowed_transports.clone();
         drop(settings);
 
         self.jobsman.clone().start(ex.clone());
@@ -295,7 +295,7 @@ impl ProtocolBase for ProtocolAddress {
         // We ask for a maximum of u8::MAX addresses from a single node
         let get_addrs = GetAddrsMessage {
             max: getaddrs_max.unwrap_or(outbound_connections.min(u32::MAX as usize) as u32),
-            transports: allowed_transports,
+            transports: active_profiles,
         };
         self.channel.send(&get_addrs).await?;
 

+ 4 - 2
src/net/protocol/protocol_ping.rs

@@ -85,8 +85,10 @@ impl ProtocolPing {
 
         loop {
             let settings = self.settings.read().await;
-            let outbound_connect_timeout = settings.outbound_connect_timeout;
-            let channel_heartbeat_interval = settings.channel_heartbeat_interval;
+            let outbound_connect_timeout =
+                settings.outbound_connect_timeout(self.channel.address().scheme());
+            let channel_heartbeat_interval =
+                settings.channel_heartbeat_interval(self.channel.address().scheme());
             drop(settings);
 
             // Create a random nonce.

+ 2 - 2
src/net/protocol/protocol_seed.rs

@@ -111,14 +111,14 @@ impl ProtocolBase for ProtocolSeed {
         let settings = self.settings.read().await;
         let outbound_connections = settings.outbound_connections;
         let getaddrs_max = settings.getaddrs_max;
-        let allowed_transports = settings.allowed_transports.clone();
+        let active_profiles = settings.active_profiles.clone();
         drop(settings);
 
         // Send get address message
         // We ask for a maximum of u8::MAX addresses from a single node
         let get_addr = GetAddrsMessage {
             max: getaddrs_max.unwrap_or(outbound_connections.min(u32::MAX as usize) as u32),
-            transports: allowed_transports,
+            transports: active_profiles,
         };
         self.channel.send(&get_addr).await?;
 

+ 5 - 3
src/net/protocol/protocol_version.rs

@@ -69,8 +69,10 @@ impl ProtocolVersion {
     /// version ack.
     pub async fn run(self: Arc<Self>, executor: Arc<Executor<'_>>) -> Result<()> {
         debug!(target: "net::protocol_version::run()", "START => address={}", self.channel.display_address());
-        let timeout =
-            Timer::after(Duration::from_secs(self.settings.read().await.channel_handshake_timeout));
+        let channel_handshake_timeout =
+            self.settings.read().await.channel_handshake_timeout(self.channel.address().scheme());
+
+        let timeout = Timer::after(Duration::from_secs(channel_handshake_timeout));
         let version = self.clone().exchange_versions(executor);
 
         pin_mut!(timeout);
@@ -188,7 +190,7 @@ impl ProtocolVersion {
         // MAJOR and MINOR should be the same, as well as the app identifier
         if app_version.major != verack_msg.app_version.major ||
             app_version.minor != verack_msg.app_version.minor ||
-             app_name != verack_msg.app_name
+            app_name != verack_msg.app_name
         {
             error!(
                 target: "net::protocol_version::send_version()",

+ 13 - 10
src/net/session/direct_session.rs

@@ -227,8 +227,13 @@ impl DirectSession {
                             break
                         }
                         Err(_) => {
-                            let settings = self_.p2p().settings().read_arc().await;
-                            sleep(settings.outbound_connect_timeout).await;
+                            let outbound_connect_timeout = self_
+                                .p2p()
+                                .settings()
+                                .read_arc()
+                                .await
+                                .outbound_connect_timeout(addr.scheme());
+                            sleep(outbound_connect_timeout).await;
                         }
                     }
                 }
@@ -263,7 +268,7 @@ impl DirectSession {
 
         let settings = self.p2p().settings().read_arc().await;
         let seeds = settings.seeds.clone();
-        let allowed_transports = settings.allowed_transports.clone();
+        let active_profiles = settings.active_profiles.clone();
         drop(settings);
 
         // Do not establish a connection to a host that is also configured as a seed.
@@ -290,7 +295,7 @@ impl DirectSession {
         }
 
         // Abort if we do not support this transport.
-        if !allowed_transports.contains(&addr.scheme().to_string()) {
+        if !active_profiles.contains(&addr.scheme().to_string()) {
             return Err(Error::UnsupportedTransport(addr.scheme().to_string()))
         }
 
@@ -524,7 +529,7 @@ impl PeerDiscovery {
             let outbound_peer_discovery_attempt_time =
                 settings.outbound_peer_discovery_attempt_time;
             let getaddrs_max = settings.getaddrs_max;
-            let allowed_transports = settings.allowed_transports.clone();
+            let active_profiles = settings.active_profiles.clone();
             let seeds = settings.seeds.clone();
             drop(settings);
 
@@ -560,7 +565,7 @@ impl PeerDiscovery {
                         .p2p()
                         .hosts()
                         .container
-                        .fetch_random_with_schemes(color.clone(), &allowed_transports)
+                        .fetch_random_with_schemes(color.clone(), &active_profiles)
                     {
                         channel = self.p2p().session_direct().get_channel(&entry.0).await.ok();
                         break;
@@ -582,10 +587,8 @@ impl PeerDiscovery {
                     state: "getaddr",
                 });
 
-                let get_addrs = GetAddrsMessage {
-                    max: getaddrs_max.unwrap_or(1),
-                    transports: allowed_transports,
-                };
+                let get_addrs =
+                    GetAddrsMessage { max: getaddrs_max.unwrap_or(1), transports: active_profiles };
 
                 self.p2p().broadcast(&get_addrs).await;
 

+ 1 - 1
src/net/session/manual_session.rs

@@ -163,7 +163,7 @@ impl Slot {
 
             let settings = self.p2p().settings().read_arc().await;
             let seeds = settings.seeds.clone();
-            let outbound_connect_timeout = settings.outbound_connect_timeout;
+            let outbound_connect_timeout = settings.outbound_connect_timeout(self.addr.scheme());
             drop(settings);
 
             // Do not establish a connection to a host that is also configured as a seed.

+ 3 - 3
src/net/session/outbound_session.rs

@@ -216,7 +216,7 @@ impl Slot {
         let white_count = (settings.white_connect_percent * settings.outbound_connections) / 100;
         let gold_count = settings.gold_connect_count;
 
-        let transports = settings.allowed_transports.clone();
+        let transports = settings.active_profiles.clone();
         let preference_strict = settings.slot_preference_strict;
 
         // Drop Settings read lock
@@ -537,7 +537,7 @@ impl PeerDiscoveryBase for PeerDiscovery {
                 settings.outbound_peer_discovery_attempt_time;
             let outbound_connections = settings.outbound_connections;
             let getaddrs_max = settings.getaddrs_max;
-            let allowed_transports = settings.allowed_transports.clone();
+            let active_profiles = settings.active_profiles.clone();
             let seeds = settings.seeds.clone();
             drop(settings);
 
@@ -581,7 +581,7 @@ impl PeerDiscoveryBase for PeerDiscovery {
 
                 let get_addrs = GetAddrsMessage {
                     max: getaddrs_max.unwrap_or(outbound_connections.min(u32::MAX as usize) as u32),
-                    transports: allowed_transports,
+                    transports: active_profiles,
                 };
 
                 self.p2p().broadcast(&get_addrs).await;

+ 2 - 2
src/net/session/refine_session.rs

@@ -229,7 +229,7 @@ impl GreylistRefinery {
             let settings = self.p2p().settings().read_arc().await;
             let greylist_refinery_interval = settings.greylist_refinery_interval;
             let time_with_no_connections = settings.time_with_no_connections;
-            let allowed_transports = settings.allowed_transports.clone();
+            let active_profiles = settings.active_profiles.clone();
             drop(settings);
 
             sleep(greylist_refinery_interval).await;
@@ -267,7 +267,7 @@ impl GreylistRefinery {
             }
 
             // Only attempt to refine peers that match our transports.
-            match hosts.container.fetch_random_with_schemes(HostColor::Grey, &allowed_transports) {
+            match hosts.container.fetch_random_with_schemes(HostColor::Grey, &active_profiles) {
                 Some((entry, _)) => {
                     let url = &entry.0;
 

+ 28 - 2
src/net/settings.rs

@@ -16,6 +16,7 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 use std::collections::HashMap;
+
 use structopt::StructOpt;
 use url::Url;
 
@@ -171,8 +172,30 @@ impl Default for Settings {
     }
 }
 
-// The following is used so we can have P2P settings configurable
-// from TOML files.
+impl Settings {
+    /// Returns `outbound_connect_timeout` for a specific profile.
+    pub fn outbound_connect_timeout(&self, profile: &str) -> u64 {
+        self.profiles.get(profile).unwrap_or(&NetworkProfile::default()).outbound_connect_timeout
+    }
+
+    /// Returns the maximum `outbound_connect_timeout` across all profiles,
+    /// selecting a conservative value suitable for the slowest network profile.
+    pub fn outbound_connect_timeout_max(&self) -> u64 {
+        self.profiles
+            .values()
+            .map(|p| p.outbound_connect_timeout)
+            .max()
+            .unwrap_or(NetworkProfile::default().outbound_connect_timeout)
+    }
+
+    pub fn channel_heartbeat_interval(&self, profile: &str) -> u64 {
+        self.profiles.get(profile).unwrap_or(&NetworkProfile::default()).channel_heartbeat_interval
+    }
+
+    pub fn channel_handshake_timeout(&self, profile: &str) -> u64 {
+        self.profiles.get(profile).unwrap_or(&NetworkProfile::default()).channel_handshake_timeout
+    }
+}
 
 /// Distinguishes distinct P2P networks
 #[derive(serde::Deserialize, Debug, Clone)]
@@ -184,6 +207,9 @@ impl Default for MagicBytes {
     }
 }
 
+// The following is used so we can have P2P settings configurable
+// from TOML files.
+
 /// Defines the network settings.
 #[derive(Clone, Debug, serde::Deserialize, structopt::StructOpt, structopt_toml::StructOptToml)]
 #[structopt()]

+ 24 - 6
src/net/tests.rs

@@ -18,7 +18,12 @@
 
 // cargo test --release --features=net --lib p2p -- --include-ignored
 
-use std::{collections::HashSet, net::TcpListener, panic, sync::Arc};
+use std::{
+    collections::{HashMap, HashSet},
+    net::TcpListener,
+    panic,
+    sync::Arc,
+};
 
 use darkfi_serial::{async_trait, SerialDecodable, SerialEncodable};
 use rand::{prelude::SliceRandom, rngs::ThreadRng, Rng};
@@ -31,6 +36,7 @@ use crate::{
         hosts::HostColor,
         message::{GetAddrsMessage, Message},
         metering::{MeteringConfiguration, DEFAULT_METERING_CONFIGURATION},
+        settings::NetworkProfile,
         P2p, Settings,
     },
     system::sleep,
@@ -103,6 +109,12 @@ async fn spawn_seed_session(
     let mut outbound_instances = vec![];
     let ports = get_unique_ports(n_nodes);
 
+    let mut profiles = HashMap::new();
+    profiles.insert(
+        "tcp".to_string(),
+        NetworkProfile { outbound_connect_timeout: 2, ..Default::default() },
+    );
+
     for port in ports {
         let settings = Settings {
             localnet: true,
@@ -110,13 +122,13 @@ async fn spawn_seed_session(
             external_addrs: vec![Url::parse(&format!("tcp://127.0.0.1:{port}")).unwrap()],
             outbound_connections: 2,
             outbound_peer_discovery_cooloff_time: 2,
-            outbound_connect_timeout: 2,
             inbound_connections: usize::MAX,
             greylist_refinery_interval: 15,
             peers: vec![],
             seeds: vec![seed_addr.clone()],
             node_id: (port).to_string(),
-            allowed_transports: vec!["tcp".to_string()],
+            active_profiles: vec!["tcp".to_string()],
+            profiles: profiles.clone(),
             ..Default::default()
         };
 
@@ -139,6 +151,12 @@ async fn spawn_manual_session(
     let mut rng = rand::thread_rng();
     let ports = get_unique_ports(n_nodes);
 
+    let mut profiles = HashMap::new();
+    profiles.insert(
+        "tcp".to_string(),
+        NetworkProfile { outbound_connect_timeout: 2, ..Default::default() },
+    );
+
     for i in 0..n_nodes {
         let mut peer_indexes_copy: Vec<usize> = (0..n_nodes).collect();
         peer_indexes_copy.remove(i);
@@ -158,13 +176,13 @@ async fn spawn_manual_session(
             external_addrs: vec![Url::parse(&format!("tcp://127.0.0.1:{inbound_port}")).unwrap()],
             outbound_connections: 2,
             outbound_peer_discovery_cooloff_time: 2,
-            outbound_connect_timeout: 2,
             inbound_connections: usize::MAX,
             greylist_refinery_interval: 15,
             peers,
             seeds: vec![],
             node_id: inbound_port.to_string(),
-            allowed_transports: vec!["tcp".to_string()],
+            active_profiles: vec!["tcp".to_string()],
+            profiles: profiles.clone(),
             ..Default::default()
         };
 
@@ -307,7 +325,7 @@ async fn p2p_test_real(ex: Arc<Executor<'static>>) {
         inbound_connections: usize::MAX,
         seeds: vec![],
         peers: vec![],
-        allowed_transports: vec!["tcp".to_string()],
+        active_profiles: vec!["tcp".to_string()],
         greylist_refinery_interval: 12,
         node_id: "seed".to_string(),
         ..Default::default()