Эх сурвалжийг харах

net: improve outbound_session connection loop logic.

lunar-mining 2 жил өмнө
parent
commit
0096f778c6

+ 102 - 38
src/net/session/outbound_session.rs

@@ -31,7 +31,7 @@ use std::{
         atomic::{AtomicU32, Ordering},
         Arc, Weak,
     },
-    time::{Duration, Instant},
+    time::{Duration, Instant, UNIX_EPOCH},
 };
 
 use async_trait::async_trait;
@@ -203,6 +203,7 @@ impl Slot {
     // Fetch address, try to connect to it, call setup_channel.
     async fn run(self: Arc<Self>) {
         let hosts = self.p2p().hosts();
+        // TODO: reimplement
         let slot_count = self.p2p().settings().outbound_connections;
         let white_count = slot_count * DEFAULT_WHITE_CONN_PERCENT / 100;
 
@@ -235,49 +236,102 @@ impl Slot {
                 continue
             }
 
-            // For the first 2 loops, connect to a host from the anchorlist.
+            
+            // Uo to DEFAULT_ANCHOR_CONN_COUNT connections:
+            //
+            //  Select from the anchorlist
+            //  If the anchorlist is empty, select from the whitelist
+            //  If the whitelist is empty, select from the greylist
+            //  If the greylist is empty, do peer discovery
+            //
+            // Up to DEFAULT_WHITE_CONN_PERCENT connections:
+            //
+            //  Select from the whitelist
+            //  If the whitelist is empty, select from the greylist
+            //  If the greylist is empty, do peer discovery
+            //
+            // All other connections:
+            //
+            //  Select from the greylist
+            //  If the greylist is empty, do peer discovery
+
             if connect_count < DEFAULT_ANCHOR_CONN_COUNT {
-                if let Some(host) =
-                    hosts.anchorlist_fetch_address_with_lock(self.p2p(), transports).await
-                {
-                    // TODO: Error handling.
-                    self.connect_slot(&host.0, self.slot).await.unwrap();
-                } else {
-                    continue
+                // There's no hosts on the anchorlist, connect to addrs on the greylist.
+                if hosts.is_empty_anchorlist().await {
+                    match hosts.whitelist_fetch_address_with_lock(self.p2p(), transports).await {
+                        Some(white) => {
+                            // Connect to whitelist addr
+                            self.connect_slot(&white.0, self.slot).await.unwrap();
+                        }
+                        None => {
+                            // If we can't find a peer on the whitelist, chose from the greylist.
+                            match hosts
+                                .greylist_fetch_address_with_lock(self.p2p(), transports)
+                                .await
+                            {
+                                Some(grey) => {
+                                    // Connect to greylist addr
+                                    self.connect_slot(&grey.0, self.slot).await.unwrap();
+                                }
+                                None => {
+                                    // peer discovery
+                                }
+                            }
+                        }
+                    }
+                }
+                // Connect to an addr from the anchor list.
+                else {
+                    let anchor = hosts
+                        .anchorlist_fetch_address_with_lock(self.p2p(), transports)
+                        .await
+                        .unwrap();
+                    self.connect_slot(&anchor.0, self.slot).await.unwrap();
                 }
-            }
 
-            //// For the next N loops, connect to a host from the whitelist.
-            if connect_count < white_count {
-                if let Some(host) =
-                    hosts.whitelist_fetch_address_with_lock(self.p2p(), transports).await
-                {
-                    // TODO: Error handling.
-                    self.connect_slot(&host.0, self.slot).await.unwrap();
-                } else {
-                    continue
+                // If the filled slots are less than the default whitelist slots limit,
+                // search for connections from the whitelist.
+            } else if connect_count < white_count {
+                if hosts.is_empty_whitelist().await {
+                    // Take from the greylist if there's nothing on the whitelist.
+                    match hosts.greylist_fetch_address_with_lock(self.p2p(), transports).await {
+                        Some(grey) => self.connect_slot(&grey.0, self.slot).await.unwrap(),
+                        None => {
+                            // We haven't been able to connect to any known peers. Activate peer discovery.
+                            dnetev!(self, OutboundSlotSleeping, {
+                                slot: self.slot,
+                            });
+
+                            self.wakeup_self.reset();
+                            // Peer discovery
+                            self.session().wakeup_peer_discovery();
+                            // Wait to be woken up by peer discovery
+                            self.wakeup_self.wait().await;
+                            continue
+                        }
+                    }
                 }
-            }
 
             // For any remaining slots, connect to a host on the greylist.
-            if connect_count < slot_count {
-                if let Some(host) =
-                    hosts.greylist_fetch_address_with_lock(self.p2p(), transports).await
-                {
-                    // TODO: Error handling.
-                    self.connect_slot(&host.0, self.slot).await.unwrap();
-                } else {
-                    // We haven't been able to connect to any known peers. Activate peer discovery.
-                    dnetev!(self, OutboundSlotSleeping, {
-                        slot: self.slot,
-                    });
-
-                    self.wakeup_self.reset();
-                    // Peer discovery
-                    self.session().wakeup_peer_discovery();
-                    // Wait to be woken up by peer discovery
-                    self.wakeup_self.wait().await;
-                    continue
+            } else if connect_count < slot_count {
+                match hosts.greylist_fetch_address_with_lock(self.p2p(), transports).await {
+                    Some(grey) => {
+                        self.connect_slot(&grey.0, self.slot).await.unwrap();
+                    }
+
+                    None => {
+                        // We haven't been able to connect to any known peers. Activate peer discovery.
+                        dnetev!(self, OutboundSlotSleeping, {
+                            slot: self.slot,
+                        });
+
+                        self.wakeup_self.reset();
+                        // Peer discovery
+                        self.session().wakeup_peer_discovery();
+                        // Wait to be woken up by peer discovery
+                        self.wakeup_self.wait().await;
+                        continue
+                    }
                 }
             }
         }
@@ -498,8 +552,18 @@ impl Slot {
 
     async fn setup_channel(&self, addr: Url, channel: ChannelPtr) -> Result<()> {
         // Register the new channel
+        debug!(target: "net::outbound_session::setup_channel", "register_channel {}", channel.clone().address());
         self.session().register_channel(channel.clone(), self.p2p().executor()).await?;
 
+        // Channel is now initialized. Timestamp this.
+        let last_seen = UNIX_EPOCH.elapsed().unwrap().as_secs();
+
+        // Save this connection on the anchorlist.
+        self.p2p()
+            .hosts()
+            .anchorlist_store_or_update(&[(channel.address().clone(), last_seen)])
+            .await?;
+
         // Channel is now connected but not yet setup
         // Remove pending lock since register_channel will add the channel to p2p
         self.p2p().remove_pending(&addr).await;