From ddb74d993f44fca67a12d8d06aacca9a5d809ba9 Mon Sep 17 00:00:00 2001 From: John Smith Date: Fri, 8 Apr 2022 10:17:09 -0400 Subject: [PATCH] checkpoint --- veilid-core/proto/veilid.capnp | 28 ++++--- veilid-core/src/intf/native/network/mod.rs | 6 +- veilid-core/src/network_manager.rs | 5 +- veilid-core/src/routing_table/bucket_entry.rs | 61 +++++--------- veilid-core/src/routing_table/find_nodes.rs | 21 +++-- veilid-core/src/routing_table/mod.rs | 45 +++++----- veilid-core/src/routing_table/node_ref.rs | 14 +++- veilid-core/src/rpc_processor/coders/mod.rs | 2 + .../src/rpc_processor/coders/node_info.rs | 82 +++++++++++++++---- .../src/rpc_processor/coders/node_status.rs | 27 ++++++ .../src/rpc_processor/coders/peer_info.rs | 32 ++------ veilid-core/src/rpc_processor/mod.rs | 18 ++-- veilid-core/src/veilid_api/mod.rs | 64 ++++++++++++++- 13 files changed, 263 insertions(+), 142 deletions(-) create mode 100644 veilid-core/src/rpc_processor/coders/node_status.rs diff --git a/veilid-core/proto/veilid.capnp b/veilid-core/proto/veilid.capnp index e2bbcdb0..e0ba8bc9 100644 --- a/veilid-core/proto/veilid.capnp +++ b/veilid-core/proto/veilid.capnp @@ -163,7 +163,7 @@ struct ValueData { ############################## struct OperationInfoQ { - nodeInfo @0 :NodeInfo; # node info update about the infoq sender + nodeStatus @0 :NodeStatus; # node status update about the infoq sender } @@ -178,13 +178,18 @@ enum NetworkClass { invalid @7; # I = Invalid } +struct NodeStatus { + willRoute @0 :Bool; + willTunnel @1 :Bool; + willSignal @2 :Bool; + willRelay @3 :Bool; + willValidateDialInfo @4 :Bool; +} + struct NodeInfo { - networkClass @0 :NetworkClass; - willRoute @1 :Bool; - willTunnel @2 :Bool; - willSignal @3 :Bool; - willRelay @4 :Bool; - willValidateDialInfo @5 :Bool; + networkClass @0 :NetworkClass; # network class of this node + dialInfoList @1 :List(DialInfo); # dial info for this node + relayDialInfoList @2 :List(DialInfo); # relay dial info for this node } struct SenderInfo { @@ -192,7 +197,7 @@ struct SenderInfo { } struct OperationInfoA { - nodeInfo @0 :NodeInfo; # returned node information + nodeStatus @0 :NodeStatus; # returned node status senderInfo @1 :SenderInfo; # info about InfoQ sender from the perspective of the replier } @@ -210,11 +215,12 @@ struct OperationReturnReceipt { struct OperationFindNodeQ { nodeId @0 :NodeID; # node id to locate dialInfoList @1 :List(DialInfo); # dial info for the node asking the question + relayDialInfoList @2 :List(DialInfo); # relay dial info for the node asking the question } struct PeerInfo { - nodeId @0 :NodeID; # node id or 'closer peer' - dialInfoList @1 :List(DialInfo); # dial info for 'closer peer' + nodeId @0 :NodeID; # node id for 'closer peer' + nodeInfo @1 :NodeInfo; # node info for 'closer peer' } struct OperationFindNodeA { @@ -373,7 +379,7 @@ struct Operation { respondTo :union { none @1 :Void; # no response is desired - sender @2 :DialInfo; # (Optional) the 'best' envelope-sender dial info to be used for reply (others may exist via findNodeQ) + sender @2 :NodeInfo; # (Optional) some envelope-sender node info to be used for reply (others may exist via findNodeQ) privateRoute @3 :PrivateRoute; # embedded private route to be used for reply } diff --git a/veilid-core/src/intf/native/network/mod.rs b/veilid-core/src/intf/native/network/mod.rs index 94fabff6..81d3e2f2 100644 --- a/veilid-core/src/intf/native/network/mod.rs +++ b/veilid-core/src/intf/native/network/mod.rs @@ -404,10 +404,12 @@ impl Network { }; // If that fails, try to make a connection or reach out to the peer via its dial info - let dial_info = node_ref - .best_dial_info() + let node_info = node_ref + .best_node_info() .ok_or_else(|| "couldn't send data, no dial info or peer address".to_owned())?; + xxx write logic to determine if a relay needs to be used first xxx + self.send_data_to_dial_info(dial_info, data) .await .map_err(logthru_net!()) diff --git a/veilid-core/src/network_manager.rs b/veilid-core/src/network_manager.rs index 8d77ec0c..f30154eb 100644 --- a/veilid-core/src/network_manager.rs +++ b/veilid-core/src/network_manager.rs @@ -368,7 +368,7 @@ impl NetworkManager { } // Get our node's capabilities - pub fn generate_node_info(&self) -> NodeInfo { + pub fn generate_node_status(&self) -> NodeStatus { let network_class = self.get_network_class().unwrap_or(NetworkClass::Invalid); let will_route = network_class.can_inbound_relay(); // xxx: eventually this may have more criteria added @@ -377,8 +377,7 @@ impl NetworkManager { let will_relay = network_class.can_inbound_relay(); let will_validate_dial_info = network_class.can_validate_dial_info(); - NodeInfo { - network_class, + NodeStatus { will_route, will_tunnel, will_signal, diff --git a/veilid-core/src/routing_table/bucket_entry.rs b/veilid-core/src/routing_table/bucket_entry.rs index f6a6638b..65e6cc12 100644 --- a/veilid-core/src/routing_table/bucket_entry.rs +++ b/veilid-core/src/routing_table/bucket_entry.rs @@ -37,10 +37,10 @@ pub struct BucketEntry { min_max_version: Option<(u8, u8)>, seen_our_dial_info: bool, last_connection: Option<(ConnectionDescriptor, u64)>, - dial_infos: Vec, + node_info: NodeInfo, + peer_stats: PeerStats, latency_stats_accounting: LatencyStatsAccounting, transfer_stats_accounting: TransferStatsAccounting, - peer_stats: PeerStats, } impl BucketEntry { @@ -51,7 +51,7 @@ impl BucketEntry { min_max_version: None, seen_our_dial_info: false, last_connection: None, - dial_infos: Vec::new(), + node_info: NodeInfo::default(), latency_stats_accounting: LatencyStatsAccounting::new(), transfer_stats_accounting: TransferStatsAccounting::new(), peer_stats: PeerStats { @@ -60,7 +60,7 @@ impl BucketEntry { ping_stats: PingStats::default(), latency: None, transfer: TransferStatsDownUp::default(), - node_info: None, + status: None, }, } } @@ -105,50 +105,37 @@ impl BucketEntry { move |e1, e2| Self::cmp_fastest_reliable(cur_ts, e1, e2) } - pub fn update_dial_infos(&mut self, dial_infos: &[DialInfo]) { - self.dial_infos = dial_infos.to_vec(); - self.dial_infos.sort(); + pub fn update_node_info(&mut self, node_info: NodeInfo) { + self.node_info = node_info } - pub fn update_single_dial_info(&mut self, dial_info: &DialInfo) { - let dif = dial_info.make_filter(true); - self.dial_infos.retain(|di| !di.matches_filter(&dif)); - self.dial_infos.push(dial_info.clone()); - self.dial_infos.sort(); + pub fn node_info(&self) -> &NodeInfo { + &self.node_info } - pub fn first_filtered_dial_info(&self, filter: F) -> Option + pub fn first_filtered_node_info(&self, filter: F) -> Option where F: Fn(&DialInfo) -> bool, { - for di in &self.dial_infos { - if filter(di) { - return Some(di.clone()); - } + let out = self.node_info.first_filtered(filter); + if out.dial_infos.is_empty() && out.relay_dial_infos.is_empty() { + None + } else { + Some(out) } - None } - pub fn all_filtered_dial_infos(&self, filter: F) -> Vec + + pub fn all_filtered_node_info(&self, filter: F) -> NodeInfo where F: Fn(&DialInfo) -> bool, { - let mut ret = Vec::new(); - for di in &self.dial_infos { - if filter(di) { - ret.push(di.clone()); - } - } - ret - } - - pub fn dial_infos(&self) -> &[DialInfo] { - &self.dial_infos + self.node_info.all_filtered(filter) } pub fn get_peer_info(&self, key: DHTKey, scope: PeerScope) -> PeerInfo { PeerInfo { node_id: NodeId::new(key), - dial_infos: self.all_filtered_dial_infos(|di| di.matches_peer_scope(scope)), + node_info: self.all_filtered_node_info(|di| di.matches_peer_scope(scope)), } } @@ -182,8 +169,8 @@ impl BucketEntry { &self.peer_stats } - pub fn update_node_info(&mut self, node_info: NodeInfo) { - self.peer_stats.node_info = Some(node_info); + pub fn update_node_status(&mut self, status: NodeStatus) { + self.peer_stats.status = Some(status); } pub fn set_seen_our_dial_info(&mut self, seen: bool) { @@ -250,12 +237,8 @@ impl BucketEntry { // See which ping pattern we are to use let state = self.state(cur_ts); - // If the current dial info hasn't been recognized then we gotta ping regardless - if !self.seen_our_dial_info && matches!(state, BucketEntryState::Reliable) { - return self.needs_constant_ping(cur_ts, UNRELIABLE_PING_INTERVAL_SECS as u64); - } - // If this entry is our relay node, then we should ping it regularly - else if let Some(relay_node) = relay_node { + // If this entry is our relay node, then we should ping it regularly to keep our association alive + if let Some(relay_node) = relay_node { if relay_node.node_id() == *node_id { return self.needs_constant_ping(cur_ts, KEEPALIVE_PING_INTERVAL_SECS as u64); } diff --git a/veilid-core/src/routing_table/find_nodes.rs b/veilid-core/src/routing_table/find_nodes.rs index b779639a..71c5e483 100644 --- a/veilid-core/src/routing_table/find_nodes.rs +++ b/veilid-core/src/routing_table/find_nodes.rs @@ -21,7 +21,7 @@ impl RoutingTable { .1 .as_ref() .unwrap() - .first_filtered_dial_info(|di| di.matches_filter(&dial_info_filter1)) + .first_filtered_node_info(|di| di.matches_filter(&dial_info_filter1)) .is_some() }, )), @@ -39,14 +39,21 @@ impl RoutingTable { pub fn get_own_peer_info(&self, scope: PeerScope) -> PeerInfo { let filter = DialInfoFilter::scoped(scope); - + let netman = self.network_manager(); + let relay_node = netman.relay_node(); PeerInfo { node_id: NodeId::new(self.node_id()), - dial_infos: self - .all_filtered_dial_info_details(&filter) - .iter() - .map(|did| did.dial_info.clone()) - .collect(), + node_info: NodeInfo { + network_class: netman.get_network_class().unwrap_or(NetworkClass::Invalid), + dial_infos: self + .all_filtered_dial_info_details(&filter) + .iter() + .map(|did| did.dial_info.clone()) + .collect(), + relay_dial_infos: relay_node + .map(|rn| rn.node_info().dial_infos) + .unwrap_or_default(), + }, } } diff --git a/veilid-core/src/routing_table/mod.rs b/veilid-core/src/routing_table/mod.rs index 246ad9bd..44cd29e6 100644 --- a/veilid-core/src/routing_table/mod.rs +++ b/veilid-core/src/routing_table/mod.rs @@ -268,6 +268,7 @@ impl RoutingTable { e.1.set_seen_our_dial_info(false); } } + // // Release any waiters let mut new_eventual = Eventual::new(); @@ -420,14 +421,14 @@ impl RoutingTable { // Shortcut function to add a node to our routing table if it doesn't exist // and add the dial info we have for it, since that's pretty common - pub fn register_node_with_dial_info( + pub fn register_node_with_node_info( &self, node_id: DHTKey, - dial_infos: &[DialInfo], + node_info: NodeInfo, ) -> Result { let nr = self.create_node_ref(node_id)?; nr.operate(move |e| -> Result<(), String> { - e.update_dial_infos(dial_infos); + e.update_node_info(node_info); Ok(()) })?; @@ -451,21 +452,6 @@ impl RoutingTable { Ok(nr) } - // Add a node if it doesn't exist, or update a single dial info on an already registered node - pub fn update_node_with_single_dial_info( - &self, - node_id: DHTKey, - dial_info: &DialInfo, - ) -> Result { - let nr = self.create_node_ref(node_id)?; - nr.operate(move |e| -> Result<(), String> { - e.update_single_dial_info(dial_info); - Ok(()) - })?; - - Ok(nr) - } - fn operate_on_bucket_entry(&self, node_id: DHTKey, f: F) -> T where F: FnOnce(&mut BucketEntry) -> T, @@ -487,9 +473,9 @@ impl RoutingTable { // Ensure it's not dead if !matches!(entry.state(cur_ts), BucketEntryState::Dead) { // Ensure we have a node info - if let Some(node_info) = &entry.peer_stats().node_info { - // Ensure network class can relay - if node_info.network_class.can_inbound_relay() { + if let Some(node_status) = &entry.peer_stats().status { + // Ensure the node will relay + if node_status.will_relay { if let Some(best_inbound_relay) = best_inbound_relay.as_mut() { if best_inbound_relay.operate(|best| { BucketEntry::cmp_fastest_reliable(cur_ts, best, entry) @@ -547,12 +533,12 @@ impl RoutingTable { // register the node if it's new let nr = self - .register_node_with_dial_info(p.node_id.key, &p.dial_infos) + .register_node_with_node_info(p.node_id.key, p.node_info.clone()) .map_err(map_to_string) .map_err(logthru_rtab!( "couldn't register node {} at {:?}", p.node_id.key, - &p.dial_infos + &p.node_info ))?; out.push(nr); } @@ -617,10 +603,17 @@ impl RoutingTable { // Run all bootstrap operations concurrently let mut unord = FuturesUnordered::new(); for (k, v) in bsmap { - let nr = self - .register_node_with_dial_info(k, &v) - .map_err(logthru_rtab!("Couldn't add bootstrap node: {}", k))?; log_rtab!(" bootstrapping {} with {:?}", k.encode(), &v); + let nr = self + .register_node_with_node_info( + k, + NodeInfo { + network_class: NetworkClass::Server, + dial_infos: v, + relay_dial_infos: Default::default(), + }, + ) + .map_err(logthru_rtab!("Couldn't add bootstrap node: {}", k))?; unord.push(self.reverse_find_node(nr, true)); } while unord.next().await.is_some() {} diff --git a/veilid-core/src/routing_table/node_ref.rs b/veilid-core/src/routing_table/node_ref.rs index b665efae..554972fb 100644 --- a/veilid-core/src/routing_table/node_ref.rs +++ b/veilid-core/src/routing_table/node_ref.rs @@ -46,6 +46,14 @@ impl NodeRef { self.routing_table.operate_on_bucket_entry(self.node_id, f) } + pub fn node_info(&self) -> NodeInfo { + self.operate(|e| e.node_info().clone()) + } + + pub fn has_dial_info(&self) -> bool { + self.operate(|e| !e.node_info().dial_infos.is_empty()) + } + // Returns if this node has seen and acknowledged our node's dial info yet pub fn has_seen_our_dial_info(&self) -> bool { self.operate(|e| e.has_seen_our_dial_info()) @@ -54,12 +62,12 @@ impl NodeRef { self.operate(|e| e.set_seen_our_dial_info(true)); } - // Returns the best dial info to attempt a connection to this node - pub fn best_dial_info(&self) -> Option { + // Returns the best node info to attempt a connection to this node + pub fn best_node_info(&self) -> Option { let nm = self.routing_table.network_manager(); let protocol_config = nm.get_protocol_config()?; self.operate(|e| { - e.first_filtered_dial_info(|di| { + e.first_filtered_node_info(|di| { // Does it match the dial info filter if !di.matches_filter(&self.dial_info_filter) { return false; diff --git a/veilid-core/src/rpc_processor/coders/mod.rs b/veilid-core/src/rpc_processor/coders/mod.rs index 8080991d..f9594371 100644 --- a/veilid-core/src/rpc_processor/coders/mod.rs +++ b/veilid-core/src/rpc_processor/coders/mod.rs @@ -3,6 +3,7 @@ mod dial_info; mod network_class; mod node_dial_info; mod node_info; +mod node_status; mod nonce; mod peer_info; mod private_safety_route; @@ -15,6 +16,7 @@ pub use dial_info::*; pub use network_class::*; pub use node_dial_info::*; pub use node_info::*; +pub use node_status::*; pub use nonce::*; pub use peer_info::*; pub use private_safety_route::*; diff --git a/veilid-core/src/rpc_processor/coders/node_info.rs b/veilid-core/src/rpc_processor/coders/node_info.rs index 448a3370..e88690b3 100644 --- a/veilid-core/src/rpc_processor/coders/node_info.rs +++ b/veilid-core/src/rpc_processor/coders/node_info.rs @@ -6,27 +6,77 @@ pub fn encode_node_info( builder: &mut veilid_capnp::node_info::Builder, ) -> Result<(), RPCError> { builder.set_network_class(encode_network_class(node_info.network_class)); - builder.set_will_route(node_info.will_route); - builder.set_will_tunnel(node_info.will_tunnel); - builder.set_will_signal(node_info.will_signal); - builder.set_will_relay(node_info.will_relay); - builder.set_will_validate_dial_info(node_info.will_validate_dial_info); + + let mut dil_builder = builder.reborrow().init_dial_info_list( + node_info + .dial_infos + .len() + .try_into() + .map_err(map_error_protocol!("too many dial infos in node info"))?, + ); + + for idx in 0..node_info.dial_infos.len() { + let mut di_builder = dil_builder.reborrow().get(idx as u32); + encode_dial_info(&node_info.dial_infos[idx], &mut di_builder)?; + } + + let mut rdil_builder = builder.reborrow().init_relay_dial_info_list( + node_info + .relay_dial_infos + .len() + .try_into() + .map_err(map_error_protocol!( + "too many relay dial infos in node info" + ))?, + ); + + for idx in 0..node_info.relay_dial_infos.len() { + let mut rdi_builder = rdil_builder.reborrow().get(idx as u32); + encode_dial_info(&node_info.relay_dial_infos[idx], &mut rdi_builder)?; + } Ok(()) } pub fn decode_node_info(reader: &veilid_capnp::node_info::Reader) -> Result { + let network_class = decode_network_class( + reader + .reborrow() + .get_network_class() + .map_err(map_error_capnp_notinschema!())?, + ); + + let dil_reader = reader + .reborrow() + .get_dial_info_list() + .map_err(map_error_capnp_error!())?; + let mut dial_infos = Vec::::with_capacity( + dil_reader + .len() + .try_into() + .map_err(map_error_protocol!("too many dial infos"))?, + ); + for di in dil_reader.iter() { + dial_infos.push(decode_dial_info(&di)?) + } + + let rdil_reader = reader + .reborrow() + .get_relay_dial_info_list() + .map_err(map_error_capnp_error!())?; + let mut relay_dial_infos = Vec::::with_capacity( + rdil_reader + .len() + .try_into() + .map_err(map_error_protocol!("too many relay dial infos"))?, + ); + for di in rdil_reader.iter() { + relay_dial_infos.push(decode_dial_info(&di)?) + } + Ok(NodeInfo { - network_class: decode_network_class( - reader - .reborrow() - .get_network_class() - .map_err(map_error_capnp_notinschema!())?, - ), - will_route: reader.reborrow().get_will_route(), - will_tunnel: reader.reborrow().get_will_tunnel(), - will_signal: reader.reborrow().get_will_signal(), - will_relay: reader.reborrow().get_will_relay(), - will_validate_dial_info: reader.reborrow().get_will_validate_dial_info(), + network_class, + dial_infos, + relay_dial_infos, }) } diff --git a/veilid-core/src/rpc_processor/coders/node_status.rs b/veilid-core/src/rpc_processor/coders/node_status.rs new file mode 100644 index 00000000..5e42a42f --- /dev/null +++ b/veilid-core/src/rpc_processor/coders/node_status.rs @@ -0,0 +1,27 @@ +use crate::*; +use rpc_processor::*; + +pub fn encode_node_status( + node_status: &NodeStatus, + builder: &mut veilid_capnp::node_status::Builder, +) -> Result<(), RPCError> { + builder.set_will_route(node_status.will_route); + builder.set_will_tunnel(node_status.will_tunnel); + builder.set_will_signal(node_status.will_signal); + builder.set_will_relay(node_status.will_relay); + builder.set_will_validate_dial_info(node_status.will_validate_dial_info); + + Ok(()) +} + +pub fn decode_node_status( + reader: &veilid_capnp::node_status::Reader, +) -> Result { + Ok(NodeStatus { + will_route: reader.reborrow().get_will_route(), + will_tunnel: reader.reborrow().get_will_tunnel(), + will_signal: reader.reborrow().get_will_signal(), + will_relay: reader.reborrow().get_will_relay(), + will_validate_dial_info: reader.reborrow().get_will_validate_dial_info(), + }) +} diff --git a/veilid-core/src/rpc_processor/coders/peer_info.rs b/veilid-core/src/rpc_processor/coders/peer_info.rs index 77eec87a..49d2c068 100644 --- a/veilid-core/src/rpc_processor/coders/peer_info.rs +++ b/veilid-core/src/rpc_processor/coders/peer_info.rs @@ -1,6 +1,4 @@ -use crate::xx::*; use crate::*; -use core::convert::TryInto; use rpc_processor::*; pub fn encode_peer_info( @@ -10,18 +8,9 @@ pub fn encode_peer_info( // let mut nid_builder = builder.reborrow().init_node_id(); encode_public_key(&peer_info.node_id.key, &mut nid_builder)?; - let mut dil_builder = builder.reborrow().init_dial_info_list( - peer_info - .dial_infos - .len() - .try_into() - .map_err(map_error_protocol!("too many dial infos in peer info"))?, - ); + let mut ni_builder = builder.reborrow().init_node_info(); + encode_node_info(&peer_info.node_info, &mut ni_builder)?; - for idx in 0..peer_info.dial_infos.len() { - let mut di_builder = dil_builder.reborrow().get(idx as u32); - encode_dial_info(&peer_info.dial_infos[idx], &mut di_builder)?; - } Ok(()) } @@ -30,21 +19,14 @@ pub fn decode_peer_info(reader: &veilid_capnp::peer_info::Reader) -> Result::with_capacity( - dil_reader - .len() - .try_into() - .map_err(map_error_protocol!("too many dial infos"))?, - ); - for di in dil_reader.iter() { - dial_infos.push(decode_dial_info(&di)?) - } + let node_info = decode_node_info(&ni_reader)?; + Ok(PeerInfo { node_id: NodeId::new(decode_public_key(&nid_reader)), - dial_infos, + node_info, }) } diff --git a/veilid-core/src/rpc_processor/mod.rs b/veilid-core/src/rpc_processor/mod.rs index 679f1a41..6f59e536 100644 --- a/veilid-core/src/rpc_processor/mod.rs +++ b/veilid-core/src/rpc_processor/mod.rs @@ -30,7 +30,7 @@ pub enum Destination { #[derive(Debug, Clone)] pub enum RespondTo { None, - Sender(Option), + Sender(Option), PrivateRoute(PrivateRoute), } @@ -43,9 +43,9 @@ impl RespondTo { Self::None => { builder.set_none(()); } - Self::Sender(Some(di)) => { - let mut di_builder = builder.reborrow().init_sender(); - encode_dial_info(di, &mut di_builder)?; + Self::Sender(Some(ni)) => { + let mut ni_builder = builder.reborrow().init_sender(); + encode_node_info(ni, &mut ni_builder)?; } Self::Sender(None) => { builder.reborrow().init_sender(); @@ -220,7 +220,13 @@ impl RPCProcessor { fn filter_peer_scope(&self, peer_info: &PeerInfo) -> bool { // reject attempts to include non-public addresses in results if self.default_peer_scope == PeerScope::Global { - for di in &peer_info.dial_infos { + for di in &peer_info.node_info.dial_infos { + if !di.is_global() { + // non-public address causes rejection + return false; + } + } + for di in &peer_info.node_info.relay_dial_infos { if !di.is_global() { // non-public address causes rejection return false; @@ -273,7 +279,7 @@ impl RPCProcessor { if let Some(nr) = routing_table.lookup_node_ref(node_id) { // ensure we have dial_info for the entry already, // if not, we should do the find_node anyway - if !nr.operate(|e| e.dial_infos().is_empty()) { + if !nr.has_dial_info() { return Ok(nr); } } diff --git a/veilid-core/src/veilid_api/mod.rs b/veilid-core/src/veilid_api/mod.rs index 7f5f3857..76d69f04 100644 --- a/veilid-core/src/veilid_api/mod.rs +++ b/veilid-core/src/veilid_api/mod.rs @@ -313,8 +313,7 @@ impl Default for NetworkClass { } #[derive(Clone, Debug, Default, Serialize, Deserialize)] -pub struct NodeInfo { - pub network_class: NetworkClass, +pub struct NodeStatus { pub will_route: bool, pub will_tunnel: bool, pub will_signal: bool, @@ -322,6 +321,56 @@ pub struct NodeInfo { pub will_validate_dial_info: bool, } +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +pub struct NodeInfo { + pub network_class: NetworkClass, + pub dial_infos: Vec, + pub relay_dial_infos: Vec, +} + +impl NodeInfo { + pub fn first_filtered(&self, filter: F) -> NodeInfo + where + F: Fn(&DialInfo) -> bool, + { + let mut node_info = NodeInfo::default(); + node_info.network_class = self.network_class; + + for di in &self.dial_infos { + if filter(di) { + node_info.dial_infos.push(di.clone()); + break; + } + } + for di in &self.relay_dial_infos { + if filter(di) { + node_info.relay_dial_infos.push(di.clone()); + break; + } + } + node_info + } + pub fn all_filtered(&self, filter: F) -> NodeInfo + where + F: Fn(&DialInfo) -> bool, + { + let mut node_info = NodeInfo::default(); + node_info.network_class = self.network_class; + + for di in &self.dial_infos { + if filter(di) { + node_info.dial_infos.push(di.clone()); + } + } + for di in &self.relay_dial_infos { + if filter(di) { + node_info.relay_dial_infos.push(di.clone()); + } + } + node_info + } +} + #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Serialize, Deserialize)] // The derived ordering here is the order of preference, lower is preferred for connections // Must match DialInfo order @@ -569,6 +618,13 @@ pub struct DialInfoWSS { pub request: String, } +#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize)] +#[serde(tag = "kind")] +pub enum DialInfoClass { + Direct, + Relay, +} + #[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize)] #[serde(tag = "kind")] // The derived ordering here is the order of preference, lower is preferred for connections @@ -834,7 +890,7 @@ impl Default for PeerScope { #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct PeerInfo { pub node_id: NodeId, - pub dial_infos: Vec, + pub node_info: NodeInfo, } #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] @@ -989,7 +1045,7 @@ pub struct PeerStats { pub ping_stats: PingStats, // information about pings pub latency: Option, // latencies for communications with the peer pub transfer: TransferStatsDownUp, // Stats for communications with the peer - pub node_info: Option, // Last known node info + pub status: Option, // Last known node status } cfg_if! {