more capability work
This commit is contained in:
@@ -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()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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> {
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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()
|
||||
);
|
||||
|
||||
|
@@ -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
|
||||
)));
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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),
|
||||
|
@@ -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)
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user