mirror of
https://gitlab.com/veilid/veilid.git
synced 2025-01-25 22:15:59 -05:00
Merge branch 'capability' into 'main'
Capability support for FindNode See merge request veilid/veilid!45
This commit is contained in:
commit
c682de9c27
@ -50,6 +50,7 @@ core:
|
|||||||
reverse_connection_receipt_time_ms: 5000
|
reverse_connection_receipt_time_ms: 5000
|
||||||
hole_punch_receipt_time_ms: 5000
|
hole_punch_receipt_time_ms: 5000
|
||||||
network_key_password: null
|
network_key_password: null
|
||||||
|
disable_capabilites: []
|
||||||
routing_table:
|
routing_table:
|
||||||
node_id: null
|
node_id: null
|
||||||
node_id_secret: null
|
node_id_secret: null
|
||||||
|
@ -189,6 +189,7 @@ network:
|
|||||||
reverse_connection_receipt_time_ms: 5000
|
reverse_connection_receipt_time_ms: 5000
|
||||||
hole_punch_receipt_time_ms: 5000
|
hole_punch_receipt_time_ms: 5000
|
||||||
network_key_password: null
|
network_key_password: null
|
||||||
|
disable_capabilites: []
|
||||||
node_id: null
|
node_id: null
|
||||||
node_id_secret: null
|
node_id_secret: null
|
||||||
bootstrap: ['bootstrap.veilid.net']
|
bootstrap: ['bootstrap.veilid.net']
|
||||||
|
@ -34,6 +34,7 @@ using TunnelID = UInt64; # Id for tunnels
|
|||||||
using CryptoKind = UInt32; # FOURCC code for cryptography type
|
using CryptoKind = UInt32; # FOURCC code for cryptography type
|
||||||
using ValueSeqNum = UInt32; # sequence numbers for values
|
using ValueSeqNum = UInt32; # sequence numbers for values
|
||||||
using Subkey = UInt32; # subkey index for dht
|
using Subkey = UInt32; # subkey index for dht
|
||||||
|
using Capability = UInt32; # FOURCC code for capability
|
||||||
|
|
||||||
struct TypedKey @0xe2d567a9f1e61b29 {
|
struct TypedKey @0xe2d567a9f1e61b29 {
|
||||||
kind @0 :CryptoKind;
|
kind @0 :CryptoKind;
|
||||||
@ -189,24 +190,8 @@ struct DialInfoDetail @0x96423aa1d67b74d8 {
|
|||||||
class @1 :DialInfoClass;
|
class @1 :DialInfoClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PublicInternetNodeStatus @0x9c9d7f1f12eb088f {
|
|
||||||
willRoute @0 :Bool;
|
|
||||||
willTunnel @1 :Bool;
|
|
||||||
willSignal @2 :Bool;
|
|
||||||
willRelay @3 :Bool;
|
|
||||||
willValidateDialInfo @4 :Bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LocalNetworkNodeStatus @0x957f5bfed2d0b5a5 {
|
|
||||||
willRelay @0 :Bool;
|
|
||||||
willValidateDialInfo @1 :Bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NodeStatus @0xd36b9e7a3bf3330d {
|
struct NodeStatus @0xd36b9e7a3bf3330d {
|
||||||
union {
|
# Reserved for non-nodeinfo status
|
||||||
publicInternet @0 :PublicInternetNodeStatus;
|
|
||||||
localNetwork @1 :LocalNetworkNodeStatus;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ProtocolTypeSet @0x82f12f55a1b73326 {
|
struct ProtocolTypeSet @0x82f12f55a1b73326 {
|
||||||
@ -231,7 +216,8 @@ struct NodeInfo @0xe125d847e3f9f419 {
|
|||||||
addressTypes @2 :AddressTypeSet; # address types supported
|
addressTypes @2 :AddressTypeSet; # address types supported
|
||||||
envelopeSupport @3 :List(UInt8); # supported rpc envelope/receipt versions
|
envelopeSupport @3 :List(UInt8); # supported rpc envelope/receipt versions
|
||||||
cryptoSupport @4 :List(CryptoKind); # cryptography systems supported
|
cryptoSupport @4 :List(CryptoKind); # cryptography systems supported
|
||||||
dialInfoDetailList @5 :List(DialInfoDetail); # inbound dial info details for this node
|
capabilities @5 :List(Capability); # capabilities supported by the node
|
||||||
|
dialInfoDetailList @6 :List(DialInfoDetail); # inbound dial info details for this node
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SignedDirectNodeInfo @0xe0e7ea3e893a3dd7 {
|
struct SignedDirectNodeInfo @0xe0e7ea3e893a3dd7 {
|
||||||
@ -288,6 +274,7 @@ struct OperationReturnReceipt @0xeb0fb5b5a9160eeb {
|
|||||||
|
|
||||||
struct OperationFindNodeQ @0xfdef788fe9623bcd {
|
struct OperationFindNodeQ @0xfdef788fe9623bcd {
|
||||||
nodeId @0 :TypedKey; # node id to locate
|
nodeId @0 :TypedKey; # node id to locate
|
||||||
|
capabilities @1 :List(Capability); # required capabilities returned peers must have
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OperationFindNodeA @0xa84cf2fb40c77089 {
|
struct OperationFindNodeA @0xa84cf2fb40c77089 {
|
||||||
|
@ -4,7 +4,7 @@ use data_encoding::BASE64URL_NOPAD;
|
|||||||
use digest::Digest;
|
use digest::Digest;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
const AEAD_OVERHEAD: usize = PUBLIC_KEY_LENGTH;
|
const AEAD_OVERHEAD: usize = PUBLIC_KEY_LENGTH;
|
||||||
pub const CRYPTO_KIND_NONE: CryptoKind = FourCC([b'N', b'O', b'N', b'E']);
|
pub const CRYPTO_KIND_NONE: CryptoKind = FourCC(*b"NONE");
|
||||||
|
|
||||||
pub fn none_generate_keypair() -> KeyPair {
|
pub fn none_generate_keypair() -> KeyPair {
|
||||||
let mut csprng = VeilidRng {};
|
let mut csprng = VeilidRng {};
|
||||||
|
@ -15,7 +15,7 @@ use ed25519_dalek as ed;
|
|||||||
use x25519_dalek as xd;
|
use x25519_dalek as xd;
|
||||||
|
|
||||||
const AEAD_OVERHEAD: usize = 16;
|
const AEAD_OVERHEAD: usize = 16;
|
||||||
pub const CRYPTO_KIND_VLD0: CryptoKind = FourCC([b'V', b'L', b'D', b'0']);
|
pub const CRYPTO_KIND_VLD0: CryptoKind = FourCC(*b"VLD0");
|
||||||
|
|
||||||
fn ed25519_to_x25519_pk(key: &ed::PublicKey) -> VeilidAPIResult<xd::PublicKey> {
|
fn ed25519_to_x25519_pk(key: &ed::PublicKey) -> VeilidAPIResult<xd::PublicKey> {
|
||||||
let bytes = key.to_bytes();
|
let bytes = key.to_bytes();
|
||||||
|
@ -115,6 +115,7 @@ impl AddressFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for key in dead_keys {
|
for key in dead_keys {
|
||||||
|
log_net!(debug ">>> FORGIVING: {}", key);
|
||||||
inner.punishments_by_ip4.remove(&key);
|
inner.punishments_by_ip4.remove(&key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,6 +131,7 @@ impl AddressFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for key in dead_keys {
|
for key in dead_keys {
|
||||||
|
log_net!(debug ">>> FORGIVING: {}", key);
|
||||||
inner.punishments_by_ip6_prefix.remove(&key);
|
inner.punishments_by_ip6_prefix.remove(&key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,31 +5,31 @@ mod native;
|
|||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
mod wasm;
|
mod wasm;
|
||||||
|
|
||||||
mod direct_boot;
|
|
||||||
mod send_data;
|
|
||||||
mod connection_handle;
|
|
||||||
mod address_filter;
|
mod address_filter;
|
||||||
|
mod connection_handle;
|
||||||
mod connection_manager;
|
mod connection_manager;
|
||||||
mod connection_table;
|
mod connection_table;
|
||||||
|
mod direct_boot;
|
||||||
mod network_connection;
|
mod network_connection;
|
||||||
|
mod send_data;
|
||||||
|
mod stats;
|
||||||
mod tasks;
|
mod tasks;
|
||||||
mod types;
|
mod types;
|
||||||
mod stats;
|
|
||||||
|
|
||||||
pub mod tests;
|
pub mod tests;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
pub use connection_manager::*;
|
pub use connection_manager::*;
|
||||||
pub use network_connection::*;
|
|
||||||
pub use types::*;
|
|
||||||
pub use send_data::*;
|
|
||||||
pub use direct_boot::*;
|
pub use direct_boot::*;
|
||||||
|
pub use network_connection::*;
|
||||||
|
pub use send_data::*;
|
||||||
pub use stats::*;
|
pub use stats::*;
|
||||||
|
pub use types::*;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
use connection_handle::*;
|
|
||||||
use address_filter::*;
|
use address_filter::*;
|
||||||
|
use connection_handle::*;
|
||||||
use crypto::*;
|
use crypto::*;
|
||||||
use futures_util::stream::FuturesUnordered;
|
use futures_util::stream::FuturesUnordered;
|
||||||
use hashlink::LruCache;
|
use hashlink::LruCache;
|
||||||
@ -47,13 +47,16 @@ use wasm::*;
|
|||||||
|
|
||||||
pub const MAX_MESSAGE_SIZE: usize = MAX_ENVELOPE_SIZE;
|
pub const MAX_MESSAGE_SIZE: usize = MAX_ENVELOPE_SIZE;
|
||||||
pub const IPADDR_TABLE_SIZE: usize = 1024;
|
pub const IPADDR_TABLE_SIZE: usize = 1024;
|
||||||
pub const IPADDR_MAX_INACTIVE_DURATION_US: TimestampDuration = TimestampDuration::new(300_000_000u64); // 5 minutes
|
pub const IPADDR_MAX_INACTIVE_DURATION_US: TimestampDuration =
|
||||||
|
TimestampDuration::new(300_000_000u64); // 5 minutes
|
||||||
pub const NODE_CONTACT_METHOD_CACHE_SIZE: usize = 1024;
|
pub const NODE_CONTACT_METHOD_CACHE_SIZE: usize = 1024;
|
||||||
pub const PUBLIC_ADDRESS_CHANGE_DETECTION_COUNT: usize = 3;
|
pub const PUBLIC_ADDRESS_CHANGE_DETECTION_COUNT: usize = 3;
|
||||||
pub const PUBLIC_ADDRESS_CHECK_CACHE_SIZE: usize = 8;
|
pub const PUBLIC_ADDRESS_CHECK_CACHE_SIZE: usize = 8;
|
||||||
pub const PUBLIC_ADDRESS_CHECK_TASK_INTERVAL_SECS: u32 = 60;
|
pub const PUBLIC_ADDRESS_CHECK_TASK_INTERVAL_SECS: u32 = 60;
|
||||||
pub const PUBLIC_ADDRESS_INCONSISTENCY_TIMEOUT_US: TimestampDuration = TimestampDuration::new(300_000_000u64); // 5 minutes
|
pub const PUBLIC_ADDRESS_INCONSISTENCY_TIMEOUT_US: TimestampDuration =
|
||||||
pub const PUBLIC_ADDRESS_INCONSISTENCY_PUNISHMENT_TIMEOUT_US: TimestampDuration = TimestampDuration::new(3600_000_000u64); // 60 minutes
|
TimestampDuration::new(300_000_000u64); // 5 minutes
|
||||||
|
pub const PUBLIC_ADDRESS_INCONSISTENCY_PUNISHMENT_TIMEOUT_US: TimestampDuration =
|
||||||
|
TimestampDuration::new(3600_000_000u64); // 60 minutes
|
||||||
pub const ADDRESS_FILTER_TASK_INTERVAL_SECS: u32 = 60;
|
pub const ADDRESS_FILTER_TASK_INTERVAL_SECS: u32 = 60;
|
||||||
pub const BOOT_MAGIC: &[u8; 4] = b"BOOT";
|
pub const BOOT_MAGIC: &[u8; 4] = b"BOOT";
|
||||||
|
|
||||||
@ -75,7 +78,6 @@ struct NetworkComponents {
|
|||||||
receipt_manager: ReceiptManager,
|
receipt_manager: ReceiptManager,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct ClientWhitelistEntry {
|
struct ClientWhitelistEntry {
|
||||||
last_seen_ts: Timestamp,
|
last_seen_ts: Timestamp,
|
||||||
@ -134,7 +136,7 @@ struct NetworkManagerUnlockedInner {
|
|||||||
storage_manager: StorageManager,
|
storage_manager: StorageManager,
|
||||||
protected_store: ProtectedStore,
|
protected_store: ProtectedStore,
|
||||||
table_store: TableStore,
|
table_store: TableStore,
|
||||||
#[cfg(feature="unstable-blockstore")]
|
#[cfg(feature = "unstable-blockstore")]
|
||||||
block_store: BlockStore,
|
block_store: BlockStore,
|
||||||
crypto: Crypto,
|
crypto: Crypto,
|
||||||
address_filter: AddressFilter,
|
address_filter: AddressFilter,
|
||||||
@ -171,8 +173,7 @@ impl NetworkManager {
|
|||||||
storage_manager: StorageManager,
|
storage_manager: StorageManager,
|
||||||
protected_store: ProtectedStore,
|
protected_store: ProtectedStore,
|
||||||
table_store: TableStore,
|
table_store: TableStore,
|
||||||
#[cfg(feature="unstable-blockstore")]
|
#[cfg(feature = "unstable-blockstore")] block_store: BlockStore,
|
||||||
block_store: BlockStore,
|
|
||||||
crypto: Crypto,
|
crypto: Crypto,
|
||||||
network_key: Option<SharedSecret>,
|
network_key: Option<SharedSecret>,
|
||||||
) -> NetworkManagerUnlockedInner {
|
) -> NetworkManagerUnlockedInner {
|
||||||
@ -181,7 +182,7 @@ impl NetworkManager {
|
|||||||
storage_manager,
|
storage_manager,
|
||||||
protected_store,
|
protected_store,
|
||||||
table_store,
|
table_store,
|
||||||
#[cfg(feature="unstable-blockstore")]
|
#[cfg(feature = "unstable-blockstore")]
|
||||||
block_store,
|
block_store,
|
||||||
crypto,
|
crypto,
|
||||||
address_filter: AddressFilter::new(config),
|
address_filter: AddressFilter::new(config),
|
||||||
@ -200,18 +201,20 @@ impl NetworkManager {
|
|||||||
storage_manager: StorageManager,
|
storage_manager: StorageManager,
|
||||||
protected_store: ProtectedStore,
|
protected_store: ProtectedStore,
|
||||||
table_store: TableStore,
|
table_store: TableStore,
|
||||||
#[cfg(feature="unstable-blockstore")]
|
#[cfg(feature = "unstable-blockstore")] block_store: BlockStore,
|
||||||
block_store: BlockStore,
|
|
||||||
crypto: Crypto,
|
crypto: Crypto,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
|
||||||
// Make the network key
|
// Make the network key
|
||||||
let network_key = {
|
let network_key = {
|
||||||
let c = config.get();
|
let c = config.get();
|
||||||
let network_key_password = if let Some(nkp) = c.network.network_key_password.clone() {
|
let network_key_password = if let Some(nkp) = c.network.network_key_password.clone() {
|
||||||
Some(nkp)
|
Some(nkp)
|
||||||
} else {
|
} else {
|
||||||
if c.network.routing_table.bootstrap.contains(&"bootstrap.veilid.net".to_owned()) {
|
if c.network
|
||||||
|
.routing_table
|
||||||
|
.bootstrap
|
||||||
|
.contains(&"bootstrap.veilid.net".to_owned())
|
||||||
|
{
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(c.network.routing_table.bootstrap.join(","))
|
Some(c.network.routing_table.bootstrap.join(","))
|
||||||
@ -224,7 +227,13 @@ impl NetworkManager {
|
|||||||
|
|
||||||
let bcs = crypto.best();
|
let bcs = crypto.best();
|
||||||
// Yes the use of the salt this way is generally bad, but this just needs to be hashed
|
// Yes the use of the salt this way is generally bad, but this just needs to be hashed
|
||||||
Some(bcs.derive_shared_secret(network_key_password.as_bytes(), network_key_password.as_bytes()).expect("failed to derive network key"))
|
Some(
|
||||||
|
bcs.derive_shared_secret(
|
||||||
|
network_key_password.as_bytes(),
|
||||||
|
network_key_password.as_bytes(),
|
||||||
|
)
|
||||||
|
.expect("failed to derive network key"),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -242,7 +251,7 @@ impl NetworkManager {
|
|||||||
storage_manager,
|
storage_manager,
|
||||||
protected_store,
|
protected_store,
|
||||||
table_store,
|
table_store,
|
||||||
#[cfg(feature="unstable-blockstore")]
|
#[cfg(feature = "unstable-blockstore")]
|
||||||
block_store,
|
block_store,
|
||||||
crypto,
|
crypto,
|
||||||
network_key,
|
network_key,
|
||||||
@ -271,7 +280,7 @@ impl NetworkManager {
|
|||||||
pub fn table_store(&self) -> TableStore {
|
pub fn table_store(&self) -> TableStore {
|
||||||
self.unlocked_inner.table_store.clone()
|
self.unlocked_inner.table_store.clone()
|
||||||
}
|
}
|
||||||
#[cfg(feature="unstable-blockstore")]
|
#[cfg(feature = "unstable-blockstore")]
|
||||||
pub fn block_store(&self) -> BlockStore {
|
pub fn block_store(&self) -> BlockStore {
|
||||||
self.unlocked_inner.block_store.clone()
|
self.unlocked_inner.block_store.clone()
|
||||||
}
|
}
|
||||||
@ -443,7 +452,7 @@ impl NetworkManager {
|
|||||||
|
|
||||||
pub fn update_client_whitelist(&self, client: TypedKey) {
|
pub fn update_client_whitelist(&self, client: TypedKey) {
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
match inner.client_whitelist.entry(client, |_k,_v| {
|
match inner.client_whitelist.entry(client, |_k, _v| {
|
||||||
// do nothing on LRU evict
|
// do nothing on LRU evict
|
||||||
}) {
|
}) {
|
||||||
hashlink::lru_cache::Entry::Occupied(mut entry) => {
|
hashlink::lru_cache::Entry::Occupied(mut entry) => {
|
||||||
@ -461,7 +470,7 @@ impl NetworkManager {
|
|||||||
pub fn check_client_whitelist(&self, client: TypedKey) -> bool {
|
pub fn check_client_whitelist(&self, client: TypedKey) -> bool {
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
|
|
||||||
match inner.client_whitelist.entry(client, |_k,_v| {
|
match inner.client_whitelist.entry(client, |_k, _v| {
|
||||||
// do nothing on LRU evict
|
// do nothing on LRU evict
|
||||||
}) {
|
}) {
|
||||||
hashlink::lru_cache::Entry::Occupied(mut entry) => {
|
hashlink::lru_cache::Entry::Occupied(mut entry) => {
|
||||||
@ -475,7 +484,8 @@ impl NetworkManager {
|
|||||||
pub fn purge_client_whitelist(&self) {
|
pub fn purge_client_whitelist(&self) {
|
||||||
let timeout_ms = self.with_config(|c| c.network.client_whitelist_timeout_ms);
|
let timeout_ms = self.with_config(|c| c.network.client_whitelist_timeout_ms);
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
let cutoff_timestamp = get_aligned_timestamp() - TimestampDuration::new((timeout_ms as u64) * 1000u64);
|
let cutoff_timestamp =
|
||||||
|
get_aligned_timestamp() - TimestampDuration::new((timeout_ms as u64) * 1000u64);
|
||||||
// Remove clients from the whitelist that haven't been since since our whitelist timeout
|
// Remove clients from the whitelist that haven't been since since our whitelist timeout
|
||||||
while inner
|
while inner
|
||||||
.client_whitelist
|
.client_whitelist
|
||||||
@ -493,66 +503,8 @@ impl NetworkManager {
|
|||||||
net.needs_restart()
|
net.needs_restart()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get our node's capabilities in the PublicInternet routing domain
|
pub fn generate_node_status(&self, _routing_domain: RoutingDomain) -> NodeStatus {
|
||||||
fn generate_public_internet_node_status(&self) -> PublicInternetNodeStatus {
|
NodeStatus {}
|
||||||
let Some(own_peer_info) = self
|
|
||||||
.routing_table()
|
|
||||||
.get_own_peer_info(RoutingDomain::PublicInternet) else {
|
|
||||||
return PublicInternetNodeStatus {
|
|
||||||
will_route: false,
|
|
||||||
will_tunnel: false,
|
|
||||||
will_signal: false,
|
|
||||||
will_relay: false,
|
|
||||||
will_validate_dial_info: false,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
let own_node_info = own_peer_info.signed_node_info().node_info();
|
|
||||||
|
|
||||||
let will_route = own_node_info.can_inbound_relay(); // xxx: eventually this may have more criteria added
|
|
||||||
let will_tunnel = own_node_info.can_inbound_relay(); // xxx: we may want to restrict by battery life and network bandwidth at some point
|
|
||||||
let will_signal = own_node_info.can_signal();
|
|
||||||
let will_relay = own_node_info.can_inbound_relay();
|
|
||||||
let will_validate_dial_info = own_node_info.can_validate_dial_info();
|
|
||||||
|
|
||||||
PublicInternetNodeStatus {
|
|
||||||
will_route,
|
|
||||||
will_tunnel,
|
|
||||||
will_signal,
|
|
||||||
will_relay,
|
|
||||||
will_validate_dial_info,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// Get our node's capabilities in the LocalNetwork routing domain
|
|
||||||
fn generate_local_network_node_status(&self) -> LocalNetworkNodeStatus {
|
|
||||||
let Some(own_peer_info) = self
|
|
||||||
.routing_table()
|
|
||||||
.get_own_peer_info(RoutingDomain::LocalNetwork) else {
|
|
||||||
return LocalNetworkNodeStatus {
|
|
||||||
will_relay: false,
|
|
||||||
will_validate_dial_info: false,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
let own_node_info = own_peer_info.signed_node_info().node_info();
|
|
||||||
|
|
||||||
let will_relay = own_node_info.can_inbound_relay();
|
|
||||||
let will_validate_dial_info = own_node_info.can_validate_dial_info();
|
|
||||||
|
|
||||||
LocalNetworkNodeStatus {
|
|
||||||
will_relay,
|
|
||||||
will_validate_dial_info,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn generate_node_status(&self, routing_domain: RoutingDomain) -> NodeStatus {
|
|
||||||
match routing_domain {
|
|
||||||
RoutingDomain::PublicInternet => {
|
|
||||||
NodeStatus::PublicInternet(self.generate_public_internet_node_status())
|
|
||||||
}
|
|
||||||
RoutingDomain::LocalNetwork => {
|
|
||||||
NodeStatus::LocalNetwork(self.generate_local_network_node_status())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates a multi-shot/normal receipt
|
/// Generates a multi-shot/normal receipt
|
||||||
@ -574,7 +526,13 @@ impl NetworkManager {
|
|||||||
let node_id = routing_table.node_id(vcrypto.kind());
|
let node_id = routing_table.node_id(vcrypto.kind());
|
||||||
let node_id_secret = routing_table.node_id_secret_key(vcrypto.kind());
|
let node_id_secret = routing_table.node_id_secret_key(vcrypto.kind());
|
||||||
|
|
||||||
let receipt = Receipt::try_new(best_envelope_version(), node_id.kind, nonce, node_id.value, extra_data)?;
|
let receipt = Receipt::try_new(
|
||||||
|
best_envelope_version(),
|
||||||
|
node_id.kind,
|
||||||
|
nonce,
|
||||||
|
node_id.value,
|
||||||
|
extra_data,
|
||||||
|
)?;
|
||||||
let out = receipt
|
let out = receipt
|
||||||
.to_signed_data(self.crypto(), &node_id_secret)
|
.to_signed_data(self.crypto(), &node_id_secret)
|
||||||
.wrap_err("failed to generate signed receipt")?;
|
.wrap_err("failed to generate signed receipt")?;
|
||||||
@ -603,7 +561,13 @@ impl NetworkManager {
|
|||||||
let node_id = routing_table.node_id(vcrypto.kind());
|
let node_id = routing_table.node_id(vcrypto.kind());
|
||||||
let node_id_secret = routing_table.node_id_secret_key(vcrypto.kind());
|
let node_id_secret = routing_table.node_id_secret_key(vcrypto.kind());
|
||||||
|
|
||||||
let receipt = Receipt::try_new(best_envelope_version(), node_id.kind, nonce, node_id.value, extra_data)?;
|
let receipt = Receipt::try_new(
|
||||||
|
best_envelope_version(),
|
||||||
|
node_id.kind,
|
||||||
|
nonce,
|
||||||
|
node_id.value,
|
||||||
|
extra_data,
|
||||||
|
)?;
|
||||||
let out = receipt
|
let out = receipt
|
||||||
.to_signed_data(self.crypto(), &node_id_secret)
|
.to_signed_data(self.crypto(), &node_id_secret)
|
||||||
.wrap_err("failed to generate signed receipt")?;
|
.wrap_err("failed to generate signed receipt")?;
|
||||||
@ -715,9 +679,10 @@ impl NetworkManager {
|
|||||||
) {
|
) {
|
||||||
Ok(nr) => nr,
|
Ok(nr) => nr,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Ok(NetworkResult::invalid_message(
|
return Ok(NetworkResult::invalid_message(format!(
|
||||||
format!("unable to register reverse connect peerinfo: {}", e)
|
"unable to register reverse connect peerinfo: {}",
|
||||||
));
|
e
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -738,9 +703,10 @@ impl NetworkManager {
|
|||||||
) {
|
) {
|
||||||
Ok(nr) => nr,
|
Ok(nr) => nr,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Ok(NetworkResult::invalid_message(
|
return Ok(NetworkResult::invalid_message(format!(
|
||||||
format!("unable to register hole punch connect peerinfo: {}", e)
|
"unable to register hole punch connect peerinfo: {}",
|
||||||
));
|
e
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -784,7 +750,10 @@ impl NetworkManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Builds an envelope for sending over the network
|
/// Builds an envelope for sending over the network
|
||||||
#[cfg_attr(feature="verbose-tracing", instrument(level = "trace", skip(self, body), err))]
|
#[cfg_attr(
|
||||||
|
feature = "verbose-tracing",
|
||||||
|
instrument(level = "trace", skip(self, body), err)
|
||||||
|
)]
|
||||||
fn build_envelope<B: AsRef<[u8]>>(
|
fn build_envelope<B: AsRef<[u8]>>(
|
||||||
&self,
|
&self,
|
||||||
dest_node_id: TypedKey,
|
dest_node_id: TypedKey,
|
||||||
@ -805,9 +774,21 @@ impl NetworkManager {
|
|||||||
let nonce = vcrypto.random_nonce();
|
let nonce = vcrypto.random_nonce();
|
||||||
|
|
||||||
// Encode envelope
|
// Encode envelope
|
||||||
let envelope = Envelope::new(version, node_id.kind, ts, nonce, node_id.value, dest_node_id.value);
|
let envelope = Envelope::new(
|
||||||
|
version,
|
||||||
|
node_id.kind,
|
||||||
|
ts,
|
||||||
|
nonce,
|
||||||
|
node_id.value,
|
||||||
|
dest_node_id.value,
|
||||||
|
);
|
||||||
envelope
|
envelope
|
||||||
.to_encrypted_data(self.crypto(), body.as_ref(), &node_id_secret, &self.unlocked_inner.network_key)
|
.to_encrypted_data(
|
||||||
|
self.crypto(),
|
||||||
|
body.as_ref(),
|
||||||
|
&node_id_secret,
|
||||||
|
&self.unlocked_inner.network_key,
|
||||||
|
)
|
||||||
.wrap_err("envelope failed to encode")
|
.wrap_err("envelope failed to encode")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -815,14 +796,16 @@ impl NetworkManager {
|
|||||||
/// node_ref is the direct destination to which the envelope will be sent
|
/// node_ref is the direct destination to which the envelope will be sent
|
||||||
/// If 'destination_node_ref' is specified, it can be different than the node_ref being sent to
|
/// If 'destination_node_ref' is specified, it can be different than the node_ref being sent to
|
||||||
/// which will cause the envelope to be relayed
|
/// which will cause the envelope to be relayed
|
||||||
#[cfg_attr(feature="verbose-tracing", instrument(level = "trace", skip(self, body), ret, err))]
|
#[cfg_attr(
|
||||||
|
feature = "verbose-tracing",
|
||||||
|
instrument(level = "trace", skip(self, body), ret, err)
|
||||||
|
)]
|
||||||
pub async fn send_envelope<B: AsRef<[u8]>>(
|
pub async fn send_envelope<B: AsRef<[u8]>>(
|
||||||
&self,
|
&self,
|
||||||
node_ref: NodeRef,
|
node_ref: NodeRef,
|
||||||
destination_node_ref: Option<NodeRef>,
|
destination_node_ref: Option<NodeRef>,
|
||||||
body: B,
|
body: B,
|
||||||
) -> EyreResult<NetworkResult<SendDataKind>> {
|
) -> EyreResult<NetworkResult<SendDataKind>> {
|
||||||
|
|
||||||
let destination_node_ref = destination_node_ref.as_ref().unwrap_or(&node_ref).clone();
|
let destination_node_ref = destination_node_ref.as_ref().unwrap_or(&node_ref).clone();
|
||||||
|
|
||||||
if !node_ref.same_entry(&destination_node_ref) {
|
if !node_ref.same_entry(&destination_node_ref) {
|
||||||
@ -886,7 +869,7 @@ impl NetworkManager {
|
|||||||
data: &mut [u8],
|
data: &mut [u8],
|
||||||
connection_descriptor: ConnectionDescriptor,
|
connection_descriptor: ConnectionDescriptor,
|
||||||
) -> EyreResult<bool> {
|
) -> EyreResult<bool> {
|
||||||
#[cfg(feature="verbose-tracing")]
|
#[cfg(feature = "verbose-tracing")]
|
||||||
let root = span!(
|
let root = span!(
|
||||||
parent: None,
|
parent: None,
|
||||||
Level::TRACE,
|
Level::TRACE,
|
||||||
@ -894,7 +877,7 @@ impl NetworkManager {
|
|||||||
"data.len" = data.len(),
|
"data.len" = data.len(),
|
||||||
"descriptor" = ?connection_descriptor
|
"descriptor" = ?connection_descriptor
|
||||||
);
|
);
|
||||||
#[cfg(feature="verbose-tracing")]
|
#[cfg(feature = "verbose-tracing")]
|
||||||
let _root_enter = root.enter();
|
let _root_enter = root.enter();
|
||||||
|
|
||||||
log_net!(
|
log_net!(
|
||||||
@ -905,10 +888,7 @@ impl NetworkManager {
|
|||||||
let remote_addr = connection_descriptor.remote_address().to_ip_addr();
|
let remote_addr = connection_descriptor.remote_address().to_ip_addr();
|
||||||
|
|
||||||
// Network accounting
|
// Network accounting
|
||||||
self.stats_packet_rcvd(
|
self.stats_packet_rcvd(remote_addr, ByteCount::new(data.len() as u64));
|
||||||
remote_addr,
|
|
||||||
ByteCount::new(data.len() as u64),
|
|
||||||
);
|
|
||||||
|
|
||||||
// If this is a zero length packet, just drop it, because these are used for hole punching
|
// If this is a zero length packet, just drop it, because these are used for hole punching
|
||||||
// and possibly other low-level network connectivity tasks and will never require
|
// and possibly other low-level network connectivity tasks and will never require
|
||||||
@ -949,7 +929,9 @@ impl NetworkManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decode envelope header (may fail signature validation)
|
// Decode envelope header (may fail signature validation)
|
||||||
let envelope = match Envelope::from_signed_data(self.crypto(), data, &self.unlocked_inner.network_key) {
|
let envelope =
|
||||||
|
match Envelope::from_signed_data(self.crypto(), data, &self.unlocked_inner.network_key)
|
||||||
|
{
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log_net!(debug "envelope failed to decode: {}", e);
|
log_net!(debug "envelope failed to decode: {}", e);
|
||||||
@ -961,8 +943,16 @@ impl NetworkManager {
|
|||||||
// Get timestamp range
|
// Get timestamp range
|
||||||
let (tsbehind, tsahead) = self.with_config(|c| {
|
let (tsbehind, tsahead) = self.with_config(|c| {
|
||||||
(
|
(
|
||||||
c.network.rpc.max_timestamp_behind_ms.map(ms_to_us).map(TimestampDuration::new),
|
c.network
|
||||||
c.network.rpc.max_timestamp_ahead_ms.map(ms_to_us).map(TimestampDuration::new),
|
.rpc
|
||||||
|
.max_timestamp_behind_ms
|
||||||
|
.map(ms_to_us)
|
||||||
|
.map(TimestampDuration::new),
|
||||||
|
c.network
|
||||||
|
.rpc
|
||||||
|
.max_timestamp_ahead_ms
|
||||||
|
.map(ms_to_us)
|
||||||
|
.map(TimestampDuration::new),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1005,7 +995,10 @@ impl NetworkManager {
|
|||||||
|
|
||||||
let some_relay_nr = if self.check_client_whitelist(sender_id) {
|
let some_relay_nr = if self.check_client_whitelist(sender_id) {
|
||||||
// Full relay allowed, do a full resolve_node
|
// Full relay allowed, do a full resolve_node
|
||||||
match rpc.resolve_node(recipient_id, SafetySelection::Unsafe(Sequencing::default())).await {
|
match rpc
|
||||||
|
.resolve_node(recipient_id, SafetySelection::Unsafe(Sequencing::default()))
|
||||||
|
.await
|
||||||
|
{
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log_net!(debug "failed to resolve recipient node for relay, dropping outbound relayed packet: {}" ,e);
|
log_net!(debug "failed to resolve recipient node for relay, dropping outbound relayed packet: {}" ,e);
|
||||||
@ -1064,8 +1057,12 @@ impl NetworkManager {
|
|||||||
let node_id_secret = routing_table.node_id_secret_key(envelope.get_crypto_kind());
|
let node_id_secret = routing_table.node_id_secret_key(envelope.get_crypto_kind());
|
||||||
|
|
||||||
// Decrypt the envelope body
|
// Decrypt the envelope body
|
||||||
let body = match envelope
|
let body = match envelope.decrypt_body(
|
||||||
.decrypt_body(self.crypto(), data, &node_id_secret, &self.unlocked_inner.network_key) {
|
self.crypto(),
|
||||||
|
data,
|
||||||
|
&node_id_secret,
|
||||||
|
&self.unlocked_inner.network_key,
|
||||||
|
) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log_net!(debug "failed to decrypt envelope body: {}",e);
|
log_net!(debug "failed to decrypt envelope body: {}",e);
|
||||||
@ -1166,7 +1163,7 @@ impl NetworkManager {
|
|||||||
if pait.contains_key(&ipblock) {
|
if pait.contains_key(&ipblock) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pacc.insert(ipblock, socket_address, |_k,_v| {
|
pacc.insert(ipblock, socket_address, |_k, _v| {
|
||||||
// do nothing on LRU evict
|
// do nothing on LRU evict
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1224,8 +1221,8 @@ impl NetworkManager {
|
|||||||
.public_address_inconsistencies_table
|
.public_address_inconsistencies_table
|
||||||
.entry(key)
|
.entry(key)
|
||||||
.or_insert_with(|| HashMap::new());
|
.or_insert_with(|| HashMap::new());
|
||||||
let exp_ts =
|
let exp_ts = get_aligned_timestamp()
|
||||||
get_aligned_timestamp() + PUBLIC_ADDRESS_INCONSISTENCY_PUNISHMENT_TIMEOUT_US;
|
+ PUBLIC_ADDRESS_INCONSISTENCY_PUNISHMENT_TIMEOUT_US;
|
||||||
for i in inconsistencies {
|
for i in inconsistencies {
|
||||||
pait.insert(i, exp_ts);
|
pait.insert(i, exp_ts);
|
||||||
}
|
}
|
||||||
@ -1296,5 +1293,4 @@ impl NetworkManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -686,30 +686,30 @@ impl Network {
|
|||||||
let c = self.config.get();
|
let c = self.config.get();
|
||||||
let mut inbound = ProtocolTypeSet::new();
|
let mut inbound = ProtocolTypeSet::new();
|
||||||
|
|
||||||
if c.network.protocol.udp.enabled && c.capabilities.protocol_udp {
|
if c.network.protocol.udp.enabled {
|
||||||
inbound.insert(ProtocolType::UDP);
|
inbound.insert(ProtocolType::UDP);
|
||||||
}
|
}
|
||||||
if c.network.protocol.tcp.listen && c.capabilities.protocol_accept_tcp {
|
if c.network.protocol.tcp.listen {
|
||||||
inbound.insert(ProtocolType::TCP);
|
inbound.insert(ProtocolType::TCP);
|
||||||
}
|
}
|
||||||
if c.network.protocol.ws.listen && c.capabilities.protocol_accept_ws {
|
if c.network.protocol.ws.listen {
|
||||||
inbound.insert(ProtocolType::WS);
|
inbound.insert(ProtocolType::WS);
|
||||||
}
|
}
|
||||||
if c.network.protocol.wss.listen && c.capabilities.protocol_accept_wss {
|
if c.network.protocol.wss.listen {
|
||||||
inbound.insert(ProtocolType::WSS);
|
inbound.insert(ProtocolType::WSS);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut outbound = ProtocolTypeSet::new();
|
let mut outbound = ProtocolTypeSet::new();
|
||||||
if c.network.protocol.udp.enabled && c.capabilities.protocol_udp {
|
if c.network.protocol.udp.enabled {
|
||||||
outbound.insert(ProtocolType::UDP);
|
outbound.insert(ProtocolType::UDP);
|
||||||
}
|
}
|
||||||
if c.network.protocol.tcp.connect && c.capabilities.protocol_connect_tcp {
|
if c.network.protocol.tcp.connect {
|
||||||
outbound.insert(ProtocolType::TCP);
|
outbound.insert(ProtocolType::TCP);
|
||||||
}
|
}
|
||||||
if c.network.protocol.ws.connect && c.capabilities.protocol_connect_ws {
|
if c.network.protocol.ws.connect {
|
||||||
outbound.insert(ProtocolType::WS);
|
outbound.insert(ProtocolType::WS);
|
||||||
}
|
}
|
||||||
if c.network.protocol.wss.connect && c.capabilities.protocol_connect_wss {
|
if c.network.protocol.wss.connect {
|
||||||
outbound.insert(ProtocolType::WSS);
|
outbound.insert(ProtocolType::WSS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -773,16 +773,34 @@ impl Network {
|
|||||||
|
|
||||||
// set up the routing table's network config
|
// set up the routing table's network config
|
||||||
// if we have static public dialinfo, upgrade our network class
|
// if we have static public dialinfo, upgrade our network class
|
||||||
|
let public_internet_capabilities = {
|
||||||
|
let c = self.config.get();
|
||||||
|
PUBLIC_INTERNET_CAPABILITIES
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.filter(|cap| !c.capabilities.disable.contains(cap))
|
||||||
|
.collect::<Vec<Capability>>()
|
||||||
|
};
|
||||||
|
let local_network_capabilities = {
|
||||||
|
let c = self.config.get();
|
||||||
|
LOCAL_NETWORK_CAPABILITIES
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.filter(|cap| !c.capabilities.disable.contains(cap))
|
||||||
|
.collect::<Vec<Capability>>()
|
||||||
|
};
|
||||||
|
|
||||||
editor_public_internet.setup_network(
|
editor_public_internet.setup_network(
|
||||||
protocol_config.outbound,
|
protocol_config.outbound,
|
||||||
protocol_config.inbound,
|
protocol_config.inbound,
|
||||||
protocol_config.family_global,
|
protocol_config.family_global,
|
||||||
|
public_internet_capabilities,
|
||||||
);
|
);
|
||||||
editor_local_network.setup_network(
|
editor_local_network.setup_network(
|
||||||
protocol_config.outbound,
|
protocol_config.outbound,
|
||||||
protocol_config.inbound,
|
protocol_config.inbound,
|
||||||
protocol_config.family_local,
|
protocol_config.family_local,
|
||||||
|
local_network_capabilities,
|
||||||
);
|
);
|
||||||
let detect_address_changes = {
|
let detect_address_changes = {
|
||||||
let c = self.config.get();
|
let c = self.config.get();
|
||||||
|
@ -118,8 +118,8 @@ impl Network {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let address_filter = self.network_manager().address_filter();
|
|
||||||
// Check to see if it is punished
|
// Check to see if it is punished
|
||||||
|
let address_filter = self.network_manager().address_filter();
|
||||||
if address_filter.is_punished(peer_addr.ip()) {
|
if address_filter.is_punished(peer_addr.ip()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -240,6 +240,7 @@ impl NetworkConnection {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let network_manager = connection_manager.network_manager();
|
let network_manager = connection_manager.network_manager();
|
||||||
|
let address_filter = network_manager.address_filter();
|
||||||
let mut unord = FuturesUnordered::new();
|
let mut unord = FuturesUnordered::new();
|
||||||
let mut need_receiver = true;
|
let mut need_receiver = true;
|
||||||
let mut need_sender = true;
|
let mut need_sender = true;
|
||||||
@ -301,11 +302,20 @@ impl NetworkConnection {
|
|||||||
.then(|res| async {
|
.then(|res| async {
|
||||||
match res {
|
match res {
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
if v.is_no_connection() {
|
|
||||||
let peer_address = protocol_connection.descriptor().remote();
|
let peer_address = protocol_connection.descriptor().remote();
|
||||||
log_net!(debug "Connection closed from: {} ({})", peer_address.socket_address().to_socket_addr(), peer_address.protocol_type());
|
|
||||||
|
// Check to see if it is punished
|
||||||
|
if address_filter.is_punished(peer_address.to_socket_addr().ip()) {
|
||||||
return RecvLoopAction::Finish;
|
return RecvLoopAction::Finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for connection close
|
||||||
|
if v.is_no_connection() {
|
||||||
|
log_net!(debug "Connection closed from: {} ({})", peer_address.to_socket_addr(), peer_address.protocol_type());
|
||||||
|
return RecvLoopAction::Finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log other network results
|
||||||
let mut message = network_result_value_or_log!(v => [ format!(": protocol_connection={:?}", protocol_connection) ] {
|
let mut message = network_result_value_or_log!(v => [ format!(": protocol_connection={:?}", protocol_connection) ] {
|
||||||
return RecvLoopAction::Finish;
|
return RecvLoopAction::Finish;
|
||||||
});
|
});
|
||||||
|
@ -20,6 +20,7 @@ pub async fn test_signed_node_info() {
|
|||||||
AddressTypeSet::all(),
|
AddressTypeSet::all(),
|
||||||
VALID_ENVELOPE_VERSIONS.to_vec(),
|
VALID_ENVELOPE_VERSIONS.to_vec(),
|
||||||
VALID_CRYPTO_KINDS.to_vec(),
|
VALID_CRYPTO_KINDS.to_vec(),
|
||||||
|
PUBLIC_INTERNET_CAPABILITIES.to_vec(),
|
||||||
vec![DialInfoDetail {
|
vec![DialInfoDetail {
|
||||||
class: DialInfoClass::Mapped,
|
class: DialInfoClass::Mapped,
|
||||||
dial_info: DialInfo::udp(SocketAddress::default()),
|
dial_info: DialInfo::udp(SocketAddress::default()),
|
||||||
@ -75,6 +76,7 @@ pub async fn test_signed_node_info() {
|
|||||||
AddressTypeSet::all(),
|
AddressTypeSet::all(),
|
||||||
VALID_ENVELOPE_VERSIONS.to_vec(),
|
VALID_ENVELOPE_VERSIONS.to_vec(),
|
||||||
VALID_CRYPTO_KINDS.to_vec(),
|
VALID_CRYPTO_KINDS.to_vec(),
|
||||||
|
PUBLIC_INTERNET_CAPABILITIES.to_vec(),
|
||||||
vec![DialInfoDetail {
|
vec![DialInfoDetail {
|
||||||
class: DialInfoClass::Blocked,
|
class: DialInfoClass::Blocked,
|
||||||
dial_info: DialInfo::udp(SocketAddress::default()),
|
dial_info: DialInfo::udp(SocketAddress::default()),
|
||||||
|
@ -51,7 +51,7 @@ pub struct BucketEntryPublicInternet {
|
|||||||
/// The last node info timestamp of ours that this entry has seen
|
/// The last node info timestamp of ours that this entry has seen
|
||||||
last_seen_our_node_info_ts: Timestamp,
|
last_seen_our_node_info_ts: Timestamp,
|
||||||
/// Last known node status
|
/// Last known node status
|
||||||
node_status: Option<PublicInternetNodeStatus>,
|
node_status: Option<NodeStatus>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bucket entry information specific to the LocalNetwork RoutingDomain
|
/// 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
|
/// The last node info timestamp of ours that this entry has seen
|
||||||
last_seen_our_node_info_ts: Timestamp,
|
last_seen_our_node_info_ts: Timestamp,
|
||||||
/// Last known node status
|
/// Last known node status
|
||||||
node_status: Option<LocalNetworkNodeStatus>,
|
node_status: Option<NodeStatus>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The data associated with each bucket entry
|
/// The data associated with each bucket entry
|
||||||
@ -170,6 +170,13 @@ impl BucketEntryInner {
|
|||||||
common_crypto_kinds(&self.validated_node_ids.kinds(), other)
|
common_crypto_kinds(&self.validated_node_ids.kinds(), other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Capability check
|
||||||
|
pub fn has_capabilities(&self, routing_domain: RoutingDomain, capabilities: &[Capability]) -> bool {
|
||||||
|
let Some(ni) = self.node_info(routing_domain) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
ni.has_capabilities(capabilities)
|
||||||
|
}
|
||||||
|
|
||||||
// Less is faster
|
// Less is faster
|
||||||
pub fn cmp_fastest(e1: &Self, e2: &Self) -> std::cmp::Ordering {
|
pub fn cmp_fastest(e1: &Self, e2: &Self) -> std::cmp::Ordering {
|
||||||
@ -502,13 +509,13 @@ impl BucketEntryInner {
|
|||||||
&self.peer_stats
|
&self.peer_stats
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_node_status(&mut self, status: NodeStatus) {
|
pub fn update_node_status(&mut self, routing_domain: RoutingDomain, status: NodeStatus) {
|
||||||
match status {
|
match routing_domain {
|
||||||
NodeStatus::LocalNetwork(ln) => {
|
RoutingDomain::LocalNetwork => {
|
||||||
self.local_network.node_status = Some(ln);
|
self.local_network.node_status = Some(status);
|
||||||
}
|
}
|
||||||
NodeStatus::PublicInternet(pi) => {
|
RoutingDomain::PublicInternet => {
|
||||||
self.public_internet.node_status = Some(pi);
|
self.public_internet.node_status = Some(status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -518,12 +525,12 @@ impl BucketEntryInner {
|
|||||||
.local_network
|
.local_network
|
||||||
.node_status
|
.node_status
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|ln| NodeStatus::LocalNetwork(ln.clone())),
|
.map(|ns| ns.clone()),
|
||||||
RoutingDomain::PublicInternet => self
|
RoutingDomain::PublicInternet => self
|
||||||
.public_internet
|
.public_internet
|
||||||
.node_status
|
.node_status
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|pi| NodeStatus::PublicInternet(pi.clone())),
|
.map(|ns| ns.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,11 @@ use super::*;
|
|||||||
|
|
||||||
impl RoutingTable {
|
impl RoutingTable {
|
||||||
/// Utility to find all closest nodes to a particular key, including possibly our own node and nodes further away from the key than our own, returning their peer info
|
/// Utility to find all closest nodes to a particular key, including possibly our own node and nodes further away from the key than our own, returning their peer info
|
||||||
pub fn find_all_closest_peers(&self, key: TypedKey) -> NetworkResult<Vec<PeerInfo>> {
|
pub fn find_all_closest_peers(
|
||||||
|
&self,
|
||||||
|
key: TypedKey,
|
||||||
|
capabilities: &[Capability],
|
||||||
|
) -> NetworkResult<Vec<PeerInfo>> {
|
||||||
let Some(own_peer_info) = self.get_own_peer_info(RoutingDomain::PublicInternet) else {
|
let Some(own_peer_info) = self.get_own_peer_info(RoutingDomain::PublicInternet) else {
|
||||||
// Our own node info is not yet available, drop this request.
|
// Our own node info is not yet available, drop this request.
|
||||||
return NetworkResult::service_unavailable("Not finding closest peers because our peer info is not yet available");
|
return NetworkResult::service_unavailable("Not finding closest peers because our peer info is not yet available");
|
||||||
@ -12,11 +16,27 @@ impl RoutingTable {
|
|||||||
let filter = Box::new(
|
let filter = Box::new(
|
||||||
move |rti: &RoutingTableInner, opt_entry: Option<Arc<BucketEntry>>| {
|
move |rti: &RoutingTableInner, opt_entry: Option<Arc<BucketEntry>>| {
|
||||||
// Ensure only things that are valid/signed in the PublicInternet domain are returned
|
// Ensure only things that are valid/signed in the PublicInternet domain are returned
|
||||||
rti.filter_has_valid_signed_node_info(
|
if !rti.filter_has_valid_signed_node_info(
|
||||||
RoutingDomain::PublicInternet,
|
RoutingDomain::PublicInternet,
|
||||||
true,
|
true,
|
||||||
opt_entry,
|
opt_entry.clone(),
|
||||||
)
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Ensure capabilities are met
|
||||||
|
match opt_entry {
|
||||||
|
Some(entry) => entry.with(rti, |_rti, e| {
|
||||||
|
e.has_capabilities(RoutingDomain::PublicInternet, capabilities)
|
||||||
|
}),
|
||||||
|
None => rti
|
||||||
|
.get_own_peer_info(RoutingDomain::PublicInternet)
|
||||||
|
.map(|pi| {
|
||||||
|
pi.signed_node_info()
|
||||||
|
.node_info()
|
||||||
|
.has_capabilities(capabilities)
|
||||||
|
})
|
||||||
|
.unwrap_or(false),
|
||||||
|
}
|
||||||
},
|
},
|
||||||
) as RoutingTableEntryFilter;
|
) as RoutingTableEntryFilter;
|
||||||
let filters = VecDeque::from([filter]);
|
let filters = VecDeque::from([filter]);
|
||||||
@ -40,7 +60,12 @@ impl RoutingTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Utility to find nodes that are closer to a key than our own node, returning their peer info
|
/// Utility to find nodes that are closer to a key than our own node, returning their peer info
|
||||||
pub fn find_peers_closer_to_key(&self, key: TypedKey) -> NetworkResult<Vec<PeerInfo>> {
|
/// Can filter based on a particular set of capabiltiies
|
||||||
|
pub fn find_peers_closer_to_key(
|
||||||
|
&self,
|
||||||
|
key: TypedKey,
|
||||||
|
required_capabilities: Vec<Capability>,
|
||||||
|
) -> NetworkResult<Vec<PeerInfo>> {
|
||||||
// add node information for the requesting node to our routing table
|
// add node information for the requesting node to our routing table
|
||||||
let crypto_kind = key.kind;
|
let crypto_kind = key.kind;
|
||||||
let own_node_id = self.node_id(crypto_kind);
|
let own_node_id = self.node_id(crypto_kind);
|
||||||
@ -59,6 +84,11 @@ impl RoutingTable {
|
|||||||
let Some(entry) = opt_entry else {
|
let Some(entry) = opt_entry else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
// Ensure only things that have a minimum set of capabilities are returned
|
||||||
|
entry.with(rti, |rti, e| {
|
||||||
|
if !e.has_capabilities(RoutingDomain::PublicInternet, &required_capabilities) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// Ensure only things that are valid/signed in the PublicInternet domain are returned
|
// Ensure only things that are valid/signed in the PublicInternet domain are returned
|
||||||
if !rti.filter_has_valid_signed_node_info(
|
if !rti.filter_has_valid_signed_node_info(
|
||||||
RoutingDomain::PublicInternet,
|
RoutingDomain::PublicInternet,
|
||||||
@ -68,15 +98,15 @@ impl RoutingTable {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Ensure things further from the key than our own node are not included
|
// Ensure things further from the key than our own node are not included
|
||||||
let Some(entry_node_id) = entry.with(rti, |_rti, e| e.node_ids().get(crypto_kind)) else {
|
let Some(entry_node_id) = e.node_ids().get(crypto_kind) else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
let entry_distance = vcrypto.distance(&entry_node_id.value, &key.value);
|
let entry_distance = vcrypto.distance(&entry_node_id.value, &key.value);
|
||||||
if entry_distance >= own_distance {
|
if entry_distance >= own_distance {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
|
})
|
||||||
},
|
},
|
||||||
) as RoutingTableEntryFilter;
|
) as RoutingTableEntryFilter;
|
||||||
let filters = VecDeque::from([filter]);
|
let filters = VecDeque::from([filter]);
|
||||||
|
@ -1072,7 +1072,7 @@ impl RoutingTable {
|
|||||||
let res = network_result_try!(
|
let res = network_result_try!(
|
||||||
rpc_processor
|
rpc_processor
|
||||||
.clone()
|
.clone()
|
||||||
.rpc_call_find_node(Destination::direct(node_ref), node_id)
|
.rpc_call_find_node(Destination::direct(node_ref), node_id, vec![])
|
||||||
.await?
|
.await?
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -118,9 +118,9 @@ pub trait NodeRefBase: Sized {
|
|||||||
fn set_updated_since_last_network_change(&self) {
|
fn set_updated_since_last_network_change(&self) {
|
||||||
self.operate_mut(|_rti, e| e.set_updated_since_last_network_change(true));
|
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| {
|
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> {
|
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
|
// Exclude nodes with no publicinternet nodeinfo, or incompatible nodeinfo or node status won't route
|
||||||
entry.with_inner(|e| {
|
entry.with_inner(|e| {
|
||||||
let node_info_ok =
|
e.signed_node_info(RoutingDomain::PublicInternet).map(|sni|
|
||||||
if let Some(sni) = e.signed_node_info(RoutingDomain::PublicInternet) {
|
sni.has_sequencing_matched_dial_info(sequencing) && sni.node_info().has_capability(CAP_ROUTE)
|
||||||
sni.has_sequencing_matched_dial_info(sequencing)
|
).unwrap_or(false)
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
let node_status_ok =
|
|
||||||
if let Some(ns) = e.node_status(RoutingDomain::PublicInternet) {
|
|
||||||
ns.will_route()
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
node_info_ok && node_status_ok
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
) as RoutingTableEntryFilter;
|
) as RoutingTableEntryFilter;
|
||||||
|
@ -13,6 +13,7 @@ enum RoutingDomainChange {
|
|||||||
outbound_protocols: ProtocolTypeSet,
|
outbound_protocols: ProtocolTypeSet,
|
||||||
inbound_protocols: ProtocolTypeSet,
|
inbound_protocols: ProtocolTypeSet,
|
||||||
address_types: AddressTypeSet,
|
address_types: AddressTypeSet,
|
||||||
|
capabilities: Vec<Capability>,
|
||||||
},
|
},
|
||||||
SetNetworkClass {
|
SetNetworkClass {
|
||||||
network_class: Option<NetworkClass>,
|
network_class: Option<NetworkClass>,
|
||||||
@ -79,11 +80,13 @@ impl RoutingDomainEditor {
|
|||||||
outbound_protocols: ProtocolTypeSet,
|
outbound_protocols: ProtocolTypeSet,
|
||||||
inbound_protocols: ProtocolTypeSet,
|
inbound_protocols: ProtocolTypeSet,
|
||||||
address_types: AddressTypeSet,
|
address_types: AddressTypeSet,
|
||||||
|
capabilities: Vec<Capability>,
|
||||||
) {
|
) {
|
||||||
self.changes.push(RoutingDomainChange::SetupNetwork {
|
self.changes.push(RoutingDomainChange::SetupNetwork {
|
||||||
outbound_protocols,
|
outbound_protocols,
|
||||||
inbound_protocols,
|
inbound_protocols,
|
||||||
address_types,
|
address_types,
|
||||||
|
capabilities,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,27 +145,32 @@ impl RoutingDomainEditor {
|
|||||||
outbound_protocols,
|
outbound_protocols,
|
||||||
inbound_protocols,
|
inbound_protocols,
|
||||||
address_types,
|
address_types,
|
||||||
|
capabilities,
|
||||||
} => {
|
} => {
|
||||||
let old_outbound_protocols = detail.common().outbound_protocols();
|
let old_outbound_protocols = detail.common().outbound_protocols();
|
||||||
let old_inbound_protocols = detail.common().inbound_protocols();
|
let old_inbound_protocols = detail.common().inbound_protocols();
|
||||||
let old_address_types = detail.common().address_types();
|
let old_address_types = detail.common().address_types();
|
||||||
|
let old_capabilities = detail.common().capabilities();
|
||||||
|
|
||||||
let this_changed = old_outbound_protocols != outbound_protocols
|
let this_changed = old_outbound_protocols != outbound_protocols
|
||||||
|| old_inbound_protocols != inbound_protocols
|
|| old_inbound_protocols != inbound_protocols
|
||||||
|| old_address_types != address_types;
|
|| old_address_types != address_types
|
||||||
|
|| old_capabilities != capabilities;
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"[{:?}] setup network: {:?} {:?} {:?}",
|
"[{:?}] setup network: {:?} {:?} {:?} {:?}",
|
||||||
self.routing_domain,
|
self.routing_domain,
|
||||||
outbound_protocols,
|
outbound_protocols,
|
||||||
inbound_protocols,
|
inbound_protocols,
|
||||||
address_types
|
address_types,
|
||||||
|
capabilities
|
||||||
);
|
);
|
||||||
|
|
||||||
detail.common_mut().setup_network(
|
detail.common_mut().setup_network(
|
||||||
outbound_protocols,
|
outbound_protocols,
|
||||||
inbound_protocols,
|
inbound_protocols,
|
||||||
address_types,
|
address_types,
|
||||||
|
capabilities,
|
||||||
);
|
);
|
||||||
if this_changed {
|
if this_changed {
|
||||||
changed = true;
|
changed = true;
|
||||||
|
@ -27,6 +27,7 @@ pub struct RoutingDomainDetailCommon {
|
|||||||
inbound_protocols: ProtocolTypeSet,
|
inbound_protocols: ProtocolTypeSet,
|
||||||
address_types: AddressTypeSet,
|
address_types: AddressTypeSet,
|
||||||
relay_node: Option<NodeRef>,
|
relay_node: Option<NodeRef>,
|
||||||
|
capabilities: Vec<Capability>,
|
||||||
dial_info_details: Vec<DialInfoDetail>,
|
dial_info_details: Vec<DialInfoDetail>,
|
||||||
// caches
|
// caches
|
||||||
cached_peer_info: Mutex<Option<PeerInfo>>,
|
cached_peer_info: Mutex<Option<PeerInfo>>,
|
||||||
@ -41,6 +42,7 @@ impl RoutingDomainDetailCommon {
|
|||||||
inbound_protocols: Default::default(),
|
inbound_protocols: Default::default(),
|
||||||
address_types: Default::default(),
|
address_types: Default::default(),
|
||||||
relay_node: Default::default(),
|
relay_node: Default::default(),
|
||||||
|
capabilities: Default::default(),
|
||||||
dial_info_details: Default::default(),
|
dial_info_details: Default::default(),
|
||||||
cached_peer_info: Mutex::new(Default::default()),
|
cached_peer_info: Mutex::new(Default::default()),
|
||||||
}
|
}
|
||||||
@ -52,10 +54,12 @@ impl RoutingDomainDetailCommon {
|
|||||||
outbound_protocols: ProtocolTypeSet,
|
outbound_protocols: ProtocolTypeSet,
|
||||||
inbound_protocols: ProtocolTypeSet,
|
inbound_protocols: ProtocolTypeSet,
|
||||||
address_types: AddressTypeSet,
|
address_types: AddressTypeSet,
|
||||||
|
capabilities: Vec<Capability>,
|
||||||
) {
|
) {
|
||||||
self.outbound_protocols = outbound_protocols;
|
self.outbound_protocols = outbound_protocols;
|
||||||
self.inbound_protocols = inbound_protocols;
|
self.inbound_protocols = inbound_protocols;
|
||||||
self.address_types = address_types;
|
self.address_types = address_types;
|
||||||
|
self.capabilities = capabilities;
|
||||||
self.clear_cache();
|
self.clear_cache();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,6 +79,9 @@ impl RoutingDomainDetailCommon {
|
|||||||
pub fn address_types(&self) -> AddressTypeSet {
|
pub fn address_types(&self) -> AddressTypeSet {
|
||||||
self.address_types
|
self.address_types
|
||||||
}
|
}
|
||||||
|
pub fn capabilities(&self) -> Vec<Capability> {
|
||||||
|
self.capabilities.clone()
|
||||||
|
}
|
||||||
pub fn relay_node(&self) -> Option<NodeRef> {
|
pub fn relay_node(&self) -> Option<NodeRef> {
|
||||||
self.relay_node.clone()
|
self.relay_node.clone()
|
||||||
}
|
}
|
||||||
@ -108,6 +115,7 @@ impl RoutingDomainDetailCommon {
|
|||||||
self.address_types,
|
self.address_types,
|
||||||
VALID_ENVELOPE_VERSIONS.to_vec(),
|
VALID_ENVELOPE_VERSIONS.to_vec(),
|
||||||
VALID_CRYPTO_KINDS.to_vec(),
|
VALID_CRYPTO_KINDS.to_vec(),
|
||||||
|
self.capabilities.clone(),
|
||||||
self.dial_info_details.clone()
|
self.dial_info_details.clone()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -344,6 +344,7 @@ impl RoutingTable {
|
|||||||
AddressTypeSet::all(), // Bootstraps are always IPV4 and IPV6 capable
|
AddressTypeSet::all(), // Bootstraps are always IPV4 and IPV6 capable
|
||||||
bsrec.envelope_support, // Envelope support is as specified in the bootstrap list
|
bsrec.envelope_support, // Envelope support is as specified in the bootstrap list
|
||||||
crypto_support, // Crypto support is derived from list of node ids
|
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
|
bsrec.dial_info_details, // Dial info is as specified in the bootstrap list
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
@ -7,6 +7,14 @@ use stop_token::future::FutureExt as StopFutureExt;
|
|||||||
const BACKGROUND_SAFETY_ROUTE_COUNT: usize = 2;
|
const BACKGROUND_SAFETY_ROUTE_COUNT: usize = 2;
|
||||||
|
|
||||||
impl RoutingTable {
|
impl RoutingTable {
|
||||||
|
fn get_background_safety_route_count(&self) -> usize {
|
||||||
|
let c = self.config.get();
|
||||||
|
if c.capabilities.disable.contains(&CAP_ROUTE) {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
BACKGROUND_SAFETY_ROUTE_COUNT
|
||||||
|
}
|
||||||
|
}
|
||||||
/// Fastest routes sort
|
/// Fastest routes sort
|
||||||
fn route_sort_latency_fn(a: &(RouteId, u64), b: &(RouteId, u64)) -> cmp::Ordering {
|
fn route_sort_latency_fn(a: &(RouteId, u64), b: &(RouteId, u64)) -> cmp::Ordering {
|
||||||
let mut al = a.1;
|
let mut al = a.1;
|
||||||
@ -69,13 +77,14 @@ impl RoutingTable {
|
|||||||
unpublished_routes.sort_by(Self::route_sort_latency_fn);
|
unpublished_routes.sort_by(Self::route_sort_latency_fn);
|
||||||
|
|
||||||
// Save up to N unpublished routes and test them
|
// Save up to N unpublished routes and test them
|
||||||
for x in 0..(usize::min(BACKGROUND_SAFETY_ROUTE_COUNT, unpublished_routes.len())) {
|
let background_safety_route_count = self.get_background_safety_route_count();
|
||||||
|
for x in 0..(usize::min(background_safety_route_count, unpublished_routes.len())) {
|
||||||
must_test_routes.push(unpublished_routes[x].0);
|
must_test_routes.push(unpublished_routes[x].0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kill off all but N unpublished routes rather than testing them
|
// Kill off all but N unpublished routes rather than testing them
|
||||||
if unpublished_routes.len() > BACKGROUND_SAFETY_ROUTE_COUNT {
|
if unpublished_routes.len() > background_safety_route_count {
|
||||||
for x in &unpublished_routes[BACKGROUND_SAFETY_ROUTE_COUNT..] {
|
for x in &unpublished_routes[background_safety_route_count..] {
|
||||||
expired_routes.push(x.0);
|
expired_routes.push(x.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -192,8 +201,11 @@ impl RoutingTable {
|
|||||||
}
|
}
|
||||||
Option::<()>::None
|
Option::<()>::None
|
||||||
});
|
});
|
||||||
if local_unpublished_route_count < BACKGROUND_SAFETY_ROUTE_COUNT {
|
|
||||||
let routes_to_allocate = BACKGROUND_SAFETY_ROUTE_COUNT - local_unpublished_route_count;
|
let background_safety_route_count = self.get_background_safety_route_count();
|
||||||
|
|
||||||
|
if local_unpublished_route_count < background_safety_route_count {
|
||||||
|
let routes_to_allocate = background_safety_route_count - local_unpublished_route_count;
|
||||||
|
|
||||||
// Newly allocated routes
|
// Newly allocated routes
|
||||||
let mut newly_allocated_routes = Vec::new();
|
let mut newly_allocated_routes = Vec::new();
|
||||||
|
@ -100,6 +100,11 @@ impl RoutingTable {
|
|||||||
let can_serve_as_relay = e
|
let can_serve_as_relay = e
|
||||||
.node_info(RoutingDomain::PublicInternet)
|
.node_info(RoutingDomain::PublicInternet)
|
||||||
.map(|n| {
|
.map(|n| {
|
||||||
|
if !(n.has_capability(CAP_RELAY) && n.is_signal_capable()) {
|
||||||
|
// Needs to be able to signal and relay
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
let dids = n.all_filtered_dial_info_details(DialInfoDetail::NO_SORT, |did| {
|
let dids = n.all_filtered_dial_info_details(DialInfoDetail::NO_SORT, |did| {
|
||||||
did.matches_filter(&outbound_dif)
|
did.matches_filter(&outbound_dif)
|
||||||
});
|
});
|
||||||
@ -145,10 +150,8 @@ impl RoutingTable {
|
|||||||
inner.with_entries(cur_ts, BucketEntryState::Unreliable, |rti, entry| {
|
inner.with_entries(cur_ts, BucketEntryState::Unreliable, |rti, entry| {
|
||||||
let entry2 = entry.clone();
|
let entry2 = entry.clone();
|
||||||
entry.with(rti, |rti, e| {
|
entry.with(rti, |rti, e| {
|
||||||
// Ensure we have the node's status
|
// Filter this node
|
||||||
if let Some(node_status) = e.node_status(routing_domain) {
|
if relay_node_filter(e) {
|
||||||
// Ensure the node will relay
|
|
||||||
if node_status.will_relay() {
|
|
||||||
// Compare against previous candidate
|
// Compare against previous candidate
|
||||||
if let Some(best_inbound_relay) = best_inbound_relay.as_mut() {
|
if let Some(best_inbound_relay) = best_inbound_relay.as_mut() {
|
||||||
// Less is faster
|
// Less is faster
|
||||||
@ -158,15 +161,14 @@ impl RoutingTable {
|
|||||||
== std::cmp::Ordering::Less
|
== std::cmp::Ordering::Less
|
||||||
});
|
});
|
||||||
// Now apply filter function and see if this node should be included
|
// Now apply filter function and see if this node should be included
|
||||||
if better && relay_node_filter(e) {
|
if better {
|
||||||
*best_inbound_relay = entry2;
|
*best_inbound_relay = entry2;
|
||||||
}
|
}
|
||||||
} else if relay_node_filter(e) {
|
} else {
|
||||||
// Always store the first candidate
|
// Always store the first candidate
|
||||||
best_inbound_relay = Some(entry2);
|
best_inbound_relay = Some(entry2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
// Don't end early, iterate through all entries
|
// Don't end early, iterate through all entries
|
||||||
Option::<()>::None
|
Option::<()>::None
|
||||||
|
@ -100,6 +100,7 @@ pub async fn test_round_trip_peerinfo() {
|
|||||||
AddressTypeSet::new(),
|
AddressTypeSet::new(),
|
||||||
vec![0],
|
vec![0],
|
||||||
vec![CRYPTO_KIND_VLD0],
|
vec![CRYPTO_KIND_VLD0],
|
||||||
|
PUBLIC_INTERNET_CAPABILITIES.to_vec(),
|
||||||
vec![],
|
vec![],
|
||||||
),
|
),
|
||||||
Timestamp::new(0),
|
Timestamp::new(0),
|
||||||
|
@ -1,5 +1,54 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
pub type Capability = FourCC;
|
||||||
|
pub const CAP_ROUTE: Capability = FourCC(*b"ROUT");
|
||||||
|
#[cfg(feature = "unstable-tunnels")]
|
||||||
|
pub const CAP_TUNNEL: Capability = FourCC(*b"TUNL");
|
||||||
|
pub const CAP_SIGNAL: Capability = FourCC(*b"SGNL");
|
||||||
|
pub const CAP_RELAY: Capability = FourCC(*b"RLAY");
|
||||||
|
pub const CAP_VALIDATE_DIAL_INFO: Capability = FourCC(*b"DIAL");
|
||||||
|
pub const CAP_DHT: Capability = FourCC(*b"DHTV");
|
||||||
|
pub const CAP_APPMESSAGE: Capability = FourCC(*b"APPM");
|
||||||
|
#[cfg(feature = "unstable-blockstore")]
|
||||||
|
pub const CAP_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_ROUTE,
|
||||||
|
#[cfg(feature = "unstable-tunnels")]
|
||||||
|
CAP_TUNNEL,
|
||||||
|
CAP_SIGNAL,
|
||||||
|
CAP_RELAY,
|
||||||
|
CAP_VALIDATE_DIAL_INFO,
|
||||||
|
CAP_DHT,
|
||||||
|
CAP_APPMESSAGE,
|
||||||
|
#[cfg(feature = "unstable-blockstore")]
|
||||||
|
CAP_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_RELAY,
|
||||||
|
CAP_DHT,
|
||||||
|
CAP_APPMESSAGE,
|
||||||
|
#[cfg(feature = "unstable-blockstore")]
|
||||||
|
CAP_BLOCKSTORE,
|
||||||
|
];
|
||||||
|
|
||||||
|
pub const MAX_CAPABILITIES: usize = 64;
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone,
|
Clone,
|
||||||
Default,
|
Default,
|
||||||
@ -21,6 +70,7 @@ pub struct NodeInfo {
|
|||||||
address_types: AddressTypeSet,
|
address_types: AddressTypeSet,
|
||||||
envelope_support: Vec<u8>,
|
envelope_support: Vec<u8>,
|
||||||
crypto_support: Vec<CryptoKind>,
|
crypto_support: Vec<CryptoKind>,
|
||||||
|
capabilities: Vec<Capability>,
|
||||||
dial_info_detail_list: Vec<DialInfoDetail>,
|
dial_info_detail_list: Vec<DialInfoDetail>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,6 +81,7 @@ impl NodeInfo {
|
|||||||
address_types: AddressTypeSet,
|
address_types: AddressTypeSet,
|
||||||
envelope_support: Vec<u8>,
|
envelope_support: Vec<u8>,
|
||||||
crypto_support: Vec<CryptoKind>,
|
crypto_support: Vec<CryptoKind>,
|
||||||
|
capabilities: Vec<Capability>,
|
||||||
dial_info_detail_list: Vec<DialInfoDetail>,
|
dial_info_detail_list: Vec<DialInfoDetail>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -39,6 +90,7 @@ impl NodeInfo {
|
|||||||
address_types,
|
address_types,
|
||||||
envelope_support,
|
envelope_support,
|
||||||
crypto_support,
|
crypto_support,
|
||||||
|
capabilities,
|
||||||
dial_info_detail_list,
|
dial_info_detail_list,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,6 +110,9 @@ impl NodeInfo {
|
|||||||
pub fn crypto_support(&self) -> &[CryptoKind] {
|
pub fn crypto_support(&self) -> &[CryptoKind] {
|
||||||
&self.crypto_support
|
&self.crypto_support
|
||||||
}
|
}
|
||||||
|
pub fn capabilities(&self) -> &[Capability] {
|
||||||
|
&self.capabilities
|
||||||
|
}
|
||||||
pub fn dial_info_detail_list(&self) -> &[DialInfoDetail] {
|
pub fn dial_info_detail_list(&self) -> &[DialInfoDetail] {
|
||||||
&self.dial_info_detail_list
|
&self.dial_info_detail_list
|
||||||
}
|
}
|
||||||
@ -144,8 +199,27 @@ impl NodeInfo {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_capability(&self, cap: Capability) -> bool {
|
||||||
|
self.capabilities.contains(&cap)
|
||||||
|
}
|
||||||
|
pub fn has_capabilities(&self, capabilities: &[Capability]) -> bool {
|
||||||
|
for cap in capabilities {
|
||||||
|
if !self.has_capability(*cap) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
/// Can this node assist with signalling? Yes but only if it doesn't require signalling, itself.
|
/// Can this node assist with signalling? Yes but only if it doesn't require signalling, itself.
|
||||||
pub fn can_signal(&self) -> bool {
|
/// Also used to determine if nodes are capable of validation of dial info, as that operation
|
||||||
|
/// has the same requirements, inbound capability and a dial info that requires no assistance
|
||||||
|
pub fn is_signal_capable(&self) -> bool {
|
||||||
|
// Has capability?
|
||||||
|
if !self.has_capability(CAP_SIGNAL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Must be inbound capable
|
// Must be inbound capable
|
||||||
if !matches!(self.network_class, NetworkClass::InboundCapable) {
|
if !matches!(self.network_class, NetworkClass::InboundCapable) {
|
||||||
return false;
|
return false;
|
||||||
@ -158,16 +232,4 @@ impl NodeInfo {
|
|||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Can this node relay be an inbound relay?
|
|
||||||
pub fn can_inbound_relay(&self) -> bool {
|
|
||||||
// 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 {
|
|
||||||
// For now this is the same
|
|
||||||
self.can_signal()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,66 +1,9 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// RoutingDomain-specific status for each node
|
/// Non-nodeinfo status for each node is returned by the StatusA call
|
||||||
/// is returned by the StatusA call
|
|
||||||
|
|
||||||
/// PublicInternet RoutingDomain Status
|
|
||||||
#[derive(
|
|
||||||
Clone, Debug, Default, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
|
|
||||||
)]
|
|
||||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(
|
|
||||||
Clone, Debug, Default, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
|
|
||||||
)]
|
|
||||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
|
||||||
pub struct LocalNetworkNodeStatus {
|
|
||||||
pub will_relay: bool,
|
|
||||||
pub will_validate_dial_info: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
|
||||||
#[archive_attr(repr(u8), derive(CheckBytes))]
|
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||||
pub enum NodeStatus {
|
pub struct NodeStatus {
|
||||||
PublicInternet(PublicInternetNodeStatus),
|
// Reserved for expansion
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,18 @@ pub fn encode_node_info(
|
|||||||
s.clone_from_slice(&csvec);
|
s.clone_from_slice(&csvec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut cap_builder = builder
|
||||||
|
.reborrow()
|
||||||
|
.init_capabilities(node_info.capabilities().len() as u32);
|
||||||
|
if let Some(s) = cap_builder.as_slice() {
|
||||||
|
let capvec: Vec<u32> = node_info
|
||||||
|
.capabilities()
|
||||||
|
.iter()
|
||||||
|
.map(|x| u32::from_be_bytes(x.0))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
s.clone_from_slice(&capvec);
|
||||||
|
}
|
||||||
let mut didl_builder = builder.reborrow().init_dial_info_detail_list(
|
let mut didl_builder = builder.reborrow().init_dial_info_detail_list(
|
||||||
node_info
|
node_info
|
||||||
.dial_info_detail_list()
|
.dial_info_detail_list()
|
||||||
@ -71,13 +83,11 @@ pub fn decode_node_info(reader: &veilid_capnp::node_info::Reader) -> Result<Node
|
|||||||
.map_err(RPCError::protocol)?,
|
.map_err(RPCError::protocol)?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let envelope_support = reader
|
let es_reader = reader
|
||||||
.reborrow()
|
.reborrow()
|
||||||
.get_envelope_support()
|
.get_envelope_support()
|
||||||
.map_err(RPCError::protocol)?
|
.map_err(RPCError::protocol)?;
|
||||||
.as_slice()
|
let envelope_support = es_reader.as_slice().map(|s| s.to_vec()).unwrap_or_default();
|
||||||
.map(|s| s.to_vec())
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
// Ensure envelope versions are not duplicated
|
// Ensure envelope versions are not duplicated
|
||||||
// Unsorted is okay, some nodes may have a different envelope order preference
|
// Unsorted is okay, some nodes may have a different envelope order preference
|
||||||
@ -94,10 +104,16 @@ pub fn decode_node_info(reader: &veilid_capnp::node_info::Reader) -> Result<Node
|
|||||||
return Err(RPCError::protocol("no envelope versions"));
|
return Err(RPCError::protocol("no envelope versions"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let crypto_support: Vec<CryptoKind> = reader
|
let cs_reader = reader
|
||||||
.reborrow()
|
.reborrow()
|
||||||
.get_crypto_support()
|
.get_crypto_support()
|
||||||
.map_err(RPCError::protocol)?
|
.map_err(RPCError::protocol)?;
|
||||||
|
|
||||||
|
if cs_reader.len() as usize > MAX_CRYPTO_KINDS {
|
||||||
|
return Err(RPCError::protocol("too many crypto kinds"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let crypto_support: Vec<CryptoKind> = cs_reader
|
||||||
.as_slice()
|
.as_slice()
|
||||||
.map(|s| s.iter().map(|x| FourCC::from(x.to_be_bytes())).collect())
|
.map(|s| s.iter().map(|x| FourCC::from(x.to_be_bytes())).collect())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
@ -117,6 +133,18 @@ pub fn decode_node_info(reader: &veilid_capnp::node_info::Reader) -> Result<Node
|
|||||||
return Err(RPCError::protocol("no crypto kinds"));
|
return Err(RPCError::protocol("no crypto kinds"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let cap_reader = reader
|
||||||
|
.reborrow()
|
||||||
|
.get_capabilities()
|
||||||
|
.map_err(RPCError::protocol)?;
|
||||||
|
if cap_reader.len() as usize > MAX_CAPABILITIES {
|
||||||
|
return Err(RPCError::protocol("too many capabilities"));
|
||||||
|
}
|
||||||
|
let capabilities = cap_reader
|
||||||
|
.as_slice()
|
||||||
|
.map(|s| s.iter().map(|x| FourCC::from(x.to_be_bytes())).collect())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
let didl_reader = reader
|
let didl_reader = reader
|
||||||
.reborrow()
|
.reborrow()
|
||||||
.get_dial_info_detail_list()
|
.get_dial_info_detail_list()
|
||||||
@ -137,6 +165,7 @@ pub fn decode_node_info(reader: &veilid_capnp::node_info::Reader) -> Result<Node
|
|||||||
address_types,
|
address_types,
|
||||||
envelope_support,
|
envelope_support,
|
||||||
crypto_support,
|
crypto_support,
|
||||||
|
capabilities,
|
||||||
dial_info_detail_list,
|
dial_info_detail_list,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -1,83 +1,14 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub fn encode_public_internet_node_status(
|
|
||||||
public_internet_node_status: &PublicInternetNodeStatus,
|
|
||||||
builder: &mut veilid_capnp::public_internet_node_status::Builder,
|
|
||||||
) -> Result<(), RPCError> {
|
|
||||||
builder.set_will_route(public_internet_node_status.will_route);
|
|
||||||
builder.set_will_tunnel(public_internet_node_status.will_tunnel);
|
|
||||||
builder.set_will_signal(public_internet_node_status.will_signal);
|
|
||||||
builder.set_will_relay(public_internet_node_status.will_relay);
|
|
||||||
builder.set_will_validate_dial_info(public_internet_node_status.will_validate_dial_info);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn decode_public_internet_node_status(
|
|
||||||
reader: &veilid_capnp::public_internet_node_status::Reader,
|
|
||||||
) -> Result<PublicInternetNodeStatus, RPCError> {
|
|
||||||
Ok(PublicInternetNodeStatus {
|
|
||||||
will_route: reader.reborrow().get_will_route(),
|
|
||||||
will_tunnel: reader.reborrow().get_will_tunnel(),
|
|
||||||
will_signal: reader.reborrow().get_will_signal(),
|
|
||||||
will_relay: reader.reborrow().get_will_relay(),
|
|
||||||
will_validate_dial_info: reader.reborrow().get_will_validate_dial_info(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn encode_local_network_node_status(
|
|
||||||
local_network_node_status: &LocalNetworkNodeStatus,
|
|
||||||
builder: &mut veilid_capnp::local_network_node_status::Builder,
|
|
||||||
) -> Result<(), RPCError> {
|
|
||||||
builder.set_will_relay(local_network_node_status.will_relay);
|
|
||||||
builder.set_will_validate_dial_info(local_network_node_status.will_validate_dial_info);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn decode_local_network_node_status(
|
|
||||||
reader: &veilid_capnp::local_network_node_status::Reader,
|
|
||||||
) -> Result<LocalNetworkNodeStatus, RPCError> {
|
|
||||||
Ok(LocalNetworkNodeStatus {
|
|
||||||
will_relay: reader.reborrow().get_will_relay(),
|
|
||||||
will_validate_dial_info: reader.reborrow().get_will_validate_dial_info(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn encode_node_status(
|
pub fn encode_node_status(
|
||||||
node_status: &NodeStatus,
|
_node_status: &NodeStatus,
|
||||||
builder: &mut veilid_capnp::node_status::Builder,
|
_builder: &mut veilid_capnp::node_status::Builder,
|
||||||
) -> Result<(), RPCError> {
|
) -> Result<(), RPCError> {
|
||||||
match node_status {
|
Ok(())
|
||||||
NodeStatus::PublicInternet(ns) => {
|
|
||||||
let mut pi_builder = builder.reborrow().init_public_internet();
|
|
||||||
encode_public_internet_node_status(&ns, &mut pi_builder)
|
|
||||||
}
|
|
||||||
NodeStatus::LocalNetwork(ns) => {
|
|
||||||
let mut ln_builder = builder.reborrow().init_local_network();
|
|
||||||
encode_local_network_node_status(&ns, &mut ln_builder)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode_node_status(
|
pub fn decode_node_status(
|
||||||
reader: &veilid_capnp::node_status::Reader,
|
_reader: &veilid_capnp::node_status::Reader,
|
||||||
) -> Result<NodeStatus, RPCError> {
|
) -> Result<NodeStatus, RPCError> {
|
||||||
Ok(
|
Ok(NodeStatus {})
|
||||||
match reader
|
|
||||||
.which()
|
|
||||||
.map_err(RPCError::map_internal("invalid node status"))?
|
|
||||||
{
|
|
||||||
veilid_capnp::node_status::PublicInternet(pi) => {
|
|
||||||
let r = pi.map_err(RPCError::protocol)?;
|
|
||||||
let pins = decode_public_internet_node_status(&r)?;
|
|
||||||
NodeStatus::PublicInternet(pins)
|
|
||||||
}
|
|
||||||
veilid_capnp::node_status::LocalNetwork(ln) => {
|
|
||||||
let r = ln.map_err(RPCError::protocol)?;
|
|
||||||
let lnns = decode_local_network_node_status(&r)?;
|
|
||||||
NodeStatus::LocalNetwork(lnns)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,15 @@ const MAX_FIND_NODE_A_PEERS_LEN: usize = 20;
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct RPCOperationFindNodeQ {
|
pub struct RPCOperationFindNodeQ {
|
||||||
node_id: TypedKey,
|
node_id: TypedKey,
|
||||||
|
capabilities: Vec<Capability>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RPCOperationFindNodeQ {
|
impl RPCOperationFindNodeQ {
|
||||||
pub fn new(node_id: TypedKey) -> Self {
|
pub fn new(node_id: TypedKey, capabilities: Vec<Capability>) -> Self {
|
||||||
Self { node_id }
|
Self {
|
||||||
|
node_id,
|
||||||
|
capabilities,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -18,15 +22,33 @@ impl RPCOperationFindNodeQ {
|
|||||||
// pub fn node_id(&self) -> &TypedKey {
|
// pub fn node_id(&self) -> &TypedKey {
|
||||||
// &self.node_id
|
// &self.node_id
|
||||||
// }
|
// }
|
||||||
|
// pub fn capabilities(&self) -> &[Capability] {
|
||||||
|
// &self.capabilities
|
||||||
|
// }
|
||||||
|
|
||||||
pub fn destructure(self) -> TypedKey {
|
pub fn destructure(self) -> (TypedKey, Vec<Capability>) {
|
||||||
self.node_id
|
(self.node_id, self.capabilities)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode(reader: &veilid_capnp::operation_find_node_q::Reader) -> Result<Self, RPCError> {
|
pub fn decode(reader: &veilid_capnp::operation_find_node_q::Reader) -> Result<Self, RPCError> {
|
||||||
let ni_reader = reader.get_node_id().map_err(RPCError::protocol)?;
|
let ni_reader = reader.get_node_id().map_err(RPCError::protocol)?;
|
||||||
let node_id = decode_typed_key(&ni_reader)?;
|
let node_id = decode_typed_key(&ni_reader)?;
|
||||||
Ok(Self { node_id })
|
let cap_reader = reader
|
||||||
|
.reborrow()
|
||||||
|
.get_capabilities()
|
||||||
|
.map_err(RPCError::protocol)?;
|
||||||
|
if cap_reader.len() as usize > MAX_CAPABILITIES {
|
||||||
|
return Err(RPCError::protocol("too many capabilities"));
|
||||||
|
}
|
||||||
|
let capabilities = cap_reader
|
||||||
|
.as_slice()
|
||||||
|
.map(|s| s.iter().map(|x| FourCC::from(x.to_be_bytes())).collect())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
node_id,
|
||||||
|
capabilities,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
pub fn encode(
|
pub fn encode(
|
||||||
&self,
|
&self,
|
||||||
@ -34,6 +56,19 @@ impl RPCOperationFindNodeQ {
|
|||||||
) -> Result<(), RPCError> {
|
) -> Result<(), RPCError> {
|
||||||
let mut ni_builder = builder.reborrow().init_node_id();
|
let mut ni_builder = builder.reborrow().init_node_id();
|
||||||
encode_typed_key(&self.node_id, &mut ni_builder);
|
encode_typed_key(&self.node_id, &mut ni_builder);
|
||||||
|
|
||||||
|
let mut cap_builder = builder
|
||||||
|
.reborrow()
|
||||||
|
.init_capabilities(self.capabilities.len() as u32);
|
||||||
|
if let Some(s) = cap_builder.as_slice() {
|
||||||
|
let capvec: Vec<u32> = self
|
||||||
|
.capabilities
|
||||||
|
.iter()
|
||||||
|
.map(|x| u32::from_be_bytes(x.0))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
s.clone_from_slice(&capvec);
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,13 @@ impl RPCMessageHeader {
|
|||||||
// RPCMessageHeaderDetail::PrivateRouted(p) => p.direct.peer_noderef.clone(),
|
// RPCMessageHeaderDetail::PrivateRouted(p) => p.direct.peer_noderef.clone(),
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
pub fn routing_domain(&self) -> RoutingDomain {
|
||||||
|
match &self.detail {
|
||||||
|
RPCMessageHeaderDetail::Direct(d) => d.routing_domain,
|
||||||
|
RPCMessageHeaderDetail::SafetyRouted(s) => s.direct.routing_domain,
|
||||||
|
RPCMessageHeaderDetail::PrivateRouted(p) => p.direct.routing_domain,
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn direct_sender_node_id(&self) -> TypedKey {
|
pub fn direct_sender_node_id(&self) -> TypedKey {
|
||||||
match &self.detail {
|
match &self.detail {
|
||||||
RPCMessageHeaderDetail::Direct(d) => {
|
RPCMessageHeaderDetail::Direct(d) => {
|
||||||
@ -435,9 +442,11 @@ impl RPCProcessor {
|
|||||||
&self,
|
&self,
|
||||||
routing_domain: RoutingDomain,
|
routing_domain: RoutingDomain,
|
||||||
signed_node_info: &SignedNodeInfo,
|
signed_node_info: &SignedNodeInfo,
|
||||||
|
capabilities: &[Capability],
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
routing_table.signed_node_info_is_valid_in_routing_domain(routing_domain, &signed_node_info)
|
routing_table.signed_node_info_is_valid_in_routing_domain(routing_domain, &signed_node_info)
|
||||||
|
&& signed_node_info.node_info().has_capabilities(capabilities)
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
@ -463,6 +472,7 @@ impl RPCProcessor {
|
|||||||
.rpc_call_find_node(
|
.rpc_call_find_node(
|
||||||
Destination::direct(next_node).with_safety(safety_selection),
|
Destination::direct(next_node).with_safety(safety_selection),
|
||||||
node_id,
|
node_id,
|
||||||
|
vec![],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
@ -1467,7 +1477,11 @@ impl RPCProcessor {
|
|||||||
// Ensure the sender peer info is for the actual sender specified in the envelope
|
// Ensure the sender peer info is for the actual sender specified in the envelope
|
||||||
|
|
||||||
// Sender PeerInfo was specified, update our routing table with it
|
// Sender PeerInfo was specified, update our routing table with it
|
||||||
if !self.verify_node_info(routing_domain, sender_peer_info.signed_node_info()) {
|
if !self.verify_node_info(
|
||||||
|
routing_domain,
|
||||||
|
sender_peer_info.signed_node_info(),
|
||||||
|
&[],
|
||||||
|
) {
|
||||||
return Ok(NetworkResult::invalid_message(
|
return Ok(NetworkResult::invalid_message(
|
||||||
"sender peerinfo has invalid peer scope",
|
"sender peerinfo has invalid peer scope",
|
||||||
));
|
));
|
||||||
|
@ -53,6 +53,22 @@ impl RPCProcessor {
|
|||||||
&self,
|
&self,
|
||||||
msg: RPCMessage,
|
msg: RPCMessage,
|
||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
|
// Ignore if disabled
|
||||||
|
let routing_table = self.routing_table();
|
||||||
|
{
|
||||||
|
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||||
|
if !opi
|
||||||
|
.signed_node_info()
|
||||||
|
.node_info()
|
||||||
|
.has_capability(CAP_APPMESSAGE)
|
||||||
|
{
|
||||||
|
return Ok(NetworkResult::service_unavailable(
|
||||||
|
"app call is not available",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get the question
|
// Get the question
|
||||||
let (op_id, _, _, kind) = msg.operation.clone().destructure();
|
let (op_id, _, _, kind) = msg.operation.clone().destructure();
|
||||||
let app_call_q = match kind {
|
let app_call_q = match kind {
|
||||||
|
@ -24,6 +24,22 @@ impl RPCProcessor {
|
|||||||
&self,
|
&self,
|
||||||
msg: RPCMessage,
|
msg: RPCMessage,
|
||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
|
// Ignore if disabled
|
||||||
|
let routing_table = self.routing_table();
|
||||||
|
{
|
||||||
|
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||||
|
if !opi
|
||||||
|
.signed_node_info()
|
||||||
|
.node_info()
|
||||||
|
.has_capability(CAP_APPMESSAGE)
|
||||||
|
{
|
||||||
|
return Ok(NetworkResult::service_unavailable(
|
||||||
|
"app message is not available",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get the statement
|
// Get the statement
|
||||||
let (_, _, _, kind) = msg.operation.destructure();
|
let (_, _, _, kind) = msg.operation.destructure();
|
||||||
let app_message = match kind {
|
let app_message = match kind {
|
||||||
|
@ -6,6 +6,25 @@ impl RPCProcessor {
|
|||||||
&self,
|
&self,
|
||||||
msg: RPCMessage,
|
msg: RPCMessage,
|
||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
|
// Ignore if disabled
|
||||||
|
#[cfg(feature = "unstable-tunnels")]
|
||||||
|
{
|
||||||
|
let routing_table = self.routing_table();
|
||||||
|
{
|
||||||
|
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||||
|
if !opi
|
||||||
|
.signed_node_info()
|
||||||
|
.node_info()
|
||||||
|
.has_capability(CAP_TUNNEL)
|
||||||
|
{
|
||||||
|
return Ok(NetworkResult::service_unavailable(
|
||||||
|
"tunnel is not available",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Err(RPCError::unimplemented("process_cancel_tunnel_q"))
|
Err(RPCError::unimplemented("process_cancel_tunnel_q"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,24 @@ impl RPCProcessor {
|
|||||||
&self,
|
&self,
|
||||||
msg: RPCMessage,
|
msg: RPCMessage,
|
||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
|
// Ignore if disabled
|
||||||
|
#[cfg(feature = "unstable-tunnels")]
|
||||||
|
{
|
||||||
|
let routing_table = self.routing_table();
|
||||||
|
{
|
||||||
|
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||||
|
if !opi
|
||||||
|
.signed_node_info()
|
||||||
|
.node_info()
|
||||||
|
.has_capability(CAP_TUNNEL)
|
||||||
|
{
|
||||||
|
return Ok(NetworkResult::service_unavailable(
|
||||||
|
"tunnel is not available",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Err(RPCError::unimplemented("process_complete_tunnel_q"))
|
Err(RPCError::unimplemented("process_complete_tunnel_q"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,20 @@ impl RPCProcessor {
|
|||||||
&self,
|
&self,
|
||||||
msg: RPCMessage,
|
msg: RPCMessage,
|
||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
|
// Ignore if disabled
|
||||||
|
#[cfg(feature = "unstable-blockstore")]
|
||||||
|
{
|
||||||
|
let routing_table = self.routing_table();
|
||||||
|
{
|
||||||
|
if let Some(opi) = routing_table.get_own_peer_info(detail.routing_domain) {
|
||||||
|
if !opi.signed_node_info().node_info().can_blockstore() {
|
||||||
|
return Ok(NetworkResult::service_unavailable(
|
||||||
|
"block store is not available",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Err(RPCError::unimplemented("process_find_block_q"))
|
Err(RPCError::unimplemented("process_find_block_q"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ impl RPCProcessor {
|
|||||||
self,
|
self,
|
||||||
dest: Destination,
|
dest: Destination,
|
||||||
node_id: TypedKey,
|
node_id: TypedKey,
|
||||||
|
capabilities: Vec<Capability>,
|
||||||
) -> Result<NetworkResult<Answer<Vec<PeerInfo>>>, RPCError> {
|
) -> Result<NetworkResult<Answer<Vec<PeerInfo>>>, RPCError> {
|
||||||
// Ensure destination never has a private route
|
// Ensure destination never has a private route
|
||||||
if matches!(
|
if matches!(
|
||||||
@ -29,7 +30,8 @@ impl RPCProcessor {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let find_node_q_detail = RPCQuestionDetail::FindNodeQ(RPCOperationFindNodeQ::new(node_id));
|
let find_node_q_detail =
|
||||||
|
RPCQuestionDetail::FindNodeQ(RPCOperationFindNodeQ::new(node_id, capabilities.clone()));
|
||||||
let find_node_q = RPCQuestion::new(
|
let find_node_q = RPCQuestion::new(
|
||||||
network_result_try!(self.get_destination_respond_to(&dest)?),
|
network_result_try!(self.get_destination_respond_to(&dest)?),
|
||||||
find_node_q_detail,
|
find_node_q_detail,
|
||||||
@ -60,9 +62,13 @@ impl RPCProcessor {
|
|||||||
let peers = find_node_a.destructure();
|
let peers = find_node_a.destructure();
|
||||||
|
|
||||||
for peer_info in &peers {
|
for peer_info in &peers {
|
||||||
if !self.verify_node_info(RoutingDomain::PublicInternet, peer_info.signed_node_info()) {
|
if !self.verify_node_info(
|
||||||
|
RoutingDomain::PublicInternet,
|
||||||
|
peer_info.signed_node_info(),
|
||||||
|
&capabilities,
|
||||||
|
) {
|
||||||
return Ok(NetworkResult::invalid_message(
|
return Ok(NetworkResult::invalid_message(
|
||||||
"find_node response has invalid peer scope",
|
"find_node response does not meet peer criteria",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,11 +100,12 @@ impl RPCProcessor {
|
|||||||
},
|
},
|
||||||
_ => panic!("not a question"),
|
_ => panic!("not a question"),
|
||||||
};
|
};
|
||||||
let node_id = find_node_q.destructure();
|
let (node_id, capabilities) = find_node_q.destructure();
|
||||||
|
|
||||||
// Get a chunk of the routing table near the requested node id
|
// Get a chunk of the routing table near the requested node id
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
let closest_nodes = network_result_try!(routing_table.find_all_closest_peers(node_id));
|
let closest_nodes =
|
||||||
|
network_result_try!(routing_table.find_all_closest_peers(node_id, &capabilities));
|
||||||
|
|
||||||
// Make FindNode answer
|
// Make FindNode answer
|
||||||
let find_node_a = RPCOperationFindNodeA::new(closest_nodes)?;
|
let find_node_a = RPCOperationFindNodeA::new(closest_nodes)?;
|
||||||
|
@ -163,6 +163,7 @@ impl RPCProcessor {
|
|||||||
&self,
|
&self,
|
||||||
msg: RPCMessage,
|
msg: RPCMessage,
|
||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
|
|
||||||
// Ensure this never came over a private route, safety route is okay though
|
// Ensure this never came over a private route, safety route is okay though
|
||||||
match &msg.header.detail {
|
match &msg.header.detail {
|
||||||
RPCMessageHeaderDetail::Direct(_) | RPCMessageHeaderDetail::SafetyRouted(_) => {}
|
RPCMessageHeaderDetail::Direct(_) | RPCMessageHeaderDetail::SafetyRouted(_) => {}
|
||||||
@ -172,7 +173,17 @@ impl RPCProcessor {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Ignore if disabled
|
||||||
|
let routing_table = self.routing_table();
|
||||||
|
{
|
||||||
|
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||||
|
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
|
||||||
|
return Ok(NetworkResult::service_unavailable(
|
||||||
|
"dht is not available",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// Get the question
|
// Get the question
|
||||||
let kind = msg.operation.kind().clone();
|
let kind = msg.operation.kind().clone();
|
||||||
let get_value_q = match kind {
|
let get_value_q = match kind {
|
||||||
@ -188,7 +199,7 @@ impl RPCProcessor {
|
|||||||
|
|
||||||
// Get the nodes that we know about that are closer to the the key than our own node
|
// Get the nodes that we know about that are closer to the the key than our own node
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
let closer_to_key_peers = network_result_try!(routing_table.find_peers_closer_to_key(key));
|
let closer_to_key_peers = network_result_try!(routing_table.find_peers_closer_to_key(key, vec![CAP_DHT]));
|
||||||
|
|
||||||
let debug_string = format!(
|
let debug_string = format!(
|
||||||
"IN <=== GetValueQ({} #{}{}) <== {}",
|
"IN <=== GetValueQ({} #{}{}) <== {}",
|
||||||
|
@ -365,6 +365,18 @@ impl RPCProcessor {
|
|||||||
&self,
|
&self,
|
||||||
msg: RPCMessage,
|
msg: RPCMessage,
|
||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
|
// Ignore if disabled
|
||||||
|
let routing_table = self.routing_table();
|
||||||
|
{
|
||||||
|
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||||
|
if !opi.signed_node_info().node_info().has_capability(CAP_ROUTE) {
|
||||||
|
return Ok(NetworkResult::service_unavailable(
|
||||||
|
"route is not available",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get header detail, must be direct and not inside a route itself
|
// Get header detail, must be direct and not inside a route itself
|
||||||
let detail = match msg.header.detail {
|
let detail = match msg.header.detail {
|
||||||
RPCMessageHeaderDetail::Direct(detail) => detail,
|
RPCMessageHeaderDetail::Direct(detail) => detail,
|
||||||
|
@ -175,6 +175,17 @@ impl RPCProcessor {
|
|||||||
&self,
|
&self,
|
||||||
msg: RPCMessage,
|
msg: RPCMessage,
|
||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
|
// Ignore if disabled
|
||||||
|
let routing_table = self.routing_table();
|
||||||
|
{
|
||||||
|
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||||
|
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
|
||||||
|
return Ok(NetworkResult::service_unavailable(
|
||||||
|
"dht is not available",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// Ensure this never came over a private route, safety route is okay though
|
// Ensure this never came over a private route, safety route is okay though
|
||||||
match &msg.header.detail {
|
match &msg.header.detail {
|
||||||
RPCMessageHeaderDetail::Direct(_) | RPCMessageHeaderDetail::SafetyRouted(_) => {}
|
RPCMessageHeaderDetail::Direct(_) | RPCMessageHeaderDetail::SafetyRouted(_) => {}
|
||||||
@ -200,7 +211,7 @@ impl RPCProcessor {
|
|||||||
|
|
||||||
// Get the nodes that we know about that are closer to the the key than our own node
|
// Get the nodes that we know about that are closer to the the key than our own node
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
let closer_to_key_peers = network_result_try!(routing_table.find_peers_closer_to_key(key));
|
let closer_to_key_peers = network_result_try!(routing_table.find_peers_closer_to_key(key, vec![CAP_DHT]));
|
||||||
|
|
||||||
let debug_string = format!(
|
let debug_string = format!(
|
||||||
"IN <=== SetValueQ({} #{} len={} seq={} writer={}{}) <== {}",
|
"IN <=== SetValueQ({} #{} len={} seq={} writer={}{}) <== {}",
|
||||||
|
@ -37,6 +37,18 @@ impl RPCProcessor {
|
|||||||
&self,
|
&self,
|
||||||
msg: RPCMessage,
|
msg: RPCMessage,
|
||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
|
// Ignore if disabled
|
||||||
|
let routing_table = self.routing_table();
|
||||||
|
{
|
||||||
|
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||||
|
if !opi.signed_node_info().node_info().is_signal_capable() {
|
||||||
|
return Ok(NetworkResult::service_unavailable(
|
||||||
|
"signal is not available",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Can't allow anything other than direct packets here, as handling reverse connections
|
// Can't allow anything other than direct packets here, as handling reverse connections
|
||||||
// or anything like via signals over private routes would deanonymize the route
|
// or anything like via signals over private routes would deanonymize the route
|
||||||
match &msg.header.detail {
|
match &msg.header.detail {
|
||||||
|
@ -6,6 +6,24 @@ impl RPCProcessor {
|
|||||||
&self,
|
&self,
|
||||||
msg: RPCMessage,
|
msg: RPCMessage,
|
||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
|
// Ignore if disabled
|
||||||
|
#[cfg(feature = "unstable-tunnels")]
|
||||||
|
{
|
||||||
|
let routing_table = self.routing_table();
|
||||||
|
{
|
||||||
|
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||||
|
if !opi
|
||||||
|
.signed_node_info()
|
||||||
|
.node_info()
|
||||||
|
.has_capability(CAP_TUNNEL)
|
||||||
|
{
|
||||||
|
return Ok(NetworkResult::service_unavailable(
|
||||||
|
"tunnel is not available",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Err(RPCError::unimplemented("process_start_tunnel_q"))
|
Err(RPCError::unimplemented("process_start_tunnel_q"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,25 +133,8 @@ impl RPCProcessor {
|
|||||||
// Ensure the returned node status is the kind for the routing domain we asked for
|
// Ensure the returned node status is the kind for the routing domain we asked for
|
||||||
if let Some(target_nr) = opt_target_nr {
|
if let Some(target_nr) = opt_target_nr {
|
||||||
if let Some(a_node_status) = a_node_status {
|
if let Some(a_node_status) = a_node_status {
|
||||||
match routing_domain {
|
|
||||||
RoutingDomain::PublicInternet => {
|
|
||||||
if !matches!(a_node_status, NodeStatus::PublicInternet(_)) {
|
|
||||||
return Ok(NetworkResult::invalid_message(
|
|
||||||
"node status doesn't match PublicInternet routing domain",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RoutingDomain::LocalNetwork => {
|
|
||||||
if !matches!(a_node_status, NodeStatus::LocalNetwork(_)) {
|
|
||||||
return Ok(NetworkResult::invalid_message(
|
|
||||||
"node status doesn't match LocalNetwork routing domain",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update latest node status in routing table
|
// Update latest node status in routing table
|
||||||
target_nr.update_node_status(a_node_status.clone());
|
target_nr.update_node_status(routing_domain, a_node_status.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,27 +219,10 @@ impl RPCProcessor {
|
|||||||
|
|
||||||
// Ensure the node status from the question is the kind for the routing domain we received the request in
|
// Ensure the node status from the question is the kind for the routing domain we received the request in
|
||||||
if let Some(q_node_status) = q_node_status {
|
if let Some(q_node_status) = q_node_status {
|
||||||
match routing_domain {
|
|
||||||
RoutingDomain::PublicInternet => {
|
|
||||||
if !matches!(q_node_status, NodeStatus::PublicInternet(_)) {
|
|
||||||
return Ok(NetworkResult::invalid_message(
|
|
||||||
"node status doesn't match PublicInternet routing domain",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RoutingDomain::LocalNetwork => {
|
|
||||||
if !matches!(q_node_status, NodeStatus::LocalNetwork(_)) {
|
|
||||||
return Ok(NetworkResult::invalid_message(
|
|
||||||
"node status doesn't match LocalNetwork routing domain",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// update node status for the requesting node to our routing table
|
// update node status for the requesting node to our routing table
|
||||||
if let Some(sender_nr) = msg.opt_sender_nr.clone() {
|
if let Some(sender_nr) = msg.opt_sender_nr.clone() {
|
||||||
// Update latest node status in routing table for the statusq sender
|
// Update latest node status in routing table for the statusq sender
|
||||||
sender_nr.update_node_status(q_node_status.clone());
|
sender_nr.update_node_status(routing_domain, q_node_status.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,20 @@ impl RPCProcessor {
|
|||||||
&self,
|
&self,
|
||||||
msg: RPCMessage,
|
msg: RPCMessage,
|
||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
|
// Ignore if disabled
|
||||||
|
#[cfg(feature = "unstable-blockstore")]
|
||||||
|
{
|
||||||
|
let routing_table = self.routing_table();
|
||||||
|
{
|
||||||
|
if let Some(opi) = routing_table.get_own_peer_info(detail.routing_domain) {
|
||||||
|
if !opi.signed_node_info().node_info().can_blockstore() {
|
||||||
|
return Ok(NetworkResult::service_unavailable(
|
||||||
|
"block store is not available",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Err(RPCError::unimplemented("process_supply_block_q"))
|
Err(RPCError::unimplemented("process_supply_block_q"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,19 @@ impl RPCProcessor {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Ignore if disabled
|
||||||
|
let routing_table = self.routing_table();
|
||||||
|
{
|
||||||
|
if let Some(opi) = routing_table.get_own_peer_info(detail.routing_domain) {
|
||||||
|
let ni = opi.signed_node_info().node_info();
|
||||||
|
if !ni.has_capability(CAP_VALIDATE_DIAL_INFO) || !ni.is_signal_capable() {
|
||||||
|
return Ok(NetworkResult::service_unavailable(
|
||||||
|
"validate dial info is not available",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get the statement
|
// Get the statement
|
||||||
let (_, _, _, kind) = msg.operation.destructure();
|
let (_, _, _, kind) = msg.operation.destructure();
|
||||||
let (dial_info, receipt, redirect) = match kind {
|
let (dial_info, receipt, redirect) = match kind {
|
||||||
@ -83,7 +96,6 @@ impl RPCProcessor {
|
|||||||
// We filter on the -outgoing- protocol capability status not the node's dial info
|
// We filter on the -outgoing- protocol capability status not the node's dial info
|
||||||
// Use the address type though, to ensure we reach an ipv6 capable node if this is
|
// Use the address type though, to ensure we reach an ipv6 capable node if this is
|
||||||
// an ipv6 address
|
// an ipv6 address
|
||||||
let routing_table = self.routing_table();
|
|
||||||
let sender_node_id = TypedKey::new(
|
let sender_node_id = TypedKey::new(
|
||||||
detail.envelope.get_crypto_kind(),
|
detail.envelope.get_crypto_kind(),
|
||||||
detail.envelope.get_sender_id(),
|
detail.envelope.get_sender_id(),
|
||||||
@ -104,11 +116,11 @@ impl RPCProcessor {
|
|||||||
move |rti: &RoutingTableInner, v: Option<Arc<BucketEntry>>| {
|
move |rti: &RoutingTableInner, v: Option<Arc<BucketEntry>>| {
|
||||||
let entry = v.unwrap();
|
let entry = v.unwrap();
|
||||||
entry.with(rti, move |_rti, e| {
|
entry.with(rti, move |_rti, e| {
|
||||||
if let Some(status) = &e.node_status(routing_domain) {
|
e.node_info(routing_domain)
|
||||||
status.will_validate_dial_info()
|
.map(|ni| {
|
||||||
} else {
|
ni.has_capability(CAP_VALIDATE_DIAL_INFO) && ni.is_signal_capable()
|
||||||
true
|
})
|
||||||
}
|
.unwrap_or(false)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
) as RoutingTableEntryFilter;
|
) as RoutingTableEntryFilter;
|
||||||
|
@ -6,6 +6,15 @@ impl RPCProcessor {
|
|||||||
&self,
|
&self,
|
||||||
msg: RPCMessage,
|
msg: RPCMessage,
|
||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
|
// Ignore if disabled
|
||||||
|
let routing_table = self.routing_table();
|
||||||
|
{
|
||||||
|
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||||
|
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
|
||||||
|
return Ok(NetworkResult::service_unavailable("dht is not available"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Err(RPCError::unimplemented("process_value_changed"))
|
Err(RPCError::unimplemented("process_value_changed"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,15 @@ impl RPCProcessor {
|
|||||||
&self,
|
&self,
|
||||||
msg: RPCMessage,
|
msg: RPCMessage,
|
||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
|
// Ignore if disabled
|
||||||
|
let routing_table = self.routing_table();
|
||||||
|
{
|
||||||
|
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||||
|
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
|
||||||
|
return Ok(NetworkResult::service_unavailable("dht is not available"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Err(RPCError::unimplemented("process_watch_value_q"))
|
Err(RPCError::unimplemented("process_watch_value_q"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,13 +168,7 @@ fn config_callback(key: String) -> ConfigCallbackReturn {
|
|||||||
match key.as_str() {
|
match key.as_str() {
|
||||||
"program_name" => Ok(Box::new(String::from("VeilidCoreTests"))),
|
"program_name" => Ok(Box::new(String::from("VeilidCoreTests"))),
|
||||||
"namespace" => Ok(Box::new(String::from(""))),
|
"namespace" => Ok(Box::new(String::from(""))),
|
||||||
"capabilities.protocol_udp" => Ok(Box::new(true)),
|
"capabilities.disable" => Ok(Box::new(Vec::<FourCC>::new())),
|
||||||
"capabilities.protocol_connect_tcp" => Ok(Box::new(true)),
|
|
||||||
"capabilities.protocol_accept_tcp" => Ok(Box::new(true)),
|
|
||||||
"capabilities.protocol_connect_ws" => Ok(Box::new(true)),
|
|
||||||
"capabilities.protocol_accept_ws" => Ok(Box::new(true)),
|
|
||||||
"capabilities.protocol_connect_wss" => Ok(Box::new(true)),
|
|
||||||
"capabilities.protocol_accept_wss" => Ok(Box::new(true)),
|
|
||||||
"table_store.directory" => Ok(Box::new(get_table_store_path())),
|
"table_store.directory" => Ok(Box::new(get_table_store_path())),
|
||||||
"table_store.delete" => Ok(Box::new(true)),
|
"table_store.delete" => Ok(Box::new(true)),
|
||||||
"block_store.directory" => Ok(Box::new(get_block_store_path())),
|
"block_store.directory" => Ok(Box::new(get_block_store_path())),
|
||||||
@ -299,13 +293,7 @@ pub async fn test_config() {
|
|||||||
let inner = vc.get();
|
let inner = vc.get();
|
||||||
assert_eq!(inner.program_name, String::from("VeilidCoreTests"));
|
assert_eq!(inner.program_name, String::from("VeilidCoreTests"));
|
||||||
assert_eq!(inner.namespace, String::from(""));
|
assert_eq!(inner.namespace, String::from(""));
|
||||||
assert_eq!(inner.capabilities.protocol_udp, true);
|
assert_eq!(inner.capabilities.disable, Vec::<FourCC>::new());
|
||||||
assert_eq!(inner.capabilities.protocol_connect_tcp, true);
|
|
||||||
assert_eq!(inner.capabilities.protocol_accept_tcp, true);
|
|
||||||
assert_eq!(inner.capabilities.protocol_connect_ws, true);
|
|
||||||
assert_eq!(inner.capabilities.protocol_accept_ws, true);
|
|
||||||
assert_eq!(inner.capabilities.protocol_connect_wss, true);
|
|
||||||
assert_eq!(inner.capabilities.protocol_accept_wss, true);
|
|
||||||
assert_eq!(inner.table_store.directory, get_table_store_path());
|
assert_eq!(inner.table_store.directory, get_table_store_path());
|
||||||
assert_eq!(inner.table_store.delete, true);
|
assert_eq!(inner.table_store.delete, true);
|
||||||
assert_eq!(inner.block_store.directory, get_block_store_path());
|
assert_eq!(inner.block_store.directory, get_block_store_path());
|
||||||
|
@ -76,13 +76,7 @@ pub fn fix_veilidconfiginner() -> VeilidConfigInner {
|
|||||||
program_name: "Bob".to_string(),
|
program_name: "Bob".to_string(),
|
||||||
namespace: "Internets".to_string(),
|
namespace: "Internets".to_string(),
|
||||||
capabilities: VeilidConfigCapabilities {
|
capabilities: VeilidConfigCapabilities {
|
||||||
protocol_udp: false,
|
disable: Vec::new(),
|
||||||
protocol_connect_tcp: true,
|
|
||||||
protocol_accept_tcp: false,
|
|
||||||
protocol_connect_ws: true,
|
|
||||||
protocol_accept_ws: false,
|
|
||||||
protocol_connect_wss: true,
|
|
||||||
protocol_accept_wss: false,
|
|
||||||
},
|
},
|
||||||
protected_store: VeilidConfigProtectedStore {
|
protected_store: VeilidConfigProtectedStore {
|
||||||
allow_insecure_fallback: true,
|
allow_insecure_fallback: true,
|
||||||
|
@ -468,13 +468,7 @@ pub struct VeilidConfigProtectedStore {
|
|||||||
JsonSchema,
|
JsonSchema,
|
||||||
)]
|
)]
|
||||||
pub struct VeilidConfigCapabilities {
|
pub struct VeilidConfigCapabilities {
|
||||||
pub protocol_udp: bool,
|
pub disable: Vec<FourCC>,
|
||||||
pub protocol_connect_tcp: bool,
|
|
||||||
pub protocol_accept_tcp: bool,
|
|
||||||
pub protocol_connect_ws: bool,
|
|
||||||
pub protocol_accept_ws: bool,
|
|
||||||
pub protocol_connect_wss: bool,
|
|
||||||
pub protocol_accept_wss: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
@ -670,13 +664,7 @@ impl VeilidConfig {
|
|||||||
|
|
||||||
get_config!(inner.program_name);
|
get_config!(inner.program_name);
|
||||||
get_config!(inner.namespace);
|
get_config!(inner.namespace);
|
||||||
get_config!(inner.capabilities.protocol_udp);
|
get_config!(inner.capabilities.disable);
|
||||||
get_config!(inner.capabilities.protocol_connect_tcp);
|
|
||||||
get_config!(inner.capabilities.protocol_accept_tcp);
|
|
||||||
get_config!(inner.capabilities.protocol_connect_ws);
|
|
||||||
get_config!(inner.capabilities.protocol_accept_ws);
|
|
||||||
get_config!(inner.capabilities.protocol_connect_wss);
|
|
||||||
get_config!(inner.capabilities.protocol_accept_wss);
|
|
||||||
get_config!(inner.table_store.directory);
|
get_config!(inner.table_store.directory);
|
||||||
get_config!(inner.table_store.delete);
|
get_config!(inner.table_store.delete);
|
||||||
get_config!(inner.block_store.directory);
|
get_config!(inner.block_store.directory);
|
||||||
|
@ -52,15 +52,7 @@ Future<VeilidConfig> getDefaultVeilidConfig(String programName) async {
|
|||||||
return VeilidConfig(
|
return VeilidConfig(
|
||||||
programName: programName,
|
programName: programName,
|
||||||
namespace: "",
|
namespace: "",
|
||||||
capabilities: VeilidConfigCapabilities(
|
capabilities: VeilidConfigCapabilities(disable: []),
|
||||||
protocolUDP: !kIsWeb,
|
|
||||||
protocolConnectTCP: !kIsWeb,
|
|
||||||
protocolAcceptTCP: !kIsWeb,
|
|
||||||
protocolConnectWS: true,
|
|
||||||
protocolAcceptWS: !kIsWeb,
|
|
||||||
protocolConnectWSS: true,
|
|
||||||
protocolAcceptWSS: false,
|
|
||||||
),
|
|
||||||
protectedStore: VeilidConfigProtectedStore(
|
protectedStore: VeilidConfigProtectedStore(
|
||||||
allowInsecureFallback: false,
|
allowInsecureFallback: false,
|
||||||
alwaysUseInsecureStorage: false,
|
alwaysUseInsecureStorage: false,
|
||||||
|
@ -867,44 +867,19 @@ class VeilidConfigProtectedStore {
|
|||||||
////////////
|
////////////
|
||||||
|
|
||||||
class VeilidConfigCapabilities {
|
class VeilidConfigCapabilities {
|
||||||
bool protocolUDP;
|
List<String> disable;
|
||||||
bool protocolConnectTCP;
|
|
||||||
bool protocolAcceptTCP;
|
|
||||||
bool protocolConnectWS;
|
|
||||||
bool protocolAcceptWS;
|
|
||||||
bool protocolConnectWSS;
|
|
||||||
bool protocolAcceptWSS;
|
|
||||||
|
|
||||||
VeilidConfigCapabilities({
|
VeilidConfigCapabilities({
|
||||||
required this.protocolUDP,
|
required this.disable,
|
||||||
required this.protocolConnectTCP,
|
|
||||||
required this.protocolAcceptTCP,
|
|
||||||
required this.protocolConnectWS,
|
|
||||||
required this.protocolAcceptWS,
|
|
||||||
required this.protocolConnectWSS,
|
|
||||||
required this.protocolAcceptWSS,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
return {
|
return {
|
||||||
'protocol_udp': protocolUDP,
|
'disable': disable,
|
||||||
'protocol_connect_tcp': protocolConnectTCP,
|
|
||||||
'protocol_accept_tcp': protocolAcceptTCP,
|
|
||||||
'protocol_connect_ws': protocolConnectWS,
|
|
||||||
'protocol_accept_ws': protocolAcceptWS,
|
|
||||||
'protocol_connect_wss': protocolConnectWSS,
|
|
||||||
'protocol_accept_wss': protocolAcceptWSS,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
VeilidConfigCapabilities.fromJson(dynamic json)
|
VeilidConfigCapabilities.fromJson(dynamic json) : disable = json['disable'];
|
||||||
: protocolUDP = json['protocol_udp'],
|
|
||||||
protocolConnectTCP = json['protocol_connect_tcp'],
|
|
||||||
protocolAcceptTCP = json['protocol_accept_tcp'],
|
|
||||||
protocolConnectWS = json['protocol_connect_ws'],
|
|
||||||
protocolAcceptWS = json['protocol_accept_ws'],
|
|
||||||
protocolConnectWSS = json['protocol_connect_wss'],
|
|
||||||
protocolAcceptWSS = json['protocol_accept_wss'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////
|
////////////
|
||||||
|
@ -2,7 +2,7 @@ from dataclasses import dataclass, fields
|
|||||||
from enum import StrEnum
|
from enum import StrEnum
|
||||||
from typing import Optional, Self
|
from typing import Optional, Self
|
||||||
|
|
||||||
from .types import TypedKey, TypedSecret
|
from .types import TypedKey, TypedSecret, Capability
|
||||||
|
|
||||||
|
|
||||||
class VeilidConfigLogLevel(StrEnum):
|
class VeilidConfigLogLevel(StrEnum):
|
||||||
@ -41,13 +41,7 @@ class ConfigBase:
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class VeilidConfigCapabilities(ConfigBase):
|
class VeilidConfigCapabilities(ConfigBase):
|
||||||
protocol_udp: bool
|
disable: list[Capability]
|
||||||
protocol_connect_tcp: bool
|
|
||||||
protocol_accept_tcp: bool
|
|
||||||
protocol_connect_ws: bool
|
|
||||||
protocol_accept_ws: bool
|
|
||||||
protocol_connect_wss: bool
|
|
||||||
protocol_accept_wss: bool
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
@ -52,6 +52,17 @@ class CryptoKind(StrEnum):
|
|||||||
CRYPTO_KIND_VLD0 = "VLD0"
|
CRYPTO_KIND_VLD0 = "VLD0"
|
||||||
|
|
||||||
|
|
||||||
|
class Capability(StrEnum):
|
||||||
|
CAP_WILL_ROUTE = "ROUT"
|
||||||
|
CAP_TUNNEL = "TUNL"
|
||||||
|
CAP_WILL_SIGNAL = "SGNL"
|
||||||
|
CAP_WILL_RELAY = "RLAY"
|
||||||
|
CAP_WILL_VALIDATE_DIAL_INFO = "DIAL"
|
||||||
|
CAP_WILL_DHT = "DHTV"
|
||||||
|
CAP_WILL_APPMESSAGE = "APPM"
|
||||||
|
CAP_BLOCKSTORE = "BLOC"
|
||||||
|
|
||||||
|
|
||||||
class Stability(StrEnum):
|
class Stability(StrEnum):
|
||||||
LOW_LATENCY = "LowLatency"
|
LOW_LATENCY = "LowLatency"
|
||||||
RELIABLE = "Reliable"
|
RELIABLE = "Reliable"
|
||||||
@ -67,6 +78,7 @@ class DHTSchemaKind(StrEnum):
|
|||||||
DFLT = "DFLT"
|
DFLT = "DFLT"
|
||||||
SMPL = "SMPL"
|
SMPL = "SMPL"
|
||||||
|
|
||||||
|
|
||||||
class SafetySelectionKind(StrEnum):
|
class SafetySelectionKind(StrEnum):
|
||||||
UNSAFE = "Unsafe"
|
UNSAFE = "Unsafe"
|
||||||
SAFE = "Safe"
|
SAFE = "Safe"
|
||||||
@ -239,7 +251,6 @@ class VeilidVersion:
|
|||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return isinstance(other, VeilidVersion) and self.data == other.data and self.seq == other.seq and self.writer == other.writer
|
return isinstance(other, VeilidVersion) and self.data == other.data and self.seq == other.seq and self.writer == other.writer
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def major(self):
|
def major(self):
|
||||||
return self._major
|
return self._major
|
||||||
@ -308,7 +319,8 @@ class DHTSchema:
|
|||||||
if DHTSchemaKind(j["kind"]) == DHTSchemaKind.SMPL:
|
if DHTSchemaKind(j["kind"]) == DHTSchemaKind.SMPL:
|
||||||
return cls.smpl(
|
return cls.smpl(
|
||||||
j["o_cnt"],
|
j["o_cnt"],
|
||||||
[DHTSchemaSMPLMember.from_json(member) for member in j["members"]],
|
[DHTSchemaSMPLMember.from_json(member)
|
||||||
|
for member in j["members"]],
|
||||||
)
|
)
|
||||||
raise Exception("Unknown DHTSchema kind", j["kind"])
|
raise Exception("Unknown DHTSchema kind", j["kind"])
|
||||||
|
|
||||||
@ -339,7 +351,8 @@ class DHTRecordDescriptor:
|
|||||||
return cls(
|
return cls(
|
||||||
TypedKey(j["key"]),
|
TypedKey(j["key"]),
|
||||||
PublicKey(j["owner"]),
|
PublicKey(j["owner"]),
|
||||||
None if j["owner_secret"] is None else SecretKey(j["owner_secret"]),
|
None if j["owner_secret"] is None else SecretKey(
|
||||||
|
j["owner_secret"]),
|
||||||
DHTSchema.from_json(j["schema"]),
|
DHTSchema.from_json(j["schema"]),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -412,6 +425,7 @@ class SafetySpec:
|
|||||||
def to_json(self) -> dict:
|
def to_json(self) -> dict:
|
||||||
return self.__dict__
|
return self.__dict__
|
||||||
|
|
||||||
|
|
||||||
class SafetySelection:
|
class SafetySelection:
|
||||||
kind: SafetySelectionKind
|
kind: SafetySelectionKind
|
||||||
|
|
||||||
@ -438,9 +452,8 @@ class SafetySelection:
|
|||||||
|
|
||||||
def to_json(self) -> dict:
|
def to_json(self) -> dict:
|
||||||
if self.kind == SafetySelectionKind.UNSAFE:
|
if self.kind == SafetySelectionKind.UNSAFE:
|
||||||
return {"Unsafe": self.sequencing }
|
return {"Unsafe": self.sequencing}
|
||||||
elif self.kind == SafetySelectionKind.SAFE:
|
elif self.kind == SafetySelectionKind.SAFE:
|
||||||
return {"Safe": self.safety_spec.to_json() }
|
return {"Safe": self.safety_spec.to_json()}
|
||||||
else:
|
else:
|
||||||
raise Exception("Invalid SafetySelection")
|
raise Exception("Invalid SafetySelection")
|
||||||
|
|
||||||
|
@ -46,6 +46,8 @@ logging:
|
|||||||
testing:
|
testing:
|
||||||
subnode_index: 0
|
subnode_index: 0
|
||||||
core:
|
core:
|
||||||
|
capabilities:
|
||||||
|
disable: []
|
||||||
protected_store:
|
protected_store:
|
||||||
allow_insecure_fallback: true
|
allow_insecure_fallback: true
|
||||||
always_use_insecure_storage: true
|
always_use_insecure_storage: true
|
||||||
@ -70,6 +72,7 @@ core:
|
|||||||
reverse_connection_receipt_time_ms: 5000
|
reverse_connection_receipt_time_ms: 5000
|
||||||
hole_punch_receipt_time_ms: 5000
|
hole_punch_receipt_time_ms: 5000
|
||||||
network_key_password: null
|
network_key_password: null
|
||||||
|
disable_capabilites: []
|
||||||
routing_table:
|
routing_table:
|
||||||
node_id: null
|
node_id: null
|
||||||
node_id_secret: null
|
node_id_secret: null
|
||||||
@ -622,8 +625,14 @@ pub struct ProtectedStore {
|
|||||||
pub new_device_encryption_key_password: Option<String>,
|
pub new_device_encryption_key_password: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct Capabilities {
|
||||||
|
pub disable: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct Core {
|
pub struct Core {
|
||||||
|
pub capabilities: Capabilities,
|
||||||
pub protected_store: ProtectedStore,
|
pub protected_store: ProtectedStore,
|
||||||
pub table_store: TableStore,
|
pub table_store: TableStore,
|
||||||
pub block_store: BlockStore,
|
pub block_store: BlockStore,
|
||||||
@ -962,6 +971,7 @@ impl Settings {
|
|||||||
set_config_value!(inner.logging.otlp.grpc_endpoint, value);
|
set_config_value!(inner.logging.otlp.grpc_endpoint, value);
|
||||||
set_config_value!(inner.logging.console.enabled, value);
|
set_config_value!(inner.logging.console.enabled, value);
|
||||||
set_config_value!(inner.testing.subnode_index, value);
|
set_config_value!(inner.testing.subnode_index, value);
|
||||||
|
set_config_value!(inner.core.capabilities.disable, value);
|
||||||
set_config_value!(inner.core.protected_store.allow_insecure_fallback, value);
|
set_config_value!(inner.core.protected_store.allow_insecure_fallback, value);
|
||||||
set_config_value!(
|
set_config_value!(
|
||||||
inner.core.protected_store.always_use_insecure_storage,
|
inner.core.protected_store.always_use_insecure_storage,
|
||||||
@ -1093,13 +1103,14 @@ impl Settings {
|
|||||||
} else {
|
} else {
|
||||||
format!("subnode{}", inner.testing.subnode_index)
|
format!("subnode{}", inner.testing.subnode_index)
|
||||||
})),
|
})),
|
||||||
"capabilities.protocol_udp" => Ok(Box::new(true)),
|
"capabilities.disable" => {
|
||||||
"capabilities.protocol_connect_tcp" => Ok(Box::new(true)),
|
let mut caps = Vec::<FourCC>::new();
|
||||||
"capabilities.protocol_accept_tcp" => Ok(Box::new(true)),
|
for c in &inner.core.capabilities.disable {
|
||||||
"capabilities.protocol_connect_ws" => Ok(Box::new(true)),
|
let cap = FourCC::from_str(c.as_str()).map_err(VeilidAPIError::generic)?;
|
||||||
"capabilities.protocol_accept_ws" => Ok(Box::new(true)),
|
caps.push(cap);
|
||||||
"capabilities.protocol_connect_wss" => Ok(Box::new(true)),
|
}
|
||||||
"capabilities.protocol_accept_wss" => Ok(Box::new(true)),
|
Ok(Box::new(caps))
|
||||||
|
}
|
||||||
"protected_store.allow_insecure_fallback" => {
|
"protected_store.allow_insecure_fallback" => {
|
||||||
Ok(Box::new(inner.core.protected_store.allow_insecure_fallback))
|
Ok(Box::new(inner.core.protected_store.allow_insecure_fallback))
|
||||||
}
|
}
|
||||||
|
@ -33,13 +33,7 @@ fn init_callbacks() {
|
|||||||
window.configCallback = (configKey) => {
|
window.configCallback = (configKey) => {
|
||||||
switch(configKey) {
|
switch(configKey) {
|
||||||
case "namespace": return "";
|
case "namespace": return "";
|
||||||
case "capabilities.protocol_udp": return false;
|
case "capabilities.disable": return [];
|
||||||
case "capabilities.protocol_connect_tcp": return false;
|
|
||||||
case "capabilities.protocol_accept_tcp": return false;
|
|
||||||
case "capabilities.protocol_connect_ws": return true;
|
|
||||||
case "capabilities.protocol_accept_ws": return false;
|
|
||||||
case "capabilities.protocol_connect_wss": return true;
|
|
||||||
case "capabilities.protocol_accept_wss": return false;
|
|
||||||
case "tablestore.directory": return "";
|
case "tablestore.directory": return "";
|
||||||
case "network.routing_table.node_id": return [];
|
case "network.routing_table.node_id": return [];
|
||||||
case "network.routing_table.node_id_secret": return [];
|
case "network.routing_table.node_id_secret": return [];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user