Prechádzať zdrojové kódy

net/hosts: move transport mixing logic to one place in HostContainer::mix_host function and perform transport mixing in Connector only

oars 1 rok pred
rodič
commit
ce95d31c4d
3 zmenil súbory, kde vykonal 101 pridanie a 206 odobranie
  1. 14 43
      src/net/connector.rs
  2. 83 132
      src/net/hosts.rs
  3. 4 31
      src/net/session/outbound_session.rs

+ 14 - 43
src/net/connector.rs

@@ -36,7 +36,7 @@ use super::{
     settings::Settings,
     settings::Settings,
     transport::Dialer,
     transport::Dialer,
 };
 };
-use crate::{system::CondVar, Error, Result};
+use crate::{net::hosts::HostContainer, system::CondVar, Error, Result};
 
 
 /// Create outbound socket connections
 /// Create outbound socket connections
 pub struct Connector {
 pub struct Connector {
@@ -72,48 +72,19 @@ impl Connector {
         let nym_socks5_proxy = settings.nym_socks5_proxy.clone();
         let nym_socks5_proxy = settings.nym_socks5_proxy.clone();
         drop(settings);
         drop(settings);
 
 
-        let mut endpoint = url.clone();
-        let scheme = endpoint.scheme();
-
-        if mixed_transports.contains(&scheme.to_string()) {
-            if transports.contains(&"socks5".to_string()) && (scheme == "tcp" || scheme == "tor") {
-                // Prioritize connection through nym socks5 proxy for tcp endpoint mixing
-                if scheme == "tcp" && nym_socks5_proxy.is_some() {
-                    endpoint = nym_socks5_proxy.unwrap();
-                } else if tor_socks5_proxy.is_some() {
-                    endpoint = tor_socks5_proxy.unwrap();
-                } else {
-                    warn!(target: "net::connector::connect", "Transport mixing is enabled but socks5 proxy is not set");
-                    return Err(Error::ConnectFailed)
-                }
-
-                endpoint.set_path(&format!("{}:{}", url.host().unwrap(), url.port().unwrap()));
-                endpoint.set_scheme("socks5")?;
-            } else if transports.contains(&"socks5+tls".to_string()) &&
-                (scheme == "tcp+tls" || scheme == "tor+tls")
-            {
-                // Prioritize connection through nym socks5 proxy for tcp+tls endpoint mixing
-                if scheme == "tcp+tls" && nym_socks5_proxy.is_some() {
-                    endpoint = nym_socks5_proxy.unwrap();
-                } else if tor_socks5_proxy.is_some() {
-                    endpoint = tor_socks5_proxy.unwrap();
-                } else {
-                    warn!(target: "net::connector::connect", "Transport mixing is enabled but socks5 proxy is not set");
-                    return Err(Error::ConnectFailed)
-                }
-
-                endpoint.set_path(&format!("{}:{}", url.host().unwrap(), url.port().unwrap()));
-                endpoint.set_scheme("socks5+tls")?;
-            } else if transports.contains(&"tor".to_string()) && scheme == "tcp" {
-                endpoint.set_scheme("tor")?;
-            } else if transports.contains(&"tor+tls".to_string()) && scheme == "tcp+tls" {
-                endpoint.set_scheme("tor+tls")?;
-            } else if transports.contains(&"nym".to_string()) && scheme == "tcp" {
-                endpoint.set_scheme("nym")?;
-            } else if transports.contains(&"nym+tls".to_string()) && scheme == "tcp+tls" {
-                endpoint.set_scheme("nym+tls")?;
-            }
-        }
+        let endpoint = if let Some(mixed_host) = HostContainer::mix_host(
+            url.clone(),
+            &transports,
+            &mixed_transports,
+            tor_socks5_proxy,
+            nym_socks5_proxy,
+        )
+        .first()
+        {
+            mixed_host.clone()
+        } else {
+            url.clone()
+        };
 
 
         let dialer = Dialer::new(endpoint.clone(), datastore, Some(i2p_socks5_proxy)).await?;
         let dialer = Dialer::new(endpoint.clone(), datastore, Some(i2p_socks5_proxy)).await?;
         let timeout = Duration::from_secs(outbound_connect_timeout);
         let timeout = Duration::from_secs(outbound_connect_timeout);

+ 83 - 132
src/net/hosts.rs

@@ -412,96 +412,9 @@ impl HostContainer {
         list.last().cloned()
         list.last().cloned()
     }
     }
 
 
-    /// Fetch addresses that match the provided transports or acceptable
-    /// mixed transports.  Will return an empty Vector if no such addresses
-    /// were found.
-    pub(in crate::net) fn fetch(
-        &self,
-        color: HostColor,
-        transports: &[String],
-        mixed_transports: &[String],
-        tor_socks5_proxy: Option<Url>,
-        nym_socks5_proxy: Option<Url>,
-    ) -> Vec<(Url, u64)> {
-        trace!(target: "net::hosts::fetch_addrs()", "[START] {color:?}");
-        let mut hosts = vec![];
-        let index = color as usize;
-
-        // If transport mixing is enabled, then for example we're allowed to
-        // use tor:// to connect to tcp:// and tor+tls:// to connect to tcp+tls://.
-        // However, **do not** mix tor:// and tcp+tls://, nor tor+tls:// and tcp://.
-        macro_rules! mix_transport {
-            ($a:expr, $b:expr) => {
-                if transports.contains(&$a.to_string()) &&
-                    mixed_transports.contains(&$b.to_string())
-                {
-                    let mut a_to_b = self.fetch_with_schemes(index, &[$b.to_string()], None);
-                    for (addr, last_seen) in a_to_b.iter_mut() {
-                        addr.set_scheme($a).unwrap();
-                        hosts.push((addr.clone(), last_seen.clone()));
-                    }
-                }
-            };
-        }
-
-        macro_rules! mix_socks5_transport {
-            ($a:expr, $b:expr, $proxies:expr) => {
-                if transports.contains(&$a.to_string()) &&
-                    mixed_transports.contains(&$b.to_string())
-                {
-                    let mut a_to_b = self.fetch_with_schemes(index, &[$b.to_string()], None);
-                    for (addr, last_seen) in a_to_b.iter_mut() {
-                        for proxy in $proxies {
-                            if let Some(mut endpoint) = proxy {
-                                endpoint.set_path(&format!(
-                                    "{}:{}",
-                                    addr.host().unwrap(),
-                                    addr.port().unwrap()
-                                ));
-                                endpoint.set_scheme($a).unwrap();
-                                hosts.push((endpoint, last_seen.clone()));
-                            }
-                        }
-                    }
-                }
-            };
-        }
-
-        mix_transport!("tor", "tcp");
-        mix_transport!("tor+tls", "tcp+tls");
-        mix_transport!("nym", "tcp");
-        mix_transport!("nym+tls", "tcp+tls");
-        mix_socks5_transport!(
-            "socks5",
-            "tcp",
-            [tor_socks5_proxy.clone(), nym_socks5_proxy.clone()]
-        );
-        mix_socks5_transport!(
-            "socks5+tls",
-            "tcp+tls",
-            [tor_socks5_proxy.clone(), nym_socks5_proxy.clone()]
-        );
-        mix_socks5_transport!("socks5", "tor", [tor_socks5_proxy.clone()]);
-        mix_socks5_transport!("socks5+tls", "tor+tls", [tor_socks5_proxy.clone()]);
-
-        // Filter out a transport from requested transport if we set it to be mixed as
-        // we don't want to connect directly to that host
-        let transports: Vec<String> =
-            transports.iter().filter(|tp| !mixed_transports.contains(tp)).cloned().collect();
-
-        // And now the actual requested transports
-        for (addr, last_seen) in self.fetch_with_schemes(index, &transports, None) {
-            hosts.push((addr, last_seen));
-        }
-
-        trace!(target: "net::hosts::fetch_addrs()", "Grabbed hosts, length: {}", hosts.len());
-
-        hosts
-    }
-
     /// Get up to limit peers that match the given transport schemes from
     /// Get up to limit peers that match the given transport schemes from
     /// a hostlist.  If limit was not provided, return all matching peers.
     /// a hostlist.  If limit was not provided, return all matching peers.
-    fn fetch_with_schemes(
+    pub(in crate::net) fn fetch_with_schemes(
         &self,
         &self,
         color: usize,
         color: usize,
         schemes: &[String],
         schemes: &[String],
@@ -885,6 +798,71 @@ impl HostContainer {
 
 
         Ok(())
         Ok(())
     }
     }
+
+    /// Performs transport mixing for an url returning a list of addresses
+    /// with mixed transports.
+    /// For example we're allowed to use tor:// to connect to tcp:// and tor+tls://
+    /// 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,
+        transports: &[String],
+        mixed_transports: &[String],
+        tor_socks5_proxy: Option<Url>,
+        nym_socks5_proxy: Option<Url>,
+    ) -> Vec<Url> {
+        let mut hosts = vec![];
+
+        if !mixed_transports.contains(&addr.scheme().to_string()) {
+            return hosts;
+        }
+
+        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());
+                }
+            };
+        }
+        macro_rules! mix_socks5_transport {
+            ($a:expr, $b:expr, $proxies:expr) => {
+                if transports.contains(&$a.to_string()) && addr.scheme() == $b {
+                    for proxy in $proxies {
+                        if let Some(mut endpoint) = proxy {
+                            endpoint.set_path(&format!(
+                                "{}:{}",
+                                addr.host().unwrap(),
+                                addr.port().unwrap()
+                            ));
+                            endpoint.set_scheme($a).unwrap();
+                            hosts.push(endpoint);
+                        }
+                    }
+                }
+            };
+        }
+
+        mix_transport!("tor", "tcp");
+        mix_transport!("tor+tls", "tcp+tls");
+        mix_transport!("nym", "tcp");
+        mix_transport!("nym+tls", "tcp+tls");
+        mix_socks5_transport!(
+            "socks5",
+            "tcp",
+            [tor_socks5_proxy.clone(), nym_socks5_proxy.clone()]
+        );
+        mix_socks5_transport!(
+            "socks5+tls",
+            "tcp+tls",
+            [tor_socks5_proxy.clone(), nym_socks5_proxy.clone()]
+        );
+        mix_socks5_transport!("socks5", "tor", [tor_socks5_proxy.clone()]);
+        mix_socks5_transport!("socks5+tls", "tor+tls", [tor_socks5_proxy.clone()]);
+
+        hosts
+    }
 }
 }
 
 
 /// Main parent class for the management and manipulation of
 /// Main parent class for the management and manipulation of
@@ -1930,42 +1908,29 @@ mod tests {
     // Test tcp endpoint is changed to tor and tcp will not be used to
     // Test tcp endpoint is changed to tor and tcp will not be used to
     // connect to any host directly
     // connect to any host directly
     #[test]
     #[test]
-    fn test_transport_tor_mixed_with_tcp_fetch() {
-        let host_container = HostContainer::new();
-        host_container.store_or_update(
-            HostColor::Grey,
+    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(),
-            0,
-        );
-
-        let fetched_hosts = host_container.fetch(
-            HostColor::Grey,
             &["tor+tls".to_string(), "tcp".to_string(), "tor".to_string()],
             &["tor+tls".to_string(), "tcp".to_string(), "tor".to_string()],
             &["tcp".to_string()],
             &["tcp".to_string()],
             Url::parse("socks5://127.0.0.1:9050").ok(),
             Url::parse("socks5://127.0.0.1:9050").ok(),
             None,
             None,
         );
         );
 
 
-        assert_eq!(fetched_hosts.len(), 1);
-        assert_eq!(fetched_hosts[0].0.to_string(), "tor://dark.fi:28880/");
+        assert_eq!(mixed_hosts.len(), 1);
+        assert_eq!(mixed_hosts[0].to_string(), "tor://dark.fi:28880/");
     }
     }
 
 
     // Test when both tor_socks5_proxy and nym_socks5_proxy are passed
     // Test when both tor_socks5_proxy and nym_socks5_proxy are passed
     // tcp+tls endpoint is changed to socks5+tls and the endpoint is changed to two
     // tcp+tls endpoint is changed to socks5+tls and the endpoint is changed to two
     // endpoints where one is routed through tor and another through nym
     // endpoints where one is routed through tor and another through nym
     #[test]
     #[test]
-    fn test_transport_socks5_mixed_with_tcp_through_tor_and_nym_proxy_fetch() {
-        let host_container = HostContainer::new();
-        host_container.store_or_update(
-            HostColor::Grey,
-            Url::parse("tcp+tls://dark.fi:28880").unwrap(),
-            0,
-        );
+    fn test_transport_socks5_mixed_with_tcp_through_tor_and_nym_proxy() {
         let tor_socks5_proxy_url = Url::parse("socks5://127.0.0.1:9050").ok();
         let tor_socks5_proxy_url = Url::parse("socks5://127.0.0.1:9050").ok();
         let nym_socks5_proxy_url = Url::parse("socks5://127.0.0.1:1080").ok();
         let nym_socks5_proxy_url = Url::parse("socks5://127.0.0.1:1080").ok();
 
 
-        let fetched_hosts = host_container.fetch(
-            HostColor::Grey,
+        let fetched_hosts = HostContainer::mix_host(
+            Url::parse("tcp+tls://dark.fi:28880").unwrap(),
             &["socks5".to_string(), "socks5+tls".to_string()],
             &["socks5".to_string(), "socks5+tls".to_string()],
             &["tcp+tls".to_string()],
             &["tcp+tls".to_string()],
             tor_socks5_proxy_url.clone(),
             tor_socks5_proxy_url.clone(),
@@ -1974,20 +1939,19 @@ mod tests {
 
 
         assert_eq!(fetched_hosts.len(), 2);
         assert_eq!(fetched_hosts.len(), 2);
         assert!(
         assert!(
-            fetched_hosts[0].0.scheme() == "socks5+tls" &&
-                fetched_hosts[1].0.scheme() == "socks5+tls"
+            fetched_hosts[0].scheme() == "socks5+tls" && fetched_hosts[1].scheme() == "socks5+tls"
         );
         );
         assert_eq!(
         assert_eq!(
             fetched_hosts
             fetched_hosts
                 .iter()
                 .iter()
-                .filter(|h| h.0.port() == tor_socks5_proxy_url.as_ref().unwrap().port())
+                .filter(|h| h.port() == tor_socks5_proxy_url.as_ref().unwrap().port())
                 .count(),
                 .count(),
             1
             1
         );
         );
         assert_eq!(
         assert_eq!(
             fetched_hosts
             fetched_hosts
                 .iter()
                 .iter()
-                .filter(|h| h.0.port() == nym_socks5_proxy_url.as_ref().unwrap().port())
+                .filter(|h| h.port() == nym_socks5_proxy_url.as_ref().unwrap().port())
                 .count(),
                 .count(),
             1
             1
         );
         );
@@ -1996,19 +1960,13 @@ mod tests {
     // Test tor endpoint is changed to socks5 and tor will not be used to
     // Test tor endpoint is changed to socks5 and tor will not be used to
     // connect to any host directly and tor endpoints are not routed through nym
     // connect to any host directly and tor endpoints are not routed through nym
     #[test]
     #[test]
-    fn test_transport_socks5_mixed_with_tor_fetch() {
-        let host_container = HostContainer::new();
+    fn test_transport_socks5_mixed_with_tor() {
         let addr = "eweiibe6tdjsdprb4px6rqrzzcsi22m4koia44kc5pcjr7nec2rlxyad.onion:23330";
         let addr = "eweiibe6tdjsdprb4px6rqrzzcsi22m4koia44kc5pcjr7nec2rlxyad.onion:23330";
-        host_container.store_or_update(
-            HostColor::Grey,
-            Url::parse(&format!("tor://{addr}")).unwrap(),
-            0,
-        );
         let tor_socks5_proxy_url = Url::parse("socks5://127.0.0.1:9050").ok();
         let tor_socks5_proxy_url = Url::parse("socks5://127.0.0.1:9050").ok();
         let nym_socks5_proxy_url = Url::parse("socks5://127.0.0.1:1080").ok();
         let nym_socks5_proxy_url = Url::parse("socks5://127.0.0.1:1080").ok();
 
 
-        let fetched_hosts = host_container.fetch(
-            HostColor::Grey,
+        let fetched_hosts = HostContainer::mix_host(
+            Url::parse(&format!("tor://{addr}")).unwrap(),
             &["socks5".to_string(), "socks5+tls".to_string(), "tor".to_string()],
             &["socks5".to_string(), "socks5+tls".to_string(), "tor".to_string()],
             &["tor".to_string()],
             &["tor".to_string()],
             tor_socks5_proxy_url.clone(),
             tor_socks5_proxy_url.clone(),
@@ -2016,7 +1974,7 @@ mod tests {
         );
         );
 
 
         assert_eq!(fetched_hosts.len(), 1);
         assert_eq!(fetched_hosts.len(), 1);
-        let mixed_url = fetched_hosts[0].0.clone();
+        let mixed_url = fetched_hosts[0].clone();
         assert_eq!(mixed_url.scheme(), tor_socks5_proxy_url.as_ref().unwrap().scheme());
         assert_eq!(mixed_url.scheme(), tor_socks5_proxy_url.as_ref().unwrap().scheme());
         assert_eq!(mixed_url.host(), tor_socks5_proxy_url.as_ref().unwrap().host());
         assert_eq!(mixed_url.host(), tor_socks5_proxy_url.as_ref().unwrap().host());
         assert_eq!(mixed_url.port(), tor_socks5_proxy_url.as_ref().unwrap().port());
         assert_eq!(mixed_url.port(), tor_socks5_proxy_url.as_ref().unwrap().port());
@@ -2025,16 +1983,9 @@ mod tests {
 
 
     // Test the tcp endpoint is changed to two endpoints socks5 and tor.
     // Test the tcp endpoint is changed to two endpoints socks5 and tor.
     #[test]
     #[test]
-    fn test_transport_tor_and_socks5_mixed_with_tcp_fetch() {
-        let host_container = HostContainer::new();
-        host_container.store_or_update(
-            HostColor::Grey,
+    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(),
-            0,
-        );
-
-        let fetched_hosts = host_container.fetch(
-            HostColor::Grey,
             &[
             &[
                 "tor".to_string(),
                 "tor".to_string(),
                 "tor+tls".to_string(),
                 "tor+tls".to_string(),
@@ -2047,7 +1998,7 @@ mod tests {
         );
         );
 
 
         assert_eq!(fetched_hosts.len(), 2);
         assert_eq!(fetched_hosts.len(), 2);
-        let endpoints: Vec<_> = fetched_hosts.iter().map(|item| item.0.scheme()).collect();
+        let endpoints: Vec<_> = fetched_hosts.iter().map(|item| item.scheme()).collect();
         assert!(endpoints.iter().all(|&scheme| scheme == "tor" || scheme == "socks5"));
         assert!(endpoints.iter().all(|&scheme| scheme == "tor" || scheme == "socks5"));
     }
     }
 }
 }

+ 4 - 31
src/net/session/outbound_session.rs

@@ -216,10 +216,7 @@ impl Slot {
         let gold_count = settings.gold_connect_count;
         let gold_count = settings.gold_connect_count;
 
 
         let transports = settings.allowed_transports.clone();
         let transports = settings.allowed_transports.clone();
-        let mixed_transports = settings.mixed_transports.clone();
         let preference_strict = settings.slot_preference_strict;
         let preference_strict = settings.slot_preference_strict;
-        let tor_socks5_proxy = settings.tor_socks5_proxy.clone();
-        let nym_socks5_proxy = settings.nym_socks5_proxy.clone();
 
 
         // Drop Settings read lock
         // Drop Settings read lock
         drop(settings);
         drop(settings);
@@ -231,37 +228,13 @@ impl Slot {
         // If we only have grey entries, select from the greylist. Otherwise,
         // If we only have grey entries, select from the greylist. Otherwise,
         // use the preference defined in settings.
         // use the preference defined in settings.
         let addrs = if grey_only && !preference_strict {
         let addrs = if grey_only && !preference_strict {
-            container.fetch(
-                HostColor::Grey,
-                &transports,
-                &mixed_transports,
-                tor_socks5_proxy,
-                nym_socks5_proxy,
-            )
+            container.fetch_with_schemes(HostColor::Grey as usize, &transports, None)
         } else if slot < gold_count {
         } else if slot < gold_count {
-            container.fetch(
-                HostColor::Gold,
-                &transports,
-                &mixed_transports,
-                tor_socks5_proxy,
-                nym_socks5_proxy,
-            )
+            container.fetch_with_schemes(HostColor::Gold as usize, &transports, None)
         } else if slot < white_count {
         } else if slot < white_count {
-            container.fetch(
-                HostColor::White,
-                &transports,
-                &mixed_transports,
-                tor_socks5_proxy,
-                nym_socks5_proxy,
-            )
+            container.fetch_with_schemes(HostColor::White as usize, &transports, None)
         } else {
         } else {
-            container.fetch(
-                HostColor::Grey,
-                &transports,
-                &mixed_transports,
-                tor_socks5_proxy,
-                nym_socks5_proxy,
-            )
+            container.fetch_with_schemes(HostColor::Grey as usize, &transports, None)
         };
         };
 
 
         hosts.check_addrs(addrs).await
         hosts.check_addrs(addrs).await