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