From 4284458e17066fe6788e32f8ab04546bed72b34b Mon Sep 17 00:00:00 2001 From: Antioch Peverell Date: Tue, 2 Mar 2021 20:34:55 +0000 Subject: [PATCH] more consistent handling of peers_preferred during startup (#3578) --- p2p/src/msg.rs | 34 ++++++++++++++++++ p2p/src/peers.rs | 5 ++- servers/src/grin/seed.rs | 70 ++++++++++++++++++++------------------ servers/src/grin/server.rs | 11 ++---- 4 files changed, 77 insertions(+), 43 deletions(-) diff --git a/p2p/src/msg.rs b/p2p/src/msg.rs index b47d39c0d..92153b6b9 100644 --- a/p2p/src/msg.rs +++ b/p2p/src/msg.rs @@ -529,6 +529,40 @@ impl Readable for PeerAddrs { } } +impl IntoIterator for PeerAddrs { + type Item = PeerAddr; + type IntoIter = std::vec::IntoIter; + fn into_iter(self) -> Self::IntoIter { + self.peers.into_iter() + } +} + +impl Default for PeerAddrs { + fn default() -> Self { + PeerAddrs { peers: vec![] } + } +} + +impl PeerAddrs { + pub fn as_slice(&self) -> &[PeerAddr] { + self.peers.as_slice() + } + + pub fn contains(&self, addr: &PeerAddr) -> bool { + self.peers.contains(addr) + } + + pub fn difference(&self, other: &[PeerAddr]) -> PeerAddrs { + let peers = self + .peers + .iter() + .filter(|x| !other.contains(x)) + .cloned() + .collect(); + PeerAddrs { peers } + } +} + /// We found some issue in the communication, sending an error back, usually /// followed by closing the connection. pub struct PeerError { diff --git a/p2p/src/peers.rs b/p2p/src/peers.rs index f81134f7d..b0fde05da 100644 --- a/p2p/src/peers.rs +++ b/p2p/src/peers.rs @@ -27,6 +27,7 @@ use crate::core::core::hash::{Hash, Hashed}; use crate::core::core::{OutputIdentifier, Segment, SegmentIdentifier, TxKernel}; use crate::core::global; use crate::core::pow::Difficulty; +use crate::msg::PeerAddrs; use crate::peer::Peer; use crate::store::{PeerData, PeerStore, State}; use crate::types::{ @@ -322,8 +323,10 @@ impl Peers { &self, max_inbound_count: usize, max_outbound_count: usize, - preferred_peers: &[PeerAddr], + config: P2PConfig, ) { + let preferred_peers = config.peers_preferred.unwrap_or(PeerAddrs::default()); + let mut rm = vec![]; // build a list of peers to be cleaned up diff --git a/servers/src/grin/seed.rs b/servers/src/grin/seed.rs index fc310bcbe..2a29a907a 100644 --- a/servers/src/grin/seed.rs +++ b/servers/src/grin/seed.rs @@ -19,6 +19,7 @@ use chrono::prelude::{DateTime, Utc}; use chrono::{Duration, MIN_DATE}; +use p2p::{msg::PeerAddrs, P2PConfig}; use rand::prelude::*; use std::collections::HashMap; use std::net::ToSocketAddrs; @@ -51,11 +52,9 @@ const TESTNET_DNS_SEEDS: &[&str] = &[ pub fn connect_and_monitor( p2p_server: Arc, seed_list: Box Vec + Send>, - preferred_peers: &[PeerAddr], + config: P2PConfig, stop_state: Arc, ) -> std::io::Result> { - let preferred_peers = preferred_peers.to_vec(); - thread::Builder::new() .name("seed".to_string()) .spawn(move || { @@ -66,12 +65,7 @@ pub fn connect_and_monitor( let (tx, rx) = mpsc::channel(); // check seeds first - connect_to_seeds_and_preferred_peers( - peers.clone(), - tx.clone(), - seed_list, - &preferred_peers, - ); + connect_to_seeds_and_peers(peers.clone(), tx.clone(), seed_list, config); let mut prev = MIN_DATE.and_hms(0, 0, 0); let mut prev_expire_check = MIN_DATE.and_hms(0, 0, 0); @@ -109,12 +103,7 @@ pub fn connect_and_monitor( ); // monitor additional peers if we need to add more - monitor_peers( - peers.clone(), - p2p_server.config.clone(), - tx.clone(), - &preferred_peers, - ); + monitor_peers(peers.clone(), p2p_server.config.clone(), tx.clone()); prev = Utc::now(); start_attempt = cmp::min(6, start_attempt + 1); @@ -137,12 +126,7 @@ pub fn connect_and_monitor( }) } -fn monitor_peers( - peers: Arc, - config: p2p::P2PConfig, - tx: mpsc::Sender, - preferred_peers: &[PeerAddr], -) { +fn monitor_peers(peers: Arc, config: p2p::P2PConfig, tx: mpsc::Sender) { // regularly check if we need to acquire more peers and if so, gets // them from db let mut total_count = 0; @@ -195,7 +179,7 @@ fn monitor_peers( peers.clean_peers( config.peer_max_inbound_count() as usize, config.peer_max_outbound_count() as usize, - preferred_peers, + config.clone(), ); if peers.enough_outbound_peers() { @@ -221,13 +205,14 @@ fn monitor_peers( } // Attempt to connect to any preferred peers. - for p in preferred_peers { + let peers_preferred = config.peers_preferred.unwrap_or(PeerAddrs::default()); + for p in peers_preferred { if !connected_peers.is_empty() { - if !connected_peers.contains(p) { - tx.send(*p).unwrap(); + if !connected_peers.contains(&p) { + let _ = tx.send(p); } } else { - tx.send(*p).unwrap(); + let _ = tx.send(p); } } @@ -261,33 +246,50 @@ fn monitor_peers( // Check if we have any pre-existing peer in db. If so, start with those, // otherwise use the seeds provided. -fn connect_to_seeds_and_preferred_peers( +fn connect_to_seeds_and_peers( peers: Arc, tx: mpsc::Sender, seed_list: Box Vec>, - peers_preferred: &[PeerAddr], + config: P2PConfig, ) { + let peers_deny = config.peers_deny.unwrap_or(PeerAddrs::default()); + + // If "peers_allow" is explicitly configured then just use this list + // remembering to filter out "peers_deny". + if let Some(peers) = config.peers_allow { + for addr in peers.difference(peers_deny.as_slice()) { + let _ = tx.send(addr); + } + return; + } + + // Always try our "peers_preferred" remembering to filter out "peers_deny". + if let Some(peers) = config.peers_preferred { + for addr in peers.difference(peers_deny.as_slice()) { + let _ = tx.send(addr); + } + } + // check if we have some peers in db // look for peers that are able to give us other peers (via PEER_LIST capability) let peers = peers.find_peers(p2p::State::Healthy, p2p::Capabilities::PEER_LIST, 100); // if so, get their addresses, otherwise use our seeds - let mut peer_addrs = if peers.len() > 3 { + let peer_addrs = if peers.len() > 3 { peers.iter().map(|p| p.addr).collect::>() } else { seed_list() }; - // If we have preferred peers add them to the initial list - peer_addrs.extend_from_slice(peers_preferred); - if peer_addrs.is_empty() { warn!("No seeds were retrieved."); } - // connect to this first set of addresses + // connect to this initial set of peer addresses (either seeds or from our local db). for addr in peer_addrs { - tx.send(addr).unwrap(); + if !peers_deny.as_slice().contains(&addr) { + let _ = tx.send(addr); + } } } diff --git a/servers/src/grin/server.rs b/servers/src/grin/server.rs index 929f675c8..2cda4eab8 100644 --- a/servers/src/grin/server.rs +++ b/servers/src/grin/server.rs @@ -240,7 +240,7 @@ impl Server { let mut connect_thread = None; if config.p2p_config.seeding_type != p2p::Seeding::Programmatic { - let seeder = match config.p2p_config.seeding_type { + let seed_list = match config.p2p_config.seeding_type { p2p::Seeding::None => { warn!("No seed configured, will stay solo until connected to"); seed::predefined_seeds(vec![]) @@ -257,15 +257,10 @@ impl Server { _ => unreachable!(), }; - let preferred_peers = match &config.p2p_config.peers_preferred { - Some(addrs) => addrs.peers.clone(), - None => vec![], - }; - connect_thread = Some(seed::connect_and_monitor( p2p_server.clone(), - seeder, - &preferred_peers, + seed_list, + config.p2p_config.clone(), stop_state.clone(), )?); }