diff --git a/veilid-core/src/routing_table/node_ref.rs b/veilid-core/src/routing_table/node_ref.rs index 296486bc..bf44ab99 100644 --- a/veilid-core/src/routing_table/node_ref.rs +++ b/veilid-core/src/routing_table/node_ref.rs @@ -556,6 +556,10 @@ impl<'a> NodeRefLockedMut<'a> { nr, } } + + pub fn unlocked(&self) -> NodeRef { + self.nr.clone() + } } impl<'a> NodeRefBase for NodeRefLockedMut<'a> { diff --git a/veilid-core/src/routing_table/route_spec_store/route_set_spec_detail.rs b/veilid-core/src/routing_table/route_spec_store/route_set_spec_detail.rs index 89449149..9a95e4af 100644 --- a/veilid-core/src/routing_table/route_spec_store/route_set_spec_detail.rs +++ b/veilid-core/src/routing_table/route_spec_store/route_set_spec_detail.rs @@ -124,11 +124,11 @@ impl RouteSetSpecDetail { } /// Generate a key for the cache that can be used to uniquely identify this route's contents - pub fn make_cache_key(&self) -> Vec { + pub fn make_cache_key(&self, rti: &RoutingTableInner) -> Vec { let hops = &self.hop_node_refs; let mut cache: Vec = Vec::with_capacity(hops.len() * PUBLIC_KEY_LENGTH); for hop in hops { - cache.extend_from_slice(&hop.best_node_id().value.bytes); + cache.extend_from_slice(&hop.locked(rti).best_node_id().value.bytes); } cache } diff --git a/veilid-core/src/routing_table/route_spec_store/route_spec_store.rs b/veilid-core/src/routing_table/route_spec_store/route_spec_store.rs index e6ca0fc5..7f5d79ae 100644 --- a/veilid-core/src/routing_table/route_spec_store/route_spec_store.rs +++ b/veilid-core/src/routing_table/route_spec_store/route_spec_store.rs @@ -72,8 +72,9 @@ impl RouteSpecStore { }; // Rebuild the routespecstore cache + let rti = &*routing_table.inner.read(); for (_, rssd) in inner.content.iter_details() { - inner.cache.add_to_cache(&rssd); + inner.cache.add_to_cache(rti, &rssd); } // Return the loaded RouteSpecStore @@ -81,7 +82,7 @@ impl RouteSpecStore { unlocked_inner: Arc::new(RouteSpecStoreUnlockedInner { max_route_hop_count, default_route_hop_count, - routing_table, + routing_table: routing_table.clone(), }), inner: Arc::new(Mutex::new(inner)), }; @@ -338,8 +339,8 @@ impl RouteSpecStore { }; // Pull the whole routing table in sorted order - let nodes:Vec = - rti.find_peers_with_sort_and_filter(usize::MAX, cur_ts, filters, compare, transform).iter().map(|n| n.locked(rti)).collect(); + let nodes:Vec = + rti.find_peers_with_sort_and_filter(usize::MAX, cur_ts, filters, compare, transform); // If we couldn't find enough nodes, wait until we have more nodes in the routing table if nodes.len() < hop_count { @@ -348,20 +349,20 @@ impl RouteSpecStore { } // Get peer info for everything - let nodes_pi: Vec = nodes.iter().map(|nr| nr.make_peer_info(RoutingDomain::PublicInternet).unwrap()).collect(); + let nodes_pi: Vec = nodes.iter().map(|nr| nr.locked(rti).make_peer_info(RoutingDomain::PublicInternet).unwrap()).collect(); // Now go through nodes and try to build a route we haven't seen yet let mut perm_func = Box::new(|permutation: &[usize]| { - /// Get the hop cache key for a particular route permutation - /// uses the same algorithm as RouteSetSpecDetail::make_cache_key - fn route_permutation_to_hop_cache(_rti: &RoutingTableInner, nodes: &[NodeRefLocked], perm: &[usize]) -> Vec { + // Get the hop cache key for a particular route permutation + // uses the same algorithm as RouteSetSpecDetail::make_cache_key + let route_permutation_to_hop_cache = |_rti: &RoutingTableInner, nodes: &[NodeRef], perm: &[usize]| -> Vec { let mut cache: Vec = Vec::with_capacity(perm.len() * PUBLIC_KEY_LENGTH); for n in perm { - cache.extend_from_slice(&nodes[*n].best_node_id().value.bytes) + cache.extend_from_slice(&nodes[*n].locked(rti).best_node_id().value.bytes) } cache - } + }; let cache_key = route_permutation_to_hop_cache(rti, &nodes, permutation); // Skip routes we have already seen @@ -373,12 +374,12 @@ impl RouteSpecStore { let mut seen_nodes: HashSet = HashSet::new(); for n in permutation { let node = nodes.get(*n).unwrap(); - if !seen_nodes.insert(node.best_node_id()) { + if !seen_nodes.insert(node.locked(rti).best_node_id()) { // Already seen this node, should not be in the route twice return None; } - if let Some(relay) = node.relay(RoutingDomain::PublicInternet).map(|n| n.locked(rti)) { - let relay_id = relay.best_node_id(); + if let Some(relay) = node.locked_mut(rti).relay(RoutingDomain::PublicInternet) { + let relay_id = relay.locked(rti).best_node_id(); if !seen_nodes.insert(relay_id) { // Already seen this node, should not be in the route twice return None; @@ -482,16 +483,18 @@ impl RouteSpecStore { return Ok(None); } + drop(perm_func); + // Got a unique route, lets build the details, register it, and return it let hop_node_refs:Vec = route_nodes .iter() - .map(|k| nodes[*k].unlocked()) + .map(|k| nodes[*k].clone()) .collect(); let mut route_set = BTreeMap::::new(); for crypto_kind in crypto_kinds.iter().copied() { let vcrypto = self.unlocked_inner.routing_table.crypto().get(crypto_kind).unwrap(); let keypair = vcrypto.generate_keypair(); - let hops: Vec = route_nodes.iter().map(|v| nodes[*v].node_ids().get(crypto_kind).unwrap().value).collect(); + let hops: Vec = route_nodes.iter().map(|v| nodes[*v].locked(rti).node_ids().get(crypto_kind).unwrap().value).collect(); route_set.insert(keypair.key, RouteSpecDetail { crypto_kind, @@ -509,13 +512,12 @@ impl RouteSpecStore { can_do_sequenced, ); - drop(perm_func); // make id let id = self.generate_allocated_route_id(&rssd)?; // Add to cache - inner.cache.add_to_cache(&rssd); + inner.cache.add_to_cache(rti, &rssd); // Keep route in spec store inner.content.add_detail(id.clone(), rssd); @@ -686,7 +688,8 @@ impl RouteSpecStore { }; // Remove from hop cache - if !inner.cache.remove_from_cache(id, &rssd) { + let rti = &*self.unlocked_inner.routing_table.inner.read(); + if !inner.cache.remove_from_cache(rti, id, &rssd) { panic!("hop cache should have contained cache key"); } diff --git a/veilid-core/src/routing_table/route_spec_store/route_spec_store_cache.rs b/veilid-core/src/routing_table/route_spec_store/route_spec_store_cache.rs index b484c084..e4f9b3ef 100644 --- a/veilid-core/src/routing_table/route_spec_store/route_spec_store_cache.rs +++ b/veilid-core/src/routing_table/route_spec_store/route_spec_store_cache.rs @@ -41,8 +41,8 @@ pub struct RouteSpecStoreCache { impl RouteSpecStoreCache { /// add an allocated route set to our cache via its cache key - pub fn add_to_cache(&mut self, rssd: &RouteSetSpecDetail) { - let cache_key = rssd.make_cache_key(); + pub fn add_to_cache(&mut self, rti: &RoutingTableInner, rssd: &RouteSetSpecDetail) { + let cache_key = rssd.make_cache_key(rti); if !self.hop_cache.insert(cache_key) { panic!("route should never be inserted twice"); } @@ -66,8 +66,13 @@ impl RouteSpecStoreCache { } /// removes an allocated route set from our cache - pub fn remove_from_cache(&mut self, id: RouteId, rssd: &RouteSetSpecDetail) -> bool { - let cache_key = rssd.make_cache_key(); + pub fn remove_from_cache( + &mut self, + rti: &RoutingTableInner, + id: RouteId, + rssd: &RouteSetSpecDetail, + ) -> bool { + let cache_key = rssd.make_cache_key(rti); // Remove from hop cache if !self.hop_cache.remove(&cache_key) { diff --git a/veilid-core/src/rpc_processor/rpc_route.rs b/veilid-core/src/rpc_processor/rpc_route.rs index 0b8916d6..5ba33922 100644 --- a/veilid-core/src/rpc_processor/rpc_route.rs +++ b/veilid-core/src/rpc_processor/rpc_route.rs @@ -156,17 +156,18 @@ impl RPCProcessor { // Look up the private route and ensure it's one in our spec store // Ensure the route is validated, and construct a return safetyspec that matches the inbound preferences let rss = self.routing_table.route_spec_store(); + let preferred_route = rss.get_route_id_for_key(&pr_pubkey.value); let Some((secret_key, safety_spec)) = rss .with_signature_validated_route( &pr_pubkey, &routed_operation.signatures, &routed_operation.data, sender_id, - |rssd, rsd| { + |rssd, rsd| { ( rsd.secret_key, SafetySpec { - preferred_route: rss.get_route_id_for_key(&pr_pubkey.value), + preferred_route, hop_count: rssd.hop_count(), stability: rssd.get_stability(), sequencing: routed_operation.sequencing,