refactor checkpoint
This commit is contained in:
@@ -39,7 +39,7 @@ pub enum BucketEntryState {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
||||
struct LastConnectionKey(RoutingDomain, ProtocolType, AddressType);
|
||||
struct LastConnectionKey(ProtocolType, AddressType);
|
||||
|
||||
/// Bucket entry information specific to the LocalNetwork RoutingDomain
|
||||
#[derive(Debug)]
|
||||
@@ -148,17 +148,11 @@ impl BucketEntryInner {
|
||||
// Retuns true if the node info changed
|
||||
pub fn update_signed_node_info(
|
||||
&mut self,
|
||||
routing_domain: RoutingDomain,
|
||||
signed_node_info: SignedNodeInfo,
|
||||
allow_invalid_signature: bool,
|
||||
) {
|
||||
// Don't allow invalid signatures unless we are explicitly allowing it
|
||||
if !allow_invalid_signature && !signed_node_info.signature.valid {
|
||||
log_rtab!(debug "Invalid signature on signed node info: {:?}", signed_node_info);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the correct signed_node_info for the chosen routing domain
|
||||
let opt_current_sni = match signed_node_info.routing_domain {
|
||||
let opt_current_sni = match routing_domain {
|
||||
RoutingDomain::LocalNetwork => &mut self.local_network.signed_node_info,
|
||||
RoutingDomain::PublicInternet => &mut self.public_internet.signed_node_info,
|
||||
};
|
||||
@@ -208,31 +202,23 @@ impl BucketEntryInner {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn has_valid_signed_node_info(&self, routing_domain_set: RoutingDomainSet) -> bool {
|
||||
for routing_domain in routing_domain_set {
|
||||
// Get the correct signed_node_info for the chosen routing domain
|
||||
let opt_current_sni = match routing_domain {
|
||||
RoutingDomain::LocalNetwork => &mut self.local_network.signed_node_info,
|
||||
RoutingDomain::PublicInternet => &mut self.public_internet.signed_node_info,
|
||||
};
|
||||
if let Some(sni) = opt_current_sni {
|
||||
if sni.is_valid() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn node_info(&self, routing_domain: RoutingDomain) -> Option<NodeInfo> {
|
||||
pub fn node_info(&self, routing_domain: RoutingDomain) -> Option<&NodeInfo> {
|
||||
let opt_current_sni = match routing_domain {
|
||||
RoutingDomain::LocalNetwork => &mut self.local_network.signed_node_info,
|
||||
RoutingDomain::PublicInternet => &mut self.public_internet.signed_node_info,
|
||||
};
|
||||
opt_current_sni.as_ref().map(|s| s.node_info.clone())
|
||||
opt_current_sni.as_ref().map(|s| &s.node_info)
|
||||
}
|
||||
|
||||
pub fn peer_info(&self, key: DHTKey, routing_domain: RoutingDomain) -> Option<PeerInfo> {
|
||||
pub fn signed_node_info(&self, routing_domain: RoutingDomain) -> Option<&SignedNodeInfo> {
|
||||
let opt_current_sni = match routing_domain {
|
||||
RoutingDomain::LocalNetwork => &mut self.local_network.signed_node_info,
|
||||
RoutingDomain::PublicInternet => &mut self.public_internet.signed_node_info,
|
||||
};
|
||||
opt_current_sni.as_ref().map(|s| s.as_ref())
|
||||
}
|
||||
|
||||
pub fn make_peer_info(&self, key: DHTKey, routing_domain: RoutingDomain) -> Option<PeerInfo> {
|
||||
let opt_current_sni = match routing_domain {
|
||||
RoutingDomain::LocalNetwork => &mut self.local_network.signed_node_info,
|
||||
RoutingDomain::PublicInternet => &mut self.public_internet.signed_node_info,
|
||||
@@ -253,18 +239,14 @@ impl BucketEntryInner {
|
||||
RoutingDomain::PublicInternet => &mut self.public_internet.signed_node_info,
|
||||
};
|
||||
if let Some(sni) = opt_current_sni {
|
||||
if sni.is_valid() {
|
||||
return Some(routing_domain);
|
||||
}
|
||||
return Some(routing_domain);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn descriptor_to_key(&self, last_connection: ConnectionDescriptor) -> LastConnectionKey {
|
||||
let routing_domain = self.routing_domain_for_address(last_connection.remote().address());
|
||||
LastConnectionKey(
|
||||
routing_domain,
|
||||
last_connection.protocol_type(),
|
||||
last_connection.address_type(),
|
||||
)
|
||||
@@ -285,17 +267,23 @@ impl BucketEntryInner {
|
||||
// Gets the best 'last connection' that matches a set of routing domain, protocol types and address types
|
||||
pub fn last_connection(
|
||||
&self,
|
||||
routing_domain_set: RoutingDomainSet,
|
||||
dial_info_filter: Option<DialInfoFilter>,
|
||||
routing_table_inner: &RoutingTableInner,
|
||||
node_ref_filter: &Option<NodeRefFilter>,
|
||||
) -> Option<(ConnectionDescriptor, u64)> {
|
||||
// Iterate peer scopes and protocol types and address type in order to ensure we pick the preferred protocols if all else is the same
|
||||
let dif = dial_info_filter.unwrap_or_default();
|
||||
for rd in routing_domain_set {
|
||||
for pt in dif.protocol_type_set {
|
||||
for at in dif.address_type_set {
|
||||
let key = LastConnectionKey(rd, pt, at);
|
||||
if let Some(v) = self.last_connections.get(&key) {
|
||||
return Some(*v);
|
||||
let nrf = node_ref_filter.unwrap_or_default();
|
||||
for pt in nrf.dial_info_filter.protocol_type_set {
|
||||
for at in nrf.dial_info_filter.address_type_set {
|
||||
let key = LastConnectionKey(pt, at);
|
||||
if let Some(v) = self.last_connections.get(&key) {
|
||||
// Verify this connection could be in the filtered routing domain
|
||||
let address = v.0.remote_address().address();
|
||||
if let Some(rd) =
|
||||
RoutingTable::routing_domain_for_address_inner(routing_table_inner, address)
|
||||
{
|
||||
if nrf.routing_domain_set.contains(rd) {
|
||||
return Some(*v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -52,7 +52,10 @@ impl RoutingTable {
|
||||
}
|
||||
|
||||
// Make a filter that wraps another filter
|
||||
pub fn combine_filters<F, G>(mut f1: F, mut f2: G) -> impl FnMut(&BucketEntryInner) -> bool
|
||||
pub fn combine_entry_filters<F, G>(
|
||||
mut f1: F,
|
||||
mut f2: G,
|
||||
) -> impl FnMut(&BucketEntryInner) -> bool
|
||||
where
|
||||
F: FnMut(&BucketEntryInner) -> bool,
|
||||
G: FnMut(&BucketEntryInner) -> bool,
|
||||
@@ -81,7 +84,7 @@ impl RoutingTable {
|
||||
// count
|
||||
node_count,
|
||||
// filter
|
||||
Some(|_k: DHTKey, v: Option<Arc<BucketEntry>>| {
|
||||
|_k: DHTKey, v: Option<Arc<BucketEntry>>| {
|
||||
let entry = v.unwrap();
|
||||
entry.with(|e| {
|
||||
// skip nodes on local network
|
||||
@@ -95,7 +98,7 @@ impl RoutingTable {
|
||||
// skip nodes that dont match entry filter
|
||||
entry_filter(e)
|
||||
})
|
||||
}),
|
||||
},
|
||||
// transform
|
||||
|k: DHTKey, v: Option<Arc<BucketEntry>>| {
|
||||
NodeRef::new(self.clone(), k, v.unwrap().clone(), None)
|
||||
@@ -118,16 +121,16 @@ impl RoutingTable {
|
||||
// count
|
||||
protocol_types.len() * 2 * max_per_type,
|
||||
// filter
|
||||
Some(move |_k: DHTKey, v: Option<Arc<BucketEntry>>| {
|
||||
move |_k: DHTKey, v: Option<Arc<BucketEntry>>| {
|
||||
let entry = v.unwrap();
|
||||
entry.with(|e| {
|
||||
// skip nodes on our local network here
|
||||
if e.has_node_info(RoutingDomainSet::only(RoutingDomain::LocalNetwork)) {
|
||||
if e.has_node_info(RoutingDomain::LocalNetwork.into()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// does it have some dial info we need?
|
||||
let filter = |n: NodeInfo| {
|
||||
let filter = |n: &NodeInfo| {
|
||||
let mut keep = false;
|
||||
for did in n.dial_info_detail_list {
|
||||
if matches!(did.dial_info.address_type(), AddressType::IPV4) {
|
||||
@@ -157,7 +160,7 @@ impl RoutingTable {
|
||||
.map(filter)
|
||||
.unwrap_or(false)
|
||||
})
|
||||
}),
|
||||
},
|
||||
// transform
|
||||
|k: DHTKey, v: Option<Arc<BucketEntry>>| {
|
||||
NodeRef::new(self.clone(), k, v.unwrap().clone(), None)
|
||||
@@ -167,14 +170,16 @@ impl RoutingTable {
|
||||
|
||||
pub fn filter_has_valid_signed_node_info(
|
||||
&self,
|
||||
routing_domain: RoutingDomain,
|
||||
v: Option<Arc<BucketEntry>>,
|
||||
own_peer_info_is_valid: bool,
|
||||
routing_domain_set: RoutingDomainSet,
|
||||
) -> bool {
|
||||
let routing_table = self.clone();
|
||||
match v {
|
||||
None => own_peer_info_is_valid,
|
||||
Some(entry) => entry.with(|e| e.has_valid_signed_node_info(routing_domain_set)),
|
||||
None => self.has_valid_own_node_info(routing_domain),
|
||||
Some(entry) => entry.with(|e| {
|
||||
e.signed_node_info(routing_domain.into())
|
||||
.map(|sni| sni.has_valid_signature())
|
||||
.unwrap_or(false)
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,12 +188,10 @@ impl RoutingTable {
|
||||
routing_domain: RoutingDomain,
|
||||
k: DHTKey,
|
||||
v: Option<Arc<BucketEntry>>,
|
||||
own_peer_info: &PeerInfo,
|
||||
) -> PeerInfo {
|
||||
let routing_table = self.clone();
|
||||
match v {
|
||||
None => own_peer_info.clone(),
|
||||
Some(entry) => entry.with(|e| e.peer_info(k, routing_domain).unwrap()),
|
||||
None => self.get_own_peer_info(routing_domain),
|
||||
Some(entry) => entry.with(|e| e.make_peer_info(k, routing_domain).unwrap()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,8 +249,8 @@ impl RoutingTable {
|
||||
pub fn find_fastest_nodes<T, F, O>(
|
||||
&self,
|
||||
node_count: usize,
|
||||
mut filter: Option<F>,
|
||||
transform: T,
|
||||
mut filter: F,
|
||||
mut transform: T,
|
||||
) -> Vec<O>
|
||||
where
|
||||
F: FnMut(DHTKey, Option<Arc<BucketEntry>>) -> bool,
|
||||
@@ -264,7 +267,7 @@ impl RoutingTable {
|
||||
if entry.with(|e| e.state(cur_ts) == BucketEntryState::Dead) {
|
||||
false
|
||||
} else {
|
||||
filter.as_mut().map(|f| f(k, v)).unwrap_or(true)
|
||||
filter(k, v)
|
||||
}
|
||||
} else {
|
||||
// always filter out self peer, as it is irrelevant to the 'fastest nodes' search
|
||||
@@ -328,12 +331,12 @@ impl RoutingTable {
|
||||
pub fn find_closest_nodes<F, T, O>(
|
||||
&self,
|
||||
node_id: DHTKey,
|
||||
mut filter: Option<F>,
|
||||
mut filter: F,
|
||||
mut transform: T,
|
||||
) -> Vec<O>
|
||||
where
|
||||
T: FnMut(DHTKey, Option<Arc<BucketEntry>>) -> O,
|
||||
F: FnMut(DHTKey, Option<Arc<BucketEntry>>) -> bool,
|
||||
T: FnMut(DHTKey, Option<Arc<BucketEntry>>) -> O,
|
||||
{
|
||||
let cur_ts = intf::get_timestamp();
|
||||
let node_count = {
|
||||
@@ -344,7 +347,7 @@ impl RoutingTable {
|
||||
node_count,
|
||||
cur_ts,
|
||||
// filter
|
||||
|k, v| filter.as_mut().map(|f| f(k, v)).unwrap_or(true),
|
||||
filter,
|
||||
// sort
|
||||
|(a_key, a_entry), (b_key, b_entry)| {
|
||||
// same nodes are always the same
|
||||
@@ -390,7 +393,7 @@ impl RoutingTable {
|
||||
let mut protocol_to_port =
|
||||
BTreeMap::<(ProtocolType, AddressType), (LowLevelProtocolType, u16)>::new();
|
||||
let our_dids = self.all_filtered_dial_info_details(
|
||||
RoutingDomainSet::only(RoutingDomain::PublicInternet),
|
||||
RoutingDomain::PublicInternet.into(),
|
||||
&DialInfoFilter::all(),
|
||||
);
|
||||
for did in our_dids {
|
||||
@@ -417,12 +420,12 @@ impl RoutingTable {
|
||||
// Get all our outbound protocol/address types
|
||||
let outbound_dif = self
|
||||
.network_manager()
|
||||
.get_outbound_node_ref_filter(RoutingDomain::PublicInternet);
|
||||
.get_outbound_dial_info_filter(RoutingDomain::PublicInternet);
|
||||
let mapped_port_info = self.get_mapped_port_info();
|
||||
|
||||
move |e: &BucketEntryInner| {
|
||||
// Ensure this node is not on the local network
|
||||
if e.has_node_info(RoutingDomainSet::only(RoutingDomain::LocalNetwork)) {
|
||||
if e.has_node_info(RoutingDomain::LocalNetwork.into()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -549,7 +552,7 @@ impl RoutingTable {
|
||||
let res = network_result_try!(
|
||||
rpc_processor
|
||||
.clone()
|
||||
.rpc_call_find_node(Destination::direct(node_ref), node_id,)
|
||||
.rpc_call_find_node(Destination::direct(node_ref), node_id)
|
||||
.await?
|
||||
);
|
||||
|
||||
@@ -560,37 +563,24 @@ impl RoutingTable {
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self), ret, err)]
|
||||
pub async fn find_self(
|
||||
&self,
|
||||
routing_domain: RoutingDomain,
|
||||
node_ref: NodeRef,
|
||||
) -> EyreResult<NetworkResult<Vec<NodeRef>>> {
|
||||
pub async fn find_self(&self, node_ref: NodeRef) -> EyreResult<NetworkResult<Vec<NodeRef>>> {
|
||||
let node_id = self.node_id();
|
||||
self.find_node(routing_domain, node_ref, node_id).await
|
||||
self.find_node(node_ref, node_id).await
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self), ret, err)]
|
||||
pub async fn find_target(
|
||||
&self,
|
||||
routing_domain: RoutingDomain,
|
||||
node_ref: NodeRef,
|
||||
) -> EyreResult<NetworkResult<Vec<NodeRef>>> {
|
||||
pub async fn find_target(&self, node_ref: NodeRef) -> EyreResult<NetworkResult<Vec<NodeRef>>> {
|
||||
let node_id = node_ref.node_id();
|
||||
self.find_node(routing_domain, node_ref, node_id).await
|
||||
self.find_node(node_ref, node_id).await
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
pub async fn reverse_find_node(
|
||||
&self,
|
||||
routing_domain: RoutingDomain,
|
||||
node_ref: NodeRef,
|
||||
wide: bool,
|
||||
) {
|
||||
pub async fn reverse_find_node(&self, node_ref: NodeRef, wide: bool) {
|
||||
// Ask bootstrap node to 'find' our own node so we can get some more nodes near ourselves
|
||||
// and then contact those nodes to inform -them- that we exist
|
||||
|
||||
// Ask bootstrap server for nodes closest to our own node
|
||||
let closest_nodes = network_result_value_or_log!(debug match self.find_self(routing_domain, node_ref.clone()).await {
|
||||
let closest_nodes = network_result_value_or_log!(debug match self.find_self(node_ref.clone()).await {
|
||||
Err(e) => {
|
||||
log_rtab!(error
|
||||
"find_self failed for {:?}: {:?}",
|
||||
@@ -606,7 +596,7 @@ impl RoutingTable {
|
||||
// Ask each node near us to find us as well
|
||||
if wide {
|
||||
for closest_nr in closest_nodes {
|
||||
network_result_value_or_log!(debug match self.find_self(routing_domain, closest_nr.clone()).await {
|
||||
network_result_value_or_log!(debug match self.find_self(closest_nr.clone()).await {
|
||||
Err(e) => {
|
||||
log_rtab!(error
|
||||
"find_self failed for {:?}: {:?}",
|
||||
|
@@ -3,6 +3,7 @@ mod bucket_entry;
|
||||
mod debug;
|
||||
mod find_nodes;
|
||||
mod node_ref;
|
||||
mod routing_domain_editor;
|
||||
mod routing_domains;
|
||||
mod stats_accounting;
|
||||
mod tasks;
|
||||
@@ -18,6 +19,7 @@ pub use debug::*;
|
||||
pub use find_nodes::*;
|
||||
use hashlink::LruCache;
|
||||
pub use node_ref::*;
|
||||
pub use routing_domain_editor::*;
|
||||
pub use routing_domains::*;
|
||||
pub use stats_accounting::*;
|
||||
|
||||
@@ -138,11 +140,13 @@ impl RoutingTable {
|
||||
self.inner.read().node_id_secret
|
||||
}
|
||||
|
||||
pub fn routing_domain_for_address(&self, address: Address) -> Option<RoutingDomain> {
|
||||
let inner = self.inner.read();
|
||||
pub fn routing_domain_for_address_inner(
|
||||
inner: &RoutingTableInner,
|
||||
address: Address,
|
||||
) -> Option<RoutingDomain> {
|
||||
for rd in RoutingDomain::all() {
|
||||
let can_contain =
|
||||
Self::with_routing_domain(&*inner, rd, |rdd| rdd.can_contain_address(address));
|
||||
Self::with_routing_domain(inner, rd, |rdd| rdd.can_contain_address(address));
|
||||
if can_contain {
|
||||
return Some(rd);
|
||||
}
|
||||
@@ -150,6 +154,11 @@ impl RoutingTable {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn routing_domain_for_address(&self, address: Address) -> Option<RoutingDomain> {
|
||||
let inner = self.inner.read();
|
||||
Self::routing_domain_for_address_inner(&*inner, address)
|
||||
}
|
||||
|
||||
fn with_routing_domain<F, R>(inner: &RoutingTableInner, domain: RoutingDomain, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&dyn RoutingDomainDetail) -> R,
|
||||
@@ -256,6 +265,36 @@ impl RoutingTable {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn node_info_is_valid_in_routing_domain(
|
||||
&self,
|
||||
routing_domain: RoutingDomain,
|
||||
node_info: &NodeInfo,
|
||||
) -> bool {
|
||||
// Should not be passing around nodeinfo with an invalid network class
|
||||
if matches!(node_info.network_class, NetworkClass::Invalid) {
|
||||
return false;
|
||||
}
|
||||
// Ensure all of the dial info works in this routing domain
|
||||
for did in node_info.dial_info_detail_list {
|
||||
if !self.ensure_dial_info_is_valid(routing_domain, &did.dial_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 {
|
||||
let relay_ni = &relay_peer_info.signed_node_info.node_info;
|
||||
if !self.node_info_is_valid_in_routing_domain(routing_domain, relay_ni) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub fn edit_routing_domain(&self, domain: RoutingDomain) -> RoutingDomainEditor {
|
||||
RoutingDomainEditor::new(self.clone(), domain)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self), err)]
|
||||
pub fn register_dial_info(
|
||||
&self,
|
||||
@@ -349,7 +388,8 @@ impl RoutingTable {
|
||||
min_version: MIN_VERSION,
|
||||
max_version: MAX_VERSION,
|
||||
dial_info_detail_list: self.dial_info_details(routing_domain),
|
||||
relay_peer_info: relay_node.and_then(|rn| rn.peer_info(routing_domain).map(Box::new)),
|
||||
relay_peer_info: relay_node
|
||||
.and_then(|rn| rn.make_peer_info(routing_domain).map(Box::new)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,6 +464,8 @@ impl RoutingTable {
|
||||
Self::with_entries(&*inner, cur_ts, BucketEntryState::Dead, |_rti, e| {
|
||||
e.with_mut(|e| {
|
||||
e.clear_signed_node_info(RoutingDomain::LocalNetwork);
|
||||
e.set_seen_our_node_info(RoutingDomain::LocalNetwork, false);
|
||||
e.set_updated_since_last_network_change(false);
|
||||
});
|
||||
Option::<()>::None
|
||||
});
|
||||
@@ -549,7 +591,12 @@ impl RoutingTable {
|
||||
Self::with_entries(&*inner, cur_ts, BucketEntryState::Unreliable, |k, v| {
|
||||
// Only update nodes that haven't seen our node info yet
|
||||
if all || !v.with(|e| e.has_seen_our_node_info(routing_domain)) {
|
||||
node_refs.push(NodeRef::new(self.clone(), k, v, None));
|
||||
node_refs.push(NodeRef::new(
|
||||
self.clone(),
|
||||
k,
|
||||
v,
|
||||
Some(NodeRefFilter::new().with_routing_domain(routing_domain)),
|
||||
));
|
||||
}
|
||||
Option::<()>::None
|
||||
});
|
||||
@@ -572,10 +619,15 @@ impl RoutingTable {
|
||||
let mut node_refs = Vec::<NodeRef>::with_capacity(inner.bucket_entry_count);
|
||||
Self::with_entries(&*inner, cur_ts, BucketEntryState::Unreliable, |k, v| {
|
||||
if v.with(|e| {
|
||||
e.has_node_info(RoutingDomainSet::only(routing_domain))
|
||||
e.has_node_info(routing_domain.into())
|
||||
&& e.needs_ping(&k, cur_ts, opt_relay_id == Some(k))
|
||||
}) {
|
||||
node_refs.push(NodeRef::new(self.clone(), k, v, None));
|
||||
node_refs.push(NodeRef::new(
|
||||
self.clone(),
|
||||
k,
|
||||
v,
|
||||
Some(NodeRefFilter::new().with_routing_domain(routing_domain)),
|
||||
));
|
||||
}
|
||||
Option::<()>::None
|
||||
});
|
||||
@@ -670,12 +722,14 @@ impl RoutingTable {
|
||||
}
|
||||
|
||||
// Shortcut function to add a node to our routing table if it doesn't exist
|
||||
// and add the dial info we have for it, since that's pretty common
|
||||
// and add the dial info we have for it. Returns a noderef filtered to
|
||||
// the routing domain in which this node was registered for convenience.
|
||||
pub fn register_node_with_signed_node_info(
|
||||
&self,
|
||||
routing_domain: RoutingDomain,
|
||||
node_id: DHTKey,
|
||||
signed_node_info: SignedNodeInfo,
|
||||
allow_invalid_signature: bool,
|
||||
allow_invalid: bool,
|
||||
) -> Option<NodeRef> {
|
||||
// validate signed node info is not something malicious
|
||||
if node_id == self.node_id() {
|
||||
@@ -688,11 +742,28 @@ impl RoutingTable {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
if !allow_invalid {
|
||||
// verify signature
|
||||
if !signed_node_info.has_valid_signature() {
|
||||
log_rtab!(debug "signed node info for {} has invalid signature", node_id);
|
||||
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)
|
||||
{
|
||||
log_rtab!(debug "signed node info for {} not valid in the {:?} routing domain", node_id, routing_domain);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
self.create_node_ref(node_id, |e| {
|
||||
e.update_signed_node_info(signed_node_info, allow_invalid_signature);
|
||||
e.update_signed_node_info(routing_domain, signed_node_info);
|
||||
})
|
||||
.map(|mut nr| {
|
||||
nr.set_filter(Some(NodeRefFilter::new().with_routing_domain(signed_node_info.routing_domain)))
|
||||
nr.set_filter(Some(
|
||||
NodeRefFilter::new().with_routing_domain(routing_domain),
|
||||
));
|
||||
nr
|
||||
})
|
||||
}
|
||||
|
@@ -14,7 +14,7 @@ pub struct NodeRefFilter {
|
||||
|
||||
impl Default for NodeRefFilter {
|
||||
fn default() -> Self {
|
||||
self.new()
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ impl NodeRefFilter {
|
||||
}
|
||||
|
||||
pub fn with_routing_domain(mut self, routing_domain: RoutingDomain) -> Self {
|
||||
self.routing_domain_set = RoutingDomainSet::only(routing_domain);
|
||||
self.routing_domain_set = routing_domain.into();
|
||||
self
|
||||
}
|
||||
pub fn with_routing_domain_set(mut self, routing_domain_set: RoutingDomainSet) -> Self {
|
||||
@@ -62,7 +62,7 @@ impl NodeRefFilter {
|
||||
self
|
||||
}
|
||||
pub fn is_dead(&self) -> bool {
|
||||
self.dial_info_filter.is_empty() || self.routing_domain_set.is_empty()
|
||||
self.dial_info_filter.is_dead() || self.routing_domain_set.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,6 +154,12 @@ impl NodeRef {
|
||||
.unwrap_or(RoutingDomainSet::all())
|
||||
}
|
||||
|
||||
pub fn dial_info_filter(&self) -> DialInfoFilter {
|
||||
self.filter
|
||||
.map(|f| f.dial_info_filter)
|
||||
.unwrap_or(DialInfoFilter::all())
|
||||
}
|
||||
|
||||
pub fn best_routing_domain(&self) -> Option<RoutingDomain> {
|
||||
self.operate(|_rti, e| {
|
||||
e.best_routing_domain(
|
||||
@@ -171,9 +177,6 @@ impl NodeRef {
|
||||
pub fn node_id(&self) -> DHTKey {
|
||||
self.node_id
|
||||
}
|
||||
pub fn has_valid_signed_node_info(&self) -> bool {
|
||||
self.operate(|_rti, e| e.has_valid_signed_node_info(self.routing_domain_set()))
|
||||
}
|
||||
pub fn has_updated_since_last_network_change(&self) -> bool {
|
||||
self.operate(|_rti, e| e.has_updated_since_last_network_change())
|
||||
}
|
||||
@@ -196,8 +199,15 @@ impl NodeRef {
|
||||
}
|
||||
|
||||
// Per-RoutingDomain accessors
|
||||
pub fn peer_info(&self, routing_domain: RoutingDomain) -> Option<PeerInfo> {
|
||||
self.operate(|_rti, e| e.peer_info(self.node_id(), routing_domain))
|
||||
pub fn make_peer_info(&self, routing_domain: RoutingDomain) -> Option<PeerInfo> {
|
||||
self.operate(|_rti, e| e.make_peer_info(self.node_id(), routing_domain))
|
||||
}
|
||||
pub fn signed_node_info_has_valid_signature(&self, routing_domain: RoutingDomain) -> bool {
|
||||
self.operate(|_rti, e| {
|
||||
e.signed_node_info(routing_domain)
|
||||
.map(|sni| sni.has_valid_signature())
|
||||
.unwrap_or(false)
|
||||
})
|
||||
}
|
||||
pub fn has_seen_our_node_info(&self, routing_domain: RoutingDomain) -> bool {
|
||||
self.operate(|_rti, e| e.has_seen_our_node_info(routing_domain))
|
||||
@@ -236,6 +246,7 @@ impl NodeRef {
|
||||
|
||||
// Register relay node and return noderef
|
||||
self.routing_table.register_node_with_signed_node_info(
|
||||
routing_domain,
|
||||
t.node_id.key,
|
||||
t.signed_node_info,
|
||||
false,
|
||||
@@ -246,15 +257,12 @@ impl NodeRef {
|
||||
// Filtered accessors
|
||||
pub fn first_filtered_dial_info_detail(&self) -> Option<DialInfoDetail> {
|
||||
let routing_domain_set = self.routing_domain_set();
|
||||
let dial_info_filter = self.dial_info_filter();
|
||||
|
||||
self.operate(|_rt, e| {
|
||||
for routing_domain in routing_domain_set {
|
||||
if let Some(ni) = e.node_info(routing_domain) {
|
||||
let filter = |did: &DialInfoDetail| {
|
||||
self.filter
|
||||
.as_ref()
|
||||
.map(|f| did.matches_filter(f))
|
||||
.unwrap_or(true)
|
||||
};
|
||||
let filter = |did: &DialInfoDetail| did.matches_filter(&dial_info_filter);
|
||||
if let Some(did) = ni.first_filtered_dial_info_detail(filter) {
|
||||
return Some(did);
|
||||
}
|
||||
@@ -266,16 +274,13 @@ impl NodeRef {
|
||||
|
||||
pub fn all_filtered_dial_info_details<F>(&self) -> Vec<DialInfoDetail> {
|
||||
let routing_domain_set = self.routing_domain_set();
|
||||
let dial_info_filter = self.dial_info_filter();
|
||||
|
||||
let mut out = Vec::new();
|
||||
self.operate(|_rt, e| {
|
||||
for routing_domain in routing_domain_set {
|
||||
if let Some(ni) = e.node_info(routing_domain) {
|
||||
let filter = |did: &DialInfoDetail| {
|
||||
self.filter
|
||||
.as_ref()
|
||||
.map(|f| did.matches_filter(f))
|
||||
.unwrap_or(true)
|
||||
};
|
||||
let filter = |did: &DialInfoDetail| did.matches_filter(&dial_info_filter);
|
||||
if let Some(did) = ni.first_filtered_dial_info_detail(filter) {
|
||||
out.push(did);
|
||||
}
|
||||
@@ -288,12 +293,8 @@ impl NodeRef {
|
||||
|
||||
pub async fn last_connection(&self) -> Option<ConnectionDescriptor> {
|
||||
// Get the last connection and the last time we saw anything with this connection
|
||||
let (last_connection, last_seen) = self.operate(|_rti, e| {
|
||||
e.last_connection(
|
||||
self.filter.routing_domain_set,
|
||||
self.filter.dial_info_filter.clone(),
|
||||
)
|
||||
})?;
|
||||
let (last_connection, last_seen) =
|
||||
self.operate(|rti, e| e.last_connection(rti, &self.filter))?;
|
||||
|
||||
// Should we check the connection table?
|
||||
if last_connection.protocol_type().is_connection_oriented() {
|
||||
|
21
veilid-core/src/routing_table/routing_domain_editor.rs
Normal file
21
veilid-core/src/routing_table/routing_domain_editor.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
use super::*;
|
||||
|
||||
enum RoutingDomainChange {}
|
||||
|
||||
pub struct RoutingDomainEditor {
|
||||
routing_table: RoutingTable,
|
||||
routing_domain: RoutingDomain,
|
||||
changes: Vec<RoutingDomainChange>,
|
||||
}
|
||||
|
||||
impl RoutingDomainEditor {
|
||||
pub(super) fn new(routing_table: RoutingTable, routing_domain: RoutingDomain) -> Self {
|
||||
Self {
|
||||
routing_table,
|
||||
routing_domain,
|
||||
changes: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn commit(self) {}
|
||||
}
|
@@ -27,8 +27,11 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
|
||||
self.relay_node.clone()
|
||||
}
|
||||
fn set_relay_node(&mut self, opt_relay_node: Option<NodeRef>) {
|
||||
self.relay_node = opt_relay_node
|
||||
.map(|nr| nr.filtered_clone(NodeRefFilter::new().with_routing_domain(PublicInternet)))
|
||||
self.relay_node = opt_relay_node.map(|nr| {
|
||||
nr.filtered_clone(
|
||||
NodeRefFilter::new().with_routing_domain(RoutingDomain::PublicInternet),
|
||||
)
|
||||
})
|
||||
}
|
||||
fn dial_info_details(&self) -> &Vec<DialInfoDetail> {
|
||||
&self.dial_info_details
|
||||
@@ -78,8 +81,9 @@ impl RoutingDomainDetail for LocalInternetRoutingDomainDetail {
|
||||
self.relay_node.clone()
|
||||
}
|
||||
fn set_relay_node(&mut self, opt_relay_node: Option<NodeRef>) {
|
||||
self.relay_node = opt_relay_node
|
||||
.map(|nr| nr.filtered_clone(NodeRefFilter::new().with_routing_domain(LocalNetwork)));
|
||||
self.relay_node = opt_relay_node.map(|nr| {
|
||||
nr.filtered_clone(NodeRefFilter::new().with_routing_domain(RoutingDomain::LocalNetwork))
|
||||
});
|
||||
}
|
||||
fn dial_info_details(&self) -> &Vec<DialInfoDetail> {
|
||||
&self.dial_info_details
|
||||
|
Reference in New Issue
Block a user