more capability work

This commit is contained in:
John Smith
2023-07-04 00:24:55 -04:00
parent e674eaf496
commit 8f721c428b
33 changed files with 456 additions and 474 deletions

View File

@@ -51,7 +51,7 @@ pub struct BucketEntryPublicInternet {
/// The last node info timestamp of ours that this entry has seen
last_seen_our_node_info_ts: Timestamp,
/// Last known node status
node_status: Option<PublicInternetNodeStatus>,
node_status: Option<NodeStatus>,
}
/// Bucket entry information specific to the LocalNetwork RoutingDomain
@@ -63,7 +63,7 @@ pub struct BucketEntryLocalNetwork {
/// The last node info timestamp of ours that this entry has seen
last_seen_our_node_info_ts: Timestamp,
/// Last known node status
node_status: Option<LocalNetworkNodeStatus>,
node_status: Option<NodeStatus>,
}
/// The data associated with each bucket entry
@@ -502,13 +502,13 @@ impl BucketEntryInner {
&self.peer_stats
}
pub fn update_node_status(&mut self, status: NodeStatus) {
match status {
NodeStatus::LocalNetwork(ln) => {
self.local_network.node_status = Some(ln);
pub fn update_node_status(&mut self, routing_domain: RoutingDomain, status: NodeStatus) {
match routing_domain {
RoutingDomain::LocalNetwork => {
self.local_network.node_status = Some(status);
}
NodeStatus::PublicInternet(pi) => {
self.public_internet.node_status = Some(pi);
RoutingDomain::PublicInternet => {
self.public_internet.node_status = Some(status);
}
}
}
@@ -518,12 +518,12 @@ impl BucketEntryInner {
.local_network
.node_status
.as_ref()
.map(|ln| NodeStatus::LocalNetwork(ln.clone())),
.map(|ns| ns.clone()),
RoutingDomain::PublicInternet => self
.public_internet
.node_status
.as_ref()
.map(|pi| NodeStatus::PublicInternet(pi.clone())),
.map(|ns| ns.clone()),
}
}

View File

@@ -118,9 +118,9 @@ pub trait NodeRefBase: Sized {
fn set_updated_since_last_network_change(&self) {
self.operate_mut(|_rti, e| e.set_updated_since_last_network_change(true));
}
fn update_node_status(&self, node_status: NodeStatus) {
fn update_node_status(&self, routing_domain: RoutingDomain, node_status: NodeStatus) {
self.operate_mut(|_rti, e| {
e.update_node_status(node_status);
e.update_node_status(routing_domain, node_status);
});
}
fn envelope_support(&self) -> Vec<u8> {

View File

@@ -257,20 +257,9 @@ impl RouteSpecStore {
// Exclude nodes with no publicinternet nodeinfo, or incompatible nodeinfo or node status won't route
entry.with_inner(|e| {
let node_info_ok =
if let Some(sni) = e.signed_node_info(RoutingDomain::PublicInternet) {
sni.has_sequencing_matched_dial_info(sequencing)
} else {
false
};
let node_status_ok =
if let Some(ns) = e.node_status(RoutingDomain::PublicInternet) {
ns.has_capability(CAP_WILL_ROUTE)
} else {
false
};
node_info_ok && node_status_ok
e.signed_node_info(RoutingDomain::PublicInternet).map(|sni|
sni.has_sequencing_matched_dial_info(sequencing) && sni.node_info().can_route()
).unwrap_or(false)
})
},
) as RoutingTableEntryFilter;

View File

@@ -13,6 +13,7 @@ enum RoutingDomainChange {
outbound_protocols: ProtocolTypeSet,
inbound_protocols: ProtocolTypeSet,
address_types: AddressTypeSet,
capabilities: Vec<Capability>,
},
SetNetworkClass {
network_class: Option<NetworkClass>,
@@ -79,11 +80,13 @@ impl RoutingDomainEditor {
outbound_protocols: ProtocolTypeSet,
inbound_protocols: ProtocolTypeSet,
address_types: AddressTypeSet,
capabilities: Vec<Capability>,
) {
self.changes.push(RoutingDomainChange::SetupNetwork {
outbound_protocols,
inbound_protocols,
address_types,
capabilities,
})
}
@@ -142,27 +145,32 @@ impl RoutingDomainEditor {
outbound_protocols,
inbound_protocols,
address_types,
capabilities,
} => {
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 old_capabilities = detail.common().capabilities();
let this_changed = old_outbound_protocols != outbound_protocols
|| old_inbound_protocols != inbound_protocols
|| old_address_types != address_types;
|| old_address_types != address_types
|| old_capabilities != capabilities;
debug!(
"[{:?}] setup network: {:?} {:?} {:?}",
"[{:?}] setup network: {:?} {:?} {:?} {:?}",
self.routing_domain,
outbound_protocols,
inbound_protocols,
address_types
address_types,
capabilities
);
detail.common_mut().setup_network(
outbound_protocols,
inbound_protocols,
address_types,
capabilities,
);
if this_changed {
changed = true;

View File

@@ -27,6 +27,7 @@ pub struct RoutingDomainDetailCommon {
inbound_protocols: ProtocolTypeSet,
address_types: AddressTypeSet,
relay_node: Option<NodeRef>,
capabilities: Vec<Capability>,
dial_info_details: Vec<DialInfoDetail>,
// caches
cached_peer_info: Mutex<Option<PeerInfo>>,
@@ -41,6 +42,7 @@ impl RoutingDomainDetailCommon {
inbound_protocols: Default::default(),
address_types: Default::default(),
relay_node: Default::default(),
capabilities: Default::default(),
dial_info_details: Default::default(),
cached_peer_info: Mutex::new(Default::default()),
}
@@ -52,10 +54,12 @@ impl RoutingDomainDetailCommon {
outbound_protocols: ProtocolTypeSet,
inbound_protocols: ProtocolTypeSet,
address_types: AddressTypeSet,
capabilities: Vec<Capability>,
) {
self.outbound_protocols = outbound_protocols;
self.inbound_protocols = inbound_protocols;
self.address_types = address_types;
self.capabilities = capabilities;
self.clear_cache();
}
@@ -75,6 +79,9 @@ impl RoutingDomainDetailCommon {
pub fn address_types(&self) -> AddressTypeSet {
self.address_types
}
pub fn capabilities(&self) -> Vec<Capability> {
self.capabilities.clone()
}
pub fn relay_node(&self) -> Option<NodeRef> {
self.relay_node.clone()
}
@@ -108,6 +115,7 @@ impl RoutingDomainDetailCommon {
self.address_types,
VALID_ENVELOPE_VERSIONS.to_vec(),
VALID_CRYPTO_KINDS.to_vec(),
self.capabilities.clone(),
self.dial_info_details.clone()
);

View File

@@ -344,6 +344,7 @@ impl RoutingTable {
AddressTypeSet::all(), // Bootstraps are always IPV4 and IPV6 capable
bsrec.envelope_support, // Envelope support is as specified in the bootstrap list
crypto_support, // Crypto support is derived from list of node ids
vec![], // Bootstrap needs no capabilities
bsrec.dial_info_details, // Dial info is as specified in the bootstrap list
)));

View File

@@ -146,9 +146,9 @@ impl RoutingTable {
let entry2 = entry.clone();
entry.with(rti, |rti, e| {
// Ensure we have the node's status
if let Some(node_status) = e.node_status(routing_domain) {
if let Some(node_info) = e.node_info(routing_domain) {
// Ensure the node will relay
if node_status.has_capability(CAP_WILL_RELAY) {
if node_info.can_inbound_relay() {
// Compare against previous candidate
if let Some(best_inbound_relay) = best_inbound_relay.as_mut() {
// Less is faster

View File

@@ -100,6 +100,7 @@ pub async fn test_round_trip_peerinfo() {
AddressTypeSet::new(),
vec![0],
vec![CRYPTO_KIND_VLD0],
PUBLIC_INTERNET_CAPABILITIES.to_vec(),
vec![],
),
Timestamp::new(0),

View File

@@ -1,5 +1,54 @@
use super::*;
pub type Capability = FourCC;
pub const CAP_WILL_ROUTE: Capability = FourCC(*b"ROUT");
#[cfg(feature = "unstable-tunnels")]
pub const CAP_WILL_TUNNEL: Capability = FourCC(*b"TUNL");
pub const CAP_WILL_SIGNAL: Capability = FourCC(*b"SGNL");
pub const CAP_WILL_RELAY: Capability = FourCC(*b"RLAY");
pub const CAP_WILL_VALIDATE_DIAL_INFO: Capability = FourCC(*b"DIAL");
pub const CAP_WILL_DHT: Capability = FourCC(*b"DHTV");
pub const CAP_WILL_APPMESSAGE: Capability = FourCC(*b"APPM");
#[cfg(feature = "unstable-blockstore")]
pub const CAP_WILL_BLOCKSTORE: Capability = FourCC(*b"BLOC");
cfg_if! {
if #[cfg(all(feature = "unstable-blockstore", feature="unstable-tunnels"))] {
const PUBLIC_INTERNET_CAPABILITIES_LEN: usize = 8;
} else if #[cfg(any(feature = "unstable-blockstore", feature="unstable-tunnels"))] {
const PUBLIC_INTERNET_CAPABILITIES_LEN: usize = 7;
} else {
const PUBLIC_INTERNET_CAPABILITIES_LEN: usize = 6;
}
}
pub const PUBLIC_INTERNET_CAPABILITIES: [Capability; PUBLIC_INTERNET_CAPABILITIES_LEN] = [
CAP_WILL_ROUTE,
#[cfg(feature = "unstable-tunnels")]
CAP_WILL_TUNNEL,
CAP_WILL_SIGNAL,
CAP_WILL_RELAY,
CAP_WILL_VALIDATE_DIAL_INFO,
CAP_WILL_DHT,
CAP_WILL_APPMESSAGE,
#[cfg(feature = "unstable-blockstore")]
CAP_WILL_BLOCKSTORE,
];
#[cfg(feature = "unstable-blockstore")]
const LOCAL_NETWORK_CAPABILITIES_LEN: usize = 4;
#[cfg(not(feature = "unstable-blockstore"))]
const LOCAL_NETWORK_CAPABILITIES_LEN: usize = 3;
pub const LOCAL_NETWORK_CAPABILITIES: [Capability; LOCAL_NETWORK_CAPABILITIES_LEN] = [
CAP_WILL_RELAY,
CAP_WILL_DHT,
CAP_WILL_APPMESSAGE,
#[cfg(feature = "unstable-blockstore")]
CAP_WILL_BLOCKSTORE,
];
pub const MAX_CAPABILITIES: usize = 64;
#[derive(
Clone,
Default,
@@ -21,6 +70,7 @@ pub struct NodeInfo {
address_types: AddressTypeSet,
envelope_support: Vec<u8>,
crypto_support: Vec<CryptoKind>,
capabilities: Vec<Capability>,
dial_info_detail_list: Vec<DialInfoDetail>,
}
@@ -31,6 +81,7 @@ impl NodeInfo {
address_types: AddressTypeSet,
envelope_support: Vec<u8>,
crypto_support: Vec<CryptoKind>,
capabilities: Vec<Capability>,
dial_info_detail_list: Vec<DialInfoDetail>,
) -> Self {
Self {
@@ -39,6 +90,7 @@ impl NodeInfo {
address_types,
envelope_support,
crypto_support,
capabilities,
dial_info_detail_list,
}
}
@@ -58,6 +110,9 @@ impl NodeInfo {
pub fn crypto_support(&self) -> &[CryptoKind] {
&self.crypto_support
}
pub fn capabilities(&self) -> &[Capability] {
&self.capabilities
}
pub fn dial_info_detail_list(&self) -> &[DialInfoDetail] {
&self.dial_info_detail_list
}
@@ -144,8 +199,17 @@ impl NodeInfo {
false
}
fn has_capability(&self, cap: Capability) -> bool {
self.capabilities.contains(&cap)
}
/// Can this node assist with signalling? Yes but only if it doesn't require signalling, itself.
pub fn can_signal(&self) -> bool {
// Has capability?
if !self.has_capability(CAP_WILL_SIGNAL) {
return false;
}
// Must be inbound capable
if !matches!(self.network_class, NetworkClass::InboundCapable) {
return false;
@@ -161,13 +225,44 @@ impl NodeInfo {
/// Can this node relay be an inbound relay?
pub fn can_inbound_relay(&self) -> bool {
// Has capability?
if !self.has_capability(CAP_WILL_RELAY) {
return false;
}
// For now this is the same
self.can_signal()
}
/// Is this node capable of validating dial info
pub fn can_validate_dial_info(&self) -> bool {
// Has capability?
if !self.has_capability(CAP_WILL_VALIDATE_DIAL_INFO) {
return false;
}
// For now this is the same
self.can_signal()
}
/// Is this node capable of private routing
pub fn can_route(&self) -> bool {
self.has_capability(CAP_WILL_ROUTE)
}
/// Is this node capable of dht operations
pub fn can_dht(&self) -> bool {
self.has_capability(CAP_WILL_DHT)
}
/// Is this node capable of app_message and app_call
pub fn can_appmessage(&self) -> bool {
self.has_capability(CAP_WILL_APPMESSAGE)
}
/// Is this node capable of tunneling
#[cfg(feature = "unstable-tunnels")]
pub fn can_tunnel(&self) -> bool {
self.has_capability(CAP_WILL_TUNNEL)
}
/// Is this node capable of block storage
#[cfg(feature = "unstable-blockstore")]
pub fn can_blockstore(&self) -> bool {
self.has_capability(CAP_WILL_BLOCKSTORE)
}
}

View File

@@ -1,47 +1,9 @@
use super::*;
/// RoutingDomain-specific status for each node
/// is returned by the StatusA call
pub type Capability = FourCC;
pub const CAP_WILL_ROUTE: Capability = FourCC(*b"ROUT");
pub const CAP_WILL_TUNNEL: Capability = FourCC(*b"TUNL");
pub const CAP_WILL_SIGNAL: Capability = FourCC(*b"SGNL");
pub const CAP_WILL_RELAY: Capability = FourCC(*b"RLAY");
pub const CAP_WILL_VALIDATE_DIAL_INFO: Capability = FourCC(*b"DIAL");
pub const CAP_WILL_DHT: Capability = FourCC(*b"DHTV");
pub const CAP_WILL_APPMESSAGE: Capability = FourCC(*b"APPM");
pub const MAX_CAPABILITIES: usize = 64;
/// PublicInternet RoutingDomain Status
#[derive(
Clone, Debug, Default, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
)]
#[archive_attr(repr(C), derive(CheckBytes))]
pub struct PublicInternetNodeStatus {
pub capabilities: Vec<Capability>,
}
#[derive(
Clone, Debug, Default, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
)]
#[archive_attr(repr(C), derive(CheckBytes))]
pub struct LocalNetworkNodeStatus {
pub capabilities: Vec<Capability>,
}
/// Non-nodeinfo status for each node is returned by the StatusA call
#[derive(Clone, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
#[archive_attr(repr(u8), derive(CheckBytes))]
pub enum NodeStatus {
PublicInternet(PublicInternetNodeStatus),
LocalNetwork(LocalNetworkNodeStatus),
}
impl NodeStatus {
pub fn has_capability(&self, cap: Capability) -> bool {
match self {
NodeStatus::PublicInternet(pi) => pi.capabilities.contains(&cap),
NodeStatus::LocalNetwork(ln) => ln.capabilities.contains(&cap),
}
}
#[archive_attr(repr(C), derive(CheckBytes))]
pub struct NodeStatus {
// Reserved for expansion
}