Files
veilid/veilid-core/src/routing_table/routing_domain_editor.rs
John Smith 2b9044fdfa close #169
2022-12-08 12:48:01 -05:00

209 lines
7.8 KiB
Rust

use super::*;
enum RoutingDomainChange {
ClearDialInfoDetails,
ClearRelayNode,
SetRelayNode {
relay_node: NodeRef,
},
AddDialInfoDetail {
dial_info_detail: DialInfoDetail,
},
SetupNetwork {
outbound_protocols: ProtocolTypeSet,
inbound_protocols: ProtocolTypeSet,
address_types: AddressTypeSet,
},
SetNetworkClass {
network_class: Option<NetworkClass>,
},
}
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(),
}
}
#[instrument(level = "debug", skip(self))]
pub fn clear_dial_info_details(&mut self) {
self.changes.push(RoutingDomainChange::ClearDialInfoDetails);
}
#[instrument(level = "debug", skip(self))]
pub fn clear_relay_node(&mut self) {
self.changes.push(RoutingDomainChange::ClearRelayNode);
}
#[instrument(level = "debug", skip(self))]
pub fn set_relay_node(&mut self, relay_node: NodeRef) {
self.changes
.push(RoutingDomainChange::SetRelayNode { relay_node })
}
#[instrument(level = "debug", skip(self), err)]
pub fn register_dial_info(
&mut self,
dial_info: DialInfo,
class: DialInfoClass,
) -> EyreResult<()> {
if !self
.routing_table
.ensure_dial_info_is_valid(self.routing_domain, &dial_info)
{
return Err(eyre!(
"dial info '{}' is not valid in routing domain '{:?}'",
dial_info,
self.routing_domain
));
}
self.changes.push(RoutingDomainChange::AddDialInfoDetail {
dial_info_detail: DialInfoDetail {
dial_info: dial_info.clone(),
class,
},
});
Ok(())
}
#[instrument(level = "debug", skip(self))]
pub fn setup_network(
&mut self,
outbound_protocols: ProtocolTypeSet,
inbound_protocols: ProtocolTypeSet,
address_types: AddressTypeSet,
) {
self.changes.push(RoutingDomainChange::SetupNetwork {
outbound_protocols,
inbound_protocols,
address_types,
})
}
#[instrument(level = "debug", skip(self))]
pub fn set_network_class(&mut self, network_class: Option<NetworkClass>) {
self.changes
.push(RoutingDomainChange::SetNetworkClass { network_class })
}
#[instrument(level = "debug", skip(self))]
pub async fn commit(self) {
// No locking if we have nothing to do
if self.changes.is_empty() {
return;
}
let mut changed = false;
{
let node_id = self.routing_table.node_id();
let mut inner = self.routing_table.inner.write();
inner.with_routing_domain_mut(self.routing_domain, |detail| {
for change in self.changes {
match change {
RoutingDomainChange::ClearDialInfoDetails => {
debug!("[{:?}] cleared dial info details", self.routing_domain);
detail.common_mut().clear_dial_info_details();
changed = true;
}
RoutingDomainChange::ClearRelayNode => {
debug!("[{:?}] cleared relay node", self.routing_domain);
detail.common_mut().set_relay_node(None);
changed = true;
}
RoutingDomainChange::SetRelayNode { relay_node } => {
debug!("[{:?}] set relay node: {}", self.routing_domain, relay_node);
detail.common_mut().set_relay_node(Some(relay_node));
changed = true;
}
RoutingDomainChange::AddDialInfoDetail { dial_info_detail } => {
debug!(
"[{:?}] add dial info detail: {:?}",
self.routing_domain, dial_info_detail
);
detail
.common_mut()
.add_dial_info_detail(dial_info_detail.clone());
info!(
"{:?} Dial Info: {}@{}",
self.routing_domain,
NodeId::new(node_id),
dial_info_detail.dial_info
);
changed = true;
}
RoutingDomainChange::SetupNetwork {
outbound_protocols,
inbound_protocols,
address_types,
} => {
let old_outbound_protocols = detail.common().outbound_protocols();
let old_inbound_protocols = detail.common().inbound_protocols();
let old_address_types = detail.common().address_types();
let this_changed = old_outbound_protocols != outbound_protocols
|| old_inbound_protocols != inbound_protocols
|| old_address_types != address_types;
debug!(
"[{:?}] setup network: {:?} {:?} {:?}",
self.routing_domain,
outbound_protocols,
inbound_protocols,
address_types
);
detail.common_mut().setup_network(
outbound_protocols,
inbound_protocols,
address_types,
);
if this_changed {
changed = true;
}
}
RoutingDomainChange::SetNetworkClass { network_class } => {
let old_network_class = detail.common().network_class();
let this_changed = old_network_class != network_class;
debug!(
"[{:?}] set network class: {:?}",
self.routing_domain, network_class,
);
detail.common_mut().set_network_class(network_class);
if this_changed {
changed = true;
}
}
}
}
if changed {
// Clear our 'peer info' cache, the peerinfo for this routing domain will get regenerated next time it is asked for
detail.common_mut().clear_cache()
}
});
if changed {
// Allow signed node info updates at same timestamp for otherwise dead nodes if our network has changed
inner.reset_all_updated_since_last_network_change();
}
}
// Clear the routespecstore cache if our PublicInternet dial info has changed
if changed {
if self.routing_domain == RoutingDomain::PublicInternet {
let rss = self.routing_table.route_spec_store();
rss.reset();
}
}
}
}