continue to refactor
This commit is contained in:
@@ -31,7 +31,7 @@ pub struct BucketEntry {
|
||||
pub(super) ref_count: u32,
|
||||
min_max_version: Option<(u8, u8)>,
|
||||
last_connection: Option<(ConnectionDescriptor, u64)>,
|
||||
dial_info_entries: VecDeque<DialInfoEntry>,
|
||||
dial_infos: Vec<DialInfo>,
|
||||
stats_accounting: StatsAccounting,
|
||||
peer_stats: PeerStats,
|
||||
}
|
||||
@@ -43,7 +43,7 @@ impl BucketEntry {
|
||||
ref_count: 0,
|
||||
min_max_version: None,
|
||||
last_connection: None,
|
||||
dial_info_entries: VecDeque::new(),
|
||||
dial_infos: Vec::new(),
|
||||
stats_accounting: StatsAccounting::new(),
|
||||
peer_stats: PeerStats {
|
||||
time_added: now,
|
||||
@@ -56,145 +56,48 @@ impl BucketEntry {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_dial_info(&mut self, dial_info: DialInfo) -> Result<(), String> {
|
||||
let mut idx: Option<usize> = None;
|
||||
for i in 0..self.dial_info_entries.len() {
|
||||
if self.dial_info_entries[i].dial_info() == &dial_info {
|
||||
idx = Some(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
match idx {
|
||||
None => {
|
||||
self.dial_info_entries
|
||||
.push_front(DialInfoEntry::try_new(dial_info)?);
|
||||
}
|
||||
Some(idx) => {
|
||||
let die = self.dial_info_entries.remove(idx).unwrap();
|
||||
self.dial_info_entries.push_front(die);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
pub fn update_dial_infos(&mut self, dial_infos: &[DialInfo]) {
|
||||
self.dial_infos = dial_infos.to_vec();
|
||||
self.dial_infos.sort();
|
||||
}
|
||||
|
||||
pub fn best_dial_info(&self) -> Option<DialInfo> {
|
||||
self.dial_info_entries
|
||||
.front()
|
||||
.map(|die| die.dial_info().clone())
|
||||
}
|
||||
|
||||
pub fn filtered_dial_info<F>(&self, filter: F) -> Option<DialInfo>
|
||||
pub fn first_filtered_dial_info<F>(&self, filter: F) -> Option<DialInfo>
|
||||
where
|
||||
F: Fn(&DialInfoEntry) -> bool,
|
||||
F: Fn(&DialInfo) -> bool,
|
||||
{
|
||||
for die in &self.dial_info_entries {
|
||||
if filter(die) {
|
||||
return Some(die.dial_info().clone());
|
||||
for di in &self.dial_infos {
|
||||
if filter(di) {
|
||||
return Some(di.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn dial_info_entries_as_ref(&self) -> &VecDeque<DialInfoEntry> {
|
||||
&self.dial_info_entries
|
||||
pub fn all_filtered_dial_infos<F>(&self, filter: F) -> Vec<DialInfo>
|
||||
where
|
||||
F: Fn(&DialInfo) -> bool,
|
||||
{
|
||||
let ret = Vec::new();
|
||||
for di in &self.dial_infos {
|
||||
if filter(di) {
|
||||
ret.push(di.clone());
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn dial_info(&self) -> Vec<DialInfo> {
|
||||
self.dial_info_entries
|
||||
.iter()
|
||||
.map(|e| e.dial_info().clone())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn global_dial_info(&self) -> Vec<DialInfo> {
|
||||
self.dial_info_entries
|
||||
.iter()
|
||||
.filter_map(|e| {
|
||||
if e.is_public() {
|
||||
Some(e.dial_info().clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn global_dial_info_for_protocol(&self, protocol_type: ProtocolType) -> Vec<DialInfo> {
|
||||
self.dial_info_entries
|
||||
.iter()
|
||||
.filter_map(|e| {
|
||||
if e.dial_info().protocol_type() != protocol_type {
|
||||
None
|
||||
} else if e.is_public() {
|
||||
Some(e.dial_info().clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn local_dial_info(&self) -> Vec<DialInfo> {
|
||||
self.dial_info_entries
|
||||
.iter()
|
||||
.filter_map(|e| {
|
||||
if e.is_private() {
|
||||
Some(e.dial_info().clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn local_dial_info_for_protocol(&mut self, protocol_type: ProtocolType) -> Vec<DialInfo> {
|
||||
self.dial_info_entries
|
||||
.iter_mut()
|
||||
.filter_map(|e| {
|
||||
if e.dial_info().protocol_type() != protocol_type {
|
||||
None
|
||||
} else if e.is_private() {
|
||||
Some(e.dial_info().clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
pub fn dial_infos(&self) -> &[DialInfo] {
|
||||
&self.dial_infos.clone()
|
||||
}
|
||||
|
||||
pub fn get_peer_info(&self, key: DHTKey, scope: PeerScope) -> PeerInfo {
|
||||
PeerInfo {
|
||||
node_id: NodeId::new(key),
|
||||
dial_infos: match scope {
|
||||
PeerScope::All => self.dial_info(),
|
||||
PeerScope::Global => self.global_dial_info(),
|
||||
PeerScope::Local => self.local_dial_info(),
|
||||
},
|
||||
dial_infos: self.all_filtered_dial_infos(|di| di.matches_peer_scope(scope)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_last_connection(&mut self, last_connection: ConnectionDescriptor, timestamp: u64) {
|
||||
self.last_connection = Some((last_connection, timestamp));
|
||||
|
||||
// sort the dialinfoentries by the last peer address if we have a match
|
||||
// if one particular peer address is being used and matches a dialinfoentry
|
||||
// then we should prefer it
|
||||
for i in 0..self.dial_info_entries.len() {
|
||||
let die = &mut self.dial_info_entries[i];
|
||||
|
||||
// see if we have a matching address
|
||||
if RoutingTable::dial_info_peer_address_match(
|
||||
die.dial_info(),
|
||||
&self.last_connection.as_ref().unwrap().0.remote,
|
||||
) {
|
||||
// push the most recent dialinfo to the front
|
||||
let dies = &mut self.dial_info_entries;
|
||||
let die = dies.remove(i).unwrap();
|
||||
dies.push_front(die);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn last_connection(&self) -> Option<ConnectionDescriptor> {
|
||||
|
@@ -1,60 +0,0 @@
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DialInfoEntry {
|
||||
dial_info: DialInfo,
|
||||
resolved_address: IpAddr,
|
||||
}
|
||||
|
||||
impl DialInfoEntry {
|
||||
pub fn try_new(dial_info: DialInfo) -> Result<Self, String> {
|
||||
let addr = dial_info
|
||||
.resolve()
|
||||
.map_err(|e| format!("failed to resolve address: {:?}", e))?;
|
||||
Ok(Self {
|
||||
dial_info,
|
||||
resolved_address: addr,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn dial_info(&self) -> &DialInfo {
|
||||
&self.dial_info
|
||||
}
|
||||
|
||||
pub fn address(&self) -> IpAddr {
|
||||
self.resolved_address
|
||||
}
|
||||
|
||||
pub fn resolve(&mut self) -> Result<Vec<IpAddr, String> {
|
||||
let addr = match self.dial_info.resolve() {
|
||||
Ok(a) => a,
|
||||
Err(_) => return Err("failed to resolve address".to_owned()),
|
||||
};
|
||||
self.resolved_address = addr;
|
||||
Ok(addr)
|
||||
}
|
||||
|
||||
pub fn matches_peer_scope(&self, scope: PeerScope) -> bool {
|
||||
match scope {
|
||||
PeerScope::All => true,
|
||||
PeerScope::Global => self.is_public(),
|
||||
PeerScope::Local => self.is_private(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_public(&self) -> bool {
|
||||
ipaddr_is_global(&self.resolved_address)
|
||||
}
|
||||
pub fn is_private(&self) -> bool {
|
||||
match self.resolved_address {
|
||||
IpAddr::V4(a) => ipv4addr_is_private(&a),
|
||||
IpAddr::V6(a) => ipv6addr_is_unicast_site_local(&a),
|
||||
}
|
||||
}
|
||||
pub fn is_valid(&self) -> bool {
|
||||
self.is_public() || self.is_private()
|
||||
}
|
||||
pub fn is_loopback(&self) -> bool {
|
||||
ipaddr_is_loopback(&self.resolved_address)
|
||||
}
|
||||
}
|
@@ -482,9 +482,7 @@ impl RoutingTable {
|
||||
) -> Result<NodeRef, String> {
|
||||
let nr = self.create_node_ref(node_id)?;
|
||||
nr.operate(move |e| -> Result<(), String> {
|
||||
for di in dial_infos {
|
||||
e.add_dial_info(di.clone())?;
|
||||
}
|
||||
e.update_dial_info(dial_infos);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
|
@@ -5,7 +5,9 @@ use alloc::fmt;
|
||||
pub struct NodeRef {
|
||||
routing_table: RoutingTable,
|
||||
node_id: DHTKey,
|
||||
protocol_address_type: Option<ProtocolAddressType>,
|
||||
// Filters
|
||||
protocol_type: Option<ProtocolType>,
|
||||
address_type: Option<AddressType>,
|
||||
}
|
||||
|
||||
impl NodeRef {
|
||||
@@ -14,20 +16,23 @@ impl NodeRef {
|
||||
Self {
|
||||
routing_table,
|
||||
node_id: key,
|
||||
protocol_address_type: None,
|
||||
protocol_type: None,
|
||||
address_type: None,
|
||||
}
|
||||
}
|
||||
pub fn new_filtered(
|
||||
routing_table: RoutingTable,
|
||||
key: DHTKey,
|
||||
entry: &mut BucketEntry,
|
||||
protocol_address_type: ProtocolAddressType,
|
||||
protocol_type: Option<ProtocolType>,
|
||||
address_type: Option<AddressType>,
|
||||
) -> Self {
|
||||
entry.ref_count += 1;
|
||||
Self {
|
||||
routing_table,
|
||||
node_id: key,
|
||||
protocol_address_type: Some(protocol_address_type),
|
||||
protocol_type,
|
||||
address_type,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,15 +40,20 @@ impl NodeRef {
|
||||
self.node_id
|
||||
}
|
||||
|
||||
pub fn protocol_address_type(&self) -> Option<ProtocolAddressType> {
|
||||
self.protocol_address_type
|
||||
pub fn protocol_type(&self) -> Option<ProtocolType> {
|
||||
self.protocol_type
|
||||
}
|
||||
|
||||
pub fn set_protocol_address_type(
|
||||
&mut self,
|
||||
protocol_address_type: Option<ProtocolAddressType>,
|
||||
) {
|
||||
self.protocol_address_type = protocol_address_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 operate<T, F>(&self, f: F) -> T
|
||||
@@ -53,8 +63,9 @@ 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> {
|
||||
match self.protocol_address_type {
|
||||
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)
|
||||
|
Reference in New Issue
Block a user