more routingdomain refactor

This commit is contained in:
John Smith 2022-08-31 21:41:48 -04:00
parent 68ea977d0f
commit 9966d25672
12 changed files with 486 additions and 279 deletions

View File

@ -200,14 +200,11 @@ struct DialInfoDetail {
}
struct NodeStatus {
# PublicInternet RoutingDomain Status
willRoute @0 :Bool;
willTunnel @1 :Bool;
willSignal @2 :Bool;
willRelay @3 :Bool;
willValidateDialInfo @4 :Bool;
# LocalNetwork RoutingDomain Status
# TODO
}
struct ProtocolTypeSet {

View File

@ -1884,7 +1884,7 @@ impl NetworkManager {
unord.push(async move {
// Update the node
if let Err(e) = rpc
.rpc_call_node_info_update(Destination::Direct(nr.clone()), None)
.rpc_call_node_info_update(nr.clone, routing_domain)
.await
{
// Not fatal, but we should be able to see if this is happening

View File

@ -118,11 +118,13 @@ impl DiscoveryContext {
// Build an filter that matches our protocol and address type
// and excludes relays so we can get an accurate external address
let dial_info_filter = DialInfoFilter::global()
let dial_info_filter = DialInfoFilter::all()
.with_protocol_type(protocol_type)
.with_address_type(address_type);
let inbound_dial_info_entry_filter =
RoutingTable::make_inbound_dial_info_entry_filter(dial_info_filter.clone());
let inbound_dial_info_entry_filter = RoutingTable::make_inbound_dial_info_entry_filter(
RoutingDomain::PublicInternet,
dial_info_filter.clone(),
);
let disallow_relays_filter = move |e: &BucketEntryInner| {
if let Some(n) = e.node_info(RoutingDomain::PublicInternet) {
n.relay_peer_info.is_none()
@ -169,7 +171,7 @@ impl DiscoveryContext {
protocol_type: ProtocolType,
address_type: AddressType,
) -> Vec<SocketAddress> {
let filter = DialInfoFilter::local()
let filter = DialInfoFilter::all()
.with_protocol_type(protocol_type)
.with_address_type(address_type);
self.routing_table

View File

@ -253,12 +253,11 @@ impl Network {
pub(super) async fn start_udp_listeners(&self) -> EyreResult<()> {
trace!("starting udp listeners");
let routing_table = self.routing_table();
let (listen_address, public_address, enable_local_peer_scope, detect_address_changes) = {
let (listen_address, public_address, detect_address_changes) = {
let c = self.config.get();
(
c.network.protocol.udp.listen_address.clone(),
c.network.protocol.udp.public_address.clone(),
c.network.enable_local_peer_scope,
c.network.detect_address_changes,
)
};
@ -288,6 +287,9 @@ impl Network {
// Register local dial info
for di in &local_dial_info_list {
xxx write routing table sieve for routing domain from dialinfo and local network detection and registration
// If the local interface address is global, or we are enabling local peer scope
// register global dial info if no public address is specified
if !detect_address_changes

View File

@ -476,7 +476,9 @@ impl NetworkManager {
// Otherwise we must need an inbound relay
} else {
// Find a node in our routing table that is an acceptable inbound relay
if let Some(nr) = routing_table.find_inbound_relay(cur_ts) {
if let Some(nr) =
routing_table.find_inbound_relay(RoutingDomain::PublicInternet, cur_ts)
{
info!("Inbound relay node selected: {}", nr);
routing_table.set_relay_node(RoutingDomain::PublicInternet, Some(nr));
node_info_changed = true;

View File

@ -39,15 +39,37 @@ pub enum BucketEntryState {
}
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
struct LastConnectionKey(PeerScope, ProtocolType, AddressType);
struct LastConnectionKey(ProtocolType, AddressType);
/// Bucket entry information specific to the LocalNetwork RoutingDomain
#[derive(Debug)]
pub struct BucketEntryPublicInternet {
/// The PublicInternet node info
signed_node_info: Option<Box<SignedNodeInfo>>,
/// If this node has seen our publicinternet node info
seen_our_node_info: bool,
/// Last known node status
node_status: Option<PublicInternetNodeStatus>,
}
/// Bucket entry information specific to the LocalNetwork RoutingDomain
#[derive(Debug)]
pub struct BucketEntryLocalNetwork {
/// The LocalNetwork node info
signed_node_info: Option<Box<SignedNodeInfo>>,
/// If this node has seen our localnetwork node info
seen_our_node_info: bool,
/// Last known node status
node_status: Option<LocalNetworkNodeStatus>,
}
#[derive(Debug)]
pub struct BucketEntryInner {
min_max_version: Option<(u8, u8)>,
updated_since_last_network_change: bool,
last_connections: BTreeMap<LastConnectionKey, (ConnectionDescriptor, u64)>,
signed_node_info: [Option<Box<SignedNodeInfo>>; RoutingDomain::count()],
seen_our_node_info: [bool; RoutingDomain::count()],
public_internet: BucketEntryPublicInternet,
local_network: BucketEntryLocalNetwork,
peer_stats: PeerStats,
latency_stats_accounting: LatencyStatsAccounting,
transfer_stats_accounting: TransferStatsAccounting,
@ -127,8 +149,14 @@ impl BucketEntryInner {
return;
}
// 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,
};
// See if we have an existing signed_node_info to update or not
if let Some(current_sni) = &self.signed_node_info[routing_domain as usize] {
if let Some(current_sni) = opt_current_sni {
// If the timestamp hasn't changed or is less, ignore this update
if signed_node_info.timestamp <= current_sni.timestamp {
// If we received a node update with the same timestamp
@ -152,54 +180,71 @@ impl BucketEntryInner {
));
// Update the signed node info
self.signed_node_info[routing_domain as usize] = Some(Box::new(signed_node_info));
*opt_current_sni = Some(Box::new(signed_node_info));
self.updated_since_last_network_change = true;
self.touch_last_seen(intf::get_timestamp());
}
pub fn has_node_info(&self, opt_routing_domain: Option<RoutingDomain>) -> bool {
if let Some(rd) = opt_routing_domain {
self.signed_node_info[rd as usize].is_some()
if let Some(routing_domain) = opt_routing_domain {
// 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,
};
opt_current_sni.is_some()
} else {
if self.local_network.signed_node_info.is_some() {
true
} else if self.public_internet.signed_node_info.is_some() {
true
} else {
for rd in RoutingDomain::all() {
if self.signed_node_info[rd as usize].is_some() {
return true;
}
}
false
}
}
}
pub fn has_valid_signed_node_info(&self, opt_routing_domain: Option<RoutingDomain>) -> bool {
if let Some(rd) = opt_routing_domain {
if let Some(sni) = &self.signed_node_info[rd as usize] {
if sni.is_valid() {
return true;
}
}
false
if let Some(routing_domain) = opt_routing_domain {
// 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 {
sni.is_valid()
} else {
for rd in RoutingDomain::all() {
if let Some(sni) = &self.signed_node_info[rd as usize] {
false
}
} else {
if let Some(sni) = self.local_network.signed_node_info {
if sni.is_valid() {
return true;
}
}
if let Some(sni) = self.public_internet.signed_node_info {
if sni.is_valid() {
return true;
}
}
false
}
}
pub fn node_info(&self, routing_domain: RoutingDomain) -> Option<NodeInfo> {
self.signed_node_info[routing_domain as usize]
.as_ref()
.map(|s| s.node_info.clone())
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())
}
pub fn peer_info(&self, key: DHTKey, routing_domain: RoutingDomain) -> Option<PeerInfo> {
self.signed_node_info[routing_domain as usize]
.as_ref()
.map(|s| 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,
};
opt_current_sni.as_ref().map(|s| PeerInfo {
node_id: NodeId::new(key),
signed_node_info: *s.clone(),
})
@ -207,7 +252,6 @@ impl BucketEntryInner {
fn descriptor_to_key(last_connection: ConnectionDescriptor) -> LastConnectionKey {
LastConnectionKey(
last_connection.peer_scope(),
last_connection.protocol_type(),
last_connection.address_type(),
)
@ -232,16 +276,14 @@ impl BucketEntryInner {
) -> 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 ps in dif.peer_scope_set {
for pt in dif.protocol_type_set {
for at in dif.address_type_set {
let key = LastConnectionKey(ps, pt, at);
let key = LastConnectionKey(pt, at);
if let Some(v) = self.last_connections.get(&key) {
return Some(*v);
}
}
}
}
None
}
pub fn set_min_max_version(&mut self, min_max_version: (u8, u8)) {
@ -267,15 +309,44 @@ impl BucketEntryInner {
}
pub fn update_node_status(&mut self, status: NodeStatus) {
self.peer_stats.status = Some(status);
match status {
NodeStatus::LocalNetwork(ln) => {
self.local_network.node_status = Some(ln);
}
NodeStatus::PublicInternet(pi) => {
self.public_internet.node_status = Some(pi);
}
}
}
pub fn node_status(&self, routing_domain: RoutingDomain) -> Option<NodeStatus> {
match routing_domain {
RoutingDomain::LocalNetwork => self
.local_network
.node_status
.map(|ln| NodeStatus::LocalNetwork(ln)),
RoutingDomain::PublicInternet => self
.local_network
.node_status
.map(|pi| NodeStatus::PublicInternet(pi)),
}
}
pub fn set_seen_our_node_info(&mut self, routing_domain: RoutingDomain, seen: bool) {
self.seen_our_node_info[routing_domain as usize] = seen;
match routing_domain {
RoutingDomain::LocalNetwork => {
self.local_network.seen_our_node_info = seen;
}
RoutingDomain::PublicInternet => {
self.public_internet.seen_our_node_info = seen;
}
}
}
pub fn has_seen_our_node_info(&self, routing_domain: RoutingDomain) -> bool {
self.seen_our_node_info[routing_domain as usize]
match routing_domain {
RoutingDomain::LocalNetwork => self.local_network.seen_our_node_info,
RoutingDomain::PublicInternet => self.public_internet.seen_our_node_info,
}
}
pub fn set_updated_since_last_network_change(&mut self, updated: bool) {
@ -502,16 +573,23 @@ impl BucketEntry {
ref_count: AtomicU32::new(0),
inner: RwLock::new(BucketEntryInner {
min_max_version: None,
seen_our_node_info: [false, false],
updated_since_last_network_change: false,
last_connections: BTreeMap::new(),
signed_node_info: [None, None],
local_network: BucketEntryLocalNetwork {
seen_our_node_info: false,
signed_node_info: None,
node_status: None,
},
public_internet: BucketEntryPublicInternet {
seen_our_node_info: false,
signed_node_info: None,
node_status: None,
},
peer_stats: PeerStats {
time_added: now,
rpc_stats: RPCStats::default(),
latency: None,
transfer: TransferStatsDownUp::default(),
status: None,
},
latency_stats_accounting: LatencyStatsAccounting::new(),
transfer_stats_accounting: TransferStatsAccounting::new(),

View File

@ -15,42 +15,38 @@ pub struct MappedPortInfo {
impl RoutingTable {
// Makes a filter that finds nodes with a matching inbound dialinfo
pub fn make_inbound_dial_info_entry_filter(
routing_domain: RoutingDomain,
dial_info_filter: DialInfoFilter,
) -> impl FnMut(&BucketEntryInner) -> bool {
// does it have matching public dial info?
move |e| {
for rd in RoutingDomain::all() {
if let Some(ni) = e.node_info(rd) {
if let Some(ni) = e.node_info(routing_domain) {
if ni
.first_filtered_dial_info_detail(|did| {
did.matches_filter(&dial_info_filter)
})
.first_filtered_dial_info_detail(|did| did.matches_filter(&dial_info_filter))
.is_some()
{
return true;
}
}
}
false
}
}
// Makes a filter that finds nodes capable of dialing a particular outbound dialinfo
pub fn make_outbound_dial_info_entry_filter(
routing_domain: RoutingDomain,
dial_info: DialInfo,
) -> impl FnMut(&BucketEntryInner) -> bool {
// does the node's outbound capabilities match the dialinfo?
move |e| {
for rd in RoutingDomain::all() {
if let Some(ni) = e.node_info(rd) {
let mut dif = DialInfoFilter::all();
dif = dif.with_protocol_type_set(ni.outbound_protocols);
dif = dif.with_address_type_set(ni.address_types);
if let Some(ni) = e.node_info(routing_domain) {
let dif = DialInfoFilter::all()
.with_protocol_type_set(ni.outbound_protocols)
.with_address_type_set(ni.address_types);
if dial_info.matches_filter(&dif) {
return true;
}
}
}
false
}
}
@ -126,7 +122,7 @@ impl RoutingTable {
let entry = v.unwrap();
entry.with(|e| {
// skip nodes on our local network here
if e.node_info(RoutingDomain::LocalNetwork).is_some() {
if e.has_node_info(Some(RoutingDomain::LocalNetwork)) {
return false;
}
@ -452,7 +448,7 @@ impl RoutingTable {
}
}
fn make_relay_node_filter(&self) -> impl Fn(&BucketEntryInner) -> bool {
fn make_public_internet_relay_node_filter(&self) -> impl Fn(&BucketEntryInner) -> bool {
// Get all our outbound protocol/address types
let outbound_dif = self
.network_manager()
@ -460,12 +456,8 @@ impl RoutingTable {
let mapped_port_info = self.get_mapped_port_info();
move |e: &BucketEntryInner| {
// Ensure this node is not on our local network
let has_local_dial_info = e
.local_node_info()
.map(|l| l.has_dial_info())
.unwrap_or(false);
if has_local_dial_info {
// Ensure this node is not on the local network
if e.has_node_info(Some(RoutingDomain::LocalNetwork)) {
return false;
}
@ -474,7 +466,7 @@ impl RoutingTable {
let mut low_level_protocol_ports = mapped_port_info.low_level_protocol_ports.clone();
let can_serve_as_relay = e
.node_info()
.node_info(RoutingDomain::PublicInternet)
.map(|n| {
let dids =
n.all_filtered_dial_info_details(|did| did.matches_filter(&outbound_dif));
@ -498,9 +490,18 @@ impl RoutingTable {
}
#[instrument(level = "trace", skip(self), ret)]
pub fn find_inbound_relay(&self, cur_ts: u64) -> Option<NodeRef> {
pub fn find_inbound_relay(
&self,
routing_domain: RoutingDomain,
cur_ts: u64,
) -> Option<NodeRef> {
// Get relay filter function
let relay_node_filter = self.make_relay_node_filter();
let relay_node_filter = match routing_domain {
RoutingDomain::PublicInternet => self.make_public_internet_relay_node_filter(),
RoutingDomain::LocalNetwork => {
unimplemented!();
}
};
// Go through all entries and find fastest entry that matches filter function
let inner = self.inner.read();
@ -512,9 +513,9 @@ impl RoutingTable {
let v2 = v.clone();
v.with(|e| {
// Ensure we have the node's status
if let Some(node_status) = e.peer_stats().status.clone() {
if let Some(node_status) = e.node_status(routing_domain) {
// Ensure the node will relay
if node_status.will_relay {
if node_status.will_relay() {
// Compare against previous candidate
if let Some(best_inbound_relay) = best_inbound_relay.as_mut() {
// Less is faster
@ -541,7 +542,11 @@ impl RoutingTable {
}
#[instrument(level = "trace", skip(self), ret)]
pub fn register_find_node_answer(&self, peers: Vec<PeerInfo>) -> Vec<NodeRef> {
pub fn register_find_node_answer(
&self,
routing_domain: RoutingDomain,
peers: Vec<PeerInfo>,
) -> Vec<NodeRef> {
let node_id = self.node_id();
// register nodes we'd found
@ -561,6 +566,7 @@ impl RoutingTable {
// register the node if it's new
if let Some(nr) = self.register_node_with_signed_node_info(
routing_domain,
p.node_id.key,
p.signed_node_info.clone(),
false,
@ -574,6 +580,7 @@ impl RoutingTable {
#[instrument(level = "trace", skip(self), ret, err)]
pub async fn find_node(
&self,
routing_domain: RoutingDomain,
node_ref: NodeRef,
node_id: DHTKey,
) -> EyreResult<NetworkResult<Vec<NodeRef>>> {
@ -583,39 +590,52 @@ impl RoutingTable {
rpc_processor
.clone()
.rpc_call_find_node(
Destination::Direct(node_ref.clone()),
Destination::direct(node_ref.clone()).with_routing_domain(routing_domain),
node_id,
None,
rpc_processor.make_respond_to_sender(node_ref.clone()),
rpc_processor.make_respond_to_sender(routing_domain, node_ref.clone()),
)
.await?
);
// register nodes we'd found
Ok(NetworkResult::value(
self.register_find_node_answer(res.answer),
self.register_find_node_answer(routing_domain, res.answer),
))
}
#[instrument(level = "trace", skip(self), ret, err)]
pub async fn find_self(&self, node_ref: NodeRef) -> EyreResult<NetworkResult<Vec<NodeRef>>> {
pub async fn find_self(
&self,
routing_domain: RoutingDomain,
node_ref: NodeRef,
) -> EyreResult<NetworkResult<Vec<NodeRef>>> {
let node_id = self.node_id();
self.find_node(node_ref, node_id).await
self.find_node(routing_domain, node_ref, node_id).await
}
#[instrument(level = "trace", skip(self), ret, err)]
pub async fn find_target(&self, node_ref: NodeRef) -> EyreResult<NetworkResult<Vec<NodeRef>>> {
pub async fn find_target(
&self,
routing_domain: RoutingDomain,
node_ref: NodeRef,
) -> EyreResult<NetworkResult<Vec<NodeRef>>> {
let node_id = node_ref.node_id();
self.find_node(node_ref, node_id).await
self.find_node(routing_domain, node_ref, node_id).await
}
#[instrument(level = "trace", skip(self))]
pub async fn reverse_find_node(&self, node_ref: NodeRef, wide: bool) {
pub async fn reverse_find_node(
&self,
routing_domain: RoutingDomain,
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(node_ref.clone()).await {
let closest_nodes = network_result_value_or_log!(debug match self.find_self(routing_domain, node_ref.clone()).await {
Err(e) => {
log_rtab!(error
"find_self failed for {:?}: {:?}",
@ -631,7 +651,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(closest_nr.clone()).await {
network_result_value_or_log!(debug match self.find_self(routing_domain, closest_nr.clone()).await {
Err(e) => {
log_rtab!(error
"find_self failed for {:?}: {:?}",

View File

@ -23,20 +23,6 @@ const RECENT_PEERS_TABLE_SIZE: usize = 64;
//////////////////////////////////////////////////////////////////////////
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
pub enum RoutingDomain {
PublicInternet = 0,
LocalNetwork = 1,
}
impl RoutingDomain {
pub const fn count() -> usize {
2
}
pub const fn all() -> [RoutingDomain; RoutingDomain::count()] {
[RoutingDomain::PublicInternet, RoutingDomain::LocalNetwork]
}
}
#[derive(Debug, Default)]
pub struct RoutingDomainDetail {
relay_node: Option<NodeRef>,
@ -519,7 +505,13 @@ 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,
RoutingDomainSet::only(routing_domain),
None,
));
}
Option::<()>::None
});

View File

@ -52,7 +52,7 @@ impl NodeRef {
pub fn merge_filter(&mut self, filter: DialInfoFilter) {
if let Some(self_filter) = self.filter.take() {
self.filter = Some(self_filter.filtered(filter));
self.filter = Some(self_filter.filtered(&filter));
} else {
self.filter = Some(filter);
}
@ -72,19 +72,6 @@ impl NodeRef {
}
}
// Returns true if some protocols can still pass the filter and false if no protocols remain
// pub fn filter_protocols(&mut self, protocol_set: ProtocolSet) -> bool {
// if protocol_set != ProtocolSet::all() {
// let mut dif = self.filter.clone().unwrap_or_default();
// dif.protocol_set &= protocol_set;
// self.filter = Some(dif);
// }
// self.filter
// .as_ref()
// .map(|f| !f.protocol_set.is_empty())
// .unwrap_or(true)
// }
pub(super) fn operate<T, F>(&self, f: F) -> T
where
F: FnOnce(&RoutingTableInner, &BucketEntryInner) -> T,
@ -129,7 +116,6 @@ impl NodeRef {
pub fn min_max_version(&self) -> Option<(u8, u8)> {
self.operate(|_rti, e| e.min_max_version())
}
pub fn set_min_max_version(&self, min_max_version: (u8, u8)) {
self.operate_mut(|_rti, e| e.set_min_max_version(min_max_version))
}

View File

@ -39,25 +39,200 @@ type OperationId = u64;
/// Where to send an RPC message
#[derive(Debug, Clone)]
pub enum Destination {
/// Send to node (target noderef)
Direct(NodeRef),
/// Send to node for relay purposes (relay noderef, target nodeid)
Relay(NodeRef, DHTKey),
/// Send to node directly
Direct {
/// The node to send to
target: NodeRef,
/// An optional routing domain to require
routing_domain: Option<RoutingDomain>,
/// An optional safety route specification to send from for sender privacy
safety_route_spec: Option<Arc<SafetyRouteSpec>>,
},
/// Send to node for relay purposes
Relay {
/// The relay to send to
relay: NodeRef,
/// The final destination the relay should send to
target: DHTKey,
/// An optional routing domain to require
routing_domain: Option<RoutingDomain>,
/// An optional safety route specification to send from for sender privacy
safety_route_spec: Option<Arc<SafetyRouteSpec>>,
},
/// Send to private route (privateroute)
PrivateRoute(PrivateRoute),
PrivateRoute {
/// A private route to send to
private_route: PrivateRoute,
/// An optional safety route specification to send from for sender privacy
safety_route_spec: Option<Arc<SafetyRouteSpec>>,
},
}
impl Destination {
pub fn direct(target: NodeRef) -> Self {
Self::Direct {
target,
routing_domain: None,
safety_route_spec: None,
}
}
pub fn relay(relay: NodeRef, target: DHTKey) -> Self {
Self::Relay {
relay,
target,
routing_domain: None,
safety_route_spec: None,
}
}
pub fn private_route(private_route: PrivateRoute) -> Self {
Self::PrivateRoute {
private_route,
safety_route_spec: None,
}
}
pub fn
pub fn routing_domain(&self) -> Option<RoutingDomain> {
match self {
Destination::Direct {
target,
routing_domain,
safety_route_spec,
} => *routing_domain,
Destination::Relay {
relay,
target,
routing_domain,
safety_route_spec,
} => *routing_domain,
Destination::PrivateRoute {
private_route,
safety_route_spec,
} => Some(RoutingDomain::PublicInternet),
}
}
pub fn safety_route_spec(&self) -> Option<Arc<SafetyRouteSpec>> {
match self {
Destination::Direct {
target,
routing_domain,
safety_route_spec,
} => safety_route_spec.clone(),
Destination::Relay {
relay,
target,
routing_domain,
safety_route_spec,
} => safety_route_spec.clone(),
Destination::PrivateRoute {
private_route,
safety_route_spec,
} => safety_route_spec.clone(),
}
}
pub fn with_routing_domain(self, routing_domain: RoutingDomain) -> Self {
match self {
Destination::Direct {
target,
routing_domain: _,
safety_route_spec,
} => Self::Direct {
target,
routing_domain: Some(routing_domain),
safety_route_spec,
},
Destination::Relay {
relay,
target,
routing_domain: _,
safety_route_spec,
} => Self::Relay {
relay,
target,
routing_domain: Some(routing_domain),
safety_route_spec,
},
Destination::PrivateRoute {
private_route: _,
safety_route_spec: _,
} => panic!("Private route is only valid in PublicInternet routing domain"),
}
}
pub fn with_safety_route_spec(self, safety_route_spec: Arc<SafetyRouteSpec>) -> Self {
match self {
Destination::Direct {
target,
routing_domain,
safety_route_spec: _,
} => Self::Direct {
target,
routing_domain,
safety_route_spec: Some(safety_route_spec),
},
Destination::Relay {
relay,
target,
routing_domain,
safety_route_spec: _,
} => Self::Relay {
relay,
target,
routing_domain,
safety_route_spec: Some(safety_route_spec),
},
Destination::PrivateRoute {
private_route,
safety_route_spec: _,
} => Self::PrivateRoute {
private_route,
safety_route_spec: Some(safety_route_spec),
},
}
}
}
impl fmt::Display for Destination {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Destination::Direct(nr) => {
write!(f, "{:?}", nr)
Destination::Direct {
target,
routing_domain,
safety_route_spec,
} => {
let rd = routing_domain
.map(|rd| format!("#{:?}", rd))
.unwrap_or_default();
let sr = safety_route_spec
.map(|_sr| "+SR".to_owned())
.unwrap_or_default();
write!(f, "{:?}{}{}", target, rd, sr)
}
Destination::Relay(nr, key) => {
write!(f, "{:?}@{:?}", key.encode(), nr)
Destination::Relay {
relay,
target,
routing_domain,
safety_route_spec,
} => {
let rd = routing_domain
.map(|rd| format!("#{:?}", rd))
.unwrap_or_default();
let sr = safety_route_spec
.map(|_sr| "+SR".to_owned())
.unwrap_or_default();
write!(f, "{:?}@{:?}{}{}", target.encode(), relay, rd, sr)
}
Destination::PrivateRoute(pr) => {
write!(f, "{}", pr)
Destination::PrivateRoute {
private_route,
safety_route_spec,
} => {
let sr = safety_route_spec
.map(|_sr| "+SR".to_owned())
.unwrap_or_default();
write!(f, "{}{}", private_route, sr)
}
}
}
@ -412,18 +587,24 @@ impl RPCProcessor {
/// Gets a 'RespondTo::Sender' that contains either our dial info,
/// or None if the peer has seen our dial info before or our node info is not yet valid
/// because of an unknown network class
pub fn make_respond_to_sender(&self, peer: NodeRef) -> RespondTo {
if peer.has_seen_our_node_info()
pub fn make_respond_to_sender(
&self,
routing_domain: RoutingDomain,
peer: NodeRef,
) -> RespondTo {
if peer.has_seen_our_node_info(routing_domain)
|| matches!(
self.network_manager()
.get_network_class()
.get_network_class(routing_domain)
.unwrap_or(NetworkClass::Invalid),
NetworkClass::Invalid
)
{
RespondTo::Sender(None)
} else {
let our_sni = self.routing_table().get_own_signed_node_info();
let our_sni = self
.routing_table()
.get_own_signed_node_info(routing_domain);
RespondTo::Sender(Some(our_sni))
}
}
@ -431,13 +612,12 @@ impl RPCProcessor {
/// Produce a byte buffer that represents the wire encoding of the entire
/// unencrypted envelope body for a RPC message. This incorporates
/// wrapping a private and/or safety route if they are specified.
#[instrument(level = "debug", skip(self, operation, safety_route_spec), err)]
#[instrument(level = "debug", skip(self, operation), err)]
fn render_operation(
&self,
dest: Destination,
operation: &RPCOperation,
safety_route_spec: Option<&SafetyRouteSpec>,
) -> Result<RenderedOperation, RPCError> {
) -> Result<RenderedOperation, RPCError> { xxx continue propagating safetyroutespec
let out_node_id; // Envelope Node Id
let mut out_node_ref: Option<NodeRef> = None; // Node to send envelope to
let out_hop_count: usize; // Total safety + private route hop count
@ -548,7 +728,6 @@ impl RPCProcessor {
&self,
dest: Destination,
question: RPCQuestion,
safety_route_spec: Option<&SafetyRouteSpec>,
) -> Result<NetworkResult<WaitableReply>, RPCError> {
// Wrap question in operation
let operation = RPCOperation::new_question(question);
@ -624,7 +803,6 @@ impl RPCProcessor {
&self,
dest: Destination,
statement: RPCStatement,
safety_route_spec: Option<&SafetyRouteSpec>,
) -> Result<NetworkResult<()>, RPCError> {
// Wrap statement in operation
let operation = RPCOperation::new_statement(statement);
@ -714,7 +892,6 @@ impl RPCProcessor {
&self,
request: RPCMessage,
answer: RPCAnswer,
safety_route_spec: Option<&SafetyRouteSpec>,
) -> Result<NetworkResult<()>, RPCError> {
// Wrap answer in operation
let operation = RPCOperation::new_answer(&request.operation, answer);

View File

@ -6,16 +6,23 @@ impl RPCProcessor {
#[instrument(level = "trace", skip(self), ret, err)]
pub async fn rpc_call_node_info_update(
self,
dest: Destination,
safety_route: Option<&SafetyRouteSpec>,
target: NodeRef,
routing_domain: RoutingDomain,
) -> Result<NetworkResult<()>, RPCError> {
let signed_node_info = self.routing_table().get_own_signed_node_info();
xxx add routing domain to capnp....
let signed_node_info = self
.routing_table()
.get_own_signed_node_info(routing_domain);
let node_info_update = RPCOperationNodeInfoUpdate { signed_node_info };
let statement = RPCStatement::new(RPCStatementDetail::NodeInfoUpdate(node_info_update));
// Send the node_info_update request
network_result_try!(self.statement(dest, statement, safety_route).await?);
network_result_try!(
self.statement(
Destination::direct(target).with_routing_domain(routing_domain),
statement,
)
.await?
);
Ok(NetworkResult::value(()))
}

View File

@ -390,16 +390,62 @@ impl NetworkClass {
}
}
/// RoutingDomain-specific status for each node
/// is returned by the StatusA call
/// PublicInternet RoutingDomain Status
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct NodeStatus {
// PublicInternet RoutingDomain Status
pub struct PublicInternetNodeStatus {
pub will_route: bool,
pub will_tunnel: bool,
pub will_signal: bool,
pub will_relay: bool,
pub will_validate_dial_info: bool,
// LocalNetwork RoutingDomain Status
// TODO
}
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct LocalNetworkNodeStatus {
pub will_relay: bool,
pub will_validate_dial_info: bool,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NodeStatus {
PublicInternet(PublicInternetNodeStatus),
LocalNetwork(LocalNetworkNodeStatus),
}
impl NodeStatus {
pub fn will_route(&self) -> bool {
match self {
NodeStatus::PublicInternet(pi) => pi.will_route,
NodeStatus::LocalNetwork(_) => false,
}
}
pub fn will_tunnel(&self) -> bool {
match self {
NodeStatus::PublicInternet(pi) => pi.will_tunnel,
NodeStatus::LocalNetwork(_) => false,
}
}
pub fn will_signal(&self) -> bool {
match self {
NodeStatus::PublicInternet(pi) => pi.will_signal,
NodeStatus::LocalNetwork(_) => false,
}
}
pub fn will_relay(&self) -> bool {
match self {
NodeStatus::PublicInternet(pi) => pi.will_relay,
NodeStatus::LocalNetwork(ln) => ln.will_relay,
}
}
pub fn will_validate_dial_info(&self) -> bool {
match self {
NodeStatus::PublicInternet(pi) => pi.will_validate_dial_info,
NodeStatus::LocalNetwork(ln) => ln.will_validate_dial_info,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
@ -556,13 +602,23 @@ pub enum AddressType {
}
pub type AddressTypeSet = EnumSet<AddressType>;
// Routing domain here is listed in order of preference, keep in order
#[allow(clippy::derive_hash_xor_eq)]
#[derive(Debug, Ord, PartialOrd, Hash, Serialize, Deserialize, EnumSetType)]
pub enum PeerScope {
Global,
Local,
pub enum RoutingDomain {
LocalNetwork = 0,
PublicInternet = 1,
}
pub type PeerScopeSet = EnumSet<PeerScope>;
impl RoutingDomain {
pub const fn count() -> usize {
2
}
pub const fn all() -> [RoutingDomain; RoutingDomain::count()] {
// Routing domain here is listed in order of preference, keep in order
[RoutingDomain::LocalNetwork, RoutingDomain::PublicInternet]
}
}
pub type RoutingDomainSet = EnumSet<RoutingDomain>;
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Serialize, Deserialize)]
pub enum Address {
@ -729,7 +785,6 @@ impl FromStr for SocketAddress {
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct DialInfoFilter {
pub peer_scope_set: PeerScopeSet,
pub protocol_type_set: ProtocolTypeSet,
pub address_type_set: AddressTypeSet,
}
@ -737,7 +792,6 @@ pub struct DialInfoFilter {
impl Default for DialInfoFilter {
fn default() -> Self {
Self {
peer_scope_set: PeerScopeSet::all(),
protocol_type_set: ProtocolTypeSet::all(),
address_type_set: AddressTypeSet::all(),
}
@ -747,28 +801,6 @@ impl Default for DialInfoFilter {
impl DialInfoFilter {
pub fn all() -> Self {
Self {
peer_scope_set: PeerScopeSet::all(),
protocol_type_set: ProtocolTypeSet::all(),
address_type_set: AddressTypeSet::all(),
}
}
pub fn global() -> Self {
Self {
peer_scope_set: PeerScopeSet::only(PeerScope::Global),
protocol_type_set: ProtocolTypeSet::all(),
address_type_set: AddressTypeSet::all(),
}
}
pub fn local() -> Self {
Self {
peer_scope_set: PeerScopeSet::only(PeerScope::Local),
protocol_type_set: ProtocolTypeSet::all(),
address_type_set: AddressTypeSet::all(),
}
}
pub fn scoped(peer_scope: PeerScope) -> Self {
Self {
peer_scope_set: PeerScopeSet::only(peer_scope),
protocol_type_set: ProtocolTypeSet::all(),
address_type_set: AddressTypeSet::all(),
}
@ -789,25 +821,19 @@ impl DialInfoFilter {
self.address_type_set = address_set;
self
}
pub fn filtered(mut self, other_dif: DialInfoFilter) -> Self {
self.peer_scope_set &= other_dif.peer_scope_set;
pub fn filtered(mut self, other_dif: &DialInfoFilter) -> Self {
self.protocol_type_set &= other_dif.protocol_type_set;
self.address_type_set &= other_dif.address_type_set;
self
}
pub fn is_dead(&self) -> bool {
self.peer_scope_set.is_empty()
|| self.protocol_type_set.is_empty()
|| self.address_type_set.is_empty()
self.protocol_type_set.is_empty() || self.address_type_set.is_empty()
}
}
impl fmt::Debug for DialInfoFilter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
let mut out = String::new();
if self.peer_scope_set != PeerScopeSet::all() {
out += &format!("+{:?}", self.peer_scope_set);
}
if self.protocol_type_set != ProtocolTypeSet::all() {
out += &format!("+{:?}", self.protocol_type_set);
}
@ -1126,49 +1152,15 @@ impl DialInfo {
Self::WSS(di) => Some(format!("wss://{}", di.request)),
}
}
pub fn is_global(&self) -> bool {
self.socket_address().address().is_global()
}
pub fn is_local(&self) -> bool {
self.socket_address().address().is_local()
}
pub fn is_valid(&self) -> bool {
let socket_address = self.socket_address();
let address = socket_address.address();
let port = socket_address.port();
(address.is_global() || address.is_local()) && port > 0
}
pub fn peer_scope(&self) -> Option<PeerScope> {
let addr = self.socket_address().address();
if addr.is_global() {
return Some(PeerScope::Global);
}
if addr.is_local() {
return Some(PeerScope::Local);
}
None
}
pub fn matches_peer_scope(&self, scope: PeerScopeSet) -> bool {
if let Some(ps) = self.peer_scope() {
scope.contains(ps)
} else {
false
}
}
pub fn make_filter(&self, scoped: bool) -> DialInfoFilter {
pub fn make_filter(&self) -> DialInfoFilter {
DialInfoFilter {
peer_scope_set: if scoped {
if self.is_global() {
PeerScopeSet::only(PeerScope::Global)
} else if self.is_local() {
PeerScopeSet::only(PeerScope::Local)
} else {
PeerScopeSet::empty()
}
} else {
PeerScopeSet::all()
},
protocol_type_set: ProtocolTypeSet::only(self.protocol_type()),
address_type_set: AddressTypeSet::only(self.address_type()),
}
@ -1355,9 +1347,6 @@ impl DialInfo {
impl MatchesDialInfoFilter for DialInfo {
fn matches_filter(&self, filter: &DialInfoFilter) -> bool {
if !self.matches_peer_scope(filter.peer_scope_set) {
return false;
}
if !filter.protocol_type_set.contains(self.protocol_type()) {
return false;
}
@ -1452,8 +1441,8 @@ impl PeerInfo {
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
pub struct PeerAddress {
socket_address: SocketAddress,
protocol_type: ProtocolType,
socket_address: SocketAddress,
}
impl PeerAddress {
@ -1488,36 +1477,13 @@ pub struct ConnectionDescriptor {
}
impl ConnectionDescriptor {
fn validate_peer_scope(remote: PeerAddress) -> Result<(), VeilidAPIError> {
// Verify address is in one of our peer scopes we care about
let addr = remote.socket_address.address();
// Allow WASM to have unresolved addresses, for bootstraps
cfg_if::cfg_if! {
if #[cfg(target_arch = "wasm32")] {
if addr.is_unspecified() {
return Ok(());
}
}
}
if !addr.is_global() && !addr.is_local() {
return Err(VeilidAPIError::generic(format!(
"not a valid peer scope: {:?}",
addr
)));
}
Ok(())
}
pub fn new(remote: PeerAddress, local: SocketAddress) -> Result<Self, VeilidAPIError> {
Self::validate_peer_scope(remote)?;
Ok(Self {
remote,
local: Some(local),
})
}
pub fn new_no_local(remote: PeerAddress) -> Result<Self, VeilidAPIError> {
Self::validate_peer_scope(remote)?;
Ok(Self {
remote,
local: None,
@ -1538,36 +1504,15 @@ impl ConnectionDescriptor {
pub fn address_type(&self) -> AddressType {
self.remote.address_type()
}
pub fn peer_scope(&self) -> PeerScope {
let addr = self.remote.socket_address.address();
// Allow WASM to have unresolved addresses, for bootstraps
cfg_if::cfg_if! {
if #[cfg(target_arch = "wasm32")] {
if addr.is_unspecified() {
return PeerScope::Global;
}
}
}
if addr.is_global() {
return PeerScope::Global;
}
PeerScope::Local
}
pub fn make_dial_info_filter(&self) -> DialInfoFilter {
DialInfoFilter::scoped(self.peer_scope())
DialInfoFilter::all()
.with_protocol_type(self.protocol_type())
.with_address_type(self.address_type())
}
pub fn matches_peer_scope(&self, scope: PeerScopeSet) -> bool {
scope.contains(self.peer_scope())
}
}
impl MatchesDialInfoFilter for ConnectionDescriptor {
fn matches_filter(&self, filter: &DialInfoFilter) -> bool {
if !self.matches_peer_scope(filter.peer_scope_set) {
return false;
}
if !filter.protocol_type_set.contains(self.protocol_type()) {
return false;
}
@ -1654,7 +1599,6 @@ pub struct PeerStats {
pub rpc_stats: RPCStats, // information about RPCs
pub latency: Option<LatencyStats>, // latencies for communications with the peer
pub transfer: TransferStatsDownUp, // Stats for communications with the peer
pub status: Option<NodeStatus>, // Last known node status
}
pub type ValueChangeCallback =