clippy work

This commit is contained in:
Christien Rioux 2023-09-17 20:45:30 -04:00
parent 6438a64fc7
commit e4ee093951
19 changed files with 350 additions and 234 deletions

View File

@ -396,7 +396,7 @@ impl NetworkManager {
dial_info_failures_map.insert(did.dial_info, ts); dial_info_failures_map.insert(did.dial_info, ts);
} }
} }
let dif_sort: Option<Arc<dyn Fn(&DialInfoDetail, &DialInfoDetail) -> core::cmp::Ordering>> = if dial_info_failures_map.is_empty() { let dif_sort: Option<Arc<DialInfoDetailSort>> = if dial_info_failures_map.is_empty() {
None None
} else { } else {
Some(Arc::new(move |a: &DialInfoDetail, b: &DialInfoDetail| { Some(Arc::new(move |a: &DialInfoDetail, b: &DialInfoDetail| {

View File

@ -75,8 +75,8 @@ impl Bucket {
}); });
} }
let bucket_data = SerializedBucketData { entries }; let bucket_data = SerializedBucketData { entries };
let out = serialize_json_bytes(&bucket_data);
out serialize_json_bytes(bucket_data)
} }
/// Create a new entry with a node_id of this crypto kind and return it /// Create a new entry with a node_id of this crypto kind and return it
@ -129,11 +129,8 @@ impl Bucket {
let mut extra_entries = bucket_len - bucket_depth; let mut extra_entries = bucket_len - bucket_depth;
// Get the sorted list of entries by their kick order // Get the sorted list of entries by their kick order
let mut sorted_entries: Vec<(PublicKey, Arc<BucketEntry>)> = self let mut sorted_entries: Vec<(PublicKey, Arc<BucketEntry>)> =
.entries self.entries.iter().map(|(k, v)| (*k, v.clone())).collect();
.iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect();
let cur_ts = get_aligned_timestamp(); let cur_ts = get_aligned_timestamp();
sorted_entries.sort_by(|a, b| -> core::cmp::Ordering { sorted_entries.sort_by(|a, b| -> core::cmp::Ordering {
if a.0 == b.0 { if a.0 == b.0 {

View File

@ -492,7 +492,7 @@ impl BucketEntryInner {
} }
if !only_live { if !only_live {
return Some(v.clone()); return Some(*v);
} }
// Check if the connection is still considered live // Check if the connection is still considered live
@ -509,7 +509,7 @@ impl BucketEntryInner {
}; };
if alive { if alive {
Some(v.clone()) Some(*v)
} else { } else {
None None
} }
@ -583,13 +583,11 @@ impl BucketEntryInner {
RoutingDomain::LocalNetwork => self RoutingDomain::LocalNetwork => self
.local_network .local_network
.node_status .node_status
.as_ref() .as_ref().cloned(),
.map(|ns| ns.clone()),
RoutingDomain::PublicInternet => self RoutingDomain::PublicInternet => self
.public_internet .public_internet
.node_status .node_status
.as_ref() .as_ref().cloned()
.map(|ns| ns.clone()),
} }
} }
@ -892,7 +890,7 @@ impl BucketEntry {
F: FnOnce(&RoutingTableInner, &BucketEntryInner) -> R, F: FnOnce(&RoutingTableInner, &BucketEntryInner) -> R,
{ {
let inner = self.inner.read(); let inner = self.inner.read();
f(rti, &*inner) f(rti, &inner)
} }
// Note, that this requires -also- holding the RoutingTable write lock, as a // Note, that this requires -also- holding the RoutingTable write lock, as a
@ -902,7 +900,7 @@ impl BucketEntry {
F: FnOnce(&mut RoutingTableInner, &mut BucketEntryInner) -> R, F: FnOnce(&mut RoutingTableInner, &mut BucketEntryInner) -> R,
{ {
let mut inner = self.inner.write(); let mut inner = self.inner.write();
f(rti, &mut *inner) f(rti, &mut inner)
} }
// Internal inner access for RoutingTableInner only // Internal inner access for RoutingTableInner only
@ -911,7 +909,7 @@ impl BucketEntry {
F: FnOnce(&BucketEntryInner) -> R, F: FnOnce(&BucketEntryInner) -> R,
{ {
let inner = self.inner.read(); let inner = self.inner.read();
f(&*inner) f(&inner)
} }
// Internal inner access for RoutingTableInner only // Internal inner access for RoutingTableInner only
@ -920,7 +918,7 @@ impl BucketEntry {
F: FnOnce(&mut BucketEntryInner) -> R, F: FnOnce(&mut BucketEntryInner) -> R,
{ {
let mut inner = self.inner.write(); let mut inner = self.inner.write();
f(&mut *inner) f(&mut inner)
} }
} }

View File

@ -112,7 +112,7 @@ impl RoutingTable {
let mut out = String::new(); let mut out = String::new();
out += &format!("Entries: {}\n", inner.bucket_entry_count()); out += &format!("Entries: {}\n", inner.bucket_entry_count());
out += &format!(" Live:\n"); out += " Live:\n";
for ec in inner.cached_entry_counts() { for ec in inner.cached_entry_counts() {
let routing_domain = ec.0 .0; let routing_domain = ec.0 .0;
let crypto_kind = ec.0 .1; let crypto_kind = ec.0 .1;

View File

@ -129,7 +129,7 @@ impl RoutingTableUnlockedInner {
where where
F: FnOnce(&VeilidConfigInner) -> R, F: FnOnce(&VeilidConfigInner) -> R,
{ {
f(&*self.config.get()) f(&self.config.get())
} }
pub fn node_id(&self, kind: CryptoKind) -> TypedKey { pub fn node_id(&self, kind: CryptoKind) -> TypedKey {
@ -541,7 +541,7 @@ impl RoutingTable {
peer_b: &PeerInfo, peer_b: &PeerInfo,
dial_info_filter: DialInfoFilter, dial_info_filter: DialInfoFilter,
sequencing: Sequencing, sequencing: Sequencing,
dif_sort: Option<Arc<dyn Fn(&DialInfoDetail, &DialInfoDetail) -> core::cmp::Ordering>>, dif_sort: Option<Arc<DialInfoDetailSort>>,
) -> ContactMethod { ) -> ContactMethod {
self.inner.read().get_contact_method( self.inner.read().get_contact_method(
routing_domain, routing_domain,
@ -885,7 +885,7 @@ impl RoutingTable {
crypto_kind: CryptoKind, crypto_kind: CryptoKind,
max_per_type: usize, max_per_type: usize,
) -> Vec<NodeRef> { ) -> Vec<NodeRef> {
let protocol_types = vec![ let protocol_types = [
ProtocolType::UDP, ProtocolType::UDP,
ProtocolType::TCP, ProtocolType::TCP,
ProtocolType::WS, ProtocolType::WS,
@ -893,8 +893,8 @@ impl RoutingTable {
]; ];
let protocol_types_len = protocol_types.len(); let protocol_types_len = protocol_types.len();
let mut nodes_proto_v4 = vec![0usize, 0usize, 0usize, 0usize]; let mut nodes_proto_v4 = [0usize, 0usize, 0usize, 0usize];
let mut nodes_proto_v6 = vec![0usize, 0usize, 0usize, 0usize]; let mut nodes_proto_v6 = [0usize, 0usize, 0usize, 0usize];
let filter = Box::new( let filter = Box::new(
move |rti: &RoutingTableInner, entry: Option<Arc<BucketEntry>>| { move |rti: &RoutingTableInner, entry: Option<Arc<BucketEntry>>| {

View File

@ -85,7 +85,7 @@ pub trait NodeRefBase: Sized {
self.common() self.common()
.filter .filter
.as_ref() .as_ref()
.map(|f| f.dial_info_filter.clone()) .map(|f| f.dial_info_filter)
.unwrap_or(DialInfoFilter::all()) .unwrap_or(DialInfoFilter::all())
} }
@ -283,7 +283,7 @@ pub trait NodeRefBase: Sized {
self.operate(|rti, e| { self.operate(|rti, e| {
// apply sequencing to filter and get sort // apply sequencing to filter and get sort
let sequencing = self.common().sequencing; let sequencing = self.common().sequencing;
let filter = self.common().filter.clone().unwrap_or_default(); let filter = self.common().filter.unwrap_or_default();
let (ordered, filter) = filter.with_sequencing(sequencing); let (ordered, filter) = filter.with_sequencing(sequencing);
let mut last_connections = e.last_connections(rti, true, filter); let mut last_connections = e.last_connections(rti, true, filter);
@ -444,7 +444,7 @@ impl Clone for NodeRef {
common: NodeRefBaseCommon { common: NodeRefBaseCommon {
routing_table: self.common.routing_table.clone(), routing_table: self.common.routing_table.clone(),
entry: self.common.entry.clone(), entry: self.common.entry.clone(),
filter: self.common.filter.clone(), filter: self.common.filter,
sequencing: self.common.sequencing, sequencing: self.common.sequencing,
#[cfg(feature = "tracking")] #[cfg(feature = "tracking")]
track_id: self.common.entry.write().track(), track_id: self.common.entry.write().track(),

View File

@ -18,7 +18,7 @@ pub enum RouteNode {
/// Route node is optimized, no contact method information as this node id has been seen before /// Route node is optimized, no contact method information as this node id has been seen before
NodeId(PublicKey), NodeId(PublicKey),
/// Route node with full contact method information to ensure the peer is reachable /// Route node with full contact method information to ensure the peer is reachable
PeerInfo(PeerInfo), PeerInfo(Box<PeerInfo>),
} }
impl RouteNode { impl RouteNode {
@ -41,7 +41,7 @@ impl RouteNode {
Ok(nr) => nr, Ok(nr) => nr,
Err(e) => { Err(e) => {
log_rtab!(debug "failed to look up route node: {}", e); log_rtab!(debug "failed to look up route node: {}", e);
return None; None
} }
} }
} }
@ -49,13 +49,13 @@ impl RouteNode {
// //
match routing_table.register_node_with_peer_info( match routing_table.register_node_with_peer_info(
RoutingDomain::PublicInternet, RoutingDomain::PublicInternet,
pi.clone(), *pi.clone(),
false, false,
) { ) {
Ok(nr) => Some(nr), Ok(nr) => Some(nr),
Err(e) => { Err(e) => {
log_rtab!(debug "failed to register route node: {}", e); log_rtab!(debug "failed to register route node: {}", e);
return None; None
} }
} }
} }
@ -95,7 +95,7 @@ impl RouteHop {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum PrivateRouteHops { pub enum PrivateRouteHops {
/// The first hop of a private route, unencrypted, route_hops == total hop count /// The first hop of a private route, unencrypted, route_hops == total hop count
FirstHop(RouteHop), FirstHop(Box<RouteHop>),
/// Private route internal node. Has > 0 private route hops left but < total hop count /// Private route internal node. Has > 0 private route hops left but < total hop count
Data(RouteHopData), Data(RouteHopData),
/// Private route has ended (hop count = 0) /// Private route has ended (hop count = 0)
@ -134,10 +134,10 @@ impl PrivateRoute {
Self { Self {
public_key, public_key,
hop_count: 1, hop_count: 1,
hops: PrivateRouteHops::FirstHop(RouteHop { hops: PrivateRouteHops::FirstHop(Box::new(RouteHop {
node, node,
next_hop: None, next_hop: None,
}), })),
} }
} }

View File

@ -13,7 +13,7 @@ fn _get_route_permutation_count(hop_count: usize) -> usize {
// more than two nodes has factorial permutation // more than two nodes has factorial permutation
// hop_count = 3 -> 2! -> 2 // hop_count = 3 -> 2! -> 2
// hop_count = 4 -> 3! -> 6 // hop_count = 4 -> 3! -> 6
(3..hop_count).into_iter().fold(2usize, |acc, x| acc * x) (3..hop_count).fold(2usize, |acc, x| acc * x)
} }
pub type PermReturnType = (Vec<usize>, bool); pub type PermReturnType = (Vec<usize>, bool);
pub type PermFunc<'t> = Box<dyn FnMut(&[usize]) -> Option<PermReturnType> + Send + 't>; pub type PermFunc<'t> = Box<dyn FnMut(&[usize]) -> Option<PermReturnType> + Send + 't>;
@ -47,7 +47,7 @@ pub fn with_route_permutations(
f: &mut PermFunc, f: &mut PermFunc,
) -> Option<PermReturnType> { ) -> Option<PermReturnType> {
if size == 1 { if size == 1 {
return f(&permutation); return f(permutation);
} }
for i in 0..size { for i in 0..size {

View File

@ -112,7 +112,7 @@ impl RouteSetSpecDetail {
} }
pub fn contains_nodes(&self, nodes: &[TypedKey]) -> bool { pub fn contains_nodes(&self, nodes: &[TypedKey]) -> bool {
for tk in nodes { for tk in nodes {
for (_pk, rsd) in &self.route_set { for rsd in self.route_set.values() {
if rsd.crypto_kind == tk.kind && rsd.hops.contains(&tk.value) { if rsd.crypto_kind == tk.kind && rsd.hops.contains(&tk.value) {
return true; return true;
} }

View File

@ -90,7 +90,6 @@ impl RouteSpecStore {
Ok(rss) Ok(rss)
} }
#[instrument(level = "trace", skip(self), err)] #[instrument(level = "trace", skip(self), err)]
pub async fn save(&self) -> EyreResult<()> { pub async fn save(&self) -> EyreResult<()> {
let content = { let content = {
@ -99,7 +98,9 @@ impl RouteSpecStore {
}; };
// Save our content // Save our content
content.save(self.unlocked_inner.routing_table.clone()).await?; content
.save(self.unlocked_inner.routing_table.clone())
.await?;
Ok(()) Ok(())
} }
@ -166,6 +167,7 @@ impl RouteSpecStore {
} }
#[instrument(level = "trace", skip(self, inner, rti), ret, err)] #[instrument(level = "trace", skip(self, inner, rti), ret, err)]
#[allow(clippy::too_many_arguments)]
fn allocate_route_inner( fn allocate_route_inner(
&self, &self,
inner: &mut RouteSpecStoreInner, inner: &mut RouteSpecStoreInner,
@ -197,7 +199,9 @@ impl RouteSpecStore {
let our_peer_info = rti.get_own_peer_info(RoutingDomain::PublicInternet); 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));
// Get list of all nodes, and sort them for selection // Get list of all nodes, and sort them for selection
let cur_ts = get_aligned_timestamp(); let cur_ts = get_aligned_timestamp();
@ -218,7 +222,6 @@ impl RouteSpecStore {
// Process node info exclusions // Process node info exclusions
let keep = entry.with_inner(|e| { let keep = entry.with_inner(|e| {
// Exclude nodes that don't have our requested crypto kinds // Exclude nodes that don't have our requested crypto kinds
let common_ck = e.common_crypto_kinds(crypto_kinds); let common_ck = e.common_crypto_kinds(crypto_kinds);
if common_ck.len() != crypto_kinds.len() { if common_ck.len() != crypto_kinds.len() {
@ -242,7 +245,7 @@ impl RouteSpecStore {
// Relay check // Relay check
let relay_ids = sni.relay_ids(); let relay_ids = sni.relay_ids();
if relay_ids.len() != 0 { if !relay_ids.is_empty() {
// Exclude nodes whose relays we have chosen to avoid // Exclude nodes whose relays we have chosen to avoid
if relay_ids.contains_any(avoid_nodes) { if relay_ids.contains_any(avoid_nodes) {
return false; return false;
@ -254,7 +257,7 @@ impl RouteSpecStore {
} }
} }
} }
return true; true
}); });
if !keep { if !keep {
return false; return false;
@ -262,9 +265,12 @@ impl RouteSpecStore {
// Exclude nodes with no publicinternet nodeinfo, or incompatible nodeinfo or node status won't route // Exclude nodes with no publicinternet nodeinfo, or incompatible nodeinfo or node status won't route
entry.with_inner(|e| { entry.with_inner(|e| {
e.signed_node_info(RoutingDomain::PublicInternet).map(|sni| e.signed_node_info(RoutingDomain::PublicInternet)
sni.has_sequencing_matched_dial_info(sequencing) && sni.node_info().has_capability(CAP_ROUTE) .map(|sni| {
).unwrap_or(false) sni.has_sequencing_matched_dial_info(sequencing)
&& sni.node_info().has_capability(CAP_ROUTE)
})
.unwrap_or(false)
}) })
}, },
) as RoutingTableEntryFilter; ) as RoutingTableEntryFilter;
@ -273,7 +279,6 @@ impl RouteSpecStore {
entry1: &Option<Arc<BucketEntry>>, entry1: &Option<Arc<BucketEntry>>,
entry2: &Option<Arc<BucketEntry>>| entry2: &Option<Arc<BucketEntry>>|
-> Ordering { -> Ordering {
// Our own node is filtered out // Our own node is filtered out
let entry1 = entry1.as_ref().unwrap().clone(); let entry1 = entry1.as_ref().unwrap().clone();
let entry2 = entry2.as_ref().unwrap().clone(); let entry2 = entry2.as_ref().unwrap().clone();
@ -302,8 +307,14 @@ impl RouteSpecStore {
if matches!(sequencing, Sequencing::PreferOrdered) { if matches!(sequencing, Sequencing::PreferOrdered) {
let cmp_seq = entry1.with_inner(|e1| { let cmp_seq = entry1.with_inner(|e1| {
entry2.with_inner(|e2| { entry2.with_inner(|e2| {
let e1_can_do_ordered = e1.signed_node_info(RoutingDomain::PublicInternet).map(|sni| sni.has_sequencing_matched_dial_info(sequencing)).unwrap_or(false); let e1_can_do_ordered = e1
let e2_can_do_ordered = e2.signed_node_info(RoutingDomain::PublicInternet).map(|sni| sni.has_sequencing_matched_dial_info(sequencing)).unwrap_or(false); .signed_node_info(RoutingDomain::PublicInternet)
.map(|sni| sni.has_sequencing_matched_dial_info(sequencing))
.unwrap_or(false);
let e2_can_do_ordered = e2
.signed_node_info(RoutingDomain::PublicInternet)
.map(|sni| sni.has_sequencing_matched_dial_info(sequencing))
.unwrap_or(false);
e2_can_do_ordered.cmp(&e1_can_do_ordered) e2_can_do_ordered.cmp(&e1_can_do_ordered)
}) })
}); });
@ -313,27 +324,22 @@ impl RouteSpecStore {
} }
// always prioritize reliable nodes, but sort by oldest or fastest // always prioritize reliable nodes, but sort by oldest or fastest
let cmpout = entry1.with_inner(|e1| {
entry1.with_inner(|e1| {
entry2.with_inner(|e2| match stability { entry2.with_inner(|e2| match stability {
Stability::LowLatency => { Stability::LowLatency => BucketEntryInner::cmp_fastest_reliable(cur_ts, e1, e2),
BucketEntryInner::cmp_fastest_reliable(cur_ts, e1, e2) Stability::Reliable => BucketEntryInner::cmp_oldest_reliable(cur_ts, e1, e2),
}
Stability::Reliable => {
BucketEntryInner::cmp_oldest_reliable(cur_ts, e1, e2)
}
}) })
}); })
cmpout
}; };
let routing_table = self.unlocked_inner.routing_table.clone(); let routing_table = self.unlocked_inner.routing_table.clone();
let transform = let transform = |_rti: &RoutingTableInner, entry: Option<Arc<BucketEntry>>| -> NodeRef {
|_rti: &RoutingTableInner, entry: Option<Arc<BucketEntry>>| -> NodeRef { NodeRef::new(routing_table.clone(), entry.unwrap(), None)
NodeRef::new(routing_table.clone(), entry.unwrap(), None) };
};
// Pull the whole routing table in sorted order // Pull the whole routing table in sorted order
let nodes:Vec<NodeRef> = let nodes: Vec<NodeRef> =
rti.find_peers_with_sort_and_filter(usize::MAX, cur_ts, filters, compare, transform); 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 we couldn't find enough nodes, wait until we have more nodes in the routing table
@ -343,20 +349,27 @@ impl RouteSpecStore {
} }
// Get peer info for everything // Get peer info for everything
let nodes_pi: Vec<PeerInfo> = nodes.iter().map(|nr| nr.locked(rti).make_peer_info(RoutingDomain::PublicInternet).unwrap()).collect(); let nodes_pi: Vec<PeerInfo> = 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 // Now go through nodes and try to build a route we haven't seen yet
let mut perm_func = Box::new(|permutation: &[usize]| { let mut perm_func = Box::new(|permutation: &[usize]| {
// Get the hop cache key for a particular route permutation // Get the hop cache key for a particular route permutation
// uses the same algorithm as RouteSetSpecDetail::make_cache_key // uses the same algorithm as RouteSetSpecDetail::make_cache_key
let route_permutation_to_hop_cache = |_rti: &RoutingTableInner, nodes: &[NodeRef], perm: &[usize]| -> Vec<u8> { let route_permutation_to_hop_cache =
let mut cache: Vec<u8> = Vec::with_capacity(perm.len() * PUBLIC_KEY_LENGTH); |_rti: &RoutingTableInner, nodes: &[NodeRef], perm: &[usize]| -> Vec<u8> {
for n in perm { let mut cache: Vec<u8> = Vec::with_capacity(perm.len() * PUBLIC_KEY_LENGTH);
cache.extend_from_slice(&nodes[*n].locked(rti).best_node_id().value.bytes) for n in perm {
} cache.extend_from_slice(&nodes[*n].locked(rti).best_node_id().value.bytes)
cache }
}; cache
};
let cache_key = route_permutation_to_hop_cache(rti, &nodes, permutation); let cache_key = route_permutation_to_hop_cache(rti, &nodes, permutation);
// Skip routes we have already seen // Skip routes we have already seen
@ -491,21 +504,36 @@ impl RouteSpecStore {
drop(perm_func); drop(perm_func);
// Got a unique route, lets build the details, register it, and return it // Got a unique route, lets build the details, register it, and return it
let hop_node_refs:Vec<NodeRef> = route_nodes let hop_node_refs: Vec<NodeRef> = route_nodes.iter().map(|k| nodes[*k].clone()).collect();
.iter()
.map(|k| nodes[*k].clone())
.collect();
let mut route_set = BTreeMap::<PublicKey, RouteSpecDetail>::new(); let mut route_set = BTreeMap::<PublicKey, RouteSpecDetail>::new();
for crypto_kind in crypto_kinds.iter().copied() { for crypto_kind in crypto_kinds.iter().copied() {
let vcrypto = self.unlocked_inner.routing_table.crypto().get(crypto_kind).unwrap(); let vcrypto = self
.unlocked_inner
.routing_table
.crypto()
.get(crypto_kind)
.unwrap();
let keypair = vcrypto.generate_keypair(); let keypair = vcrypto.generate_keypair();
let hops: Vec<PublicKey> = route_nodes.iter().map(|v| nodes[*v].locked(rti).node_ids().get(crypto_kind).unwrap().value).collect(); let hops: Vec<PublicKey> = route_nodes
.iter()
.map(|v| {
nodes[*v]
.locked(rti)
.node_ids()
.get(crypto_kind)
.unwrap()
.value
})
.collect();
route_set.insert(keypair.key, RouteSpecDetail { route_set.insert(
crypto_kind, keypair.key,
secret_key: keypair.secret, RouteSpecDetail {
hops, crypto_kind,
}); secret_key: keypair.secret,
hops,
},
);
} }
let rssd = RouteSetSpecDetail::new( let rssd = RouteSetSpecDetail::new(
@ -517,7 +545,6 @@ impl RouteSpecStore {
can_do_sequenced, can_do_sequenced,
); );
// make id // make id
let id = self.generate_allocated_route_id(&rssd)?; let id = self.generate_allocated_route_id(&rssd)?;
@ -525,14 +552,17 @@ impl RouteSpecStore {
inner.cache.add_to_cache(rti, &rssd); inner.cache.add_to_cache(rti, &rssd);
// Keep route in spec store // Keep route in spec store
inner.content.add_detail(id.clone(), rssd); inner.content.add_detail(id, rssd);
Ok(Some(id)) Ok(Some(id))
} }
/// validate data using a private route's key and signature chain /// validate data using a private route's key and signature chain
#[cfg_attr(feature="verbose-tracing", instrument(level = "trace", skip(self, data, callback), ret))] #[cfg_attr(
pub fn with_signature_validated_route<F,R>( feature = "verbose-tracing",
instrument(level = "trace", skip(self, data, callback), ret)
)]
pub fn with_signature_validated_route<F, R>(
&self, &self,
public_key: &TypedKey, public_key: &TypedKey,
signatures: &[Signature], signatures: &[Signature],
@ -540,8 +570,9 @@ impl RouteSpecStore {
last_hop_id: PublicKey, last_hop_id: PublicKey,
callback: F, callback: F,
) -> Option<R> ) -> Option<R>
where F: FnOnce(&RouteSetSpecDetail, &RouteSpecDetail) -> R, where
R: fmt::Debug, F: FnOnce(&RouteSetSpecDetail, &RouteSpecDetail) -> R,
R: fmt::Debug,
{ {
let inner = &*self.inner.lock(); let inner = &*self.inner.lock();
let crypto = self.unlocked_inner.routing_table.crypto(); let crypto = self.unlocked_inner.routing_table.crypto();
@ -591,11 +622,13 @@ impl RouteSpecStore {
Some(callback(rssd, rsd)) Some(callback(rssd, rsd))
} }
#[cfg_attr(feature="verbose-tracing", instrument(level = "trace", skip(self), ret, err))] #[cfg_attr(
feature = "verbose-tracing",
instrument(level = "trace", skip(self), ret, err)
)]
async fn test_allocated_route(&self, private_route_id: RouteId) -> EyreResult<bool> { async fn test_allocated_route(&self, private_route_id: RouteId) -> EyreResult<bool> {
// Make loopback route to test with // Make loopback route to test with
let dest = { let dest = {
// Get the best private route for this id // Get the best private route for this id
let (key, hop_count) = { let (key, hop_count) = {
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
@ -646,10 +679,8 @@ impl RouteSpecStore {
#[instrument(level = "trace", skip(self), ret, err)] #[instrument(level = "trace", skip(self), ret, err)]
async fn test_remote_route(&self, private_route_id: RouteId) -> EyreResult<bool> { async fn test_remote_route(&self, private_route_id: RouteId) -> EyreResult<bool> {
// Make private route test // Make private route test
let dest = { let dest = {
// Get the route to test // Get the route to test
let Some(private_route) = self.best_remote_private_route(&private_route_id) else { let Some(private_route) = self.best_remote_private_route(&private_route_id) else {
bail!("no best key to test remote route"); bail!("no best key to test remote route");
@ -710,11 +741,17 @@ impl RouteSpecStore {
pub fn is_route_id_remote(&self, id: &RouteId) -> bool { pub fn is_route_id_remote(&self, id: &RouteId) -> bool {
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
let cur_ts = get_aligned_timestamp(); let cur_ts = get_aligned_timestamp();
inner.cache.peek_remote_private_route_mut(cur_ts, &id).is_some() inner
.cache
.peek_remote_private_route_mut(cur_ts, id)
.is_some()
} }
/// Test an allocated route for continuity /// Test an allocated route for continuity
#[cfg_attr(feature="verbose-tracing", instrument(level = "trace", skip(self), ret, err))] #[cfg_attr(
feature = "verbose-tracing",
instrument(level = "trace", skip(self), ret, err)
)]
pub async fn test_route(&self, id: RouteId) -> EyreResult<bool> { pub async fn test_route(&self, id: RouteId) -> EyreResult<bool> {
let is_remote = self.is_route_id_remote(&id); let is_remote = self.is_route_id_remote(&id);
if is_remote { if is_remote {
@ -737,8 +774,9 @@ impl RouteSpecStore {
/// Find first matching unpublished route that fits into the selection criteria /// Find first matching unpublished route that fits into the selection criteria
/// Don't pick any routes that have failed and haven't been tested yet /// Don't pick any routes that have failed and haven't been tested yet
fn first_available_route_inner<'a>( #[allow(clippy::too_many_arguments)]
inner: &'a RouteSpecStoreInner, fn first_available_route_inner(
inner: &RouteSpecStoreInner,
crypto_kind: CryptoKind, crypto_kind: CryptoKind,
min_hop_count: usize, min_hop_count: usize,
max_hop_count: usize, max_hop_count: usize,
@ -821,7 +859,7 @@ impl RouteSpecStore {
pub fn debug_route(&self, id: &RouteId) -> Option<String> { pub fn debug_route(&self, id: &RouteId) -> Option<String> {
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
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, &id) { if let Some(rpri) = inner.cache.peek_remote_private_route_mut(cur_ts, id) {
return Some(format!("{:#?}", rpri)); return Some(format!("{:#?}", rpri));
} }
if let Some(rssd) = inner.content.get_detail(id) { if let Some(rssd) = inner.content.get_detail(id) {
@ -840,7 +878,6 @@ impl RouteSpecStore {
rpri.best_private_route() rpri.best_private_route()
} }
/// Compiles a safety route to the private route, with caching /// Compiles a safety route to the private route, with caching
/// Returns an Err() if the parameters are wrong /// Returns an Err() if the parameters are wrong
/// Returns Ok(None) if no allocation could happen at this time (not an error) /// Returns Ok(None) if no allocation could happen at this time (not an error)
@ -879,15 +916,15 @@ impl RouteSpecStore {
}; };
let opt_first_hop = match pr_first_hop_node { let opt_first_hop = match pr_first_hop_node {
RouteNode::NodeId(id) => rti.lookup_node_ref(routing_table.clone(), TypedKey::new(crypto_kind, id))?, RouteNode::NodeId(id) => {
RouteNode::PeerInfo(pi) => { rti.lookup_node_ref(routing_table.clone(), TypedKey::new(crypto_kind, id))?
Some(rti.register_node_with_peer_info(
routing_table.clone(),
RoutingDomain::PublicInternet,
pi,
false,
)?)
} }
RouteNode::PeerInfo(pi) => Some(rti.register_node_with_peer_info(
routing_table.clone(),
RoutingDomain::PublicInternet,
*pi,
false,
)?),
}; };
if opt_first_hop.is_none() { if opt_first_hop.is_none() {
// Can't reach this private route any more // Can't reach this private route any more
@ -902,7 +939,10 @@ impl RouteSpecStore {
// Return the compiled safety route // Return the compiled safety route
//println!("compile_safety_route profile (stub): {} us", (get_timestamp() - profile_start_ts)); //println!("compile_safety_route profile (stub): {} us", (get_timestamp() - profile_start_ts));
return Ok(Some(CompiledRoute { return Ok(Some(CompiledRoute {
safety_route: SafetyRoute::new_stub(routing_table.node_id(crypto_kind), private_route), safety_route: SafetyRoute::new_stub(
routing_table.node_id(crypto_kind),
private_route,
),
secret: routing_table.node_id_secret_key(crypto_kind), secret: routing_table.node_id_secret_key(crypto_kind),
first_hop, first_hop,
})); }));
@ -911,14 +951,24 @@ impl RouteSpecStore {
// If the safety route requested is also the private route, this is a loopback test, just accept it // If the safety route requested is also the private route, this is a loopback test, just accept it
let opt_private_route_id = inner.content.get_id_by_key(&pr_pubkey); let opt_private_route_id = inner.content.get_id_by_key(&pr_pubkey);
let sr_pubkey = if opt_private_route_id.is_some() && safety_spec.preferred_route == opt_private_route_id { let sr_pubkey = 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
pr_pubkey pr_pubkey
} else { } else {
let Some(avoid_node_id) = private_route.first_hop_node_id() else { let Some(avoid_node_id) = private_route.first_hop_node_id() else {
bail!("compiled private route should have first hop"); bail!("compiled private route should have first hop");
}; };
let Some(sr_pubkey) = self.get_route_for_safety_spec_inner(inner, rti, crypto_kind, &safety_spec, Direction::Outbound.into(), &[avoid_node_id])? else { let Some(sr_pubkey) = self.get_route_for_safety_spec_inner(
inner,
rti,
crypto_kind,
&safety_spec,
Direction::Outbound.into(),
&[avoid_node_id],
)?
else {
// No safety route could be found for this spec // No safety route could be found for this spec
return Ok(None); return Ok(None);
}; };
@ -939,7 +989,8 @@ impl RouteSpecStore {
// We can optimize the peer info in this safety route if it has been successfully // We can optimize the peer info in this safety route if it has been successfully
// communicated over either via an outbound test, or used as a private route inbound // communicated over either via an outbound test, or used as a private route inbound
// and we are replying over the same route as our safety route outbound // and we are replying over the same route as our safety route outbound
let optimize = safety_rssd.get_stats().last_tested_ts.is_some() || safety_rssd.get_stats().last_received_ts.is_some(); let optimize = safety_rssd.get_stats().last_tested_ts.is_some()
|| safety_rssd.get_stats().last_received_ts.is_some();
// Get the first hop noderef of the safety route // Get the first hop noderef of the safety route
let mut first_hop = safety_rssd.hop_node_ref(0).unwrap(); let mut first_hop = safety_rssd.hop_node_ref(0).unwrap();
@ -952,7 +1003,10 @@ impl RouteSpecStore {
// See if we have a cached route we can use // See if we have a cached route we can use
if optimize { if optimize {
if let Some(safety_route) = inner.cache.lookup_compiled_route_cache(sr_pubkey, pr_pubkey) { if let Some(safety_route) = inner
.cache
.lookup_compiled_route_cache(sr_pubkey, pr_pubkey)
{
// Build compiled route // Build compiled route
let compiled_route = CompiledRoute { let compiled_route = CompiledRoute {
safety_route, safety_route,
@ -993,9 +1047,9 @@ impl RouteSpecStore {
let dh_secret = vcrypto let dh_secret = vcrypto
.cached_dh(&safety_rsd.hops[h], &safety_rsd.secret_key) .cached_dh(&safety_rsd.hops[h], &safety_rsd.secret_key)
.wrap_err("dh failed")?; .wrap_err("dh failed")?;
let enc_msg_data = let enc_msg_data = vcrypto
vcrypto.encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None) .encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None)
.wrap_err("encryption failed")?; .wrap_err("encryption failed")?;
// Make route hop data // Make route hop data
let route_hop_data = RouteHopData { let route_hop_data = RouteHopData {
@ -1021,7 +1075,7 @@ impl RouteSpecStore {
if pi.is_none() { if pi.is_none() {
bail!("peer info should exist for route but doesn't"); bail!("peer info should exist for route but doesn't");
} }
RouteNode::PeerInfo(pi.unwrap()) RouteNode::PeerInfo(Box::new(pi.unwrap()))
}, },
next_hop: Some(route_hop_data), next_hop: Some(route_hop_data),
}; };
@ -1045,7 +1099,8 @@ impl RouteSpecStore {
let dh_secret = vcrypto let dh_secret = vcrypto
.cached_dh(&safety_rsd.hops[0], &safety_rsd.secret_key) .cached_dh(&safety_rsd.hops[0], &safety_rsd.secret_key)
.map_err(RPCError::map_internal("dh failed"))?; .map_err(RPCError::map_internal("dh failed"))?;
let enc_msg_data = vcrypto.encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None) let enc_msg_data = vcrypto
.encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None)
.map_err(RPCError::map_internal("encryption failed"))?; .map_err(RPCError::map_internal("encryption failed"))?;
let route_hop_data = RouteHopData { let route_hop_data = RouteHopData {
@ -1065,7 +1120,9 @@ impl RouteSpecStore {
// Add to cache but only if we have an optimized route // Add to cache but only if we have an optimized route
if optimize { if optimize {
inner.cache.add_to_compiled_route_cache( pr_pubkey, safety_route.clone()); inner
.cache
.add_to_compiled_route_cache(pr_pubkey, safety_route.clone());
} }
// Build compiled route // Build compiled route
@ -1081,7 +1138,10 @@ impl RouteSpecStore {
} }
/// Get an allocated route that matches a particular safety spec /// Get an allocated route that matches a particular safety spec
#[cfg_attr(feature="verbose-tracing", instrument(level = "trace", skip(self, inner, rti), ret, err))] #[cfg_attr(
feature = "verbose-tracing",
instrument(level = "trace", skip(self, inner, rti), ret, err)
)]
fn get_route_for_safety_spec_inner( fn get_route_for_safety_spec_inner(
&self, &self,
inner: &mut RouteSpecStoreInner, inner: &mut RouteSpecStoreInner,
@ -1146,13 +1206,23 @@ impl RouteSpecStore {
sr_route_id sr_route_id
}; };
let sr_pubkey = inner.content.get_detail(&sr_route_id).unwrap().get_route_set_keys().get(crypto_kind).unwrap().value; let sr_pubkey = inner
.content
.get_detail(&sr_route_id)
.unwrap()
.get_route_set_keys()
.get(crypto_kind)
.unwrap()
.value;
Ok(Some(sr_pubkey)) Ok(Some(sr_pubkey))
} }
/// Get a private route to use for the answer to question /// Get a private route to use for the answer to question
#[cfg_attr(feature="verbose-tracing", instrument(level = "trace", skip(self), ret, err))] #[cfg_attr(
feature = "verbose-tracing",
instrument(level = "trace", skip(self), ret, err)
)]
pub fn get_private_route_for_safety_spec( pub fn get_private_route_for_safety_spec(
&self, &self,
crypto_kind: CryptoKind, crypto_kind: CryptoKind,
@ -1173,8 +1243,12 @@ impl RouteSpecStore {
)?) )?)
} }
fn assemble_private_route_inner(&self, key: &PublicKey, rsd: &RouteSpecDetail, optimized: bool) -> EyreResult<PrivateRoute> fn assemble_private_route_inner(
{ &self,
key: &PublicKey,
rsd: &RouteSpecDetail,
optimized: bool,
) -> EyreResult<PrivateRoute> {
let routing_table = self.unlocked_inner.routing_table.clone(); let routing_table = self.unlocked_inner.routing_table.clone();
let rti = &*routing_table.inner.read(); let rti = &*routing_table.inner.read();
@ -1198,7 +1272,7 @@ impl RouteSpecStore {
RouteNode::NodeId(node_id.value) RouteNode::NodeId(node_id.value)
} else { } else {
let pi = rti.get_own_peer_info(RoutingDomain::PublicInternet); let pi = rti.get_own_peer_info(RoutingDomain::PublicInternet);
RouteNode::PeerInfo(pi) RouteNode::PeerInfo(Box::new(pi))
}, },
next_hop: None, next_hop: None,
}; };
@ -1220,7 +1294,8 @@ impl RouteSpecStore {
let dh_secret = vcrypto let dh_secret = vcrypto
.cached_dh(&rsd.hops[h], &rsd.secret_key) .cached_dh(&rsd.hops[h], &rsd.secret_key)
.wrap_err("dh failed")?; .wrap_err("dh failed")?;
let enc_msg_data = vcrypto.encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None) let enc_msg_data = vcrypto
.encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None)
.wrap_err("encryption failed")?; .wrap_err("encryption failed")?;
let route_hop_data = RouteHopData { let route_hop_data = RouteHopData {
nonce, nonce,
@ -1244,7 +1319,7 @@ impl RouteSpecStore {
if pi.is_none() { if pi.is_none() {
bail!("peer info should exist for route but doesn't",); bail!("peer info should exist for route but doesn't",);
} }
RouteNode::PeerInfo(pi.unwrap()) RouteNode::PeerInfo(Box::new(pi.unwrap()))
}, },
next_hop: Some(route_hop_data), next_hop: Some(route_hop_data),
} }
@ -1261,7 +1336,10 @@ impl RouteSpecStore {
/// Assemble a single private route for publication /// Assemble a single private route for publication
/// Returns a PrivateRoute object for an allocated private route key /// Returns a PrivateRoute object for an allocated private route key
#[cfg_attr(feature="verbose-tracing", instrument(level = "trace", skip(self), err))] #[cfg_attr(
feature = "verbose-tracing",
instrument(level = "trace", skip(self), err)
)]
pub fn assemble_private_route( pub fn assemble_private_route(
&self, &self,
key: &PublicKey, key: &PublicKey,
@ -1277,18 +1355,24 @@ impl RouteSpecStore {
// See if we can optimize this compilation yet // See if we can optimize this compilation yet
// We don't want to include full nodeinfo if we don't have to // We don't want to include full nodeinfo if we don't have to
let optimized = optimized let optimized = optimized.unwrap_or(
.unwrap_or(rssd.get_stats().last_tested_ts.is_some() || rssd.get_stats().last_received_ts.is_some()); rssd.get_stats().last_tested_ts.is_some()
|| rssd.get_stats().last_received_ts.is_some(),
);
let rsd = rssd.get_route_by_key(key).expect("route key index is broken"); let rsd = rssd
.get_route_by_key(key)
.expect("route key index is broken");
self.assemble_private_route_inner(key, rsd, optimized) self.assemble_private_route_inner(key, rsd, optimized)
} }
/// Assemble private route set for publication /// Assemble private route set for publication
/// Returns a vec of PrivateRoute objects for an allocated private route /// Returns a vec of PrivateRoute objects for an allocated private route
#[cfg_attr(feature="verbose-tracing", instrument(level = "trace", skip(self), err))] #[cfg_attr(
feature = "verbose-tracing",
instrument(level = "trace", skip(self), err)
)]
pub fn assemble_private_routes( pub fn assemble_private_routes(
&self, &self,
id: &RouteId, id: &RouteId,
@ -1301,8 +1385,10 @@ impl RouteSpecStore {
// See if we can optimize this compilation yet // See if we can optimize this compilation yet
// We don't want to include full nodeinfo if we don't have to // We don't want to include full nodeinfo if we don't have to
let optimized = optimized let optimized = optimized.unwrap_or(
.unwrap_or(rssd.get_stats().last_tested_ts.is_some() || rssd.get_stats().last_received_ts.is_some()); rssd.get_stats().last_tested_ts.is_some()
|| rssd.get_stats().last_received_ts.is_some(),
);
let mut out = Vec::new(); let mut out = Vec::new();
for (key, rsd) in rssd.iter_route_set() { for (key, rsd) in rssd.iter_route_set() {
@ -1314,12 +1400,18 @@ impl RouteSpecStore {
/// Import a remote private route for compilation /// Import a remote private route for compilation
/// It is safe to import the same route more than once and it will return the same route id /// It is safe to import the same route more than once and it will return the same route id
/// Returns a route set id /// Returns a route set id
#[cfg_attr(feature="verbose-tracing", instrument(level = "trace", skip(self, blob), ret, err))] #[cfg_attr(
feature = "verbose-tracing",
instrument(level = "trace", skip(self, blob), ret, err)
)]
pub fn import_remote_private_route(&self, blob: Vec<u8>) -> EyreResult<RouteId> { pub fn import_remote_private_route(&self, blob: Vec<u8>) -> EyreResult<RouteId> {
let cur_ts = get_aligned_timestamp(); let cur_ts = get_aligned_timestamp();
// decode the pr blob // decode the pr blob
let private_routes = RouteSpecStore::blob_to_private_routes(self.unlocked_inner.routing_table.crypto(), blob)?; let private_routes = RouteSpecStore::blob_to_private_routes(
self.unlocked_inner.routing_table.crypto(),
blob,
)?;
// make the route id // make the route id
let id = self.generate_remote_route_id(&private_routes)?; let id = self.generate_remote_route_id(&private_routes)?;
@ -1327,7 +1419,6 @@ impl RouteSpecStore {
// validate the private routes // validate the private routes
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
for private_route in &private_routes { for private_route in &private_routes {
// ensure private route has first hop // ensure private route has first hop
if !matches!(private_route.hops, PrivateRouteHops::FirstHop(_)) { if !matches!(private_route.hops, PrivateRouteHops::FirstHop(_)) {
bail!("private route must have first hop"); bail!("private route must have first hop");
@ -1339,21 +1430,25 @@ impl RouteSpecStore {
// } // }
} }
inner.cache.cache_remote_private_route(cur_ts, id, private_routes); inner
.cache
.cache_remote_private_route(cur_ts, id, private_routes);
Ok(id) Ok(id)
} }
/// Release a remote private route that is no longer in use /// Release a remote private route that is no longer in use
#[cfg_attr(feature="verbose-tracing", instrument(level = "trace", skip(self), ret))] #[cfg_attr(
feature = "verbose-tracing",
instrument(level = "trace", skip(self), ret)
)]
pub fn release_remote_private_route(&self, id: RouteId) -> bool { pub fn release_remote_private_route(&self, id: RouteId) -> bool {
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
inner.cache.remove_remote_private_route(id) inner.cache.remove_remote_private_route(id)
} }
/// Get a route id for a route's public key /// Get a route id for a route's public key
pub fn get_route_id_for_key(&self, key: &PublicKey) -> Option<RouteId> pub fn get_route_id_for_key(&self, key: &PublicKey) -> Option<RouteId> {
{
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
// Check for local route // Check for local route
if let Some(id) = inner.content.get_id_by_key(key) { if let Some(id) = inner.content.get_id_by_key(key) {
@ -1371,7 +1466,6 @@ impl RouteSpecStore {
/// Check to see if this remote (not ours) private route has seen our current node info yet /// Check to see if this remote (not ours) private route has seen our current node info yet
/// This happens when you communicate with a private route without a safety route /// This happens when you communicate with a private route without a safety route
pub fn has_remote_private_route_seen_our_node_info(&self, key: &PublicKey) -> bool { pub fn has_remote_private_route_seen_our_node_info(&self, key: &PublicKey) -> bool {
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
// Check for local route. If this is not a remote private route, // Check for local route. If this is not a remote private route,
@ -1383,9 +1477,11 @@ impl RouteSpecStore {
if let Some(rrid) = inner.cache.get_remote_private_route_id_by_key(key) { if let Some(rrid) = inner.cache.get_remote_private_route_id_by_key(key) {
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 = self
let our_node_info_ts = self.unlocked_inner.routing_table.get_own_node_info_ts(RoutingDomain::PublicInternet); .unlocked_inner
.routing_table
.get_own_node_info_ts(RoutingDomain::PublicInternet);
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,7 +1500,10 @@ impl RouteSpecStore {
key: &PublicKey, key: &PublicKey,
cur_ts: Timestamp, cur_ts: Timestamp,
) -> EyreResult<()> { ) -> EyreResult<()> {
let our_node_info_ts = self.unlocked_inner.routing_table.get_own_node_info_ts(RoutingDomain::PublicInternet); let our_node_info_ts = self
.unlocked_inner
.routing_table
.get_own_node_info_ts(RoutingDomain::PublicInternet);
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
@ -1416,8 +1515,7 @@ impl RouteSpecStore {
} }
if let Some(rrid) = inner.cache.get_remote_private_route_id_by_key(key) { if let Some(rrid) = inner.cache.get_remote_private_route_id_by_key(key) {
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) {
{
rpri.set_last_seen_our_node_info_ts(our_node_info_ts); rpri.set_last_seen_our_node_info_ts(our_node_info_ts);
return Ok(()); return Ok(());
} }
@ -1434,7 +1532,11 @@ impl RouteSpecStore {
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
// Check for stub route // Check for stub route
if self.unlocked_inner.routing_table.matches_own_node_id_key(key) { if self
.unlocked_inner
.routing_table
.matches_own_node_id_key(key)
{
return None; return None;
} }
@ -1447,8 +1549,7 @@ impl RouteSpecStore {
// Check for remote route // Check for remote route
if let Some(rrid) = inner.cache.get_remote_private_route_id_by_key(key) { if let Some(rrid) = inner.cache.get_remote_private_route_id_by_key(key) {
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) {
{
return Some(f(rpri.get_stats_mut())); return Some(f(rpri.get_stats_mut()));
} }
} }
@ -1493,7 +1594,6 @@ impl RouteSpecStore {
/// Convert private route list to binary blob /// Convert private route list to binary blob
pub fn private_routes_to_blob(private_routes: &[PrivateRoute]) -> EyreResult<Vec<u8>> { pub fn private_routes_to_blob(private_routes: &[PrivateRoute]) -> EyreResult<Vec<u8>> {
let mut buffer = vec![]; let mut buffer = vec![];
// Serialize count // Serialize count
@ -1521,7 +1621,6 @@ impl RouteSpecStore {
/// Convert binary blob to private route /// Convert binary blob to private route
pub fn blob_to_private_routes(crypto: Crypto, blob: Vec<u8>) -> EyreResult<Vec<PrivateRoute>> { pub fn blob_to_private_routes(crypto: Crypto, blob: Vec<u8>) -> EyreResult<Vec<PrivateRoute>> {
// Deserialize count // Deserialize count
if blob.is_empty() { if blob.is_empty() {
bail!("not deserializing empty private route blob"); bail!("not deserializing empty private route blob");
@ -1547,16 +1646,17 @@ impl RouteSpecStore {
.get_root::<veilid_capnp::private_route::Reader>() .get_root::<veilid_capnp::private_route::Reader>()
.map_err(RPCError::internal) .map_err(RPCError::internal)
.wrap_err("failed to make reader for private_route")?; .wrap_err("failed to make reader for private_route")?;
let private_route = decode_private_route(&pr_reader).wrap_err("failed to decode private route")?; let private_route =
private_route.validate(crypto.clone()).wrap_err("failed to validate private route")?; decode_private_route(&pr_reader).wrap_err("failed to decode private route")?;
private_route
.validate(crypto.clone())
.wrap_err("failed to validate private route")?;
out.push(private_route); out.push(private_route);
} }
// Don't trust the order of the blob // Don't trust the order of the blob
out.sort_by(|a,b| { out.sort_by(|a, b| a.public_key.cmp(&b.public_key));
a.public_key.cmp(&b.public_key)
});
Ok(out) Ok(out)
} }
@ -1567,9 +1667,11 @@ impl RouteSpecStore {
let crypto = self.unlocked_inner.routing_table.crypto(); let crypto = self.unlocked_inner.routing_table.crypto();
let mut idbytes = Vec::with_capacity(PUBLIC_KEY_LENGTH * route_set_keys.len()); let mut idbytes = Vec::with_capacity(PUBLIC_KEY_LENGTH * route_set_keys.len());
let mut best_kind : Option<CryptoKind> = None; let mut best_kind: Option<CryptoKind> = None;
for tk in route_set_keys.iter() { for tk in route_set_keys.iter() {
if best_kind.is_none() || compare_crypto_kind(&tk.kind, best_kind.as_ref().unwrap()) == cmp::Ordering::Less { if best_kind.is_none()
|| compare_crypto_kind(&tk.kind, best_kind.as_ref().unwrap()) == cmp::Ordering::Less
{
best_kind = Some(tk.kind); best_kind = Some(tk.kind);
} }
idbytes.extend_from_slice(&tk.value.bytes); idbytes.extend_from_slice(&tk.value.bytes);
@ -1580,7 +1682,6 @@ impl RouteSpecStore {
let vcrypto = crypto.get(best_kind).unwrap(); let vcrypto = crypto.get(best_kind).unwrap();
Ok(RouteId::new(vcrypto.generate_hash(&idbytes).bytes)) Ok(RouteId::new(vcrypto.generate_hash(&idbytes).bytes))
} }
/// Generate RouteId from set of private routes /// Generate RouteId from set of private routes
@ -1588,9 +1689,12 @@ impl RouteSpecStore {
let crypto = self.unlocked_inner.routing_table.crypto(); let crypto = self.unlocked_inner.routing_table.crypto();
let mut idbytes = Vec::with_capacity(PUBLIC_KEY_LENGTH * private_routes.len()); let mut idbytes = Vec::with_capacity(PUBLIC_KEY_LENGTH * private_routes.len());
let mut best_kind : Option<CryptoKind> = None; let mut best_kind: Option<CryptoKind> = None;
for private_route in private_routes { for private_route in private_routes {
if best_kind.is_none() || compare_crypto_kind(&private_route.public_key.kind, best_kind.as_ref().unwrap()) == cmp::Ordering::Less { if best_kind.is_none()
|| compare_crypto_kind(&private_route.public_key.kind, best_kind.as_ref().unwrap())
== cmp::Ordering::Less
{
best_kind = Some(private_route.public_key.kind); best_kind = Some(private_route.public_key.kind);
} }
idbytes.extend_from_slice(&private_route.public_key.value.bytes); idbytes.extend_from_slice(&private_route.public_key.value.bytes);
@ -1602,5 +1706,4 @@ impl RouteSpecStore {
Ok(RouteId::new(vcrypto.generate_hash(&idbytes).bytes)) Ok(RouteId::new(vcrypto.generate_hash(&idbytes).bytes))
} }
} }

View File

@ -144,7 +144,7 @@ impl RouteSpecStoreCache {
// also store in id by key table // also store in id by key table
for private_route in rprinfo.get_private_routes() { for private_route in rprinfo.get_private_routes() {
self.remote_private_routes_by_key self.remote_private_routes_by_key
.insert(private_route.public_key.value, id.clone()); .insert(private_route.public_key.value, id);
} }
let mut dead = None; let mut dead = None;

View File

@ -29,18 +29,20 @@ impl RouteSpecStoreContent {
for (rsid, rssd) in content.details.iter_mut() { for (rsid, rssd) in content.details.iter_mut() {
// Get best route since they all should resolve // Get best route since they all should resolve
let Some(pk) = rssd.get_best_route_set_key() else { let Some(pk) = rssd.get_best_route_set_key() else {
dead_ids.push(rsid.clone()); dead_ids.push(*rsid);
continue; continue;
}; };
let Some(rsd) = rssd.get_route_by_key(&pk) else { let Some(rsd) = rssd.get_route_by_key(&pk) else {
dead_ids.push(rsid.clone()); dead_ids.push(*rsid);
continue; continue;
}; };
// Go through best route and resolve noderefs // Go through best route and resolve noderefs
let mut hop_node_refs = Vec::with_capacity(rsd.hops.len()); let mut hop_node_refs = Vec::with_capacity(rsd.hops.len());
for h in &rsd.hops { for h in &rsd.hops {
let Ok(Some(nr)) = routing_table.lookup_node_ref(TypedKey::new(rsd.crypto_kind, *h)) else { let Ok(Some(nr)) =
dead_ids.push(rsid.clone()); routing_table.lookup_node_ref(TypedKey::new(rsd.crypto_kind, *h))
else {
dead_ids.push(*rsid);
break; break;
}; };
hop_node_refs.push(nr); hop_node_refs.push(nr);
@ -72,14 +74,14 @@ impl RouteSpecStoreContent {
// also store in id by key table // also store in id by key table
for (pk, _) in detail.iter_route_set() { for (pk, _) in detail.iter_route_set() {
self.id_by_key.insert(*pk, id.clone()); self.id_by_key.insert(*pk, id);
} }
self.details.insert(id.clone(), detail); self.details.insert(id, detail);
} }
pub fn remove_detail(&mut self, id: &RouteId) -> Option<RouteSetSpecDetail> { pub fn remove_detail(&mut self, id: &RouteId) -> Option<RouteSetSpecDetail> {
let detail = self.details.remove(id)?; let detail = self.details.remove(id)?;
for (pk, _) in detail.iter_route_set() { for (pk, _) in detail.iter_route_set() {
self.id_by_key.remove(&pk).unwrap(); self.id_by_key.remove(pk).unwrap();
} }
Some(detail) Some(detail)
} }
@ -106,7 +108,7 @@ impl RouteSpecStoreContent {
/// Resets publication status and statistics for when our node info changes /// Resets publication status and statistics for when our node info changes
/// Routes must be republished /// Routes must be republished
pub fn reset_details(&mut self) { pub fn reset_details(&mut self) {
for (_k, v) in &mut self.details { for v in self.details.values_mut() {
// Must republish route now // Must republish route now
v.set_published(false); v.set_published(false);
// Restart stats for routes so we test the route again // Restart stats for routes so we test the route again

View File

@ -276,7 +276,7 @@ fn first_filtered_dial_info_detail_between_nodes(
to_node: &NodeInfo, to_node: &NodeInfo,
dial_info_filter: &DialInfoFilter, dial_info_filter: &DialInfoFilter,
sequencing: Sequencing, sequencing: Sequencing,
dif_sort: Option<Arc<dyn Fn(&DialInfoDetail, &DialInfoDetail) -> core::cmp::Ordering>> dif_sort: Option<Arc<DialInfoDetailSort>>
) -> Option<DialInfoDetail> { ) -> Option<DialInfoDetail> {
let dial_info_filter = dial_info_filter.clone().filtered( let dial_info_filter = dial_info_filter.clone().filtered(
&DialInfoFilter::all() &DialInfoFilter::all()
@ -289,7 +289,7 @@ fn first_filtered_dial_info_detail_between_nodes(
// based on an external preference table, for example the one kept by // based on an external preference table, for example the one kept by
// AddressFilter to deprioritize dialinfo that have recently failed to connect // AddressFilter to deprioritize dialinfo that have recently failed to connect
let (ordered, dial_info_filter) = dial_info_filter.with_sequencing(sequencing); let (ordered, dial_info_filter) = dial_info_filter.with_sequencing(sequencing);
let sort: Option<Box<dyn Fn(&DialInfoDetail, &DialInfoDetail) -> core::cmp::Ordering>> = if ordered { let sort: Option<Box<DialInfoDetailSort>> = if ordered {
if let Some(dif_sort) = dif_sort { if let Some(dif_sort) = dif_sort {
Some(Box::new(move |a, b| { Some(Box::new(move |a, b| {
let mut ord = dif_sort(a,b); let mut ord = dif_sort(a,b);
@ -582,7 +582,7 @@ impl RoutingDomainDetail for LocalNetworkRoutingDomainDetail {
// based on an external preference table, for example the one kept by // based on an external preference table, for example the one kept by
// AddressFilter to deprioritize dialinfo that have recently failed to connect // AddressFilter to deprioritize dialinfo that have recently failed to connect
let (ordered, dial_info_filter) = dial_info_filter.with_sequencing(sequencing); let (ordered, dial_info_filter) = dial_info_filter.with_sequencing(sequencing);
let sort: Option<Box<dyn Fn(&DialInfoDetail, &DialInfoDetail) -> core::cmp::Ordering>> = if ordered { let sort: Option<Box<DialInfoDetailSort>> = if ordered {
if let Some(dif_sort) = dif_sort { if let Some(dif_sort) = dif_sort {
Some(Box::new(move |a, b| { Some(Box::new(move |a, b| {
let mut ord = dif_sort(a,b); let mut ord = dif_sort(a,b);

View File

@ -227,7 +227,7 @@ impl RoutingTableInner {
peer_b: &PeerInfo, peer_b: &PeerInfo,
dial_info_filter: DialInfoFilter, dial_info_filter: DialInfoFilter,
sequencing: Sequencing, sequencing: Sequencing,
dif_sort: Option<Arc<dyn Fn(&DialInfoDetail, &DialInfoDetail) -> core::cmp::Ordering>>, dif_sort: Option<Arc<DialInfoDetailSort>>,
) -> ContactMethod { ) -> ContactMethod {
self.with_routing_domain(routing_domain, |rdd| { self.with_routing_domain(routing_domain, |rdd| {
rdd.get_contact_method(self, peer_a, peer_b, dial_info_filter, sequencing, dif_sort) rdd.get_contact_method(self, peer_a, peer_b, dial_info_filter, sequencing, dif_sort)

View File

@ -46,7 +46,7 @@ impl RoutingTable {
// Envelope support // Envelope support
let mut envelope_support = Vec::new(); let mut envelope_support = Vec::new();
for ess in records[1].split(",") { for ess in records[1].split(',') {
let ess = ess.trim(); let ess = ess.trim();
let es = match ess.parse::<u8>() { let es = match ess.parse::<u8>() {
Ok(v) => v, Ok(v) => v,
@ -64,9 +64,9 @@ impl RoutingTable {
// Node Id // Node Id
let mut node_ids = TypedKeyGroup::new(); let mut node_ids = TypedKeyGroup::new();
for node_id_str in records[2].split(",") { for node_id_str in records[2].split(',') {
let node_id_str = node_id_str.trim(); let node_id_str = node_id_str.trim();
let node_id = match TypedKey::from_str(&node_id_str) { let node_id = match TypedKey::from_str(node_id_str) {
Ok(v) => v, Ok(v) => v,
Err(e) => { Err(e) => {
bail!( bail!(
@ -89,7 +89,7 @@ impl RoutingTable {
// Resolve each record and store in node dial infos list // Resolve each record and store in node dial infos list
let mut dial_info_details = Vec::new(); let mut dial_info_details = Vec::new();
for rec in records[4].split(",") { for rec in records[4].split(',') {
let rec = rec.trim(); let rec = rec.trim();
let dial_infos = match DialInfo::try_vec_from_short(rec, hostname_str) { let dial_infos = match DialInfo::try_vec_from_short(rec, hostname_str) {
Ok(dis) => dis, Ok(dis) => dis,
@ -321,7 +321,7 @@ impl RoutingTable {
// See if we are specifying a direct dialinfo for bootstrap, if so use the direct mechanism // See if we are specifying a direct dialinfo for bootstrap, if so use the direct mechanism
let mut bootstrap_dialinfos = Vec::<DialInfo>::new(); let mut bootstrap_dialinfos = Vec::<DialInfo>::new();
for b in &bootstrap { for b in &bootstrap {
if let Ok(bootstrap_di_vec) = DialInfo::try_vec_from_url(&b) { if let Ok(bootstrap_di_vec) = DialInfo::try_vec_from_url(b) {
for bootstrap_di in bootstrap_di_vec { for bootstrap_di in bootstrap_di_vec {
bootstrap_dialinfos.push(bootstrap_di); bootstrap_dialinfos.push(bootstrap_di);
} }

View File

@ -8,6 +8,9 @@ use futures_util::stream::{FuturesUnordered, StreamExt};
use futures_util::FutureExt; use futures_util::FutureExt;
use stop_token::future::FutureExt as StopFutureExt; use stop_token::future::FutureExt as StopFutureExt;
type PingValidatorFuture =
SendPinBoxFuture<Result<NetworkResult<Answer<Option<SenderInfo>>>, RPCError>>;
impl RoutingTable { impl RoutingTable {
// Ping each node in the routing table if they need to be pinged // Ping each node in the routing table if they need to be pinged
// to determine their reliability // to determine their reliability
@ -16,9 +19,7 @@ impl RoutingTable {
&self, &self,
cur_ts: Timestamp, cur_ts: Timestamp,
relay_nr: NodeRef, relay_nr: NodeRef,
unord: &mut FuturesUnordered< unord: &mut FuturesUnordered<PingValidatorFuture>,
SendPinBoxFuture<Result<NetworkResult<Answer<Option<SenderInfo>>>, RPCError>>,
>,
) -> EyreResult<()> { ) -> EyreResult<()> {
let rpc = self.rpc_processor(); let rpc = self.rpc_processor();
// Get our publicinternet dial info // Get our publicinternet dial info
@ -123,9 +124,7 @@ impl RoutingTable {
async fn ping_validator_public_internet( async fn ping_validator_public_internet(
&self, &self,
cur_ts: Timestamp, cur_ts: Timestamp,
unord: &mut FuturesUnordered< unord: &mut FuturesUnordered<PingValidatorFuture>,
SendPinBoxFuture<Result<NetworkResult<Answer<Option<SenderInfo>>>, RPCError>>,
>,
) -> EyreResult<()> { ) -> EyreResult<()> {
let rpc = self.rpc_processor(); let rpc = self.rpc_processor();
@ -161,9 +160,7 @@ impl RoutingTable {
async fn ping_validator_local_network( async fn ping_validator_local_network(
&self, &self,
cur_ts: Timestamp, cur_ts: Timestamp,
unord: &mut FuturesUnordered< unord: &mut FuturesUnordered<PingValidatorFuture>,
SendPinBoxFuture<Result<NetworkResult<Answer<Option<SenderInfo>>>, RPCError>>,
>,
) -> EyreResult<()> { ) -> EyreResult<()> {
let rpc = self.rpc_processor(); let rpc = self.rpc_processor();

View File

@ -76,10 +76,10 @@ pub fn decode_route_hop(reader: &veilid_capnp::route_hop::Reader) -> Result<Rout
} }
veilid_capnp::route_hop::node::Which::PeerInfo(pi) => { veilid_capnp::route_hop::node::Which::PeerInfo(pi) => {
let pi_reader = pi.map_err(RPCError::protocol)?; let pi_reader = pi.map_err(RPCError::protocol)?;
RouteNode::PeerInfo( RouteNode::PeerInfo(Box::new(
decode_peer_info(&pi_reader) decode_peer_info(&pi_reader)
.map_err(RPCError::map_protocol("invalid peer info in route hop"))?, .map_err(RPCError::map_protocol("invalid peer info in route hop"))?,
) ))
} }
}; };
@ -134,7 +134,7 @@ pub fn decode_private_route(
let hops = match reader.get_hops().which().map_err(RPCError::protocol)? { let hops = match reader.get_hops().which().map_err(RPCError::protocol)? {
veilid_capnp::private_route::hops::Which::FirstHop(rh_reader) => { veilid_capnp::private_route::hops::Which::FirstHop(rh_reader) => {
let rh_reader = rh_reader.map_err(RPCError::protocol)?; let rh_reader = rh_reader.map_err(RPCError::protocol)?;
PrivateRouteHops::FirstHop(decode_route_hop(&rh_reader)?) PrivateRouteHops::FirstHop(Box::new(decode_route_hop(&rh_reader)?))
} }
veilid_capnp::private_route::hops::Which::Data(rhd_reader) => { veilid_capnp::private_route::hops::Which::Data(rhd_reader) => {
let rhd_reader = rhd_reader.map_err(RPCError::protocol)?; let rhd_reader = rhd_reader.map_err(RPCError::protocol)?;

View File

@ -181,10 +181,17 @@ impl RPCProcessor {
// Sent directly but with a safety route, respond to private route // Sent directly but with a safety route, respond to private route
let crypto_kind = target.best_node_id().kind; let crypto_kind = target.best_node_id().kind;
let Some(pr_key) = rss let Some(pr_key) = rss
.get_private_route_for_safety_spec(crypto_kind, safety_spec, &target.node_ids()) .get_private_route_for_safety_spec(
.map_err(RPCError::internal)? else { crypto_kind,
return Ok(NetworkResult::no_connection_other("no private route for response at this time")); safety_spec,
}; &target.node_ids(),
)
.map_err(RPCError::internal)?
else {
return Ok(NetworkResult::no_connection_other(
"no private route for response at this time",
));
};
// Get the assembled route for response // Get the assembled route for response
let private_route = rss let private_route = rss
@ -211,9 +218,12 @@ impl RPCProcessor {
avoid_nodes.add_all(&target.node_ids()); avoid_nodes.add_all(&target.node_ids());
let Some(pr_key) = rss let Some(pr_key) = rss
.get_private_route_for_safety_spec(crypto_kind, safety_spec, &avoid_nodes) .get_private_route_for_safety_spec(crypto_kind, safety_spec, &avoid_nodes)
.map_err(RPCError::internal)? else { .map_err(RPCError::internal)?
return Ok(NetworkResult::no_connection_other("no private route for response at this time")); else {
}; return Ok(NetworkResult::no_connection_other(
"no private route for response at this time",
));
};
// Get the assembled route for response // Get the assembled route for response
let private_route = rss let private_route = rss
@ -228,7 +238,9 @@ impl RPCProcessor {
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",
));
}; };
let crypto_kind = private_route.public_key.kind; let crypto_kind = private_route.public_key.kind;
@ -250,7 +262,7 @@ impl RPCProcessor {
} else { } else {
let own_peer_info = let own_peer_info =
routing_table.get_own_peer_info(RoutingDomain::PublicInternet); routing_table.get_own_peer_info(RoutingDomain::PublicInternet);
RouteNode::PeerInfo(own_peer_info) RouteNode::PeerInfo(Box::new(own_peer_info))
}; };
Ok(NetworkResult::value(RespondTo::PrivateRoute( Ok(NetworkResult::value(RespondTo::PrivateRoute(
@ -271,10 +283,17 @@ impl RPCProcessor {
} else { } else {
// Get the private route to respond to that matches the safety route spec we sent the request with // Get the private route to respond to that matches the safety route spec we sent the request with
let Some(pr_key) = rss let Some(pr_key) = rss
.get_private_route_for_safety_spec(crypto_kind, safety_spec, &[avoid_node_id]) .get_private_route_for_safety_spec(
.map_err(RPCError::internal)? else { crypto_kind,
return Ok(NetworkResult::no_connection_other("no private route for response at this time")); safety_spec,
}; &[avoid_node_id],
)
.map_err(RPCError::internal)?
else {
return Ok(NetworkResult::no_connection_other(
"no private route for response at this time",
));
};
pr_key pr_key
}; };

View File

@ -812,7 +812,7 @@ impl RPCProcessor {
}; };
let private_route = PrivateRoute::new_stub( let private_route = PrivateRoute::new_stub(
destination_node_ref.best_node_id(), destination_node_ref.best_node_id(),
RouteNode::PeerInfo(peer_info), RouteNode::PeerInfo(Box::new(peer_info)),
); );
// Wrap with safety route // Wrap with safety route