various fixes, including node_ref last_connection sorting problem

This commit is contained in:
John Smith
2022-10-04 11:27:38 -04:00
parent 0a01c0d23e
commit 4b2164a546
16 changed files with 740 additions and 517 deletions

View File

@@ -264,32 +264,62 @@ impl BucketEntryInner {
self.last_connections.clear();
}
// Gets the best 'last connection' that matches a set of routing domain, protocol types and address types
pub(super) fn last_connection(
// Gets the 'last connection' that matches a specific connection key
// pub(super) fn last_connection(
// &self,
// protocol_type: ProtocolType,
// address_type: AddressType,
// ) -> Option<(ConnectionDescriptor, u64)> {
// let key = LastConnectionKey(protocol_type, address_type);
// self.last_connections.get(&key).cloned()
// }
// Gets all the 'last connections' that match a particular filter
pub(super) fn last_connections(
&self,
routing_table_inner: &RoutingTableInner,
node_ref_filter: Option<NodeRefFilter>,
) -> Option<(ConnectionDescriptor, u64)> {
// Iterate peer scopes and protocol types and address type in order to ensure we pick the preferred protocols if all else is the same
let nrf = node_ref_filter.unwrap_or_default();
for pt in nrf.dial_info_filter.protocol_type_set {
for at in nrf.dial_info_filter.address_type_set {
let key = LastConnectionKey(pt, at);
if let Some(v) = self.last_connections.get(&key) {
// Verify this connection could be in the filtered routing domain
let address = v.0.remote_address().address();
if let Some(rd) =
RoutingTable::routing_domain_for_address_inner(routing_table_inner, address)
{
if nrf.routing_domain_set.contains(rd) {
return Some(*v);
filter: Option<NodeRefFilter>,
) -> Vec<(ConnectionDescriptor, u64)> {
let mut out: Vec<(ConnectionDescriptor, u64)> = self
.last_connections
.iter()
.filter_map(|(k, v)| {
let include = if let Some(filter) = &filter {
let remote_address = v.0.remote_address().address();
if let Some(routing_domain) = RoutingTable::routing_domain_for_address_inner(
routing_table_inner,
remote_address,
) {
if filter.routing_domain_set.contains(routing_domain)
&& filter.dial_info_filter.protocol_type_set.contains(k.0)
&& filter.dial_info_filter.address_type_set.contains(k.1)
{
// matches filter
true
} else {
// does not match filter
false
}
} else {
// no valid routing domain
false
}
} else {
// no filter
true
};
if include {
Some(v.clone())
} else {
None
}
}
}
None
})
.collect();
// Sort with newest timestamps first
out.sort_by(|a, b| b.1.cmp(&a.1));
out
}
pub fn set_min_max_version(&mut self, min_max_version: (u8, u8)) {
self.min_max_version = Some(min_max_version);
}

View File

@@ -318,24 +318,29 @@ impl NodeRef {
}
pub fn last_connection(&self) -> Option<ConnectionDescriptor> {
// Get the last connection and the last time we saw anything with this connection
let (last_connection, last_seen) =
self.operate(|rti, e| e.last_connection(rti, self.filter.clone()))?;
// Get the last connections and the last time we saw anything with this connection
// Filtered first and then sorted by most recent
let last_connections = self.operate(|rti, e| e.last_connections(rti, self.filter.clone()));
// Should we check the connection table?
if last_connection.protocol_type().is_connection_oriented() {
// Look the connection up in the connection manager and see if it's still there
let connection_manager = self.routing_table.network_manager().connection_manager();
connection_manager.get_connection(last_connection)?;
} else {
// If this is not connection oriented, then we check our last seen time
// to see if this mapping has expired (beyond our timeout)
let cur_ts = intf::get_timestamp();
if (last_seen + (CONNECTIONLESS_TIMEOUT_SECS as u64 * 1_000_000u64)) < cur_ts {
return None;
// Do some checks to ensure these are possibly still 'live'
for (last_connection, last_seen) in last_connections {
// Should we check the connection table?
if last_connection.protocol_type().is_connection_oriented() {
// Look the connection up in the connection manager and see if it's still there
let connection_manager = self.routing_table.network_manager().connection_manager();
if connection_manager.get_connection(last_connection).is_some() {
return Some(last_connection);
}
} else {
// If this is not connection oriented, then we check our last seen time
// to see if this mapping has expired (beyond our timeout)
let cur_ts = intf::get_timestamp();
if (last_seen + (CONNECTIONLESS_TIMEOUT_SECS as u64 * 1_000_000u64)) >= cur_ts {
return Some(last_connection);
}
}
}
Some(last_connection)
None
}
pub fn clear_last_connections(&self) {