allow revert to invalid nodeinfo
This commit is contained in:
parent
167374969d
commit
e61d6be6a9
@ -110,7 +110,7 @@ pub(crate) enum NodeContactMethod {
|
|||||||
}
|
}
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
|
||||||
struct NodeContactMethodCacheKey {
|
struct NodeContactMethodCacheKey {
|
||||||
own_node_info_ts: Option<Timestamp>,
|
own_node_info_ts: Timestamp,
|
||||||
target_node_info_ts: Timestamp,
|
target_node_info_ts: Timestamp,
|
||||||
target_node_ref_filter: Option<NodeRefFilter>,
|
target_node_ref_filter: Option<NodeRefFilter>,
|
||||||
target_node_ref_sequencing: Sequencing,
|
target_node_ref_sequencing: Sequencing,
|
||||||
|
@ -329,7 +329,7 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// Node A is our own node
|
// Node A is our own node
|
||||||
// Use whatever node info we've calculated so far
|
// Use whatever node info we've calculated so far
|
||||||
let peer_a = routing_table.get_best_effort_own_peer_info(routing_domain);
|
let peer_a = routing_table.get_own_peer_info(routing_domain);
|
||||||
|
|
||||||
// Node B is the target node
|
// Node B is the target node
|
||||||
let peer_b = match target_node_ref.make_peer_info(routing_domain) {
|
let peer_b = match target_node_ref.make_peer_info(routing_domain) {
|
||||||
@ -466,15 +466,18 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// Get target routing domain
|
// Get target routing domain
|
||||||
let Some(routing_domain) = target_nr.best_routing_domain() else {
|
let Some(routing_domain) = target_nr.best_routing_domain() else {
|
||||||
return Ok(NetworkResult::no_connection_other("No routing domain for target"));
|
return Ok(NetworkResult::no_connection_other("No routing domain for target for reverse connect"));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Ensure we have a valid network class so our peer info is useful
|
||||||
|
if !self.routing_table().has_valid_network_class(routing_domain){
|
||||||
|
return Ok(NetworkResult::no_connection_other("Network class not yet valid for reverse connect"));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get our peer info
|
// Get our peer info
|
||||||
let Some(peer_info) = self
|
let peer_info = self
|
||||||
.routing_table()
|
.routing_table()
|
||||||
.get_own_peer_info(routing_domain) else {
|
.get_own_peer_info(routing_domain);
|
||||||
return Ok(NetworkResult::no_connection_other("Own peer info not available"));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Issue the signal
|
// Issue the signal
|
||||||
let rpc = self.rpc_processor();
|
let rpc = self.rpc_processor();
|
||||||
@ -562,15 +565,18 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// Get target routing domain
|
// Get target routing domain
|
||||||
let Some(routing_domain) = target_nr.best_routing_domain() else {
|
let Some(routing_domain) = target_nr.best_routing_domain() else {
|
||||||
return Ok(NetworkResult::no_connection_other("No routing domain for target"));
|
return Ok(NetworkResult::no_connection_other("No routing domain for target for hole punch"));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Ensure we have a valid network class so our peer info is useful
|
||||||
|
if !self.routing_table().has_valid_network_class(routing_domain){
|
||||||
|
return Ok(NetworkResult::no_connection_other("Network class not yet valid for hole punch"));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get our peer info
|
// Get our peer info
|
||||||
let Some(peer_info) = self
|
let peer_info = self
|
||||||
.routing_table()
|
.routing_table()
|
||||||
.get_own_peer_info(routing_domain) else {
|
.get_own_peer_info(routing_domain);
|
||||||
return Ok(NetworkResult::no_connection_other("Own peer info not available"));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get the udp direct dialinfo for the hole punch
|
// Get the udp direct dialinfo for the hole punch
|
||||||
let hole_punch_did = target_nr
|
let hole_punch_did = target_nr
|
||||||
|
@ -7,12 +7,15 @@ impl RoutingTable {
|
|||||||
key: TypedKey,
|
key: TypedKey,
|
||||||
capabilities: &[Capability],
|
capabilities: &[Capability],
|
||||||
) -> NetworkResult<Vec<PeerInfo>> {
|
) -> 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.
|
// 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
|
// 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(
|
let filter = Box::new(
|
||||||
move |rti: &RoutingTableInner, opt_entry: Option<Arc<BucketEntry>>| {
|
move |rti: &RoutingTableInner, opt_entry: Option<Arc<BucketEntry>>| {
|
||||||
// Ensure only things that are valid/signed in the PublicInternet domain are returned
|
// 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| {
|
Some(entry) => entry.with(rti, |_rti, e| {
|
||||||
e.has_capabilities(RoutingDomain::PublicInternet, capabilities)
|
e.has_capabilities(RoutingDomain::PublicInternet, capabilities)
|
||||||
}),
|
}),
|
||||||
None => rti
|
None => own_peer_info
|
||||||
.get_own_peer_info(RoutingDomain::PublicInternet)
|
.signed_node_info()
|
||||||
.map(|pi| {
|
|
||||||
pi.signed_node_info()
|
|
||||||
.node_info()
|
.node_info()
|
||||||
.has_capabilities(capabilities)
|
.has_capabilities(capabilities),
|
||||||
})
|
|
||||||
.unwrap_or(false),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
) as RoutingTableEntryFilter;
|
) as RoutingTableEntryFilter;
|
||||||
@ -46,6 +45,7 @@ impl RoutingTable {
|
|||||||
c.network.dht.max_find_node_count as usize
|
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(
|
let closest_nodes = self.find_closest_nodes(
|
||||||
node_count,
|
node_count,
|
||||||
key,
|
key,
|
||||||
|
@ -549,27 +549,18 @@ impl RoutingTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return a copy of our node's peerinfo
|
/// 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)
|
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 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
|
/// 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 {
|
pub fn has_valid_network_class(&self, routing_domain: RoutingDomain) -> bool {
|
||||||
self.inner.read().has_valid_own_node_info(routing_domain)
|
self.inner.read().has_valid_network_class(routing_domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return our current node info timestamp
|
/// 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)
|
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) {
|
fn clear_last_connection(&self, connection_descriptor: ConnectionDescriptor) {
|
||||||
self.operate_mut(|rti, e| {
|
self.operate_mut(|_rti, e| {
|
||||||
e.clear_last_connection(connection_descriptor);
|
e.clear_last_connection(connection_descriptor);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -187,11 +187,15 @@ impl RouteSpecStore {
|
|||||||
bail!("Not allocating route longer than 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 {
|
// Ensure we have a valid network class so our peer info is useful
|
||||||
log_rtab!(debug "unable to allocate route until we have our own peer info");
|
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);
|
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
|
// Get relay node if we have one
|
||||||
let opt_own_relay_nr = rti.relay_node(RoutingDomain::PublicInternet).map(|nr| nr.locked(rti));
|
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");
|
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
|
// Make innermost route hop to our own node
|
||||||
let mut route_hop = RouteHop {
|
let mut route_hop = RouteHop {
|
||||||
node: if optimized {
|
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 {
|
let Some(node_id) = routing_table.node_ids().get(rsd.crypto_kind) else {
|
||||||
bail!("missing node id for crypto kind");
|
bail!("missing node id for crypto kind");
|
||||||
};
|
};
|
||||||
RouteNode::NodeId(node_id.value)
|
RouteNode::NodeId(node_id.value)
|
||||||
} else {
|
} else {
|
||||||
let Some(pi) = rti.get_own_peer_info(RoutingDomain::PublicInternet) else {
|
let pi = rti.get_own_peer_info(RoutingDomain::PublicInternet);
|
||||||
bail!("can't make private routes until our node info is valid");
|
|
||||||
};
|
|
||||||
RouteNode::PeerInfo(pi)
|
RouteNode::PeerInfo(pi)
|
||||||
},
|
},
|
||||||
next_hop: None,
|
next_hop: None,
|
||||||
@ -1377,15 +1381,7 @@ impl RouteSpecStore {
|
|||||||
let cur_ts = get_aligned_timestamp();
|
let cur_ts = get_aligned_timestamp();
|
||||||
if let Some(rpri) = inner.cache.peek_remote_private_route_mut(cur_ts, &rrid)
|
if let Some(rpri) = inner.cache.peek_remote_private_route_mut(cur_ts, &rrid)
|
||||||
{
|
{
|
||||||
let our_node_info_ts = {
|
let our_node_info_ts = self.unlocked_inner.routing_table.get_own_node_info_ts(RoutingDomain::PublicInternet);
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
return rpri.has_seen_our_node_info_ts(our_node_info_ts);
|
return rpri.has_seen_our_node_info_ts(our_node_info_ts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1404,14 +1400,7 @@ impl RouteSpecStore {
|
|||||||
key: &PublicKey,
|
key: &PublicKey,
|
||||||
cur_ts: Timestamp,
|
cur_ts: Timestamp,
|
||||||
) -> EyreResult<()> {
|
) -> EyreResult<()> {
|
||||||
let our_node_info_ts = {
|
let our_node_info_ts = self.unlocked_inner.routing_table.get_own_node_info_ts(RoutingDomain::PublicInternet);
|
||||||
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 inner = &mut *self.inner.lock();
|
let inner = &mut *self.inner.lock();
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ impl RoutingDomainDetailCommon {
|
|||||||
self.clear_cache();
|
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
|
self.network_class.unwrap_or(NetworkClass::Invalid) != NetworkClass::Invalid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,10 +180,6 @@ impl RoutingTableInner {
|
|||||||
routing_domain: RoutingDomain,
|
routing_domain: RoutingDomain,
|
||||||
node_info: &NodeInfo,
|
node_info: &NodeInfo,
|
||||||
) -> bool {
|
) -> 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
|
// Ensure all of the dial info works in this routing domain
|
||||||
for did in node_info.dial_info_detail_list() {
|
for did in node_info.dial_info_detail_list() {
|
||||||
if !self.ensure_dial_info_is_valid(routing_domain, &did.dial_info) {
|
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
|
// 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 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) {
|
if !self.node_info_is_valid_in_routing_domain(routing_domain, relay_ni) {
|
||||||
return false;
|
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
|
/// Return if this routing domain has a valid network class
|
||||||
pub fn has_valid_own_node_info(&self, routing_domain: RoutingDomain) -> bool {
|
pub fn has_valid_network_class(&self, routing_domain: RoutingDomain) -> bool {
|
||||||
self.with_routing_domain(routing_domain, |rdd| rdd.common().has_valid_own_node_info())
|
self.with_routing_domain(routing_domain, |rdd| rdd.common().has_valid_network_class())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a copy of our node's peerinfo
|
/// 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.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 {
|
|
||||||
self.with_routing_domain(routing_domain, |rdd| {
|
self.with_routing_domain(routing_domain, |rdd| {
|
||||||
rdd.common().with_peer_info(self, |pi| pi.clone())
|
rdd.common().with_peer_info(self, |pi| pi.clone())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return our current node info timestamp
|
/// 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| {
|
self.with_routing_domain(routing_domain, |rdd| {
|
||||||
if !rdd.common().has_valid_own_node_info() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(
|
|
||||||
rdd.common()
|
rdd.common()
|
||||||
.with_peer_info(self, |pi| pi.signed_node_info().timestamp()),
|
.with_peer_info(self, |pi| pi.signed_node_info().timestamp())
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -557,20 +542,18 @@ impl RoutingTableInner {
|
|||||||
let mut node_refs = Vec::<NodeRef>::with_capacity(self.bucket_entry_count());
|
let mut node_refs = Vec::<NodeRef>::with_capacity(self.bucket_entry_count());
|
||||||
self.with_entries(cur_ts, BucketEntryState::Unreliable, |rti, entry| {
|
self.with_entries(cur_ts, BucketEntryState::Unreliable, |rti, entry| {
|
||||||
if entry.with_inner(|e| {
|
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) {
|
if !e.exists_in_routing_domain(rti, routing_domain) {
|
||||||
return false;
|
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) {
|
if e.needs_ping(cur_ts) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// If we need a ping because this node hasn't seen our latest node info, then do it
|
// If this entry needs 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) {
|
if !e.has_seen_our_node_info_ts(routing_domain, own_node_info_ts) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
false
|
false
|
||||||
}) {
|
}) {
|
||||||
node_refs.push(NodeRef::new(
|
node_refs.push(NodeRef::new(
|
||||||
|
@ -169,24 +169,11 @@ impl RoutingTable {
|
|||||||
_last_ts: Timestamp,
|
_last_ts: Timestamp,
|
||||||
cur_ts: Timestamp,
|
cur_ts: Timestamp,
|
||||||
) -> EyreResult<()> {
|
) -> 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 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(());
|
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
|
// Test locally allocated routes first
|
||||||
// This may remove dead routes
|
// This may remove dead routes
|
||||||
let routes_needing_testing = self.get_allocated_routes_to_test(cur_ts);
|
let routes_needing_testing = self.get_allocated_routes_to_test(cur_ts);
|
||||||
|
@ -10,9 +10,10 @@ impl RoutingTable {
|
|||||||
cur_ts: Timestamp,
|
cur_ts: Timestamp,
|
||||||
) -> EyreResult<()> {
|
) -> EyreResult<()> {
|
||||||
// Get our node's current node info and network class and do the right thing
|
// 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(());
|
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 own_node_info = own_peer_info.signed_node_info().node_info();
|
||||||
let network_class = own_node_info.network_class();
|
let network_class = own_node_info.network_class();
|
||||||
let relay_node_filter = self.make_public_internet_relay_node_filter();
|
let relay_node_filter = self.make_public_internet_relay_node_filter();
|
||||||
|
@ -31,9 +31,19 @@ pub enum Destination {
|
|||||||
impl Destination {
|
impl Destination {
|
||||||
pub fn target(&self) -> Option<NodeRef> {
|
pub fn target(&self) -> Option<NodeRef> {
|
||||||
match self {
|
match self {
|
||||||
Destination::Direct { target, safety_selection: _ } => Some(target.clone()),
|
Destination::Direct {
|
||||||
Destination::Relay { relay:_, target, safety_selection: _ } => Some(target.clone()),
|
target,
|
||||||
Destination::PrivateRoute { private_route:_, safety_selection:_ } => None,
|
safety_selection: _,
|
||||||
|
} => Some(target.clone()),
|
||||||
|
Destination::Relay {
|
||||||
|
relay: _,
|
||||||
|
target,
|
||||||
|
safety_selection: _,
|
||||||
|
} => Some(target.clone()),
|
||||||
|
Destination::PrivateRoute {
|
||||||
|
private_route: _,
|
||||||
|
safety_selection: _,
|
||||||
|
} => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn direct(target: NodeRef) -> Self {
|
pub fn direct(target: NodeRef) -> Self {
|
||||||
@ -217,7 +227,6 @@ impl RPCProcessor {
|
|||||||
private_route,
|
private_route,
|
||||||
safety_selection,
|
safety_selection,
|
||||||
} => {
|
} => {
|
||||||
|
|
||||||
let Some(avoid_node_id) = private_route.first_hop_node_id() else {
|
let Some(avoid_node_id) = private_route.first_hop_node_id() else {
|
||||||
return Err(RPCError::internal("destination private route must have first hop"));
|
return Err(RPCError::internal("destination private route must have first hop"));
|
||||||
};
|
};
|
||||||
@ -227,20 +236,20 @@ impl RPCProcessor {
|
|||||||
match safety_selection {
|
match safety_selection {
|
||||||
SafetySelection::Unsafe(_) => {
|
SafetySelection::Unsafe(_) => {
|
||||||
// Sent to a private route with no safety route, use a stub safety route for the response
|
// Sent to a private route with no safety route, use a stub safety route for the response
|
||||||
|
if !routing_table.has_valid_network_class(RoutingDomain::PublicInternet) {
|
||||||
|
return Ok(NetworkResult::no_connection_other(
|
||||||
|
"Own node info must be valid to use private route",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// Determine if we can use optimized nodeinfo
|
// Determine if we can use optimized nodeinfo
|
||||||
let route_node = if rss
|
let route_node = if rss.has_remote_private_route_seen_our_node_info(
|
||||||
.has_remote_private_route_seen_our_node_info(&private_route.public_key.value)
|
&private_route.public_key.value,
|
||||||
{
|
) {
|
||||||
if !routing_table.has_valid_own_node_info(RoutingDomain::PublicInternet) {
|
|
||||||
return Ok(NetworkResult::no_connection_other("Own node info must be valid to use private route"));
|
|
||||||
}
|
|
||||||
RouteNode::NodeId(routing_table.node_id(crypto_kind).value)
|
RouteNode::NodeId(routing_table.node_id(crypto_kind).value)
|
||||||
} else {
|
} else {
|
||||||
let Some(own_peer_info) =
|
let own_peer_info =
|
||||||
routing_table.get_own_peer_info(RoutingDomain::PublicInternet) else {
|
routing_table.get_own_peer_info(RoutingDomain::PublicInternet);
|
||||||
return Ok(NetworkResult::no_connection_other("Own peer info must be valid to use private route"));
|
|
||||||
};
|
|
||||||
RouteNode::PeerInfo(own_peer_info)
|
RouteNode::PeerInfo(own_peer_info)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -252,8 +261,10 @@ impl RPCProcessor {
|
|||||||
// Sent to a private route via a safety route, respond to private route
|
// Sent to a private route via a safety route, respond to private route
|
||||||
|
|
||||||
// Check for loopback test
|
// Check for loopback test
|
||||||
let opt_private_route_id = rss.get_route_id_for_key(&private_route.public_key.value);
|
let opt_private_route_id =
|
||||||
let pr_key = if opt_private_route_id.is_some() && safety_spec.preferred_route == opt_private_route_id
|
rss.get_route_id_for_key(&private_route.public_key.value);
|
||||||
|
let pr_key = if opt_private_route_id.is_some()
|
||||||
|
&& safety_spec.preferred_route == opt_private_route_id
|
||||||
{
|
{
|
||||||
// Private route is also safety route during loopback test
|
// Private route is also safety route during loopback test
|
||||||
private_route.public_key.value
|
private_route.public_key.value
|
||||||
@ -308,7 +319,10 @@ impl RPCProcessor {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Reply directly to the request's source
|
// Reply directly to the request's source
|
||||||
let sender_node_id = TypedKey::new(detail.envelope.get_crypto_kind(), detail.envelope.get_sender_id());
|
let sender_node_id = TypedKey::new(
|
||||||
|
detail.envelope.get_crypto_kind(),
|
||||||
|
detail.envelope.get_sender_id(),
|
||||||
|
);
|
||||||
|
|
||||||
// This may be a different node's reference than the 'sender' in the case of a relay
|
// This may be a different node's reference than the 'sender' in the case of a relay
|
||||||
let peer_noderef = detail.peer_noderef.clone();
|
let peer_noderef = detail.peer_noderef.clone();
|
||||||
@ -321,9 +335,13 @@ impl RPCProcessor {
|
|||||||
// Look up the sender node, we should have added it via senderNodeInfo before getting here.
|
// Look up the sender node, we should have added it via senderNodeInfo before getting here.
|
||||||
let res = match self.routing_table.lookup_node_ref(sender_node_id) {
|
let res = match self.routing_table.lookup_node_ref(sender_node_id) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => return NetworkResult::invalid_message(
|
Err(e) => {
|
||||||
format!("failed to look up node info for respond to: {}", e)
|
return NetworkResult::invalid_message(format!(
|
||||||
)};
|
"failed to look up node info for respond to: {}",
|
||||||
|
e
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
if let Some(sender_noderef) = res {
|
if let Some(sender_noderef) = res {
|
||||||
NetworkResult::value(Destination::relay(peer_noderef, sender_noderef))
|
NetworkResult::value(Destination::relay(peer_noderef, sender_noderef))
|
||||||
} else {
|
} else {
|
||||||
@ -331,7 +349,6 @@ impl RPCProcessor {
|
|||||||
"not responding to sender that has no node info",
|
"not responding to sender that has no node info",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RespondTo::PrivateRoute(pr) => {
|
RespondTo::PrivateRoute(pr) => {
|
||||||
|
@ -888,10 +888,9 @@ impl RPCProcessor {
|
|||||||
// Get the target's node info timestamp
|
// Get the target's node info timestamp
|
||||||
let target_node_info_ts = target.node_info_ts(routing_domain);
|
let target_node_info_ts = target.node_info_ts(routing_domain);
|
||||||
|
|
||||||
// Don't return our node info if it's not valid yet
|
// Return whatever peer info we have even if the network class is not yet valid
|
||||||
let Some(own_peer_info) = routing_table.get_own_peer_info(routing_domain) else {
|
// That away we overwrite any prior existing valid-network-class nodeinfo in the remote routing table
|
||||||
return SenderPeerInfo::new_no_peer_info(target_node_info_ts);
|
let own_peer_info = routing_table.get_own_peer_info(routing_domain);
|
||||||
};
|
|
||||||
|
|
||||||
// Get our node info timestamp
|
// Get our node info timestamp
|
||||||
let our_node_info_ts = own_peer_info.signed_node_info().timestamp();
|
let our_node_info_ts = own_peer_info.signed_node_info().timestamp();
|
||||||
@ -1475,6 +1474,12 @@ impl RPCProcessor {
|
|||||||
let mut opt_sender_nr: Option<NodeRef> = None;
|
let mut opt_sender_nr: Option<NodeRef> = None;
|
||||||
if let Some(sender_peer_info) = operation.sender_peer_info() {
|
if let Some(sender_peer_info) = operation.sender_peer_info() {
|
||||||
// Ensure the sender peer info is for the actual sender specified in the envelope
|
// Ensure the sender peer info is for the actual sender specified in the envelope
|
||||||
|
if !sender_peer_info.node_ids().contains(&sender_node_id) {
|
||||||
|
// Attempted to update peer info for the wrong node id
|
||||||
|
return Ok(NetworkResult::invalid_message(
|
||||||
|
"attempt to update peer info for non-sender node id",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// Sender PeerInfo was specified, update our routing table with it
|
// Sender PeerInfo was specified, update our routing table with it
|
||||||
if !self.verify_node_info(
|
if !self.verify_node_info(
|
||||||
|
@ -55,8 +55,8 @@ impl RPCProcessor {
|
|||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
// Ignore if disabled
|
// Ignore if disabled
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
{
|
|
||||||
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
let opi = routing_table.get_own_peer_info(msg.header.routing_domain());
|
||||||
if !opi
|
if !opi
|
||||||
.signed_node_info()
|
.signed_node_info()
|
||||||
.node_info()
|
.node_info()
|
||||||
@ -66,8 +66,6 @@ impl RPCProcessor {
|
|||||||
"app call is not available",
|
"app call is not available",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the question
|
// Get the question
|
||||||
let (op_id, _, _, kind) = msg.operation.clone().destructure();
|
let (op_id, _, _, kind) = msg.operation.clone().destructure();
|
||||||
|
@ -26,8 +26,7 @@ impl RPCProcessor {
|
|||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
// Ignore if disabled
|
// Ignore if disabled
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
{
|
let opi = routing_table.get_own_peer_info(msg.header.routing_domain());
|
||||||
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
|
||||||
if !opi
|
if !opi
|
||||||
.signed_node_info()
|
.signed_node_info()
|
||||||
.node_info()
|
.node_info()
|
||||||
@ -37,8 +36,6 @@ impl RPCProcessor {
|
|||||||
"app message is not available",
|
"app message is not available",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the statement
|
// Get the statement
|
||||||
let (_, _, _, kind) = msg.operation.destructure();
|
let (_, _, _, kind) = msg.operation.destructure();
|
||||||
|
@ -175,15 +175,17 @@ impl RPCProcessor {
|
|||||||
}
|
}
|
||||||
// Ignore if disabled
|
// Ignore if disabled
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
|
let opi = routing_table.get_own_peer_info(msg.header.routing_domain());
|
||||||
|
if !opi
|
||||||
|
.signed_node_info()
|
||||||
|
.node_info()
|
||||||
|
.has_capability(CAP_DHT)
|
||||||
{
|
{
|
||||||
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
|
||||||
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
|
|
||||||
return Ok(NetworkResult::service_unavailable(
|
return Ok(NetworkResult::service_unavailable(
|
||||||
"dht is not available",
|
"dht is not available",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
// Get the question
|
// Get the question
|
||||||
let kind = msg.operation.kind().clone();
|
let kind = msg.operation.kind().clone();
|
||||||
let get_value_q = match kind {
|
let get_value_q = match kind {
|
||||||
|
@ -367,15 +367,22 @@ impl RPCProcessor {
|
|||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
// Ignore if disabled
|
// Ignore if disabled
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
|
if !routing_table.has_valid_network_class(msg.header.routing_domain()) {
|
||||||
|
return Ok(NetworkResult::service_unavailable(
|
||||||
|
"can't route without valid network class",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let opi = routing_table.get_own_peer_info(msg.header.routing_domain());
|
||||||
|
if !opi
|
||||||
|
.signed_node_info()
|
||||||
|
.node_info()
|
||||||
|
.has_capability(CAP_ROUTE)
|
||||||
{
|
{
|
||||||
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
|
||||||
if !opi.signed_node_info().node_info().has_capability(CAP_ROUTE) {
|
|
||||||
return Ok(NetworkResult::service_unavailable(
|
return Ok(NetworkResult::service_unavailable(
|
||||||
"route is not available",
|
"route is not available",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get header detail, must be direct and not inside a route itself
|
// Get header detail, must be direct and not inside a route itself
|
||||||
let detail = match msg.header.detail {
|
let detail = match msg.header.detail {
|
||||||
|
@ -177,15 +177,17 @@ impl RPCProcessor {
|
|||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
// Ignore if disabled
|
// Ignore if disabled
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
|
let opi = routing_table.get_own_peer_info(msg.header.routing_domain());
|
||||||
|
if !opi
|
||||||
|
.signed_node_info()
|
||||||
|
.node_info()
|
||||||
|
.has_capability(CAP_DHT)
|
||||||
{
|
{
|
||||||
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
|
||||||
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
|
|
||||||
return Ok(NetworkResult::service_unavailable(
|
return Ok(NetworkResult::service_unavailable(
|
||||||
"dht is not available",
|
"dht is not available",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
// Ensure this never came over a private route, safety route is okay though
|
// Ensure this never came over a private route, safety route is okay though
|
||||||
match &msg.header.detail {
|
match &msg.header.detail {
|
||||||
RPCMessageHeaderDetail::Direct(_) | RPCMessageHeaderDetail::SafetyRouted(_) => {}
|
RPCMessageHeaderDetail::Direct(_) | RPCMessageHeaderDetail::SafetyRouted(_) => {}
|
||||||
|
@ -39,16 +39,16 @@ impl RPCProcessor {
|
|||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
// Ignore if disabled
|
// Ignore if disabled
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
|
let opi = routing_table.get_own_peer_info(msg.header.routing_domain());
|
||||||
|
if !opi
|
||||||
|
.signed_node_info()
|
||||||
|
.node_info()
|
||||||
|
.has_capability(CAP_SIGNAL)
|
||||||
{
|
{
|
||||||
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
|
||||||
let ni = opi.signed_node_info().node_info();
|
|
||||||
if !ni.has_capability(CAP_SIGNAL) {
|
|
||||||
return Ok(NetworkResult::service_unavailable(
|
return Ok(NetworkResult::service_unavailable(
|
||||||
"signal is not available",
|
"signal is not available",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can't allow anything other than direct packets here, as handling reverse connections
|
// Can't allow anything other than direct packets here, as handling reverse connections
|
||||||
// or anything like via signals over private routes would deanonymize the route
|
// or anything like via signals over private routes would deanonymize the route
|
||||||
|
@ -58,6 +58,14 @@ impl RPCProcessor {
|
|||||||
&self,
|
&self,
|
||||||
msg: RPCMessage,
|
msg: RPCMessage,
|
||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
|
let routing_table = self.routing_table();
|
||||||
|
if !routing_table.has_valid_network_class(msg.header.routing_domain()) {
|
||||||
|
return Ok(NetworkResult::service_unavailable(
|
||||||
|
"can't validate dial info without valid network class",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let opi = routing_table.get_own_peer_info(msg.header.routing_domain());
|
||||||
|
|
||||||
let detail = match msg.header.detail {
|
let detail = match msg.header.detail {
|
||||||
RPCMessageHeaderDetail::Direct(detail) => detail,
|
RPCMessageHeaderDetail::Direct(detail) => detail,
|
||||||
RPCMessageHeaderDetail::SafetyRouted(_) | RPCMessageHeaderDetail::PrivateRouted(_) => {
|
RPCMessageHeaderDetail::SafetyRouted(_) | RPCMessageHeaderDetail::PrivateRouted(_) => {
|
||||||
@ -68,17 +76,17 @@ impl RPCProcessor {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Ignore if disabled
|
// Ignore if disabled
|
||||||
let routing_table = self.routing_table();
|
|
||||||
{
|
|
||||||
if let Some(opi) = routing_table.get_own_peer_info(detail.routing_domain) {
|
|
||||||
let ni = opi.signed_node_info().node_info();
|
let ni = opi.signed_node_info().node_info();
|
||||||
if !ni.has_capability(CAP_VALIDATE_DIAL_INFO) || !ni.is_fully_direct_inbound() {
|
if !opi
|
||||||
|
.signed_node_info()
|
||||||
|
.node_info()
|
||||||
|
.has_capability(CAP_VALIDATE_DIAL_INFO)
|
||||||
|
|| !ni.is_fully_direct_inbound()
|
||||||
|
{
|
||||||
return Ok(NetworkResult::service_unavailable(
|
return Ok(NetworkResult::service_unavailable(
|
||||||
"validate dial info is not available",
|
"validate dial info is not available",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the statement
|
// Get the statement
|
||||||
let (_, _, _, kind) = msg.operation.destructure();
|
let (_, _, _, kind) = msg.operation.destructure();
|
||||||
|
@ -8,13 +8,10 @@ impl RPCProcessor {
|
|||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
// Ignore if disabled
|
// Ignore if disabled
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
{
|
let opi = routing_table.get_own_peer_info(msg.header.routing_domain());
|
||||||
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
|
||||||
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
|
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
|
||||||
return Ok(NetworkResult::service_unavailable("dht is not available"));
|
return Ok(NetworkResult::service_unavailable("dht is not available"));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(RPCError::unimplemented("process_value_changed"))
|
Err(RPCError::unimplemented("process_value_changed"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,13 +8,10 @@ impl RPCProcessor {
|
|||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
// Ignore if disabled
|
// Ignore if disabled
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
{
|
let opi = routing_table.get_own_peer_info(msg.header.routing_domain());
|
||||||
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
|
||||||
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
|
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
|
||||||
return Ok(NetworkResult::service_unavailable("dht is not available"));
|
return Ok(NetworkResult::service_unavailable("dht is not available"));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(RPCError::unimplemented("process_watch_value_q"))
|
Err(RPCError::unimplemented("process_watch_value_q"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user