From 592c83d83a24a784339013e3da3126fefaea08bd Mon Sep 17 00:00:00 2001 From: John Smith Date: Wed, 9 Nov 2022 22:27:37 -0500 Subject: [PATCH] checkpoint --- veilid-core/src/network_manager/mod.rs | 12 +- veilid-core/src/routing_table/mod.rs | 34 +-- veilid-core/src/routing_table/node_ref.rs | 44 ++- .../src/routing_table/route_spec_store.rs | 63 ++-- .../src/routing_table/routing_domains.rs | 109 ++++--- .../src/routing_table/routing_table_inner.rs | 56 ++-- veilid-core/src/rpc_processor/mod.rs | 12 +- .../src/rpc_processor/rpc_find_node.rs | 5 +- .../src/rpc_processor/rpc_node_info_update.rs | 5 +- veilid-core/src/veilid_api/mod.rs | 284 +++++++++--------- 10 files changed, 299 insertions(+), 325 deletions(-) diff --git a/veilid-core/src/network_manager/mod.rs b/veilid-core/src/network_manager/mod.rs index 21d0f5eb..37ec14ef 100644 --- a/veilid-core/src/network_manager/mod.rs +++ b/veilid-core/src/network_manager/mod.rs @@ -1210,18 +1210,16 @@ impl NetworkManager { }; // Node A is our own node - let node_a = routing_table.get_own_node_info(routing_domain); - let node_a_id = routing_table.node_id(); + let peer_a = routing_table.get_own_peer_info(routing_domain); // Node B is the target node - let node_b = match target_node_ref.node_info(routing_domain) { + let peer_b = match target_node_ref.make_peer_info(routing_domain) { Some(ni) => ni, None => { log_net!("no node info for node {:?}", target_node_ref); return Ok(NodeContactMethod::Unreachable); } }; - let node_b_id = target_node_ref.node_id(); // Dial info filter comes from the target node ref let dial_info_filter = target_node_ref.dial_info_filter(); @@ -1229,10 +1227,8 @@ impl NetworkManager { let cm = routing_table.get_contact_method( routing_domain, - &node_a_id, - &node_a, - &node_b_id, - &node_b, + &peer_a, + &peer_b, dial_info_filter, sequencing, ); diff --git a/veilid-core/src/routing_table/mod.rs b/veilid-core/src/routing_table/mod.rs index fd1db5e2..6f585960 100644 --- a/veilid-core/src/routing_table/mod.rs +++ b/veilid-core/src/routing_table/mod.rs @@ -348,24 +348,30 @@ impl RoutingTable { .node_info_is_valid_in_routing_domain(routing_domain, node_info) } + pub fn signed_node_info_is_valid_in_routing_domain( + &self, + routing_domain: RoutingDomain, + signed_node_info: &SignedNodeInfo, + ) -> bool { + self.inner + .read() + .signed_node_info_is_valid_in_routing_domain(routing_domain, signed_node_info) + } + /// Look up the best way for two nodes to reach each other over a specific routing domain #[instrument(level = "trace", skip(self), ret)] pub fn get_contact_method( &self, routing_domain: RoutingDomain, - node_a_id: &DHTKey, - node_a: &NodeInfo, - node_b_id: &DHTKey, - node_b: &NodeInfo, + peer_a: &PeerInfo, + peer_b: &PeerInfo, dial_info_filter: DialInfoFilter, sequencing: Sequencing, ) -> ContactMethod { self.inner.read().get_contact_method( routing_domain, - node_a_id, - node_a, - node_b_id, - node_b, + peer_a, + peer_b, dial_info_filter, sequencing, ) @@ -381,16 +387,6 @@ impl RoutingTable { self.inner.read().get_own_peer_info(routing_domain) } - /// Return a copy of our node's signednodeinfo - pub fn get_own_signed_node_info(&self, routing_domain: RoutingDomain) -> SignedDirectNodeInfo { - self.inner.read().get_own_signed_node_info(routing_domain) - } - - /// Return a copy of our node's nodeinfo - pub fn get_own_node_info(&self, routing_domain: RoutingDomain) -> NodeInfo { - self.inner.read().get_own_node_info(routing_domain) - } - /// If we have a valid network class in this routing domain, then our 'NodeInfo' is valid pub fn has_valid_own_node_info(&self, routing_domain: RoutingDomain) -> bool { self.inner.read().has_valid_own_node_info(routing_domain) @@ -525,7 +521,7 @@ impl RoutingTable { &self, routing_domain: RoutingDomain, node_id: DHTKey, - signed_node_info: SignedDirectNodeInfo, + signed_node_info: SignedNodeInfo, allow_invalid: bool, ) -> Option { self.inner.write().register_node_with_signed_node_info( diff --git a/veilid-core/src/routing_table/node_ref.rs b/veilid-core/src/routing_table/node_ref.rs index 6f7f9adf..ae77c4df 100644 --- a/veilid-core/src/routing_table/node_ref.rs +++ b/veilid-core/src/routing_table/node_ref.rs @@ -116,10 +116,10 @@ pub trait NodeRefBase: Sized { e.update_node_status(node_status); }); } - fn min_max_version(&self) -> Option<(u8, u8)> { + fn min_max_version(&self) -> Option { self.operate(|_rti, e| e.min_max_version()) } - fn set_min_max_version(&self, min_max_version: (u8, u8)) { + fn set_min_max_version(&self, min_max_version: VersionRange) { self.operate_mut(|_rti, e| e.set_min_max_version(min_max_version)) } fn state(&self, cur_ts: u64) -> BucketEntryState { @@ -170,26 +170,24 @@ pub trait NodeRefBase: Sized { } fn relay(&self, routing_domain: RoutingDomain) -> Option { self.operate_mut(|rti, e| { - let opt_target_rpi = e - .node_info(routing_domain) - .map(|n| n.relay_peer_info.as_ref().map(|pi| pi.as_ref().clone())) - .flatten(); - opt_target_rpi.and_then(|t| { - // If relay is ourselves, then return None, because we can't relay through ourselves - // and to contact this node we should have had an existing inbound connection - if t.node_id.key == rti.unlocked_inner.node_id { - return None; - } + e.signed_node_info(routing_domain) + .and_then(|n| n.relay_peer_info()) + .and_then(|t| { + // If relay is ourselves, then return None, because we can't relay through ourselves + // and to contact this node we should have had an existing inbound connection + if t.node_id.key == rti.unlocked_inner.node_id { + return None; + } - // Register relay node and return noderef - rti.register_node_with_signed_node_info( - self.routing_table(), - routing_domain, - t.node_id.key, - t.signed_node_info, - false, - ) - }) + // Register relay node and return noderef + rti.register_node_with_signed_node_info( + self.routing_table(), + routing_domain, + t.node_id.key, + t.signed_node_info, + false, + ) + }) }) } @@ -301,8 +299,8 @@ pub trait NodeRefBase: Sized { fn has_any_dial_info(&self) -> bool { self.operate(|_rti, e| { for rtd in RoutingDomain::all() { - if let Some(ni) = e.node_info(rtd) { - if ni.has_any_dial_info() { + if let Some(sni) = e.signed_node_info(rtd) { + if sni.has_any_dial_info() { return true; } } diff --git a/veilid-core/src/routing_table/route_spec_store.rs b/veilid-core/src/routing_table/route_spec_store.rs index b10d2b76..a03c0614 100644 --- a/veilid-core/src/routing_table/route_spec_store.rs +++ b/veilid-core/src/routing_table/route_spec_store.rs @@ -114,10 +114,10 @@ fn route_hops_to_hop_cache(hops: &[DHTKey]) -> Vec { } /// get the hop cache key for a particular route permutation -fn route_permutation_to_hop_cache(nodes: &[(DHTKey, NodeInfo)], perm: &[usize]) -> Vec { +fn route_permutation_to_hop_cache(nodes: &[PeerInfo], perm: &[usize]) -> Vec { let mut cache: Vec = Vec::with_capacity(perm.len() * DHT_KEY_LENGTH); for n in perm { - cache.extend_from_slice(&nodes[*n].0.bytes) + cache.extend_from_slice(&nodes[*n].node_id.key.bytes) } cache } @@ -422,12 +422,12 @@ impl RouteSpecStore { // Exclude nodes with no publicinternet nodeinfo, or incompatible nodeinfo or node status won't route v.with(rti, move |_rti, e| { - let node_info_ok = if let Some(ni) = e.node_info(RoutingDomain::PublicInternet) - { - ni.has_sequencing_matched_dial_info(sequencing) - } else { - false - }; + let node_info_ok = + if let Some(sni) = e.signed_node_info(RoutingDomain::PublicInternet) { + sni.has_sequencing_matched_dial_info(sequencing) + } else { + false + }; let node_status_ok = if let Some(ns) = e.node_status(RoutingDomain::PublicInternet) { ns.will_route() @@ -495,20 +495,15 @@ impl RouteSpecStore { }); cmpout }; - let transform = |rti: &RoutingTableInner, - k: DHTKey, - v: Option>| - -> (DHTKey, NodeInfo) { - // Return the key and the nodeinfo for that key - ( - k, + let transform = + |rti: &RoutingTableInner, k: DHTKey, v: Option>| -> PeerInfo { + // Return the peerinfo for that key v.unwrap().with(rti, |_rti, e| { - e.node_info(RoutingDomain::PublicInternet.into()) + e.make_peer_info(k, RoutingDomain::PublicInternet.into()) .unwrap() .clone() - }), - ) - }; + }) + }; // Pull the whole routing table in sorted order let node_count = rti.get_entry_count( @@ -536,18 +531,15 @@ impl RouteSpecStore { // Ensure this route is viable by checking that each node can contact the next one if directions.contains(Direction::Outbound) { - let our_node_info = rti.get_own_node_info(RoutingDomain::PublicInternet); - let our_node_id = rti.node_id(); - let mut previous_node = &(our_node_id, our_node_info); + let our_peer_info = rti.get_own_peer_info(RoutingDomain::PublicInternet); + let mut previous_node = &our_peer_info; let mut reachable = true; for n in permutation { let current_node = nodes.get(*n).unwrap(); let cm = rti.get_contact_method( RoutingDomain::PublicInternet, - &previous_node.0, - &previous_node.1, - ¤t_node.0, - ¤t_node.1, + previous_node, + current_node, DialInfoFilter::all(), sequencing, ); @@ -562,18 +554,15 @@ impl RouteSpecStore { } } if directions.contains(Direction::Inbound) { - let our_node_info = rti.get_own_node_info(RoutingDomain::PublicInternet); - let our_node_id = rti.node_id(); - let mut next_node = &(our_node_id, our_node_info); + let our_peer_info = rti.get_own_peer_info(RoutingDomain::PublicInternet); + let mut next_node = &our_peer_info; let mut reachable = true; for n in permutation.iter().rev() { let current_node = nodes.get(*n).unwrap(); let cm = rti.get_contact_method( RoutingDomain::PublicInternet, - &next_node.0, - &next_node.1, - ¤t_node.0, - ¤t_node.1, + next_node, + current_node, DialInfoFilter::all(), sequencing, ); @@ -609,11 +598,11 @@ impl RouteSpecStore { } // Got a unique route, lets build the detail, register it, and return it - let hops = route_nodes.iter().map(|v| nodes[*v].0).collect(); - let hop_node_refs = route_nodes + let hops: Vec = route_nodes.iter().map(|v| nodes[*v].node_id.key).collect(); + let hop_node_refs = hops .iter() - .map(|v| { - rti.lookup_node_ref(self.unlocked_inner.routing_table.clone(), nodes[*v].0) + .map(|k| { + rti.lookup_node_ref(self.unlocked_inner.routing_table.clone(), *k) .unwrap() }) .collect(); diff --git a/veilid-core/src/routing_table/routing_domains.rs b/veilid-core/src/routing_table/routing_domains.rs index 54aeec46..d52365c8 100644 --- a/veilid-core/src/routing_table/routing_domains.rs +++ b/veilid-core/src/routing_table/routing_domains.rs @@ -111,18 +111,31 @@ impl RoutingDomainDetailCommon { dial_info_detail_list: self.dial_info_details.clone(), }; - let relay_peer_info = self + let relay_info = self .relay_node .as_ref() - .and_then(|rn| rn.locked(rti).make_peer_info(self.routing_domain)); + .and_then(|rn| { + let opt_relay_pi = rn.locked(rti).make_peer_info(self.routing_domain); + if let Some(relay_pi) = opt_relay_pi { + match relay_pi.signed_node_info { + SignedNodeInfo::Direct(d) => Some((relay_pi.node_id, d)), + SignedNodeInfo::Relayed(_) => { + warn!("relay node should not have a relay itself! if this happens, a relay updated its signed node info and became a relay, which should cause the relay to be dropped"); + None + }, + } + } else { + None + } + }); - let signed_node_info = match relay_peer_info { - Some(relay_pi) => SignedNodeInfo::Relayed( + let signed_node_info = match relay_info { + Some((relay_id, relay_sdni)) => SignedNodeInfo::Relayed( SignedRelayedNodeInfo::with_secret( NodeId::new(rti.unlocked_inner.node_id), node_info, - relay_pi.node_id, - relay_pi.signed_node_info, + relay_id, + relay_sdni, &rti.unlocked_inner.node_id_secret, ) .unwrap(), @@ -133,7 +146,7 @@ impl RoutingDomainDetailCommon { node_info, &rti.unlocked_inner.node_id_secret, ) - .unwrap(), + .unwrap() ), }; @@ -147,27 +160,8 @@ impl RoutingDomainDetailCommon { let mut cpi = self.cached_peer_info.lock(); if cpi.is_none() { // Regenerate peer info - let pi = PeerInfo::new( - NodeId::new(rti.unlocked_inner.node_id), - SignedDirectNodeInfo::with_secret( - NodeInfo { - network_class: self.network_class.unwrap_or(NetworkClass::Invalid), - outbound_protocols: self.outbound_protocols, - address_types: self.address_types, - min_version: MIN_CRYPTO_VERSION, - max_version: MAX_CRYPTO_VERSION, - dial_info_detail_list: self.dial_info_details.clone(), - relay_peer_info: self.relay_node.as_ref().and_then(|rn| { - rn.locked(rti) - .make_peer_info(self.routing_domain) - .map(Box::new) - }), - }, - NodeId::new(rti.unlocked_inner.node_id), - &rti.unlocked_inner.node_id_secret, - ) - .unwrap(), - ); + let pi = self.make_peer_info(rti); + // Cache the peer info *cpi = Some(pi); } @@ -204,10 +198,8 @@ pub trait RoutingDomainDetail { fn get_contact_method( &self, rti: &RoutingTableInner, - node_a_id: &DHTKey, - node_a: &NodeInfo, - node_b_id: &DHTKey, - node_b: &NodeInfo, + peer_a: &PeerInfo, + peer_b: &PeerInfo, dial_info_filter: DialInfoFilter, sequencing: Sequencing, ) -> ContactMethod; @@ -280,13 +272,15 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail { fn get_contact_method( &self, _rti: &RoutingTableInner, - node_a_id: &DHTKey, - node_a: &NodeInfo, - node_b_id: &DHTKey, - node_b: &NodeInfo, + peer_a: &PeerInfo, + peer_b: &PeerInfo, dial_info_filter: DialInfoFilter, sequencing: Sequencing, ) -> ContactMethod { + // Get the nodeinfos for convenience + let node_a = peer_a.signed_node_info.node_info(); + let node_b = peer_b.signed_node_info.node_info(); + // Get the best match dial info for node B if we have it if let Some(target_did) = first_filtered_dial_info_detail(node_a, node_b, &dial_info_filter, sequencing) @@ -298,17 +292,18 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail { } // Get the target's inbound relay, it must have one or it is not reachable - if let Some(inbound_relay) = &node_b.relay_peer_info { + if let Some(node_b_relay) = peer_b.signed_node_info.relay_info() { + let node_b_relay_id = peer_b.signed_node_info.relay_id().unwrap(); // Note that relay_peer_info could be node_a, in which case a connection already exists // and we shouldn't have even gotten here - if inbound_relay.node_id.key == *node_a_id { + if node_b_relay_id.key == peer_a.node_id.key { return ContactMethod::Existing; } // Can node A reach the inbound relay directly? if first_filtered_dial_info_detail( node_a, - &inbound_relay.signed_node_info.node_info, + node_b_relay, &dial_info_filter, sequencing, ) @@ -332,8 +327,8 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail { // Can we receive a direct reverse connection? if !reverse_did.class.requires_signal() { return ContactMethod::SignalReverse( - inbound_relay.node_id.key, - *node_b_id, + node_b_relay_id.key, + peer_b.node_id.key, ); } } @@ -364,8 +359,8 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail { { // The target and ourselves have a udp dialinfo that they can reach return ContactMethod::SignalHolePunch( - inbound_relay.node_id.key, - *node_b_id, + node_b_relay_id.key, + peer_a.node_id.key, ); } } @@ -373,28 +368,30 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail { // Otherwise we have to inbound relay } - return ContactMethod::InboundRelay(inbound_relay.node_id.key); + return ContactMethod::InboundRelay(node_b_relay_id.key); } } } // If the node B has no direct dial info, it needs to have an inbound relay - else if let Some(inbound_relay) = &node_b.relay_peer_info { + else if let Some(node_b_relay) = peer_b.signed_node_info.relay_info() { + let node_b_relay_id = peer_b.signed_node_info.relay_id().unwrap(); + // Can we reach the full relay? if first_filtered_dial_info_detail( node_a, - &inbound_relay.signed_node_info.node_info, + &node_b_relay, &dial_info_filter, sequencing, ) .is_some() { - return ContactMethod::InboundRelay(inbound_relay.node_id.key); + return ContactMethod::InboundRelay(node_b_relay_id.key); } } // If node A can't reach the node by other means, it may need to use its own relay - if let Some(outbound_relay) = &node_a.relay_peer_info { - return ContactMethod::OutboundRelay(outbound_relay.node_id.key); + if let Some(node_a_relay_id) = peer_a.signed_node_info.relay_id() { + return ContactMethod::OutboundRelay(node_a_relay_id.key); } ContactMethod::Unreachable @@ -450,20 +447,18 @@ impl RoutingDomainDetail for LocalNetworkRoutingDomainDetail { fn get_contact_method( &self, _rti: &RoutingTableInner, - _node_a_id: &DHTKey, - node_a: &NodeInfo, - _node_b_id: &DHTKey, - node_b: &NodeInfo, + peer_a: &PeerInfo, + peer_b: &PeerInfo, dial_info_filter: DialInfoFilter, sequencing: Sequencing, ) -> ContactMethod { // Scope the filter down to protocols node A can do outbound let dial_info_filter = dial_info_filter.filtered( &DialInfoFilter::all() - .with_address_type_set(node_a.address_types) - .with_protocol_type_set(node_a.outbound_protocols), + .with_address_type_set(peer_a.signed_node_info.node_info().address_types) + .with_protocol_type_set(peer_a.signed_node_info.node_info().outbound_protocols), ); - + // Get first filtered dialinfo let (sort, dial_info_filter) = match sequencing { Sequencing::NoPreference => (None, dial_info_filter), @@ -485,7 +480,7 @@ impl RoutingDomainDetail for LocalNetworkRoutingDomainDetail { let filter = |did: &DialInfoDetail| did.matches_filter(&dial_info_filter); - let opt_target_did = node_b.first_filtered_dial_info_detail(sort, filter); + let opt_target_did = peer_b.signed_node_info.node_info().first_filtered_dial_info_detail(sort, filter); if let Some(target_did) = opt_target_did { return ContactMethod::Direct(target_did.dial_info); } diff --git a/veilid-core/src/routing_table/routing_table_inner.rs b/veilid-core/src/routing_table/routing_table_inner.rs index cfd162aa..f37672fe 100644 --- a/veilid-core/src/routing_table/routing_table_inner.rs +++ b/veilid-core/src/routing_table/routing_table_inner.rs @@ -191,9 +191,20 @@ impl RoutingTableInner { return false; } } + true + } + + pub fn signed_node_info_is_valid_in_routing_domain( + &self, + routing_domain: RoutingDomain, + signed_node_info: &SignedNodeInfo, + ) -> bool { + if !self.node_info_is_valid_in_routing_domain(routing_domain, signed_node_info.node_info()) + { + return false; + } // Ensure the relay is also valid in this routing domain if it is provided - if let Some(relay_peer_info) = node_info.relay_peer_info.as_ref() { - let relay_ni = &relay_peer_info.signed_node_info.node_info; + if let Some(relay_ni) = signed_node_info.relay_info() { if !self.node_info_is_valid_in_routing_domain(routing_domain, relay_ni) { return false; } @@ -205,23 +216,13 @@ impl RoutingTableInner { pub fn get_contact_method( &self, routing_domain: RoutingDomain, - node_a_id: &DHTKey, - node_a: &NodeInfo, - node_b_id: &DHTKey, - node_b: &NodeInfo, + peer_a: &PeerInfo, + peer_b: &PeerInfo, dial_info_filter: DialInfoFilter, sequencing: Sequencing, ) -> ContactMethod { self.with_routing_domain(routing_domain, |rdd| { - rdd.get_contact_method( - self, - node_a_id, - node_a, - node_b_id, - node_b, - dial_info_filter, - sequencing, - ) + rdd.get_contact_method(self, peer_a, peer_b, dial_info_filter, sequencing) }) } @@ -252,22 +253,6 @@ impl RoutingTableInner { }) } - /// Return a copy of our node's signednodeinfo - pub fn get_own_signed_node_info(&self, routing_domain: RoutingDomain) -> SignedDirectNodeInfo { - self.with_routing_domain(routing_domain, |rdd| { - rdd.common() - .with_peer_info(self, |pi| pi.signed_node_info.clone()) - }) - } - - /// Return a copy of our node's nodeinfo - pub fn get_own_node_info(&self, routing_domain: RoutingDomain) -> NodeInfo { - self.with_routing_domain(routing_domain, |rdd| { - rdd.common() - .with_peer_info(self, |pi| pi.signed_node_info.node_info.clone()) - }) - } - /// Return our currently registered 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()) @@ -662,7 +647,7 @@ impl RoutingTableInner { outer_self: RoutingTable, routing_domain: RoutingDomain, node_id: DHTKey, - signed_node_info: SignedDirectNodeInfo, + signed_node_info: SignedNodeInfo, allow_invalid: bool, ) -> Option { // validate signed node info is not something malicious @@ -670,8 +655,8 @@ impl RoutingTableInner { log_rtab!(debug "can't register own node id in routing table"); return None; } - if let Some(rpi) = &signed_node_info.node_info.relay_peer_info { - if rpi.node_id.key == node_id { + if let Some(relay_id) = signed_node_info.relay_id() { + if relay_id.key == node_id { log_rtab!(debug "node can not be its own relay"); return None; } @@ -683,8 +668,7 @@ impl RoutingTableInner { return None; } // verify signed node info is valid in this routing domain - if !self - .node_info_is_valid_in_routing_domain(routing_domain, &signed_node_info.node_info) + if !self.signed_node_info_is_valid_in_routing_domain(routing_domain, &signed_node_info) { log_rtab!(debug "signed node info for {} not valid in the {:?} routing domain", node_id, routing_domain); return None; diff --git a/veilid-core/src/rpc_processor/mod.rs b/veilid-core/src/rpc_processor/mod.rs index 4d0a6f85..8b3ccc6a 100644 --- a/veilid-core/src/rpc_processor/mod.rs +++ b/veilid-core/src/rpc_processor/mod.rs @@ -336,10 +336,14 @@ impl RPCProcessor { ////////////////////////////////////////////////////////////////////// - /// Determine if a NodeInfo can be placed into the specified routing domain - fn filter_node_info(&self, routing_domain: RoutingDomain, node_info: &NodeInfo) -> bool { + /// Determine if a SignedNodeInfo can be placed into the specified routing domain + fn filter_node_info( + &self, + routing_domain: RoutingDomain, + signed_node_info: &SignedNodeInfo, + ) -> bool { let routing_table = self.routing_table(); - routing_table.node_info_is_valid_in_routing_domain(routing_domain, &node_info) + routing_table.signed_node_info_is_valid_in_routing_domain(routing_domain, &signed_node_info) } ////////////////////////////////////////////////////////////////////// @@ -619,7 +623,7 @@ impl RPCProcessor { // routing table caching when it is okay to do so // This is only done in the PublicInternet routing domain because // as far as we can tell this is the only domain that will really benefit - fn get_sender_signed_node_info(&self, dest: &Destination) -> Option { + fn get_sender_signed_node_info(&self, dest: &Destination) -> Option { // Don't do this if the sender is to remain private // Otherwise we would be attaching the original sender's identity to the final destination, // thus defeating the purpose of the safety route entirely :P diff --git a/veilid-core/src/rpc_processor/rpc_find_node.rs b/veilid-core/src/rpc_processor/rpc_find_node.rs index 42d7c4d1..219d7f9b 100644 --- a/veilid-core/src/rpc_processor/rpc_find_node.rs +++ b/veilid-core/src/rpc_processor/rpc_find_node.rs @@ -50,10 +50,7 @@ impl RPCProcessor { // Verify peers are in the correct peer scope for peer_info in &find_node_a.peers { - if !self.filter_node_info( - RoutingDomain::PublicInternet, - &peer_info.signed_node_info.node_info, - ) { + if !self.filter_node_info(RoutingDomain::PublicInternet, &peer_info.signed_node_info) { return Err(RPCError::invalid_format( "find_node response has invalid peer scope", )); diff --git a/veilid-core/src/rpc_processor/rpc_node_info_update.rs b/veilid-core/src/rpc_processor/rpc_node_info_update.rs index c5ec9f86..b264baeb 100644 --- a/veilid-core/src/rpc_processor/rpc_node_info_update.rs +++ b/veilid-core/src/rpc_processor/rpc_node_info_update.rs @@ -11,7 +11,8 @@ impl RPCProcessor { // Get the signed node info for the desired routing domain to send update with let signed_node_info = self .routing_table() - .get_own_signed_node_info(routing_domain); + .get_own_peer_info(routing_domain) + .signed_node_info; let node_info_update = RPCOperationNodeInfoUpdate { signed_node_info }; let statement = RPCStatement::new(RPCStatementDetail::NodeInfoUpdate(node_info_update)); @@ -50,7 +51,7 @@ impl RPCProcessor { }; // Update our routing table with signed node info - if !self.filter_node_info(routing_domain, &node_info_update.signed_node_info.node_info) { + if !self.filter_node_info(routing_domain, &node_info_update.signed_node_info) { log_rpc!(debug "node info doesn't belong in {:?} routing domain: {}", routing_domain, sender_node_id); return Ok(()); } diff --git a/veilid-core/src/veilid_api/mod.rs b/veilid-core/src/veilid_api/mod.rs index 9f522aba..caa0435c 100644 --- a/veilid-core/src/veilid_api/mod.rs +++ b/veilid-core/src/veilid_api/mod.rs @@ -775,6 +775,68 @@ pub struct NodeInfo { pub dial_info_detail_list: Vec, } +impl NodeInfo { + pub fn first_filtered_dial_info_detail( + &self, + sort: Option, + filter: F, + ) -> Option + where + S: Fn(&DialInfoDetail, &DialInfoDetail) -> std::cmp::Ordering, + F: Fn(&DialInfoDetail) -> bool, + { + if let Some(sort) = sort { + let mut dids = self.dial_info_detail_list.clone(); + dids.sort_by(sort); + for did in dids { + if filter(&did) { + return Some(did); + } + } + } else { + for did in &self.dial_info_detail_list { + if filter(did) { + return Some(did.clone()); + } + } + }; + None + } + + pub fn all_filtered_dial_info_details( + &self, + sort: Option, + filter: F, + ) -> Vec + where + S: Fn(&DialInfoDetail, &DialInfoDetail) -> std::cmp::Ordering, + F: Fn(&DialInfoDetail) -> bool, + { + let mut dial_info_detail_list = Vec::new(); + + if let Some(sort) = sort { + let mut dids = self.dial_info_detail_list.clone(); + dids.sort_by(sort); + for did in dids { + if filter(&did) { + dial_info_detail_list.push(did); + } + } + } else { + for did in &self.dial_info_detail_list { + if filter(did) { + dial_info_detail_list.push(did.clone()); + } + } + }; + dial_info_detail_list + } + + pub fn has_direct_dial_info(&self) -> bool { + !self.dial_info_detail_list.is_empty() + } +} + #[allow(clippy::derive_hash_xor_eq)] #[derive( Debug, @@ -2046,6 +2108,53 @@ impl SignedNodeInfo { SignedNodeInfo::Relayed(r) => Some(&r.relay_info.node_info), } } + pub fn relay_peer_info(&self) -> Option { + match self { + SignedNodeInfo::Direct(d) => None, + SignedNodeInfo::Relayed(r) => Some(PeerInfo::new( + r.relay_id.clone(), + SignedNodeInfo::Direct(r.relay_info.clone()), + )), + } + } + pub fn has_any_dial_info(&self) -> bool { + self.node_info().has_direct_dial_info() + || self + .relay_info() + .map(|relay_ni| relay_ni.has_direct_dial_info()) + .unwrap_or_default() + } + + pub fn has_sequencing_matched_dial_info(&self, sequencing: Sequencing) -> bool { + // Check our dial info + for did in &self.node_info().dial_info_detail_list { + match sequencing { + Sequencing::NoPreference | Sequencing::PreferOrdered => return true, + Sequencing::EnsureOrdered => { + if did.dial_info.protocol_type().is_connection_oriented() { + return true; + } + } + } + } + // Check our relay if we have one + return self + .relay_info() + .map(|relay_ni| { + for did in &relay_ni.dial_info_detail_list { + match sequencing { + Sequencing::NoPreference | Sequencing::PreferOrdered => return true, + Sequencing::EnsureOrdered => { + if did.dial_info.protocol_type().is_connection_oriented() { + return true; + } + } + } + } + false + }) + .unwrap_or_default(); + } } #[derive(Clone, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)] @@ -2066,157 +2175,62 @@ impl PeerInfo { impl PeerInfo { /* - pub fn first_filtered_dial_info_detail( - &self, - sort: Option, - filter: F, - ) -> Option - where - S: Fn(&DialInfoDetail, &DialInfoDetail) -> std::cmp::Ordering, - F: Fn(&DialInfoDetail) -> bool, - { - if let Some(sort) = sort { - let mut dids = self.dial_info_detail_list.clone(); - dids.sort_by(sort); - for did in dids { - if filter(&did) { - return Some(did); - } - } - } else { - for did in &self.dial_info_detail_list { - if filter(did) { - return Some(did.clone()); - } - } - }; - None - } - pub fn all_filtered_dial_info_details( - &self, - sort: Option, - filter: F, - ) -> Vec - where - S: Fn(&DialInfoDetail, &DialInfoDetail) -> std::cmp::Ordering, - F: Fn(&DialInfoDetail) -> bool, - { - let mut dial_info_detail_list = Vec::new(); + xxx move these back to NodeInfo - if let Some(sort) = sort { - let mut dids = self.dial_info_detail_list.clone(); - dids.sort_by(sort); - for did in dids { - if filter(&did) { - dial_info_detail_list.push(did); - } - } - } else { - for did in &self.dial_info_detail_list { - if filter(did) { - dial_info_detail_list.push(did.clone()); - } - } - }; - dial_info_detail_list - } - - pub fn has_any_dial_info(&self) -> bool { - !self.dial_info_detail_list.is_empty() - || !self - .relay_peer_info - .as_ref() - .map(|rpi| rpi.signed_node_info.node_info.has_direct_dial_info()) - .unwrap_or_default() - } - - pub fn has_sequencing_matched_dial_info(&self, sequencing: Sequencing) -> bool { - // Check our dial info - for did in &self.dial_info_detail_list { - match sequencing { - Sequencing::NoPreference | Sequencing::PreferOrdered => return true, - Sequencing::EnsureOrdered => { - if did.dial_info.protocol_type().is_connection_oriented() { - return true; - } - } - } + pub fn has_direct_dial_info(&self) -> bool { + !self.dial_info_detail_list.is_empty() } - // Check our relay if we have one - return self - .relay_peer_info - .as_ref() - .map(|rpi| { - let relay_ni = &rpi.signed_node_info.node_info; - for did in &relay_ni.dial_info_detail_list { - match sequencing { - Sequencing::NoPreference | Sequencing::PreferOrdered => return true, - Sequencing::EnsureOrdered => { - if did.dial_info.protocol_type().is_connection_oriented() { - return true; - } + + // Is some relay required either for signal or inbound relay or outbound relay? + pub fn requires_relay(&self) -> bool { + match self.network_class { + NetworkClass::InboundCapable => { + for did in &self.dial_info_detail_list { + if did.class.requires_relay() { + return true; } } } - false - }) - .unwrap_or_default(); - } - - pub fn has_direct_dial_info(&self) -> bool { - !self.dial_info_detail_list.is_empty() - } - - // Is some relay required either for signal or inbound relay or outbound relay? - pub fn requires_relay(&self) -> bool { - match self.network_class { - NetworkClass::InboundCapable => { - for did in &self.dial_info_detail_list { - if did.class.requires_relay() { - return true; - } + NetworkClass::OutboundOnly => { + return true; } + NetworkClass::WebApp => { + return true; + } + NetworkClass::Invalid => {} } - NetworkClass::OutboundOnly => { - return true; - } - NetworkClass::WebApp => { - return true; - } - NetworkClass::Invalid => {} + false } - false - } - // Can this node assist with signalling? Yes but only if it doesn't require signalling, itself. - pub fn can_signal(&self) -> bool { - // Must be inbound capable - if !matches!(self.network_class, NetworkClass::InboundCapable) { - return false; - } - // Do any of our dial info require signalling? if so, we can't offer signalling - for did in &self.dial_info_detail_list { - if did.class.requires_signal() { + // Can this node assist with signalling? Yes but only if it doesn't require signalling, itself. + pub fn can_signal(&self) -> bool { + // Must be inbound capable + if !matches!(self.network_class, NetworkClass::InboundCapable) { return false; } + // Do any of our dial info require signalling? if so, we can't offer signalling + for did in &self.dial_info_detail_list { + if did.class.requires_signal() { + return false; + } + } + true } - true - } - // Can this node relay be an inbound relay? - pub fn can_inbound_relay(&self) -> bool { - // For now this is the same - self.can_signal() - } + // Can this node relay be an inbound relay? + pub fn can_inbound_relay(&self) -> bool { + // For now this is the same + self.can_signal() + } - // Is this node capable of validating dial info - pub fn can_validate_dial_info(&self) -> bool { - // For now this is the same - self.can_signal() - } + // Is this node capable of validating dial info + pub fn can_validate_dial_info(&self) -> bool { + // For now this is the same + self.can_signal() + } - */ + */ } #[derive(