more refactor

This commit is contained in:
John Smith
2021-12-23 20:34:52 -05:00
parent 5826551763
commit 922470365a
9 changed files with 354 additions and 281 deletions

View File

@@ -13,15 +13,15 @@ impl RoutingTable {
out
}
pub fn debug_info_dialinfo(&self) -> String {
let ldis = self.local_dial_info();
let gdis = self.global_dial_info();
let ldis = self.local_dial_info_details();
let gdis = self.global_dial_info_details();
let mut out = String::new();
out += "Local Dial Info:\n";
out += "Local Dial Info Details:\n";
for (n, ldi) in ldis.iter().enumerate() {
out += &format!(" {:>2}: {:?}\n", n, ldi);
}
out += "Global Dial Info:\n";
out += "Global Dial Info Details:\n";
for (n, gdi) in gdis.iter().enumerate() {
out += &format!(" {:>2}: {:?}\n", n, gdi);
}

View File

@@ -10,42 +10,18 @@ pub type FilterType = Box<dyn Fn(&(&DHTKey, Option<&mut BucketEntry>)) -> bool>;
impl RoutingTable {
// Retrieve the fastest nodes in the routing table with a particular kind of protocol address type
// Returns noderefs are are scoped to that address type only
pub fn get_fast_nodes_of_type(
&self,
protocol_address_type: ProtocolAddressType,
) -> Vec<NodeRef> {
pub fn get_fast_nodes_filtered(&self, dial_info_filter: &DialInfoFilter) -> Vec<NodeRef> {
let dial_info_filter = dial_info_filter.clone();
self.find_fastest_nodes(
// filter
Some(Box::new(
move |params: &(&DHTKey, Option<&mut BucketEntry>)| {
// Only interested in nodes with node info
if let Some(node_info) = &params.1.as_ref().unwrap().peer_stats().node_info {
// Will the node validate dial info?
// and does it have a UDPv4, public scope, dial info?
if node_info.will_validate_dial_info
&& params
.1
.as_ref()
.unwrap()
.dial_info_entries_as_ref()
.iter()
.find_map(|die| {
if die.matches_peer_scope(PeerScope::Global)
&& die.dial_info().protocol_address_type()
== protocol_address_type
{
Some(())
} else {
None
}
})
.is_some()
{
// If so return true and include this node
return true;
}
}
false
params
.1
.as_ref()
.unwrap()
.first_filtered_dial_info(|di| di.matches_filter(&dial_info_filter))
.is_some()
},
)),
// transform
@@ -54,7 +30,7 @@ impl RoutingTable {
self.clone(),
*e.0,
e.1.as_mut().unwrap(),
protocol_address_type,
dial_info_filter.clone(),
)
},
)
@@ -63,13 +39,13 @@ impl RoutingTable {
pub fn get_own_peer_info(&self, scope: PeerScope) -> PeerInfo {
let dial_infos = match scope {
PeerScope::All => {
let mut divec = self.global_dial_info();
divec.append(&mut self.local_dial_info());
let mut divec = self.global_dial_info_details();
divec.append(&mut self.local_dial_info_details());
divec.dedup();
divec
}
PeerScope::Global => self.global_dial_info(),
PeerScope::Local => self.local_dial_info(),
PeerScope::Global => self.global_dial_info_details(),
PeerScope::Local => self.local_dial_info_details(),
};
PeerInfo {

View File

@@ -1,7 +1,6 @@
mod bucket;
mod bucket_entry;
mod debug;
mod dial_info_entry;
mod find_nodes;
mod node_ref;
mod stats_accounting;
@@ -12,12 +11,10 @@ use crate::network_manager::*;
use crate::rpc_processor::*;
use crate::xx::*;
use crate::*;
use alloc::collections::VecDeque;
use alloc::str::FromStr;
use bucket::*;
pub use bucket_entry::*;
pub use debug::*;
pub use dial_info_entry::*;
pub use find_nodes::*;
use futures_util::stream::{FuturesUnordered, StreamExt};
pub use node_ref::*;
@@ -157,42 +154,35 @@ impl RoutingTable {
!inner.local_dial_info.is_empty()
}
pub fn local_dial_info(&self) -> Vec<DialInfoDetail> {
pub fn local_dial_info_details(&self) -> Vec<DialInfoDetail> {
let inner = self.inner.lock();
inner.local_dial_info.clone()
}
pub fn local_dial_info_for_protocol(&self, protocol_type: ProtocolType) -> Vec<DialInfoDetail> {
pub fn first_filtered_local_dial_info_details<F>(&self, filter: F) -> Option<DialInfoDetail>
where
F: Fn(&DialInfoDetail) -> bool,
{
let inner = self.inner.lock();
inner
.local_dial_info
.iter()
.filter_map(|di| {
if di.dial_info.protocol_type() != protocol_type {
None
} else {
Some(di.clone())
}
})
.collect()
for did in &inner.local_dial_info {
if filter(did) {
return Some(did.clone());
}
}
None
}
pub fn local_dial_info_for_protocol_address_type(
&self,
protocol_address_type: ProtocolAddressType,
) -> Vec<DialInfoDetail> {
pub fn all_filtered_local_dial_info_details<F>(&self, filter: F) -> Vec<DialInfoDetail>
where
F: Fn(&DialInfoDetail) -> bool,
{
let inner = self.inner.lock();
inner
.local_dial_info
.iter()
.filter_map(|di| {
if di.dial_info.protocol_address_type() != protocol_address_type {
None
} else {
Some(di.clone())
}
})
.collect()
let ret = Vec::new();
for did in &inner.local_dial_info {
if filter(did) {
ret.push(did.clone());
}
}
ret
}
pub fn register_local_dial_info(&self, dial_info: DialInfo, origin: DialInfoOrigin) {
@@ -230,44 +220,35 @@ impl RoutingTable {
!inner.global_dial_info.is_empty()
}
pub fn global_dial_info(&self) -> Vec<DialInfoDetail> {
pub fn global_dial_info_details(&self) -> Vec<DialInfoDetail> {
let inner = self.inner.lock();
inner.global_dial_info.clone()
}
pub fn global_dial_info_for_protocol(
&self,
protocol_type: ProtocolType,
) -> Vec<DialInfoDetail> {
pub fn first_filtered_global_dial_info_details<F>(&self, filter: F) -> Option<DialInfoDetail>
where
F: Fn(&DialInfoDetail) -> bool,
{
let inner = self.inner.lock();
inner
.global_dial_info
.iter()
.filter_map(|di| {
if di.dial_info.protocol_type() != protocol_type {
None
} else {
Some(di.clone())
}
})
.collect()
for did in &inner.global_dial_info {
if filter(did) {
return Some(did.clone());
}
}
None
}
pub fn global_dial_info_for_protocol_address_type(
&self,
protocol_address_type: ProtocolAddressType,
) -> Vec<DialInfoDetail> {
pub fn all_filtered_global_dial_info_details<F>(&self, filter: F) -> Vec<DialInfoDetail>
where
F: Fn(&DialInfoDetail) -> bool,
{
let inner = self.inner.lock();
inner
.global_dial_info
.iter()
.filter_map(|di| {
if di.dial_info.protocol_address_type() != protocol_address_type {
None
} else {
Some(di.clone())
}
})
.collect()
let ret = Vec::new();
for did in &inner.global_dial_info {
if filter(did) {
ret.push(did.clone());
}
}
ret
}
pub fn register_global_dial_info(
@@ -287,7 +268,7 @@ impl RoutingTable {
});
info!(
"Public Dial Info: {}",
"Global Dial Info: {}",
NodeDialInfoSingle {
node_id: NodeId::new(inner.node_id),
dial_info
@@ -356,34 +337,6 @@ impl RoutingTable {
*self.inner.lock() = Self::new_inner(self.network_manager());
}
// Just match address and port to help sort dialinfoentries for buckets
// because inbound connections will not have dialinfo associated with them
// but should have ip addresses if they have changed
fn dial_info_peer_address_match(dial_info: &DialInfo, peer_addr: &PeerAddress) -> bool {
match dial_info {
DialInfo::UDP(_) => {
peer_addr.protocol_type == ProtocolType::UDP
&& peer_addr.port == dial_info.port()
&& peer_addr.address.address_string() == dial_info.address_string()
}
DialInfo::TCP(_) => {
peer_addr.protocol_type == ProtocolType::TCP
&& peer_addr.port == dial_info.port()
&& peer_addr.address.address_string() == dial_info.address_string()
}
DialInfo::WS(_) => {
peer_addr.protocol_type == ProtocolType::WS
&& peer_addr.port == dial_info.port()
&& peer_addr.address.address_string() == dial_info.address_string()
}
DialInfo::WSS(_) => {
peer_addr.protocol_type == ProtocolType::WSS
&& peer_addr.port == dial_info.port()
&& peer_addr.address.address_string() == dial_info.address_string()
}
}
}
// Attempt to settle buckets and remove entries down to the desired number
// which may not be possible due extant NodeRefs
fn kick_bucket(inner: &mut RoutingTableInner, idx: usize) {
@@ -482,7 +435,7 @@ impl RoutingTable {
) -> Result<NodeRef, String> {
let nr = self.create_node_ref(node_id)?;
nr.operate(move |e| -> Result<(), String> {
e.update_dial_info(dial_infos);
e.update_dial_infos(dial_infos);
Ok(())
})?;
@@ -604,6 +557,7 @@ impl RoutingTable {
let mut bsmap: BTreeMap<DHTKey, Vec<DialInfo>> = BTreeMap::new();
for b in bootstrap {
let ndis = NodeDialInfoSingle::from_str(b.as_str())
.map_err(map_to_string)
.map_err(logthru_rtab!("Invalid dial info in bootstrap entry: {}", b))?;
let node_id = ndis.node_id.key;
bsmap

View File

@@ -5,9 +5,7 @@ use alloc::fmt;
pub struct NodeRef {
routing_table: RoutingTable,
node_id: DHTKey,
// Filters
protocol_type: Option<ProtocolType>,
address_type: Option<AddressType>,
dial_info_filter: DialInfoFilter,
}
impl NodeRef {
@@ -16,23 +14,20 @@ impl NodeRef {
Self {
routing_table,
node_id: key,
protocol_type: None,
address_type: None,
dial_info_filter: DialInfoFilter::default(),
}
}
pub fn new_filtered(
routing_table: RoutingTable,
key: DHTKey,
entry: &mut BucketEntry,
protocol_type: Option<ProtocolType>,
address_type: Option<AddressType>,
dial_info_filter: DialInfoFilter,
) -> Self {
entry.ref_count += 1;
Self {
routing_table,
node_id: key,
protocol_type,
address_type,
dial_info_filter,
}
}
@@ -40,20 +35,8 @@ impl NodeRef {
self.node_id
}
pub fn protocol_type(&self) -> Option<ProtocolType> {
self.protocol_type
}
pub fn set_protocol_type(&mut self, protocol_type: Option<ProtocolType>) {
self.protocol_type = protocol_type;
}
pub fn address_type(&self) -> Option<AddressType> {
self.address_type
}
pub fn set_address_type(&mut self, address_type: Option<AddressType>) {
self.address_type = address_type;
pub fn dial_info_filter(&self) -> DialInfoFilter {
self.dial_info_filter.clone()
}
pub fn operate<T, F>(&self, f: F) -> T
@@ -63,28 +46,39 @@ impl NodeRef {
self.routing_table.operate_on_bucket_entry(self.node_id, f)
}
xxx fix the notion of 'best dial info' to sort by capability and udp/tcp/ws/wss preference order
pub fn dial_info(&self) -> Option<DialInfo> {
if self.protocol_type || self. {
None => self.operate(|e| e.best_dial_info()),
Some(pat) => self.operate(|e| {
e.filtered_dial_info(|die| die.dial_info().protocol_address_type() == pat)
}),
// Returns the best dial info to attempt a connection to this node
pub fn best_dial_info(&self) -> Option<DialInfo> {
let nm = self.routing_table.network_manager();
let protocol_config = nm.get_protocol_config();
if protocol_config.is_none() {
return None;
}
let protocol_config = protocol_config.unwrap();
self.operate(|e| {
e.first_filtered_dial_info(|di| {
// Does it match the dial info filter
if !di.matches_filter(&self.dial_info_filter) {
return false;
}
// Filter out dial infos that don't match our protocol config
// for outbound connections. This routine filters on 'connect' settings
// to ensure we connect using only the protocols we have enabled.
protocol_config.is_protocol_type_connect_enabled(di.protocol_type())
})
})
}
pub fn last_connection(&self) -> Option<ConnectionDescriptor> {
match self.operate(|e| e.last_connection()) {
None => None,
Some(c) => {
if let Some(protocol_address_type) = self.protocol_address_type {
if c.remote.protocol_address_type() == protocol_address_type {
Some(c)
} else {
None
}
} else {
Some(c)
if !c.matches_filter(&self.dial_info_filter) {
return None;
}
// We don't filter this out by protocol config because if a connection
// succeeded, it's allowed to persist and be used for communication
// regardless of any other configuration
Some(c)
}
}
}
@@ -98,17 +92,18 @@ impl Clone for NodeRef {
Self {
routing_table: self.routing_table.clone(),
node_id: self.node_id,
protocol_address_type: self.protocol_address_type,
dial_info_filter: self.dial_info_filter.clone(),
}
}
}
impl fmt::Debug for NodeRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.protocol_address_type {
None => write!(f, "{}", self.node_id.encode()),
Some(pat) => write!(f, "{}#{:?}", self.node_id.encode(), pat),
let out = format!("{}", self.node_id.encode());
if !self.dial_info_filter.is_empty() {
out += &format!("{:?}", self.dial_info_filter);
}
write!(f, "{}", out)
}
}