Просмотр исходного кода

net: Simplify Hosts to use a single lock

x 6 месяцев назад
Родитель
Сommit
436e5fe13e

+ 1 - 0
Cargo.lock

@@ -1810,6 +1810,7 @@ dependencies = [
  "monero",
  "nu-ansi-term",
  "num-bigint",
+ "parking_lot 0.12.5",
  "pin-project-lite",
  "plotters",
  "prettytable-rs",

+ 1 - 0
Cargo.toml

@@ -48,6 +48,7 @@ members = [
 libc = "0.2.178"
 thiserror = "2.0.17"
 tracing = "0.1.44"
+parking_lot = "0.12.5"
 
 # async-runtime
 async-trait = {version = "0.1.89", optional = true}

+ 1 - 1
bin/lilith/src/main.rs

@@ -199,7 +199,7 @@ impl Lilith {
                     let url = &entry.0;
                     let last_seen = &entry.1;
 
-                    if !hosts.refinable(url.clone()) {
+                    if !hosts.refinable(url) {
                         debug!(target: "net::refinery::whitelist_refinery", "Addr={} not available!",
                        url.clone());
 

+ 1 - 1
src/net/acceptor.rs

@@ -145,7 +145,7 @@ impl Acceptor {
             match listener.next().await {
                 Ok((stream, url)) => {
                     // Check if we reject this peer
-                    if hosts.container.contains(HostColor::Black as usize, &url) ||
+                    if hosts.container.contains(HostColor::Black, &url) ||
                         hosts.block_all_ports(&url)
                     {
                         warn!(target: "net::acceptor::run_accept_loop", "Peer {url} is blacklisted");

+ 1 - 1
src/net/connector.rs

@@ -57,7 +57,7 @@ impl Connector {
     /// Establish an outbound connection
     pub async fn connect(&self, url: &Url) -> Result<(Url, ChannelPtr)> {
         let hosts = self.session.upgrade().unwrap().p2p().hosts();
-        if hosts.container.contains(HostColor::Black as usize, url) || hosts.block_all_ports(url) {
+        if hosts.container.contains(HostColor::Black, url) || hosts.block_all_ports(url) {
             warn!(target: "net::connector::connect", "Peer {url} is blacklisted");
             return Err(Error::ConnectFailed(format!("[{url}]: Peer is blacklisted")));
         }

Разница между файлами не показана из-за своего большого размера
+ 640 - 1187
src/net/hosts.rs


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

@@ -155,7 +155,7 @@ impl ProtocolAddress {
             let mut addrs = self.hosts.container.fetch_n_random_with_schemes(
                 HostColor::Gold,
                 &requested_transports,
-                get_addrs_msg.max,
+                get_addrs_msg.max as usize,
             );
 
             // Then we grab address with the requested transports from the whitelist
@@ -164,7 +164,7 @@ impl ProtocolAddress {
             addrs.append(&mut self.hosts.container.fetch_n_random_with_schemes(
                 HostColor::White,
                 &requested_transports,
-                get_addrs_msg.max,
+                get_addrs_msg.max as usize,
             ));
 
             // Next we grab addresses without the requested transports
@@ -173,7 +173,7 @@ impl ProtocolAddress {
             // Then we grab address without the requested transports from the gold list
             debug!(target: "net::protocol_address::handle_receive_get_addrs",
             "Fetching gold entries without schemes");
-            let remain = 2 * get_addrs_msg.max - addrs.len() as u32;
+            let remain = 2 * get_addrs_msg.max as usize - addrs.len();
             addrs.append(&mut self.hosts.container.fetch_n_random_excluding_schemes(
                 HostColor::Gold,
                 &requested_transports,
@@ -183,7 +183,7 @@ impl ProtocolAddress {
             // Then we grab address without the requested transports from the white list
             debug!(target: "net::protocol_address::handle_receive_get_addrs",
             "Fetching white entries without schemes");
-            let remain = 2 * get_addrs_msg.max - addrs.len() as u32;
+            let remain = 2 * get_addrs_msg.max as usize - addrs.len();
             addrs.append(&mut self.hosts.container.fetch_n_random_excluding_schemes(
                 HostColor::White,
                 &requested_transports,
@@ -199,7 +199,7 @@ impl ProtocolAddress {
 
             debug!(target: "net::protocol_address::handle_receive_get_addrs",
             "Fetching dark entries");
-            let remain = 2 * get_addrs_msg.max - addrs.len() as u32;
+            let remain = 2 * get_addrs_msg.max as usize - addrs.len();
             addrs.append(&mut self.hosts.container.fetch_n_random(HostColor::Dark, remain));
 
             // Filter out transports not meant to be shared like Socks5 and Socks5+tls

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

@@ -561,13 +561,13 @@ impl PeerDiscovery {
                 });
 
                 for color in [HostColor::Gold, HostColor::White, HostColor::Grey].iter() {
-                    if let Some((entry, _)) = self
+                    if let Some((url, _last_seen)) = self
                         .p2p()
                         .hosts()
                         .container
-                        .fetch_random_with_schemes(color.clone(), &active_profiles)
+                        .fetch_random_with_schemes(*color, &active_profiles)
                     {
-                        channel = self.p2p().session_direct().get_channel(&entry.0).await.ok();
+                        channel = self.p2p().session_direct().get_channel(&url).await.ok();
                         break;
                     }
                 }

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

@@ -293,13 +293,13 @@ impl Slot {
         // If we only have grey entries, select from the greylist. Otherwise,
         // use the preference defined in settings.
         let addrs = if grey_only && !preference_strict {
-            container.fetch_with_schemes(HostColor::Grey as usize, &transports, None)
+            container.fetch_with_schemes(HostColor::Grey, &transports, None)
         } else if slot < gold_count {
-            container.fetch_with_schemes(HostColor::Gold as usize, &transports, None)
+            container.fetch_with_schemes(HostColor::Gold, &transports, None)
         } else if slot < white_count {
-            container.fetch_with_schemes(HostColor::White as usize, &transports, None)
+            container.fetch_with_schemes(HostColor::White, &transports, None)
         } else {
-            container.fetch_with_schemes(HostColor::Grey as usize, &transports, None)
+            container.fetch_with_schemes(HostColor::Grey, &transports, None)
         };
 
         hosts.check_addrs(addrs).await

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

@@ -44,7 +44,7 @@ use super::super::p2p::{P2p, P2pPtr};
 use crate::{
     net::{
         connector::Connector,
-        hosts::{HostColor, HostState},
+        hosts::HostColor,
         protocol::ProtocolVersion,
         session::{Session, SessionBitFlag, SESSION_REFINE},
     },
@@ -236,6 +236,10 @@ impl GreylistRefinery {
 
             sleep(greylist_refinery_interval).await;
 
+            // Prune stale entries from the host registry to prevent unbounded growth.
+            // Entries in Free state for longer than REGISTRY_PRUNE_AGE_SECS are removed.
+            hosts.prune_registry();
+
             if hosts.container.is_empty(HostColor::Grey) {
                 debug!(target: "net::refinery",
                 "Greylist is empty! Cannot start refinery process");
@@ -247,8 +251,7 @@ impl GreylistRefinery {
             // limit.
             let offline_limit = Duration::from_secs(time_with_no_connections);
 
-            let offline_timer =
-                { Instant::now().duration_since(*hosts.last_connection.lock().unwrap()) };
+            let offline_timer = { Instant::now().duration_since(*hosts.last_connection.lock()) };
 
             if !self.p2p().is_connected() && offline_timer >= offline_limit {
                 warn!(target: "net::refinery", "No connections for {}s. GreylistRefinery paused.",
@@ -270,17 +273,14 @@ impl GreylistRefinery {
 
             // Only attempt to refine peers that match our transports.
             match hosts.container.fetch_random_with_schemes(HostColor::Grey, &active_profiles) {
-                Some((entry, _)) => {
-                    let url = &entry.0;
-
-                    if let Err(e) = hosts.try_register(url.clone(), HostState::Refine) {
-                        debug!(target: "net::refinery", "Unable to refine addr={}, err={e}",
-                               url.clone());
+                Some((url, _last_seen)) => {
+                    if !hosts.refinable(&url) {
+                        debug!(target: "net::refinery", "Unable to refine addr={}", url);
                         continue
                     }
 
                     if !self.session().handshake_node(url.clone(), self.p2p().clone()).await {
-                        hosts.container.remove_if_exists(HostColor::Grey, url);
+                        hosts.container.remove(HostColor::Grey, &url);
 
                         debug!(
                             target: "net::refinery",
@@ -288,7 +288,7 @@ impl GreylistRefinery {
                         );
 
                         // Free up this addr for future operations.
-                        if let Err(e) = hosts.unregister(url) {
+                        if let Err(e) = hosts.unregister(&url) {
                             warn!(target: "net::refinery", "Error while unregistering addr={url}, err={e}");
                         }
 
@@ -300,7 +300,7 @@ impl GreylistRefinery {
                     );
                     let last_seen = UNIX_EPOCH.elapsed().unwrap().as_secs();
 
-                    hosts.whitelist_host(url, last_seen).await.unwrap();
+                    hosts.whitelist_host(&url, last_seen).await.unwrap();
 
                     debug!(target: "net::refinery", "GreylistRefinery complete!");
 

+ 4 - 7
src/net/tests.rs

@@ -204,11 +204,11 @@ async fn get_random_gold_host(
     info!("Getting gold addr from node={external_addr}");
     info!("========================================================");
 
-    let list = hosts.container.hostlists[HostColor::Gold as usize].read().unwrap();
+    let list = hosts.container.fetch_all(HostColor::Gold);
     assert!(!list.is_empty());
     let position = rand::thread_rng().gen_range(0..list.len());
-    let entry = &list[position];
-    (entry.clone(), position)
+    let entry = list[position].clone();
+    (entry, position)
 }
 
 async fn _check_random_hostlist(outbound_instances: &[Arc<P2p>], rng: &mut ThreadRng) {
@@ -444,10 +444,7 @@ async fn p2p_test_real(ex: Arc<Executor<'static>>) {
     // ===========================================================
     // 7. Verify the peer has been removed from the Gold list.
     // ===========================================================
-    outbound_instances[random_node_index]
-        .hosts()
-        .container
-        .contains(HostColor::Grey as usize, &addr);
+    outbound_instances[random_node_index].hosts().container.contains(HostColor::Grey, &addr);
     info!("========================================================");
     info!("Greylist downgrade occured successfully!");
     info!("========================================================");

Некоторые файлы не были показаны из-за большого количества измененных файлов