allow revert to invalid nodeinfo
This commit is contained in:
@@ -7,12 +7,15 @@ impl RoutingTable {
|
||||
key: TypedKey,
|
||||
capabilities: &[Capability],
|
||||
) -> NetworkResult<Vec<PeerInfo>> {
|
||||
let Some(own_peer_info) = self.get_own_peer_info(RoutingDomain::PublicInternet) else {
|
||||
if !self.has_valid_network_class(RoutingDomain::PublicInternet) {
|
||||
// Our own node info is not yet available, drop this request.
|
||||
return NetworkResult::service_unavailable("Not finding closest peers because our peer info is not yet available");
|
||||
};
|
||||
return NetworkResult::service_unavailable(
|
||||
"Not finding closest peers because our network class is still invalid",
|
||||
);
|
||||
}
|
||||
|
||||
// find N nodes closest to the target node in our routing table
|
||||
let own_peer_info = self.get_own_peer_info(RoutingDomain::PublicInternet);
|
||||
let filter = Box::new(
|
||||
move |rti: &RoutingTableInner, opt_entry: Option<Arc<BucketEntry>>| {
|
||||
// Ensure only things that are valid/signed in the PublicInternet domain are returned
|
||||
@@ -28,14 +31,10 @@ impl RoutingTable {
|
||||
Some(entry) => entry.with(rti, |_rti, e| {
|
||||
e.has_capabilities(RoutingDomain::PublicInternet, capabilities)
|
||||
}),
|
||||
None => rti
|
||||
.get_own_peer_info(RoutingDomain::PublicInternet)
|
||||
.map(|pi| {
|
||||
pi.signed_node_info()
|
||||
.node_info()
|
||||
.has_capabilities(capabilities)
|
||||
})
|
||||
.unwrap_or(false),
|
||||
None => own_peer_info
|
||||
.signed_node_info()
|
||||
.node_info()
|
||||
.has_capabilities(capabilities),
|
||||
}
|
||||
},
|
||||
) as RoutingTableEntryFilter;
|
||||
@@ -46,6 +45,7 @@ impl RoutingTable {
|
||||
c.network.dht.max_find_node_count as usize
|
||||
};
|
||||
|
||||
let own_peer_info = self.get_own_peer_info(RoutingDomain::PublicInternet);
|
||||
let closest_nodes = self.find_closest_nodes(
|
||||
node_count,
|
||||
key,
|
||||
|
||||
@@ -549,27 +549,18 @@ impl RoutingTable {
|
||||
}
|
||||
|
||||
/// Return a copy of our node's peerinfo
|
||||
pub fn get_own_peer_info(&self, routing_domain: RoutingDomain) -> Option<PeerInfo> {
|
||||
pub fn get_own_peer_info(&self, routing_domain: RoutingDomain) -> PeerInfo {
|
||||
self.inner.read().get_own_peer_info(routing_domain)
|
||||
}
|
||||
|
||||
/// Return the best effort copy of our node's peerinfo
|
||||
/// This may be invalid and should not be passed to other nodes,
|
||||
/// but may be used for contact method calculation
|
||||
pub fn get_best_effort_own_peer_info(&self, routing_domain: RoutingDomain) -> PeerInfo {
|
||||
self.inner
|
||||
.read()
|
||||
.get_best_effort_own_peer_info(routing_domain)
|
||||
}
|
||||
|
||||
/// If we have a valid network class in this routing domain, then our 'NodeInfo' is valid
|
||||
/// If this is true, we can get our final peer info, otherwise we only have a 'best effort' peer info
|
||||
pub fn has_valid_own_node_info(&self, routing_domain: RoutingDomain) -> bool {
|
||||
self.inner.read().has_valid_own_node_info(routing_domain)
|
||||
pub fn has_valid_network_class(&self, routing_domain: RoutingDomain) -> bool {
|
||||
self.inner.read().has_valid_network_class(routing_domain)
|
||||
}
|
||||
|
||||
/// Return our current node info timestamp
|
||||
pub fn get_own_node_info_ts(&self, routing_domain: RoutingDomain) -> Option<Timestamp> {
|
||||
pub fn get_own_node_info_ts(&self, routing_domain: RoutingDomain) -> Timestamp {
|
||||
self.inner.read().get_own_node_info_ts(routing_domain)
|
||||
}
|
||||
|
||||
|
||||
@@ -309,7 +309,7 @@ pub trait NodeRefBase: Sized {
|
||||
}
|
||||
|
||||
fn clear_last_connection(&self, connection_descriptor: ConnectionDescriptor) {
|
||||
self.operate_mut(|rti, e| {
|
||||
self.operate_mut(|_rti, e| {
|
||||
e.clear_last_connection(connection_descriptor);
|
||||
})
|
||||
}
|
||||
|
||||
@@ -186,12 +186,16 @@ impl RouteSpecStore {
|
||||
if hop_count > self.unlocked_inner.max_route_hop_count {
|
||||
bail!("Not allocating route longer than max route hop count");
|
||||
}
|
||||
|
||||
let Some(our_peer_info) = rti.get_own_peer_info(RoutingDomain::PublicInternet) else {
|
||||
log_rtab!(debug "unable to allocate route until we have our own peer info");
|
||||
|
||||
// Ensure we have a valid network class so our peer info is useful
|
||||
if !rti.has_valid_network_class(RoutingDomain::PublicInternet) {
|
||||
log_rtab!(debug "unable to allocate route until we have a valid PublicInternet network class");
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
// Get our peer info
|
||||
let our_peer_info = rti.get_own_peer_info(RoutingDomain::PublicInternet);
|
||||
|
||||
// Get relay node if we have one
|
||||
let opt_own_relay_nr = rti.relay_node(RoutingDomain::PublicInternet).map(|nr| nr.locked(rti));
|
||||
|
||||
@@ -1176,20 +1180,20 @@ impl RouteSpecStore {
|
||||
bail!("crypto not supported for route");
|
||||
};
|
||||
|
||||
// Ensure our network class is valid before attempting to assemble any routes
|
||||
if !rti.has_valid_network_class(RoutingDomain::PublicInternet) {
|
||||
bail!("can't make private routes until our node info is valid");
|
||||
}
|
||||
|
||||
// Make innermost route hop to our own node
|
||||
let mut route_hop = RouteHop {
|
||||
node: if optimized {
|
||||
if !rti.has_valid_own_node_info(RoutingDomain::PublicInternet) {
|
||||
bail!("can't make private routes until our node info is valid");
|
||||
}
|
||||
let Some(node_id) = routing_table.node_ids().get(rsd.crypto_kind) else {
|
||||
bail!("missing node id for crypto kind");
|
||||
};
|
||||
RouteNode::NodeId(node_id.value)
|
||||
} else {
|
||||
let Some(pi) = rti.get_own_peer_info(RoutingDomain::PublicInternet) else {
|
||||
bail!("can't make private routes until our node info is valid");
|
||||
};
|
||||
let pi = rti.get_own_peer_info(RoutingDomain::PublicInternet);
|
||||
RouteNode::PeerInfo(pi)
|
||||
},
|
||||
next_hop: None,
|
||||
@@ -1377,15 +1381,7 @@ impl RouteSpecStore {
|
||||
let cur_ts = get_aligned_timestamp();
|
||||
if let Some(rpri) = inner.cache.peek_remote_private_route_mut(cur_ts, &rrid)
|
||||
{
|
||||
let our_node_info_ts = {
|
||||
let rti = &*self.unlocked_inner.routing_table.inner.read();
|
||||
let Some(ts) = rti.get_own_node_info_ts(RoutingDomain::PublicInternet) else {
|
||||
// Node info is invalid, skip this
|
||||
return false;
|
||||
};
|
||||
ts
|
||||
};
|
||||
|
||||
let our_node_info_ts = self.unlocked_inner.routing_table.get_own_node_info_ts(RoutingDomain::PublicInternet);
|
||||
return rpri.has_seen_our_node_info_ts(our_node_info_ts);
|
||||
}
|
||||
}
|
||||
@@ -1404,14 +1400,7 @@ impl RouteSpecStore {
|
||||
key: &PublicKey,
|
||||
cur_ts: Timestamp,
|
||||
) -> EyreResult<()> {
|
||||
let our_node_info_ts = {
|
||||
let rti = &*self.unlocked_inner.routing_table.inner.read();
|
||||
let Some(ts) = rti.get_own_node_info_ts(RoutingDomain::PublicInternet) else {
|
||||
// Node info is invalid, skipping this
|
||||
return Ok(());
|
||||
};
|
||||
ts
|
||||
};
|
||||
let our_node_info_ts = self.unlocked_inner.routing_table.get_own_node_info_ts(RoutingDomain::PublicInternet);
|
||||
|
||||
let inner = &mut *self.inner.lock();
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ impl RoutingDomainDetailCommon {
|
||||
self.clear_cache();
|
||||
}
|
||||
|
||||
pub fn has_valid_own_node_info(&self) -> bool {
|
||||
pub fn has_valid_network_class(&self) -> bool {
|
||||
self.network_class.unwrap_or(NetworkClass::Invalid) != NetworkClass::Invalid
|
||||
}
|
||||
|
||||
|
||||
@@ -180,10 +180,6 @@ impl RoutingTableInner {
|
||||
routing_domain: RoutingDomain,
|
||||
node_info: &NodeInfo,
|
||||
) -> bool {
|
||||
// Should not be passing around nodeinfo with an invalid network class
|
||||
if matches!(node_info.network_class(), NetworkClass::Invalid) {
|
||||
return false;
|
||||
}
|
||||
// Ensure all of the dial info works in this routing domain
|
||||
for did in node_info.dial_info_detail_list() {
|
||||
if !self.ensure_dial_info_is_valid(routing_domain, &did.dial_info) {
|
||||
@@ -204,6 +200,14 @@ impl RoutingTableInner {
|
||||
}
|
||||
// Ensure the relay is also valid in this routing domain if it is provided
|
||||
if let Some(relay_ni) = signed_node_info.relay_info() {
|
||||
// If there is a relay, the relay should have inbound capable network class and the node's network class should be valid
|
||||
if relay_ni.network_class() != NetworkClass::InboundCapable {
|
||||
return false;
|
||||
}
|
||||
if signed_node_info.node_info().network_class() == NetworkClass::Invalid {
|
||||
return false;
|
||||
}
|
||||
|
||||
if !self.node_info_is_valid_in_routing_domain(routing_domain, relay_ni) {
|
||||
return false;
|
||||
}
|
||||
@@ -238,42 +242,23 @@ impl RoutingTableInner {
|
||||
});
|
||||
}
|
||||
|
||||
/// Return if our node info is valid yet, which is only true if we have a valid network class
|
||||
pub fn has_valid_own_node_info(&self, routing_domain: RoutingDomain) -> bool {
|
||||
self.with_routing_domain(routing_domain, |rdd| rdd.common().has_valid_own_node_info())
|
||||
/// Return if this routing domain has a valid network class
|
||||
pub fn has_valid_network_class(&self, routing_domain: RoutingDomain) -> bool {
|
||||
self.with_routing_domain(routing_domain, |rdd| rdd.common().has_valid_network_class())
|
||||
}
|
||||
|
||||
/// Return a copy of our node's peerinfo
|
||||
pub fn get_own_peer_info(&self, routing_domain: RoutingDomain) -> Option<PeerInfo> {
|
||||
self.with_routing_domain(routing_domain, |rdd| {
|
||||
if !rdd.common().has_valid_own_node_info() {
|
||||
None
|
||||
} else {
|
||||
Some(rdd.common().with_peer_info(self, |pi| pi.clone()))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Return the best effort copy of our node's peerinfo
|
||||
/// This may be invalid and should not be passed to other nodes,
|
||||
/// but may be used for contact method calculation
|
||||
pub fn get_best_effort_own_peer_info(&self, routing_domain: RoutingDomain) -> PeerInfo {
|
||||
pub fn get_own_peer_info(&self, routing_domain: RoutingDomain) -> PeerInfo {
|
||||
self.with_routing_domain(routing_domain, |rdd| {
|
||||
rdd.common().with_peer_info(self, |pi| pi.clone())
|
||||
})
|
||||
}
|
||||
|
||||
/// Return our current node info timestamp
|
||||
pub fn get_own_node_info_ts(&self, routing_domain: RoutingDomain) -> Option<Timestamp> {
|
||||
pub fn get_own_node_info_ts(&self, routing_domain: RoutingDomain) -> Timestamp {
|
||||
self.with_routing_domain(routing_domain, |rdd| {
|
||||
if !rdd.common().has_valid_own_node_info() {
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
rdd.common()
|
||||
.with_peer_info(self, |pi| pi.signed_node_info().timestamp()),
|
||||
)
|
||||
}
|
||||
rdd.common()
|
||||
.with_peer_info(self, |pi| pi.signed_node_info().timestamp())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -557,19 +542,17 @@ impl RoutingTableInner {
|
||||
let mut node_refs = Vec::<NodeRef>::with_capacity(self.bucket_entry_count());
|
||||
self.with_entries(cur_ts, BucketEntryState::Unreliable, |rti, entry| {
|
||||
if entry.with_inner(|e| {
|
||||
// If this isn't in the routing domain we are checking, don't include it
|
||||
// If this entry isn't in the routing domain we are checking, don't include it
|
||||
if !e.exists_in_routing_domain(rti, routing_domain) {
|
||||
return false;
|
||||
}
|
||||
// If we need a ping then do it
|
||||
// If this entry needs need a ping then do it
|
||||
if e.needs_ping(cur_ts) {
|
||||
return true;
|
||||
}
|
||||
// If we need a ping because this node hasn't seen our latest node info, then do it
|
||||
if let Some(own_node_info_ts) = own_node_info_ts {
|
||||
if !e.has_seen_our_node_info_ts(routing_domain, own_node_info_ts) {
|
||||
return true;
|
||||
}
|
||||
// If this entry needs a ping because this node hasn't seen our latest node info, then do it
|
||||
if !e.has_seen_our_node_info_ts(routing_domain, own_node_info_ts) {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}) {
|
||||
|
||||
@@ -169,24 +169,11 @@ impl RoutingTable {
|
||||
_last_ts: Timestamp,
|
||||
cur_ts: Timestamp,
|
||||
) -> EyreResult<()> {
|
||||
// Get our node's current node info and network class and do the right thing
|
||||
let network_class = self
|
||||
.get_network_class(RoutingDomain::PublicInternet)
|
||||
.unwrap_or(NetworkClass::Invalid);
|
||||
|
||||
// If we don't know our network class then don't do this yet
|
||||
if network_class == NetworkClass::Invalid {
|
||||
if !self.has_valid_network_class(RoutingDomain::PublicInternet) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// If we don't have our own peer info then don't do this yet
|
||||
if self
|
||||
.get_own_peer_info(RoutingDomain::PublicInternet)
|
||||
.is_none()
|
||||
{
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
// Test locally allocated routes first
|
||||
// This may remove dead routes
|
||||
let routes_needing_testing = self.get_allocated_routes_to_test(cur_ts);
|
||||
|
||||
@@ -10,9 +10,10 @@ impl RoutingTable {
|
||||
cur_ts: Timestamp,
|
||||
) -> EyreResult<()> {
|
||||
// Get our node's current node info and network class and do the right thing
|
||||
let Some(own_peer_info) = self.get_own_peer_info(RoutingDomain::PublicInternet) else {
|
||||
if !self.has_valid_network_class(RoutingDomain::PublicInternet) {
|
||||
return Ok(());
|
||||
};
|
||||
}
|
||||
let own_peer_info = self.get_own_peer_info(RoutingDomain::PublicInternet);
|
||||
let own_node_info = own_peer_info.signed_node_info().node_info();
|
||||
let network_class = own_node_info.network_class();
|
||||
let relay_node_filter = self.make_public_internet_relay_node_filter();
|
||||
|
||||
Reference in New Issue
Block a user