clippy work
This commit is contained in:
parent
6438a64fc7
commit
e4ee093951
@ -396,7 +396,7 @@ impl NetworkManager {
|
||||
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
|
||||
} else {
|
||||
Some(Arc::new(move |a: &DialInfoDetail, b: &DialInfoDetail| {
|
||||
|
@ -75,8 +75,8 @@ impl Bucket {
|
||||
});
|
||||
}
|
||||
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
|
||||
@ -129,11 +129,8 @@ impl Bucket {
|
||||
let mut extra_entries = bucket_len - bucket_depth;
|
||||
|
||||
// Get the sorted list of entries by their kick order
|
||||
let mut sorted_entries: Vec<(PublicKey, Arc<BucketEntry>)> = self
|
||||
.entries
|
||||
.iter()
|
||||
.map(|(k, v)| (k.clone(), v.clone()))
|
||||
.collect();
|
||||
let mut sorted_entries: Vec<(PublicKey, Arc<BucketEntry>)> =
|
||||
self.entries.iter().map(|(k, v)| (*k, v.clone())).collect();
|
||||
let cur_ts = get_aligned_timestamp();
|
||||
sorted_entries.sort_by(|a, b| -> core::cmp::Ordering {
|
||||
if a.0 == b.0 {
|
||||
|
@ -492,7 +492,7 @@ impl BucketEntryInner {
|
||||
}
|
||||
|
||||
if !only_live {
|
||||
return Some(v.clone());
|
||||
return Some(*v);
|
||||
}
|
||||
|
||||
// Check if the connection is still considered live
|
||||
@ -509,7 +509,7 @@ impl BucketEntryInner {
|
||||
};
|
||||
|
||||
if alive {
|
||||
Some(v.clone())
|
||||
Some(*v)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -583,13 +583,11 @@ impl BucketEntryInner {
|
||||
RoutingDomain::LocalNetwork => self
|
||||
.local_network
|
||||
.node_status
|
||||
.as_ref()
|
||||
.map(|ns| ns.clone()),
|
||||
.as_ref().cloned(),
|
||||
RoutingDomain::PublicInternet => self
|
||||
.public_internet
|
||||
.node_status
|
||||
.as_ref()
|
||||
.map(|ns| ns.clone()),
|
||||
.as_ref().cloned()
|
||||
}
|
||||
}
|
||||
|
||||
@ -892,7 +890,7 @@ impl BucketEntry {
|
||||
F: FnOnce(&RoutingTableInner, &BucketEntryInner) -> R,
|
||||
{
|
||||
let inner = self.inner.read();
|
||||
f(rti, &*inner)
|
||||
f(rti, &inner)
|
||||
}
|
||||
|
||||
// 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,
|
||||
{
|
||||
let mut inner = self.inner.write();
|
||||
f(rti, &mut *inner)
|
||||
f(rti, &mut inner)
|
||||
}
|
||||
|
||||
// Internal inner access for RoutingTableInner only
|
||||
@ -911,7 +909,7 @@ impl BucketEntry {
|
||||
F: FnOnce(&BucketEntryInner) -> R,
|
||||
{
|
||||
let inner = self.inner.read();
|
||||
f(&*inner)
|
||||
f(&inner)
|
||||
}
|
||||
|
||||
// Internal inner access for RoutingTableInner only
|
||||
@ -920,7 +918,7 @@ impl BucketEntry {
|
||||
F: FnOnce(&mut BucketEntryInner) -> R,
|
||||
{
|
||||
let mut inner = self.inner.write();
|
||||
f(&mut *inner)
|
||||
f(&mut inner)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ impl RoutingTable {
|
||||
let mut out = String::new();
|
||||
|
||||
out += &format!("Entries: {}\n", inner.bucket_entry_count());
|
||||
out += &format!(" Live:\n");
|
||||
out += " Live:\n";
|
||||
for ec in inner.cached_entry_counts() {
|
||||
let routing_domain = ec.0 .0;
|
||||
let crypto_kind = ec.0 .1;
|
||||
|
@ -129,7 +129,7 @@ impl RoutingTableUnlockedInner {
|
||||
where
|
||||
F: FnOnce(&VeilidConfigInner) -> R,
|
||||
{
|
||||
f(&*self.config.get())
|
||||
f(&self.config.get())
|
||||
}
|
||||
|
||||
pub fn node_id(&self, kind: CryptoKind) -> TypedKey {
|
||||
@ -541,7 +541,7 @@ impl RoutingTable {
|
||||
peer_b: &PeerInfo,
|
||||
dial_info_filter: DialInfoFilter,
|
||||
sequencing: Sequencing,
|
||||
dif_sort: Option<Arc<dyn Fn(&DialInfoDetail, &DialInfoDetail) -> core::cmp::Ordering>>,
|
||||
dif_sort: Option<Arc<DialInfoDetailSort>>,
|
||||
) -> ContactMethod {
|
||||
self.inner.read().get_contact_method(
|
||||
routing_domain,
|
||||
@ -885,7 +885,7 @@ impl RoutingTable {
|
||||
crypto_kind: CryptoKind,
|
||||
max_per_type: usize,
|
||||
) -> Vec<NodeRef> {
|
||||
let protocol_types = vec![
|
||||
let protocol_types = [
|
||||
ProtocolType::UDP,
|
||||
ProtocolType::TCP,
|
||||
ProtocolType::WS,
|
||||
@ -893,8 +893,8 @@ impl RoutingTable {
|
||||
];
|
||||
|
||||
let protocol_types_len = protocol_types.len();
|
||||
let mut nodes_proto_v4 = vec![0usize, 0usize, 0usize, 0usize];
|
||||
let mut nodes_proto_v6 = vec![0usize, 0usize, 0usize, 0usize];
|
||||
let mut nodes_proto_v4 = [0usize, 0usize, 0usize, 0usize];
|
||||
let mut nodes_proto_v6 = [0usize, 0usize, 0usize, 0usize];
|
||||
|
||||
let filter = Box::new(
|
||||
move |rti: &RoutingTableInner, entry: Option<Arc<BucketEntry>>| {
|
||||
|
@ -85,7 +85,7 @@ pub trait NodeRefBase: Sized {
|
||||
self.common()
|
||||
.filter
|
||||
.as_ref()
|
||||
.map(|f| f.dial_info_filter.clone())
|
||||
.map(|f| f.dial_info_filter)
|
||||
.unwrap_or(DialInfoFilter::all())
|
||||
}
|
||||
|
||||
@ -283,7 +283,7 @@ pub trait NodeRefBase: Sized {
|
||||
self.operate(|rti, e| {
|
||||
// apply sequencing to filter and get sort
|
||||
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 mut last_connections = e.last_connections(rti, true, filter);
|
||||
|
||||
@ -444,7 +444,7 @@ impl Clone for NodeRef {
|
||||
common: NodeRefBaseCommon {
|
||||
routing_table: self.common.routing_table.clone(),
|
||||
entry: self.common.entry.clone(),
|
||||
filter: self.common.filter.clone(),
|
||||
filter: self.common.filter,
|
||||
sequencing: self.common.sequencing,
|
||||
#[cfg(feature = "tracking")]
|
||||
track_id: self.common.entry.write().track(),
|
||||
|
@ -18,7 +18,7 @@ pub enum RouteNode {
|
||||
/// Route node is optimized, no contact method information as this node id has been seen before
|
||||
NodeId(PublicKey),
|
||||
/// Route node with full contact method information to ensure the peer is reachable
|
||||
PeerInfo(PeerInfo),
|
||||
PeerInfo(Box<PeerInfo>),
|
||||
}
|
||||
|
||||
impl RouteNode {
|
||||
@ -41,7 +41,7 @@ impl RouteNode {
|
||||
Ok(nr) => nr,
|
||||
Err(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(
|
||||
RoutingDomain::PublicInternet,
|
||||
pi.clone(),
|
||||
*pi.clone(),
|
||||
false,
|
||||
) {
|
||||
Ok(nr) => Some(nr),
|
||||
Err(e) => {
|
||||
log_rtab!(debug "failed to register route node: {}", e);
|
||||
return None;
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -95,7 +95,7 @@ impl RouteHop {
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum PrivateRouteHops {
|
||||
/// 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
|
||||
Data(RouteHopData),
|
||||
/// Private route has ended (hop count = 0)
|
||||
@ -134,10 +134,10 @@ impl PrivateRoute {
|
||||
Self {
|
||||
public_key,
|
||||
hop_count: 1,
|
||||
hops: PrivateRouteHops::FirstHop(RouteHop {
|
||||
hops: PrivateRouteHops::FirstHop(Box::new(RouteHop {
|
||||
node,
|
||||
next_hop: None,
|
||||
}),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ fn _get_route_permutation_count(hop_count: usize) -> usize {
|
||||
// more than two nodes has factorial permutation
|
||||
// hop_count = 3 -> 2! -> 2
|
||||
// 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 PermFunc<'t> = Box<dyn FnMut(&[usize]) -> Option<PermReturnType> + Send + 't>;
|
||||
@ -47,7 +47,7 @@ pub fn with_route_permutations(
|
||||
f: &mut PermFunc,
|
||||
) -> Option<PermReturnType> {
|
||||
if size == 1 {
|
||||
return f(&permutation);
|
||||
return f(permutation);
|
||||
}
|
||||
|
||||
for i in 0..size {
|
||||
|
@ -112,7 +112,7 @@ impl RouteSetSpecDetail {
|
||||
}
|
||||
pub fn contains_nodes(&self, nodes: &[TypedKey]) -> bool {
|
||||
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) {
|
||||
return true;
|
||||
}
|
||||
|
@ -89,7 +89,6 @@ impl RouteSpecStore {
|
||||
|
||||
Ok(rss)
|
||||
}
|
||||
|
||||
|
||||
#[instrument(level = "trace", skip(self), err)]
|
||||
pub async fn save(&self) -> EyreResult<()> {
|
||||
@ -99,7 +98,9 @@ impl RouteSpecStore {
|
||||
};
|
||||
|
||||
// Save our content
|
||||
content.save(self.unlocked_inner.routing_table.clone()).await?;
|
||||
content
|
||||
.save(self.unlocked_inner.routing_table.clone())
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -166,6 +167,7 @@ impl RouteSpecStore {
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self, inner, rti), ret, err)]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn allocate_route_inner(
|
||||
&self,
|
||||
inner: &mut RouteSpecStoreInner,
|
||||
@ -186,7 +188,7 @@ impl RouteSpecStore {
|
||||
if hop_count > self.unlocked_inner.max_route_hop_count {
|
||||
bail!("Not allocating route longer than max route hop count");
|
||||
}
|
||||
|
||||
|
||||
// Ensure we have a valid network class so our peer info is useful
|
||||
if !rti.has_valid_network_class(RoutingDomain::PublicInternet) {
|
||||
log_rtab!(debug "unable to allocate route until we have a valid PublicInternet network class");
|
||||
@ -197,7 +199,9 @@ impl RouteSpecStore {
|
||||
let our_peer_info = rti.get_own_peer_info(RoutingDomain::PublicInternet);
|
||||
|
||||
// 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
|
||||
let cur_ts = get_aligned_timestamp();
|
||||
@ -218,7 +222,6 @@ impl RouteSpecStore {
|
||||
|
||||
// Process node info exclusions
|
||||
let keep = entry.with_inner(|e| {
|
||||
|
||||
// Exclude nodes that don't have our requested crypto kinds
|
||||
let common_ck = e.common_crypto_kinds(crypto_kinds);
|
||||
if common_ck.len() != crypto_kinds.len() {
|
||||
@ -236,13 +239,13 @@ impl RouteSpecStore {
|
||||
}
|
||||
|
||||
// Exclude nodes that have no publicinternet signednodeinfo
|
||||
let Some(sni) = e.signed_node_info(RoutingDomain::PublicInternet) else {
|
||||
let Some(sni) = e.signed_node_info(RoutingDomain::PublicInternet) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
// Relay check
|
||||
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
|
||||
if relay_ids.contains_any(avoid_nodes) {
|
||||
return false;
|
||||
@ -254,7 +257,7 @@ impl RouteSpecStore {
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
true
|
||||
});
|
||||
if !keep {
|
||||
return false;
|
||||
@ -262,9 +265,12 @@ impl RouteSpecStore {
|
||||
|
||||
// Exclude nodes with no publicinternet nodeinfo, or incompatible nodeinfo or node status won't route
|
||||
entry.with_inner(|e| {
|
||||
e.signed_node_info(RoutingDomain::PublicInternet).map(|sni|
|
||||
sni.has_sequencing_matched_dial_info(sequencing) && sni.node_info().has_capability(CAP_ROUTE)
|
||||
).unwrap_or(false)
|
||||
e.signed_node_info(RoutingDomain::PublicInternet)
|
||||
.map(|sni| {
|
||||
sni.has_sequencing_matched_dial_info(sequencing)
|
||||
&& sni.node_info().has_capability(CAP_ROUTE)
|
||||
})
|
||||
.unwrap_or(false)
|
||||
})
|
||||
},
|
||||
) as RoutingTableEntryFilter;
|
||||
@ -273,7 +279,6 @@ impl RouteSpecStore {
|
||||
entry1: &Option<Arc<BucketEntry>>,
|
||||
entry2: &Option<Arc<BucketEntry>>|
|
||||
-> Ordering {
|
||||
|
||||
// Our own node is filtered out
|
||||
let entry1 = entry1.as_ref().unwrap().clone();
|
||||
let entry2 = entry2.as_ref().unwrap().clone();
|
||||
@ -302,8 +307,14 @@ impl RouteSpecStore {
|
||||
if matches!(sequencing, Sequencing::PreferOrdered) {
|
||||
let cmp_seq = entry1.with_inner(|e1| {
|
||||
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 e2_can_do_ordered = e2.signed_node_info(RoutingDomain::PublicInternet).map(|sni| sni.has_sequencing_matched_dial_info(sequencing)).unwrap_or(false);
|
||||
let e1_can_do_ordered = e1
|
||||
.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)
|
||||
})
|
||||
});
|
||||
@ -313,27 +324,22 @@ impl RouteSpecStore {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
Stability::LowLatency => {
|
||||
BucketEntryInner::cmp_fastest_reliable(cur_ts, e1, e2)
|
||||
}
|
||||
Stability::Reliable => {
|
||||
BucketEntryInner::cmp_oldest_reliable(cur_ts, e1, e2)
|
||||
}
|
||||
Stability::LowLatency => BucketEntryInner::cmp_fastest_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 transform =
|
||||
|_rti: &RoutingTableInner, entry: Option<Arc<BucketEntry>>| -> NodeRef {
|
||||
NodeRef::new(routing_table.clone(), entry.unwrap(), None)
|
||||
};
|
||||
let transform = |_rti: &RoutingTableInner, entry: Option<Arc<BucketEntry>>| -> NodeRef {
|
||||
NodeRef::new(routing_table.clone(), entry.unwrap(), None)
|
||||
};
|
||||
|
||||
// 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);
|
||||
|
||||
// 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
|
||||
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
|
||||
let mut perm_func = Box::new(|permutation: &[usize]| {
|
||||
|
||||
// Get the hop cache key for a particular route permutation
|
||||
// uses the same algorithm as RouteSetSpecDetail::make_cache_key
|
||||
let route_permutation_to_hop_cache = |_rti: &RoutingTableInner, nodes: &[NodeRef], perm: &[usize]| -> Vec<u8> {
|
||||
let mut cache: Vec<u8> = Vec::with_capacity(perm.len() * PUBLIC_KEY_LENGTH);
|
||||
for n in perm {
|
||||
cache.extend_from_slice(&nodes[*n].locked(rti).best_node_id().value.bytes)
|
||||
}
|
||||
cache
|
||||
};
|
||||
let route_permutation_to_hop_cache =
|
||||
|_rti: &RoutingTableInner, nodes: &[NodeRef], perm: &[usize]| -> Vec<u8> {
|
||||
let mut cache: Vec<u8> = Vec::with_capacity(perm.len() * PUBLIC_KEY_LENGTH);
|
||||
for n in perm {
|
||||
cache.extend_from_slice(&nodes[*n].locked(rti).best_node_id().value.bytes)
|
||||
}
|
||||
cache
|
||||
};
|
||||
let cache_key = route_permutation_to_hop_cache(rti, &nodes, permutation);
|
||||
|
||||
// Skip routes we have already seen
|
||||
@ -491,21 +504,36 @@ impl RouteSpecStore {
|
||||
drop(perm_func);
|
||||
|
||||
// Got a unique route, lets build the details, register it, and return it
|
||||
let hop_node_refs:Vec<NodeRef> = route_nodes
|
||||
.iter()
|
||||
.map(|k| nodes[*k].clone())
|
||||
.collect();
|
||||
let hop_node_refs: Vec<NodeRef> = route_nodes.iter().map(|k| nodes[*k].clone()).collect();
|
||||
let mut route_set = BTreeMap::<PublicKey, RouteSpecDetail>::new();
|
||||
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 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 {
|
||||
crypto_kind,
|
||||
secret_key: keypair.secret,
|
||||
hops,
|
||||
});
|
||||
route_set.insert(
|
||||
keypair.key,
|
||||
RouteSpecDetail {
|
||||
crypto_kind,
|
||||
secret_key: keypair.secret,
|
||||
hops,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
let rssd = RouteSetSpecDetail::new(
|
||||
@ -514,10 +542,9 @@ impl RouteSpecStore {
|
||||
hop_node_refs,
|
||||
directions,
|
||||
stability,
|
||||
can_do_sequenced,
|
||||
can_do_sequenced,
|
||||
);
|
||||
|
||||
|
||||
// make id
|
||||
let id = self.generate_allocated_route_id(&rssd)?;
|
||||
|
||||
@ -525,23 +552,27 @@ impl RouteSpecStore {
|
||||
inner.cache.add_to_cache(rti, &rssd);
|
||||
|
||||
// Keep route in spec store
|
||||
inner.content.add_detail(id.clone(), rssd);
|
||||
inner.content.add_detail(id, rssd);
|
||||
|
||||
Ok(Some(id))
|
||||
}
|
||||
|
||||
/// validate data using a private route's key and signature chain
|
||||
#[cfg_attr(feature="verbose-tracing", instrument(level = "trace", skip(self, data, callback), ret))]
|
||||
pub fn with_signature_validated_route<F,R>(
|
||||
#[cfg_attr(
|
||||
feature = "verbose-tracing",
|
||||
instrument(level = "trace", skip(self, data, callback), ret)
|
||||
)]
|
||||
pub fn with_signature_validated_route<F, R>(
|
||||
&self,
|
||||
public_key: &TypedKey,
|
||||
signatures: &[Signature],
|
||||
data: &[u8],
|
||||
last_hop_id: PublicKey,
|
||||
callback: F,
|
||||
) -> Option<R>
|
||||
where F: FnOnce(&RouteSetSpecDetail, &RouteSpecDetail) -> R,
|
||||
R: fmt::Debug,
|
||||
) -> Option<R>
|
||||
where
|
||||
F: FnOnce(&RouteSetSpecDetail, &RouteSpecDetail) -> R,
|
||||
R: fmt::Debug,
|
||||
{
|
||||
let inner = &*self.inner.lock();
|
||||
let crypto = self.unlocked_inner.routing_table.crypto();
|
||||
@ -549,7 +580,7 @@ impl RouteSpecStore {
|
||||
log_rpc!(debug "can't handle route with public key: {:?}", public_key);
|
||||
return None;
|
||||
};
|
||||
|
||||
|
||||
let Some(rsid) = inner.content.get_id_by_key(&public_key.value) else {
|
||||
log_rpc!(debug "route id does not exist: {:?}", public_key.value);
|
||||
return None;
|
||||
@ -587,15 +618,17 @@ impl RouteSpecStore {
|
||||
}
|
||||
}
|
||||
}
|
||||
// We got the correct signatures, return a key and response safety spec
|
||||
// We got the correct signatures, return a key and response safety spec
|
||||
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> {
|
||||
// Make loopback route to test with
|
||||
let dest = {
|
||||
|
||||
// Get the best private route for this id
|
||||
let (key, hop_count) = {
|
||||
let inner = &mut *self.inner.lock();
|
||||
@ -606,7 +639,7 @@ impl RouteSpecStore {
|
||||
bail!("no best key to test allocated route");
|
||||
};
|
||||
// Match the private route's hop length for safety route length
|
||||
let hop_count = rssd.hop_count();
|
||||
let hop_count = rssd.hop_count();
|
||||
(key, hop_count)
|
||||
};
|
||||
|
||||
@ -646,10 +679,8 @@ impl RouteSpecStore {
|
||||
|
||||
#[instrument(level = "trace", skip(self), ret, err)]
|
||||
async fn test_remote_route(&self, private_route_id: RouteId) -> EyreResult<bool> {
|
||||
|
||||
// Make private route test
|
||||
let dest = {
|
||||
|
||||
// Get the route to test
|
||||
let Some(private_route) = self.best_remote_private_route(&private_route_id) else {
|
||||
bail!("no best key to test remote route");
|
||||
@ -710,11 +741,17 @@ impl RouteSpecStore {
|
||||
pub fn is_route_id_remote(&self, id: &RouteId) -> bool {
|
||||
let inner = &mut *self.inner.lock();
|
||||
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
|
||||
#[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> {
|
||||
let is_remote = self.is_route_id_remote(&id);
|
||||
if is_remote {
|
||||
@ -737,8 +774,9 @@ impl RouteSpecStore {
|
||||
|
||||
/// 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
|
||||
fn first_available_route_inner<'a>(
|
||||
inner: &'a RouteSpecStoreInner,
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn first_available_route_inner(
|
||||
inner: &RouteSpecStoreInner,
|
||||
crypto_kind: CryptoKind,
|
||||
min_hop_count: usize,
|
||||
max_hop_count: usize,
|
||||
@ -760,7 +798,7 @@ impl RouteSpecStore {
|
||||
&& rssd.hop_count() <= max_hop_count
|
||||
&& rssd.get_directions().is_superset(directions)
|
||||
&& rssd.get_route_set_keys().kinds().contains(&crypto_kind)
|
||||
&& !rssd.is_published()
|
||||
&& !rssd.is_published()
|
||||
&& !rssd.contains_nodes(avoid_nodes)
|
||||
{
|
||||
routes.push((id, rssd));
|
||||
@ -821,7 +859,7 @@ impl RouteSpecStore {
|
||||
pub fn debug_route(&self, id: &RouteId) -> Option<String> {
|
||||
let inner = &mut *self.inner.lock();
|
||||
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));
|
||||
}
|
||||
if let Some(rssd) = inner.content.get_detail(id) {
|
||||
@ -840,7 +878,6 @@ impl RouteSpecStore {
|
||||
rpri.best_private_route()
|
||||
}
|
||||
|
||||
|
||||
/// Compiles a safety route to the private route, with caching
|
||||
/// Returns an Err() if the parameters are wrong
|
||||
/// Returns Ok(None) if no allocation could happen at this time (not an error)
|
||||
@ -863,7 +900,7 @@ impl RouteSpecStore {
|
||||
let pr_pubkey = private_route.public_key.value;
|
||||
let pr_hopcount = private_route.hop_count as usize;
|
||||
let max_route_hop_count = self.unlocked_inner.max_route_hop_count;
|
||||
|
||||
|
||||
// Check private route hop count isn't larger than the max route hop count plus one for the 'first hop' header
|
||||
if pr_hopcount > (max_route_hop_count + 1) {
|
||||
bail!("private route hop count too long");
|
||||
@ -879,15 +916,15 @@ impl RouteSpecStore {
|
||||
};
|
||||
|
||||
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::PeerInfo(pi) => {
|
||||
Some(rti.register_node_with_peer_info(
|
||||
routing_table.clone(),
|
||||
RoutingDomain::PublicInternet,
|
||||
pi,
|
||||
false,
|
||||
)?)
|
||||
RouteNode::NodeId(id) => {
|
||||
rti.lookup_node_ref(routing_table.clone(), TypedKey::new(crypto_kind, id))?
|
||||
}
|
||||
RouteNode::PeerInfo(pi) => Some(rti.register_node_with_peer_info(
|
||||
routing_table.clone(),
|
||||
RoutingDomain::PublicInternet,
|
||||
*pi,
|
||||
false,
|
||||
)?),
|
||||
};
|
||||
if opt_first_hop.is_none() {
|
||||
// Can't reach this private route any more
|
||||
@ -902,7 +939,10 @@ impl RouteSpecStore {
|
||||
// Return the compiled safety route
|
||||
//println!("compile_safety_route profile (stub): {} us", (get_timestamp() - profile_start_ts));
|
||||
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),
|
||||
first_hop,
|
||||
}));
|
||||
@ -911,20 +951,30 @@ impl RouteSpecStore {
|
||||
|
||||
// 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 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
|
||||
pr_pubkey
|
||||
} else {
|
||||
let Some(avoid_node_id) = private_route.first_hop_node_id() else {
|
||||
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
|
||||
return Ok(None);
|
||||
};
|
||||
sr_pubkey
|
||||
};
|
||||
|
||||
|
||||
// Look up a few things from the safety route detail we want for the compiled route and don't borrow inner
|
||||
let Some(safety_route_id) = inner.content.get_id_by_key(&sr_pubkey) else {
|
||||
bail!("route id missing");
|
||||
@ -939,7 +989,8 @@ impl RouteSpecStore {
|
||||
// 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
|
||||
// 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
|
||||
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
|
||||
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
|
||||
let compiled_route = CompiledRoute {
|
||||
safety_route,
|
||||
@ -993,9 +1047,9 @@ impl RouteSpecStore {
|
||||
let dh_secret = vcrypto
|
||||
.cached_dh(&safety_rsd.hops[h], &safety_rsd.secret_key)
|
||||
.wrap_err("dh failed")?;
|
||||
let enc_msg_data =
|
||||
vcrypto.encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None)
|
||||
.wrap_err("encryption failed")?;
|
||||
let enc_msg_data = vcrypto
|
||||
.encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None)
|
||||
.wrap_err("encryption failed")?;
|
||||
|
||||
// Make route hop data
|
||||
let route_hop_data = RouteHopData {
|
||||
@ -1021,7 +1075,7 @@ impl RouteSpecStore {
|
||||
if pi.is_none() {
|
||||
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),
|
||||
};
|
||||
@ -1045,7 +1099,8 @@ impl RouteSpecStore {
|
||||
let dh_secret = vcrypto
|
||||
.cached_dh(&safety_rsd.hops[0], &safety_rsd.secret_key)
|
||||
.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"))?;
|
||||
|
||||
let route_hop_data = RouteHopData {
|
||||
@ -1065,7 +1120,9 @@ impl RouteSpecStore {
|
||||
|
||||
// Add to cache but only if we have an optimized route
|
||||
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
|
||||
@ -1081,7 +1138,10 @@ impl RouteSpecStore {
|
||||
}
|
||||
|
||||
/// 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(
|
||||
&self,
|
||||
inner: &mut RouteSpecStoreInner,
|
||||
@ -1132,7 +1192,7 @@ impl RouteSpecStore {
|
||||
.allocate_route_inner(
|
||||
inner,
|
||||
rti,
|
||||
&[crypto_kind],
|
||||
&[crypto_kind],
|
||||
safety_spec.stability,
|
||||
safety_spec.sequencing,
|
||||
safety_spec.hop_count,
|
||||
@ -1146,13 +1206,23 @@ impl RouteSpecStore {
|
||||
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))
|
||||
}
|
||||
|
||||
/// 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(
|
||||
&self,
|
||||
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 rti = &*routing_table.inner.read();
|
||||
|
||||
@ -1198,7 +1272,7 @@ impl RouteSpecStore {
|
||||
RouteNode::NodeId(node_id.value)
|
||||
} else {
|
||||
let pi = rti.get_own_peer_info(RoutingDomain::PublicInternet);
|
||||
RouteNode::PeerInfo(pi)
|
||||
RouteNode::PeerInfo(Box::new(pi))
|
||||
},
|
||||
next_hop: None,
|
||||
};
|
||||
@ -1220,7 +1294,8 @@ impl RouteSpecStore {
|
||||
let dh_secret = vcrypto
|
||||
.cached_dh(&rsd.hops[h], &rsd.secret_key)
|
||||
.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")?;
|
||||
let route_hop_data = RouteHopData {
|
||||
nonce,
|
||||
@ -1244,7 +1319,7 @@ impl RouteSpecStore {
|
||||
if pi.is_none() {
|
||||
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),
|
||||
}
|
||||
@ -1258,10 +1333,13 @@ impl RouteSpecStore {
|
||||
};
|
||||
Ok(private_route)
|
||||
}
|
||||
|
||||
|
||||
/// Assemble a single private route for publication
|
||||
/// 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(
|
||||
&self,
|
||||
key: &PublicKey,
|
||||
@ -1277,18 +1355,24 @@ impl RouteSpecStore {
|
||||
|
||||
// See if we can optimize this compilation yet
|
||||
// We don't want to include full nodeinfo if we don't have to
|
||||
let optimized = optimized
|
||||
.unwrap_or(rssd.get_stats().last_tested_ts.is_some() || rssd.get_stats().last_received_ts.is_some());
|
||||
let optimized = optimized.unwrap_or(
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
/// Assemble private route set for publication
|
||||
/// 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(
|
||||
&self,
|
||||
id: &RouteId,
|
||||
@ -1301,8 +1385,10 @@ impl RouteSpecStore {
|
||||
|
||||
// See if we can optimize this compilation yet
|
||||
// We don't want to include full nodeinfo if we don't have to
|
||||
let optimized = optimized
|
||||
.unwrap_or(rssd.get_stats().last_tested_ts.is_some() || rssd.get_stats().last_received_ts.is_some());
|
||||
let optimized = optimized.unwrap_or(
|
||||
rssd.get_stats().last_tested_ts.is_some()
|
||||
|| rssd.get_stats().last_received_ts.is_some(),
|
||||
);
|
||||
|
||||
let mut out = Vec::new();
|
||||
for (key, rsd) in rssd.iter_route_set() {
|
||||
@ -1314,12 +1400,18 @@ impl RouteSpecStore {
|
||||
/// 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
|
||||
/// Returns a route set id
|
||||
#[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> {
|
||||
#[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> {
|
||||
let cur_ts = get_aligned_timestamp();
|
||||
|
||||
|
||||
// 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
|
||||
let id = self.generate_remote_route_id(&private_routes)?;
|
||||
@ -1327,7 +1419,6 @@ impl RouteSpecStore {
|
||||
// validate the private routes
|
||||
let inner = &mut *self.inner.lock();
|
||||
for private_route in &private_routes {
|
||||
|
||||
// ensure private route has first hop
|
||||
if !matches!(private_route.hops, PrivateRouteHops::FirstHop(_)) {
|
||||
bail!("private route must have first hop");
|
||||
@ -1339,27 +1430,31 @@ 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)
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
let inner = &mut *self.inner.lock();
|
||||
inner.cache.remove_remote_private_route(id)
|
||||
}
|
||||
|
||||
/// Get a route id for a route's public key
|
||||
pub fn get_route_id_for_key(&self, key: &PublicKey) -> Option<RouteId>
|
||||
{
|
||||
/// Get a route id for a route's public key
|
||||
pub fn get_route_id_for_key(&self, key: &PublicKey) -> Option<RouteId> {
|
||||
let inner = &mut *self.inner.lock();
|
||||
// Check for local route
|
||||
if let Some(id) = inner.content.get_id_by_key(key) {
|
||||
return Some(id);
|
||||
}
|
||||
|
||||
|
||||
// Check for remote route
|
||||
if let Some(rrid) = inner.cache.get_remote_private_route_id_by_key(key) {
|
||||
return Some(rrid);
|
||||
@ -1371,7 +1466,6 @@ impl RouteSpecStore {
|
||||
/// 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
|
||||
pub fn has_remote_private_route_seen_our_node_info(&self, key: &PublicKey) -> bool {
|
||||
|
||||
let inner = &mut *self.inner.lock();
|
||||
|
||||
// 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) {
|
||||
let cur_ts = get_aligned_timestamp();
|
||||
if let Some(rpri) = inner.cache.peek_remote_private_route_mut(cur_ts, &rrid)
|
||||
{
|
||||
let our_node_info_ts = self.unlocked_inner.routing_table.get_own_node_info_ts(RoutingDomain::PublicInternet);
|
||||
if let Some(rpri) = inner.cache.peek_remote_private_route_mut(cur_ts, &rrid) {
|
||||
let our_node_info_ts = self
|
||||
.unlocked_inner
|
||||
.routing_table
|
||||
.get_own_node_info_ts(RoutingDomain::PublicInternet);
|
||||
return rpri.has_seen_our_node_info_ts(our_node_info_ts);
|
||||
}
|
||||
}
|
||||
@ -1404,7 +1500,10 @@ impl RouteSpecStore {
|
||||
key: &PublicKey,
|
||||
cur_ts: Timestamp,
|
||||
) -> 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();
|
||||
|
||||
@ -1416,8 +1515,7 @@ impl RouteSpecStore {
|
||||
}
|
||||
|
||||
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);
|
||||
return Ok(());
|
||||
}
|
||||
@ -1434,7 +1532,11 @@ impl RouteSpecStore {
|
||||
let inner = &mut *self.inner.lock();
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@ -1447,8 +1549,7 @@ impl RouteSpecStore {
|
||||
|
||||
// Check for remote route
|
||||
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()));
|
||||
}
|
||||
}
|
||||
@ -1493,22 +1594,21 @@ impl RouteSpecStore {
|
||||
|
||||
/// Convert private route list to binary blob
|
||||
pub fn private_routes_to_blob(private_routes: &[PrivateRoute]) -> EyreResult<Vec<u8>> {
|
||||
|
||||
let mut buffer = vec![];
|
||||
|
||||
// Serialize count
|
||||
// Serialize count
|
||||
let pr_count = private_routes.len();
|
||||
if pr_count > MAX_CRYPTO_KINDS {
|
||||
bail!("too many crypto kinds to encode blob");
|
||||
}
|
||||
let pr_count = pr_count as u8;
|
||||
buffer.push(pr_count);
|
||||
|
||||
|
||||
// Serialize stream of private routes
|
||||
for private_route in private_routes {
|
||||
let mut pr_message = ::capnp::message::Builder::new_default();
|
||||
let mut pr_builder = pr_message.init_root::<veilid_capnp::private_route::Builder>();
|
||||
|
||||
|
||||
encode_private_route(private_route, &mut pr_builder)
|
||||
.wrap_err("failed to encode private route")?;
|
||||
|
||||
@ -1521,7 +1621,6 @@ impl RouteSpecStore {
|
||||
|
||||
/// Convert binary blob to private route
|
||||
pub fn blob_to_private_routes(crypto: Crypto, blob: Vec<u8>) -> EyreResult<Vec<PrivateRoute>> {
|
||||
|
||||
// Deserialize count
|
||||
if blob.is_empty() {
|
||||
bail!("not deserializing empty private route blob");
|
||||
@ -1547,16 +1646,17 @@ impl RouteSpecStore {
|
||||
.get_root::<veilid_capnp::private_route::Reader>()
|
||||
.map_err(RPCError::internal)
|
||||
.wrap_err("failed to make reader for private_route")?;
|
||||
let 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")?;
|
||||
let 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);
|
||||
}
|
||||
|
||||
|
||||
// Don't trust the order of the blob
|
||||
out.sort_by(|a,b| {
|
||||
a.public_key.cmp(&b.public_key)
|
||||
});
|
||||
out.sort_by(|a, b| a.public_key.cmp(&b.public_key));
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
@ -1565,13 +1665,15 @@ impl RouteSpecStore {
|
||||
fn generate_allocated_route_id(&self, rssd: &RouteSetSpecDetail) -> EyreResult<RouteId> {
|
||||
let route_set_keys = rssd.get_route_set_keys();
|
||||
let crypto = self.unlocked_inner.routing_table.crypto();
|
||||
|
||||
|
||||
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() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
idbytes.extend_from_slice(&tk.value.bytes);
|
||||
}
|
||||
let Some(best_kind) = best_kind else {
|
||||
@ -1580,19 +1682,21 @@ impl RouteSpecStore {
|
||||
let vcrypto = crypto.get(best_kind).unwrap();
|
||||
|
||||
Ok(RouteId::new(vcrypto.generate_hash(&idbytes).bytes))
|
||||
|
||||
}
|
||||
|
||||
/// Generate RouteId from set of private routes
|
||||
fn generate_remote_route_id(&self, private_routes: &[PrivateRoute]) -> EyreResult<RouteId> {
|
||||
let crypto = self.unlocked_inner.routing_table.crypto();
|
||||
|
||||
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
}
|
||||
idbytes.extend_from_slice(&private_route.public_key.value.bytes);
|
||||
}
|
||||
let Some(best_kind) = best_kind else {
|
||||
@ -1602,5 +1706,4 @@ impl RouteSpecStore {
|
||||
|
||||
Ok(RouteId::new(vcrypto.generate_hash(&idbytes).bytes))
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ impl RouteSpecStoreCache {
|
||||
// also store in id by key table
|
||||
for private_route in rprinfo.get_private_routes() {
|
||||
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;
|
||||
|
@ -29,18 +29,20 @@ impl RouteSpecStoreContent {
|
||||
for (rsid, rssd) in content.details.iter_mut() {
|
||||
// Get best route since they all should resolve
|
||||
let Some(pk) = rssd.get_best_route_set_key() else {
|
||||
dead_ids.push(rsid.clone());
|
||||
dead_ids.push(*rsid);
|
||||
continue;
|
||||
};
|
||||
let Some(rsd) = rssd.get_route_by_key(&pk) else {
|
||||
dead_ids.push(rsid.clone());
|
||||
dead_ids.push(*rsid);
|
||||
continue;
|
||||
};
|
||||
// Go through best route and resolve noderefs
|
||||
let mut hop_node_refs = Vec::with_capacity(rsd.hops.len());
|
||||
for h in &rsd.hops {
|
||||
let Ok(Some(nr)) = routing_table.lookup_node_ref(TypedKey::new(rsd.crypto_kind, *h)) else {
|
||||
dead_ids.push(rsid.clone());
|
||||
let Ok(Some(nr)) =
|
||||
routing_table.lookup_node_ref(TypedKey::new(rsd.crypto_kind, *h))
|
||||
else {
|
||||
dead_ids.push(*rsid);
|
||||
break;
|
||||
};
|
||||
hop_node_refs.push(nr);
|
||||
@ -72,14 +74,14 @@ impl RouteSpecStoreContent {
|
||||
|
||||
// also store in id by key table
|
||||
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> {
|
||||
let detail = self.details.remove(id)?;
|
||||
for (pk, _) in detail.iter_route_set() {
|
||||
self.id_by_key.remove(&pk).unwrap();
|
||||
self.id_by_key.remove(pk).unwrap();
|
||||
}
|
||||
Some(detail)
|
||||
}
|
||||
@ -106,7 +108,7 @@ impl RouteSpecStoreContent {
|
||||
/// Resets publication status and statistics for when our node info changes
|
||||
/// Routes must be republished
|
||||
pub fn reset_details(&mut self) {
|
||||
for (_k, v) in &mut self.details {
|
||||
for v in self.details.values_mut() {
|
||||
// Must republish route now
|
||||
v.set_published(false);
|
||||
// Restart stats for routes so we test the route again
|
||||
|
@ -276,7 +276,7 @@ fn first_filtered_dial_info_detail_between_nodes(
|
||||
to_node: &NodeInfo,
|
||||
dial_info_filter: &DialInfoFilter,
|
||||
sequencing: Sequencing,
|
||||
dif_sort: Option<Arc<dyn Fn(&DialInfoDetail, &DialInfoDetail) -> core::cmp::Ordering>>
|
||||
dif_sort: Option<Arc<DialInfoDetailSort>>
|
||||
) -> Option<DialInfoDetail> {
|
||||
let dial_info_filter = dial_info_filter.clone().filtered(
|
||||
&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
|
||||
// AddressFilter to deprioritize dialinfo that have recently failed to connect
|
||||
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 {
|
||||
Some(Box::new(move |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
|
||||
// AddressFilter to deprioritize dialinfo that have recently failed to connect
|
||||
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 {
|
||||
Some(Box::new(move |a, b| {
|
||||
let mut ord = dif_sort(a,b);
|
||||
|
@ -227,7 +227,7 @@ impl RoutingTableInner {
|
||||
peer_b: &PeerInfo,
|
||||
dial_info_filter: DialInfoFilter,
|
||||
sequencing: Sequencing,
|
||||
dif_sort: Option<Arc<dyn Fn(&DialInfoDetail, &DialInfoDetail) -> core::cmp::Ordering>>,
|
||||
dif_sort: Option<Arc<DialInfoDetailSort>>,
|
||||
) -> ContactMethod {
|
||||
self.with_routing_domain(routing_domain, |rdd| {
|
||||
rdd.get_contact_method(self, peer_a, peer_b, dial_info_filter, sequencing, dif_sort)
|
||||
|
@ -46,7 +46,7 @@ impl RoutingTable {
|
||||
|
||||
// Envelope support
|
||||
let mut envelope_support = Vec::new();
|
||||
for ess in records[1].split(",") {
|
||||
for ess in records[1].split(',') {
|
||||
let ess = ess.trim();
|
||||
let es = match ess.parse::<u8>() {
|
||||
Ok(v) => v,
|
||||
@ -64,9 +64,9 @@ impl RoutingTable {
|
||||
|
||||
// Node Id
|
||||
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 = match TypedKey::from_str(&node_id_str) {
|
||||
let node_id = match TypedKey::from_str(node_id_str) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
bail!(
|
||||
@ -89,7 +89,7 @@ impl RoutingTable {
|
||||
|
||||
// Resolve each record and store in node dial infos list
|
||||
let mut dial_info_details = Vec::new();
|
||||
for rec in records[4].split(",") {
|
||||
for rec in records[4].split(',') {
|
||||
let rec = rec.trim();
|
||||
let dial_infos = match DialInfo::try_vec_from_short(rec, hostname_str) {
|
||||
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
|
||||
let mut bootstrap_dialinfos = Vec::<DialInfo>::new();
|
||||
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 {
|
||||
bootstrap_dialinfos.push(bootstrap_di);
|
||||
}
|
||||
|
@ -8,6 +8,9 @@ use futures_util::stream::{FuturesUnordered, StreamExt};
|
||||
use futures_util::FutureExt;
|
||||
use stop_token::future::FutureExt as StopFutureExt;
|
||||
|
||||
type PingValidatorFuture =
|
||||
SendPinBoxFuture<Result<NetworkResult<Answer<Option<SenderInfo>>>, RPCError>>;
|
||||
|
||||
impl RoutingTable {
|
||||
// Ping each node in the routing table if they need to be pinged
|
||||
// to determine their reliability
|
||||
@ -16,9 +19,7 @@ impl RoutingTable {
|
||||
&self,
|
||||
cur_ts: Timestamp,
|
||||
relay_nr: NodeRef,
|
||||
unord: &mut FuturesUnordered<
|
||||
SendPinBoxFuture<Result<NetworkResult<Answer<Option<SenderInfo>>>, RPCError>>,
|
||||
>,
|
||||
unord: &mut FuturesUnordered<PingValidatorFuture>,
|
||||
) -> EyreResult<()> {
|
||||
let rpc = self.rpc_processor();
|
||||
// Get our publicinternet dial info
|
||||
@ -123,9 +124,7 @@ impl RoutingTable {
|
||||
async fn ping_validator_public_internet(
|
||||
&self,
|
||||
cur_ts: Timestamp,
|
||||
unord: &mut FuturesUnordered<
|
||||
SendPinBoxFuture<Result<NetworkResult<Answer<Option<SenderInfo>>>, RPCError>>,
|
||||
>,
|
||||
unord: &mut FuturesUnordered<PingValidatorFuture>,
|
||||
) -> EyreResult<()> {
|
||||
let rpc = self.rpc_processor();
|
||||
|
||||
@ -161,9 +160,7 @@ impl RoutingTable {
|
||||
async fn ping_validator_local_network(
|
||||
&self,
|
||||
cur_ts: Timestamp,
|
||||
unord: &mut FuturesUnordered<
|
||||
SendPinBoxFuture<Result<NetworkResult<Answer<Option<SenderInfo>>>, RPCError>>,
|
||||
>,
|
||||
unord: &mut FuturesUnordered<PingValidatorFuture>,
|
||||
) -> EyreResult<()> {
|
||||
let rpc = self.rpc_processor();
|
||||
|
||||
|
@ -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) => {
|
||||
let pi_reader = pi.map_err(RPCError::protocol)?;
|
||||
RouteNode::PeerInfo(
|
||||
RouteNode::PeerInfo(Box::new(
|
||||
decode_peer_info(&pi_reader)
|
||||
.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)? {
|
||||
veilid_capnp::private_route::hops::Which::FirstHop(rh_reader) => {
|
||||
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) => {
|
||||
let rhd_reader = rhd_reader.map_err(RPCError::protocol)?;
|
||||
|
@ -181,10 +181,17 @@ impl RPCProcessor {
|
||||
// Sent directly but with a safety route, respond to private route
|
||||
let crypto_kind = target.best_node_id().kind;
|
||||
let Some(pr_key) = rss
|
||||
.get_private_route_for_safety_spec(crypto_kind, 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_private_route_for_safety_spec(
|
||||
crypto_kind,
|
||||
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
|
||||
let private_route = rss
|
||||
@ -211,9 +218,12 @@ impl RPCProcessor {
|
||||
avoid_nodes.add_all(&target.node_ids());
|
||||
let Some(pr_key) = rss
|
||||
.get_private_route_for_safety_spec(crypto_kind, safety_spec, &avoid_nodes)
|
||||
.map_err(RPCError::internal)? else {
|
||||
return Ok(NetworkResult::no_connection_other("no private route for response at this time"));
|
||||
};
|
||||
.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
|
||||
let private_route = rss
|
||||
@ -228,7 +238,9 @@ impl RPCProcessor {
|
||||
safety_selection,
|
||||
} => {
|
||||
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;
|
||||
@ -250,7 +262,7 @@ impl RPCProcessor {
|
||||
} else {
|
||||
let own_peer_info =
|
||||
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(
|
||||
@ -271,10 +283,17 @@ impl RPCProcessor {
|
||||
} else {
|
||||
// Get the private route to respond to that matches the safety route spec we sent the request with
|
||||
let Some(pr_key) = rss
|
||||
.get_private_route_for_safety_spec(crypto_kind, safety_spec, &[avoid_node_id])
|
||||
.map_err(RPCError::internal)? else {
|
||||
return Ok(NetworkResult::no_connection_other("no private route for response at this time"));
|
||||
};
|
||||
.get_private_route_for_safety_spec(
|
||||
crypto_kind,
|
||||
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
|
||||
};
|
||||
|
||||
|
@ -812,7 +812,7 @@ impl RPCProcessor {
|
||||
};
|
||||
let private_route = PrivateRoute::new_stub(
|
||||
destination_node_ref.best_node_id(),
|
||||
RouteNode::PeerInfo(peer_info),
|
||||
RouteNode::PeerInfo(Box::new(peer_info)),
|
||||
);
|
||||
|
||||
// Wrap with safety route
|
||||
|
Loading…
Reference in New Issue
Block a user