checkpoint

This commit is contained in:
John Smith
2022-11-09 22:27:37 -05:00
parent e672ae0319
commit 592c83d83a
10 changed files with 299 additions and 325 deletions

View File

@@ -348,24 +348,30 @@ impl RoutingTable {
.node_info_is_valid_in_routing_domain(routing_domain, node_info)
}
pub fn signed_node_info_is_valid_in_routing_domain(
&self,
routing_domain: RoutingDomain,
signed_node_info: &SignedNodeInfo,
) -> bool {
self.inner
.read()
.signed_node_info_is_valid_in_routing_domain(routing_domain, signed_node_info)
}
/// Look up the best way for two nodes to reach each other over a specific routing domain
#[instrument(level = "trace", skip(self), ret)]
pub fn get_contact_method(
&self,
routing_domain: RoutingDomain,
node_a_id: &DHTKey,
node_a: &NodeInfo,
node_b_id: &DHTKey,
node_b: &NodeInfo,
peer_a: &PeerInfo,
peer_b: &PeerInfo,
dial_info_filter: DialInfoFilter,
sequencing: Sequencing,
) -> ContactMethod {
self.inner.read().get_contact_method(
routing_domain,
node_a_id,
node_a,
node_b_id,
node_b,
peer_a,
peer_b,
dial_info_filter,
sequencing,
)
@@ -381,16 +387,6 @@ impl RoutingTable {
self.inner.read().get_own_peer_info(routing_domain)
}
/// Return a copy of our node's signednodeinfo
pub fn get_own_signed_node_info(&self, routing_domain: RoutingDomain) -> SignedDirectNodeInfo {
self.inner.read().get_own_signed_node_info(routing_domain)
}
/// Return a copy of our node's nodeinfo
pub fn get_own_node_info(&self, routing_domain: RoutingDomain) -> NodeInfo {
self.inner.read().get_own_node_info(routing_domain)
}
/// If we have a valid network class in this routing domain, then our 'NodeInfo' is valid
pub fn has_valid_own_node_info(&self, routing_domain: RoutingDomain) -> bool {
self.inner.read().has_valid_own_node_info(routing_domain)
@@ -525,7 +521,7 @@ impl RoutingTable {
&self,
routing_domain: RoutingDomain,
node_id: DHTKey,
signed_node_info: SignedDirectNodeInfo,
signed_node_info: SignedNodeInfo,
allow_invalid: bool,
) -> Option<NodeRef> {
self.inner.write().register_node_with_signed_node_info(

View File

@@ -116,10 +116,10 @@ pub trait NodeRefBase: Sized {
e.update_node_status(node_status);
});
}
fn min_max_version(&self) -> Option<(u8, u8)> {
fn min_max_version(&self) -> Option<VersionRange> {
self.operate(|_rti, e| e.min_max_version())
}
fn set_min_max_version(&self, min_max_version: (u8, u8)) {
fn set_min_max_version(&self, min_max_version: VersionRange) {
self.operate_mut(|_rti, e| e.set_min_max_version(min_max_version))
}
fn state(&self, cur_ts: u64) -> BucketEntryState {
@@ -170,26 +170,24 @@ pub trait NodeRefBase: Sized {
}
fn relay(&self, routing_domain: RoutingDomain) -> Option<NodeRef> {
self.operate_mut(|rti, e| {
let opt_target_rpi = e
.node_info(routing_domain)
.map(|n| n.relay_peer_info.as_ref().map(|pi| pi.as_ref().clone()))
.flatten();
opt_target_rpi.and_then(|t| {
// If relay is ourselves, then return None, because we can't relay through ourselves
// and to contact this node we should have had an existing inbound connection
if t.node_id.key == rti.unlocked_inner.node_id {
return None;
}
e.signed_node_info(routing_domain)
.and_then(|n| n.relay_peer_info())
.and_then(|t| {
// If relay is ourselves, then return None, because we can't relay through ourselves
// and to contact this node we should have had an existing inbound connection
if t.node_id.key == rti.unlocked_inner.node_id {
return None;
}
// Register relay node and return noderef
rti.register_node_with_signed_node_info(
self.routing_table(),
routing_domain,
t.node_id.key,
t.signed_node_info,
false,
)
})
// Register relay node and return noderef
rti.register_node_with_signed_node_info(
self.routing_table(),
routing_domain,
t.node_id.key,
t.signed_node_info,
false,
)
})
})
}
@@ -301,8 +299,8 @@ pub trait NodeRefBase: Sized {
fn has_any_dial_info(&self) -> bool {
self.operate(|_rti, e| {
for rtd in RoutingDomain::all() {
if let Some(ni) = e.node_info(rtd) {
if ni.has_any_dial_info() {
if let Some(sni) = e.signed_node_info(rtd) {
if sni.has_any_dial_info() {
return true;
}
}

View File

@@ -114,10 +114,10 @@ fn route_hops_to_hop_cache(hops: &[DHTKey]) -> Vec<u8> {
}
/// get the hop cache key for a particular route permutation
fn route_permutation_to_hop_cache(nodes: &[(DHTKey, NodeInfo)], perm: &[usize]) -> Vec<u8> {
fn route_permutation_to_hop_cache(nodes: &[PeerInfo], perm: &[usize]) -> Vec<u8> {
let mut cache: Vec<u8> = Vec::with_capacity(perm.len() * DHT_KEY_LENGTH);
for n in perm {
cache.extend_from_slice(&nodes[*n].0.bytes)
cache.extend_from_slice(&nodes[*n].node_id.key.bytes)
}
cache
}
@@ -422,12 +422,12 @@ impl RouteSpecStore {
// Exclude nodes with no publicinternet nodeinfo, or incompatible nodeinfo or node status won't route
v.with(rti, move |_rti, e| {
let node_info_ok = if let Some(ni) = e.node_info(RoutingDomain::PublicInternet)
{
ni.has_sequencing_matched_dial_info(sequencing)
} else {
false
};
let node_info_ok =
if let Some(sni) = e.signed_node_info(RoutingDomain::PublicInternet) {
sni.has_sequencing_matched_dial_info(sequencing)
} else {
false
};
let node_status_ok =
if let Some(ns) = e.node_status(RoutingDomain::PublicInternet) {
ns.will_route()
@@ -495,20 +495,15 @@ impl RouteSpecStore {
});
cmpout
};
let transform = |rti: &RoutingTableInner,
k: DHTKey,
v: Option<Arc<BucketEntry>>|
-> (DHTKey, NodeInfo) {
// Return the key and the nodeinfo for that key
(
k,
let transform =
|rti: &RoutingTableInner, k: DHTKey, v: Option<Arc<BucketEntry>>| -> PeerInfo {
// Return the peerinfo for that key
v.unwrap().with(rti, |_rti, e| {
e.node_info(RoutingDomain::PublicInternet.into())
e.make_peer_info(k, RoutingDomain::PublicInternet.into())
.unwrap()
.clone()
}),
)
};
})
};
// Pull the whole routing table in sorted order
let node_count = rti.get_entry_count(
@@ -536,18 +531,15 @@ impl RouteSpecStore {
// Ensure this route is viable by checking that each node can contact the next one
if directions.contains(Direction::Outbound) {
let our_node_info = rti.get_own_node_info(RoutingDomain::PublicInternet);
let our_node_id = rti.node_id();
let mut previous_node = &(our_node_id, our_node_info);
let our_peer_info = rti.get_own_peer_info(RoutingDomain::PublicInternet);
let mut previous_node = &our_peer_info;
let mut reachable = true;
for n in permutation {
let current_node = nodes.get(*n).unwrap();
let cm = rti.get_contact_method(
RoutingDomain::PublicInternet,
&previous_node.0,
&previous_node.1,
&current_node.0,
&current_node.1,
previous_node,
current_node,
DialInfoFilter::all(),
sequencing,
);
@@ -562,18 +554,15 @@ impl RouteSpecStore {
}
}
if directions.contains(Direction::Inbound) {
let our_node_info = rti.get_own_node_info(RoutingDomain::PublicInternet);
let our_node_id = rti.node_id();
let mut next_node = &(our_node_id, our_node_info);
let our_peer_info = rti.get_own_peer_info(RoutingDomain::PublicInternet);
let mut next_node = &our_peer_info;
let mut reachable = true;
for n in permutation.iter().rev() {
let current_node = nodes.get(*n).unwrap();
let cm = rti.get_contact_method(
RoutingDomain::PublicInternet,
&next_node.0,
&next_node.1,
&current_node.0,
&current_node.1,
next_node,
current_node,
DialInfoFilter::all(),
sequencing,
);
@@ -609,11 +598,11 @@ impl RouteSpecStore {
}
// Got a unique route, lets build the detail, register it, and return it
let hops = route_nodes.iter().map(|v| nodes[*v].0).collect();
let hop_node_refs = route_nodes
let hops: Vec<DHTKey> = route_nodes.iter().map(|v| nodes[*v].node_id.key).collect();
let hop_node_refs = hops
.iter()
.map(|v| {
rti.lookup_node_ref(self.unlocked_inner.routing_table.clone(), nodes[*v].0)
.map(|k| {
rti.lookup_node_ref(self.unlocked_inner.routing_table.clone(), *k)
.unwrap()
})
.collect();

View File

@@ -111,18 +111,31 @@ impl RoutingDomainDetailCommon {
dial_info_detail_list: self.dial_info_details.clone(),
};
let relay_peer_info = self
let relay_info = self
.relay_node
.as_ref()
.and_then(|rn| rn.locked(rti).make_peer_info(self.routing_domain));
.and_then(|rn| {
let opt_relay_pi = rn.locked(rti).make_peer_info(self.routing_domain);
if let Some(relay_pi) = opt_relay_pi {
match relay_pi.signed_node_info {
SignedNodeInfo::Direct(d) => Some((relay_pi.node_id, d)),
SignedNodeInfo::Relayed(_) => {
warn!("relay node should not have a relay itself! if this happens, a relay updated its signed node info and became a relay, which should cause the relay to be dropped");
None
},
}
} else {
None
}
});
let signed_node_info = match relay_peer_info {
Some(relay_pi) => SignedNodeInfo::Relayed(
let signed_node_info = match relay_info {
Some((relay_id, relay_sdni)) => SignedNodeInfo::Relayed(
SignedRelayedNodeInfo::with_secret(
NodeId::new(rti.unlocked_inner.node_id),
node_info,
relay_pi.node_id,
relay_pi.signed_node_info,
relay_id,
relay_sdni,
&rti.unlocked_inner.node_id_secret,
)
.unwrap(),
@@ -133,7 +146,7 @@ impl RoutingDomainDetailCommon {
node_info,
&rti.unlocked_inner.node_id_secret,
)
.unwrap(),
.unwrap()
),
};
@@ -147,27 +160,8 @@ impl RoutingDomainDetailCommon {
let mut cpi = self.cached_peer_info.lock();
if cpi.is_none() {
// Regenerate peer info
let pi = PeerInfo::new(
NodeId::new(rti.unlocked_inner.node_id),
SignedDirectNodeInfo::with_secret(
NodeInfo {
network_class: self.network_class.unwrap_or(NetworkClass::Invalid),
outbound_protocols: self.outbound_protocols,
address_types: self.address_types,
min_version: MIN_CRYPTO_VERSION,
max_version: MAX_CRYPTO_VERSION,
dial_info_detail_list: self.dial_info_details.clone(),
relay_peer_info: self.relay_node.as_ref().and_then(|rn| {
rn.locked(rti)
.make_peer_info(self.routing_domain)
.map(Box::new)
}),
},
NodeId::new(rti.unlocked_inner.node_id),
&rti.unlocked_inner.node_id_secret,
)
.unwrap(),
);
let pi = self.make_peer_info(rti);
// Cache the peer info
*cpi = Some(pi);
}
@@ -204,10 +198,8 @@ pub trait RoutingDomainDetail {
fn get_contact_method(
&self,
rti: &RoutingTableInner,
node_a_id: &DHTKey,
node_a: &NodeInfo,
node_b_id: &DHTKey,
node_b: &NodeInfo,
peer_a: &PeerInfo,
peer_b: &PeerInfo,
dial_info_filter: DialInfoFilter,
sequencing: Sequencing,
) -> ContactMethod;
@@ -280,13 +272,15 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
fn get_contact_method(
&self,
_rti: &RoutingTableInner,
node_a_id: &DHTKey,
node_a: &NodeInfo,
node_b_id: &DHTKey,
node_b: &NodeInfo,
peer_a: &PeerInfo,
peer_b: &PeerInfo,
dial_info_filter: DialInfoFilter,
sequencing: Sequencing,
) -> ContactMethod {
// Get the nodeinfos for convenience
let node_a = peer_a.signed_node_info.node_info();
let node_b = peer_b.signed_node_info.node_info();
// Get the best match dial info for node B if we have it
if let Some(target_did) =
first_filtered_dial_info_detail(node_a, node_b, &dial_info_filter, sequencing)
@@ -298,17 +292,18 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
}
// Get the target's inbound relay, it must have one or it is not reachable
if let Some(inbound_relay) = &node_b.relay_peer_info {
if let Some(node_b_relay) = peer_b.signed_node_info.relay_info() {
let node_b_relay_id = peer_b.signed_node_info.relay_id().unwrap();
// Note that relay_peer_info could be node_a, in which case a connection already exists
// and we shouldn't have even gotten here
if inbound_relay.node_id.key == *node_a_id {
if node_b_relay_id.key == peer_a.node_id.key {
return ContactMethod::Existing;
}
// Can node A reach the inbound relay directly?
if first_filtered_dial_info_detail(
node_a,
&inbound_relay.signed_node_info.node_info,
node_b_relay,
&dial_info_filter,
sequencing,
)
@@ -332,8 +327,8 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
// Can we receive a direct reverse connection?
if !reverse_did.class.requires_signal() {
return ContactMethod::SignalReverse(
inbound_relay.node_id.key,
*node_b_id,
node_b_relay_id.key,
peer_b.node_id.key,
);
}
}
@@ -364,8 +359,8 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
{
// The target and ourselves have a udp dialinfo that they can reach
return ContactMethod::SignalHolePunch(
inbound_relay.node_id.key,
*node_b_id,
node_b_relay_id.key,
peer_a.node_id.key,
);
}
}
@@ -373,28 +368,30 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
// Otherwise we have to inbound relay
}
return ContactMethod::InboundRelay(inbound_relay.node_id.key);
return ContactMethod::InboundRelay(node_b_relay_id.key);
}
}
}
// If the node B has no direct dial info, it needs to have an inbound relay
else if let Some(inbound_relay) = &node_b.relay_peer_info {
else if let Some(node_b_relay) = peer_b.signed_node_info.relay_info() {
let node_b_relay_id = peer_b.signed_node_info.relay_id().unwrap();
// Can we reach the full relay?
if first_filtered_dial_info_detail(
node_a,
&inbound_relay.signed_node_info.node_info,
&node_b_relay,
&dial_info_filter,
sequencing,
)
.is_some()
{
return ContactMethod::InboundRelay(inbound_relay.node_id.key);
return ContactMethod::InboundRelay(node_b_relay_id.key);
}
}
// If node A can't reach the node by other means, it may need to use its own relay
if let Some(outbound_relay) = &node_a.relay_peer_info {
return ContactMethod::OutboundRelay(outbound_relay.node_id.key);
if let Some(node_a_relay_id) = peer_a.signed_node_info.relay_id() {
return ContactMethod::OutboundRelay(node_a_relay_id.key);
}
ContactMethod::Unreachable
@@ -450,20 +447,18 @@ impl RoutingDomainDetail for LocalNetworkRoutingDomainDetail {
fn get_contact_method(
&self,
_rti: &RoutingTableInner,
_node_a_id: &DHTKey,
node_a: &NodeInfo,
_node_b_id: &DHTKey,
node_b: &NodeInfo,
peer_a: &PeerInfo,
peer_b: &PeerInfo,
dial_info_filter: DialInfoFilter,
sequencing: Sequencing,
) -> ContactMethod {
// Scope the filter down to protocols node A can do outbound
let dial_info_filter = dial_info_filter.filtered(
&DialInfoFilter::all()
.with_address_type_set(node_a.address_types)
.with_protocol_type_set(node_a.outbound_protocols),
.with_address_type_set(peer_a.signed_node_info.node_info().address_types)
.with_protocol_type_set(peer_a.signed_node_info.node_info().outbound_protocols),
);
// Get first filtered dialinfo
let (sort, dial_info_filter) = match sequencing {
Sequencing::NoPreference => (None, dial_info_filter),
@@ -485,7 +480,7 @@ impl RoutingDomainDetail for LocalNetworkRoutingDomainDetail {
let filter = |did: &DialInfoDetail| did.matches_filter(&dial_info_filter);
let opt_target_did = node_b.first_filtered_dial_info_detail(sort, filter);
let opt_target_did = peer_b.signed_node_info.node_info().first_filtered_dial_info_detail(sort, filter);
if let Some(target_did) = opt_target_did {
return ContactMethod::Direct(target_did.dial_info);
}

View File

@@ -191,9 +191,20 @@ impl RoutingTableInner {
return false;
}
}
true
}
pub fn signed_node_info_is_valid_in_routing_domain(
&self,
routing_domain: RoutingDomain,
signed_node_info: &SignedNodeInfo,
) -> bool {
if !self.node_info_is_valid_in_routing_domain(routing_domain, signed_node_info.node_info())
{
return false;
}
// Ensure the relay is also valid in this routing domain if it is provided
if let Some(relay_peer_info) = node_info.relay_peer_info.as_ref() {
let relay_ni = &relay_peer_info.signed_node_info.node_info;
if let Some(relay_ni) = signed_node_info.relay_info() {
if !self.node_info_is_valid_in_routing_domain(routing_domain, relay_ni) {
return false;
}
@@ -205,23 +216,13 @@ impl RoutingTableInner {
pub fn get_contact_method(
&self,
routing_domain: RoutingDomain,
node_a_id: &DHTKey,
node_a: &NodeInfo,
node_b_id: &DHTKey,
node_b: &NodeInfo,
peer_a: &PeerInfo,
peer_b: &PeerInfo,
dial_info_filter: DialInfoFilter,
sequencing: Sequencing,
) -> ContactMethod {
self.with_routing_domain(routing_domain, |rdd| {
rdd.get_contact_method(
self,
node_a_id,
node_a,
node_b_id,
node_b,
dial_info_filter,
sequencing,
)
rdd.get_contact_method(self, peer_a, peer_b, dial_info_filter, sequencing)
})
}
@@ -252,22 +253,6 @@ impl RoutingTableInner {
})
}
/// Return a copy of our node's signednodeinfo
pub fn get_own_signed_node_info(&self, routing_domain: RoutingDomain) -> SignedDirectNodeInfo {
self.with_routing_domain(routing_domain, |rdd| {
rdd.common()
.with_peer_info(self, |pi| pi.signed_node_info.clone())
})
}
/// Return a copy of our node's nodeinfo
pub fn get_own_node_info(&self, routing_domain: RoutingDomain) -> NodeInfo {
self.with_routing_domain(routing_domain, |rdd| {
rdd.common()
.with_peer_info(self, |pi| pi.signed_node_info.node_info.clone())
})
}
/// Return our currently registered network class
pub fn has_valid_own_node_info(&self, routing_domain: RoutingDomain) -> bool {
self.with_routing_domain(routing_domain, |rdd| rdd.common().has_valid_own_node_info())
@@ -662,7 +647,7 @@ impl RoutingTableInner {
outer_self: RoutingTable,
routing_domain: RoutingDomain,
node_id: DHTKey,
signed_node_info: SignedDirectNodeInfo,
signed_node_info: SignedNodeInfo,
allow_invalid: bool,
) -> Option<NodeRef> {
// validate signed node info is not something malicious
@@ -670,8 +655,8 @@ impl RoutingTableInner {
log_rtab!(debug "can't register own node id in routing table");
return None;
}
if let Some(rpi) = &signed_node_info.node_info.relay_peer_info {
if rpi.node_id.key == node_id {
if let Some(relay_id) = signed_node_info.relay_id() {
if relay_id.key == node_id {
log_rtab!(debug "node can not be its own relay");
return None;
}
@@ -683,8 +668,7 @@ impl RoutingTableInner {
return None;
}
// verify signed node info is valid in this routing domain
if !self
.node_info_is_valid_in_routing_domain(routing_domain, &signed_node_info.node_info)
if !self.signed_node_info_is_valid_in_routing_domain(routing_domain, &signed_node_info)
{
log_rtab!(debug "signed node info for {} not valid in the {:?} routing domain", node_id, routing_domain);
return None;