mirror of
https://gitlab.com/veilid/veilid.git
synced 2025-03-12 17:06:37 -04:00
Fixed for attach speed and futures optimizations
This commit is contained in:
parent
8de19e0d26
commit
90036e0653
16
Cargo.toml
16
Cargo.toml
@ -61,3 +61,19 @@ debug-assertions = false
|
|||||||
[profile.dev.package.chacha20]
|
[profile.dev.package.chacha20]
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
debug-assertions = false
|
debug-assertions = false
|
||||||
|
|
||||||
|
[workspace.lints.clippy]
|
||||||
|
all = { level = "deny", priority = -1 }
|
||||||
|
must_use_candidate = "deny"
|
||||||
|
large_futures = "deny"
|
||||||
|
large_stack_arrays = "deny"
|
||||||
|
large_stack_frames = "deny"
|
||||||
|
large_types_passed_by_value = "deny"
|
||||||
|
unused_async = "deny"
|
||||||
|
ptr_cast_constness = "deny"
|
||||||
|
comparison_chain = "allow"
|
||||||
|
upper_case_acronyms = "allow"
|
||||||
|
|
||||||
|
[workspace.lints.rust]
|
||||||
|
unused_must_use = "deny"
|
||||||
|
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(tokio_unstable)'] }
|
||||||
|
3
clippy.toml
Normal file
3
clippy.toml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
future-size-threshold = 8192
|
||||||
|
array-size-threshold = 8192
|
||||||
|
stack-size-threshold = 128000
|
@ -77,3 +77,6 @@ console = "0.15.8"
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serial_test = "^2"
|
serial_test = "^2"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
@ -51,7 +51,7 @@ impl ClientApiConnection {
|
|||||||
inner.reply_channels.clear();
|
inner.reply_channels.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn process_veilid_state<'a>(&self, state: &json::JsonValue) {
|
fn process_veilid_state(&self, state: &json::JsonValue) {
|
||||||
let comproc = self.inner.lock().comproc.clone();
|
let comproc = self.inner.lock().comproc.clone();
|
||||||
comproc.update_attachment(&state["attachment"]);
|
comproc.update_attachment(&state["attachment"]);
|
||||||
comproc.update_network_status(&state["network"]);
|
comproc.update_network_status(&state["network"]);
|
||||||
@ -77,7 +77,7 @@ impl ClientApiConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn process_veilid_update(&self, update: json::JsonValue) {
|
fn process_veilid_update(&self, update: json::JsonValue) {
|
||||||
let comproc = self.inner.lock().comproc.clone();
|
let comproc = self.inner.lock().comproc.clone();
|
||||||
let Some(kind) = update["kind"].as_str() else {
|
let Some(kind) = update["kind"].as_str() else {
|
||||||
comproc.log_message(Level::Error, &format!("missing update kind: {}", update));
|
comproc.log_message(Level::Error, &format!("missing update kind: {}", update));
|
||||||
@ -164,7 +164,7 @@ impl ClientApiConnection {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if j["type"] == "Update" {
|
if j["type"] == "Update" {
|
||||||
this.process_veilid_update(j).await;
|
this.process_veilid_update(j);
|
||||||
} else if j["type"] == "Response" {
|
} else if j["type"] == "Response" {
|
||||||
this.process_response(j).await;
|
this.process_response(j).await;
|
||||||
}
|
}
|
||||||
@ -198,7 +198,7 @@ impl ClientApiConnection {
|
|||||||
error!("failed to get state: {}", resp["error"]);
|
error!("failed to get state: {}", resp["error"]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
capi.process_veilid_state(&resp["value"]).await;
|
capi.process_veilid_state(&resp["value"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Send and receive until we're done or a stop is requested
|
// Send and receive until we're done or a stop is requested
|
||||||
@ -420,7 +420,7 @@ impl ClientApiConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// End Client API connection
|
// End Client API connection
|
||||||
pub async fn disconnect(&self) {
|
pub fn disconnect(&self) {
|
||||||
trace!("ClientApiConnection::disconnect");
|
trace!("ClientApiConnection::disconnect");
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
if inner.disconnector.is_some() {
|
if inner.disconnector.is_some() {
|
||||||
|
@ -182,7 +182,7 @@ Core Debug Commands:
|
|||||||
let capi = self.capi();
|
let capi = self.capi();
|
||||||
let ui = self.ui_sender();
|
let ui = self.ui_sender();
|
||||||
spawn_detached_local("cmd disconnect", async move {
|
spawn_detached_local("cmd disconnect", async move {
|
||||||
capi.disconnect().await;
|
capi.disconnect();
|
||||||
ui.send_callback(callback);
|
ui.send_callback(callback);
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -195,7 +195,7 @@ Core Debug Commands:
|
|||||||
|
|
||||||
let this = self.clone();
|
let this = self.clone();
|
||||||
spawn_detached_local("cmd connect", async move {
|
spawn_detached_local("cmd connect", async move {
|
||||||
capi.disconnect().await;
|
capi.disconnect();
|
||||||
|
|
||||||
if let Some(rest) = rest {
|
if let Some(rest) = rest {
|
||||||
if let Ok(subnode_index) = u16::from_str(&rest) {
|
if let Ok(subnode_index) = u16::from_str(&rest) {
|
||||||
@ -690,7 +690,7 @@ Core Debug Commands:
|
|||||||
////////////////////////////////////////////
|
////////////////////////////////////////////
|
||||||
pub fn start_connection(&self) {
|
pub fn start_connection(&self) {
|
||||||
self.inner_mut().reconnect = true;
|
self.inner_mut().reconnect = true;
|
||||||
self.inner_mut().connection_waker.resolve();
|
drop(self.inner_mut().connection_waker.resolve());
|
||||||
}
|
}
|
||||||
// pub fn stop_connection(&self) {
|
// pub fn stop_connection(&self) {
|
||||||
// self.inner_mut().reconnect = false;
|
// self.inner_mut().reconnect = false;
|
||||||
@ -701,12 +701,12 @@ Core Debug Commands:
|
|||||||
// }
|
// }
|
||||||
pub fn cancel_reconnect(&self) {
|
pub fn cancel_reconnect(&self) {
|
||||||
self.inner_mut().reconnect = false;
|
self.inner_mut().reconnect = false;
|
||||||
self.inner_mut().connection_waker.resolve();
|
drop(self.inner_mut().connection_waker.resolve());
|
||||||
}
|
}
|
||||||
pub fn quit(&self) {
|
pub fn quit(&self) {
|
||||||
self.inner_mut().finished = true;
|
self.inner_mut().finished = true;
|
||||||
self.inner_mut().reconnect = false;
|
self.inner_mut().reconnect = false;
|
||||||
self.inner_mut().connection_waker.resolve();
|
drop(self.inner_mut().connection_waker.resolve());
|
||||||
}
|
}
|
||||||
|
|
||||||
// called by ui
|
// called by ui
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
#![deny(clippy::all)]
|
|
||||||
#![allow(clippy::comparison_chain, clippy::upper_case_acronyms)]
|
|
||||||
#![deny(unused_must_use)]
|
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
use crate::{tools::*, ui::*};
|
use crate::{tools::*, ui::*};
|
||||||
@ -290,7 +287,7 @@ fn main() -> Result<(), String> {
|
|||||||
|
|
||||||
// When UI quits, close connection and command processor cleanly
|
// When UI quits, close connection and command processor cleanly
|
||||||
comproc2.quit();
|
comproc2.quit();
|
||||||
capi.disconnect().await;
|
capi.disconnect();
|
||||||
};
|
};
|
||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
|
@ -286,3 +286,6 @@ reqwest = { version = "0.11", features = ["blocking"], optional = true }
|
|||||||
|
|
||||||
[package.metadata.wasm-pack.profile.release]
|
[package.metadata.wasm-pack.profile.release]
|
||||||
wasm-opt = ["-O", "--enable-mutable-globals"]
|
wasm-opt = ["-O", "--enable-mutable-globals"]
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
@ -16,10 +16,10 @@ pub trait VeilidComponent:
|
|||||||
AsAnyArcSendSync + VeilidComponentRegistryAccessor + core::fmt::Debug
|
AsAnyArcSendSync + VeilidComponentRegistryAccessor + core::fmt::Debug
|
||||||
{
|
{
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
fn init(&self) -> SendPinBoxFutureLifetime<'_, EyreResult<()>>;
|
fn init(&self) -> PinBoxFuture<'_, EyreResult<()>>;
|
||||||
fn post_init(&self) -> SendPinBoxFutureLifetime<'_, EyreResult<()>>;
|
fn post_init(&self) -> PinBoxFuture<'_, EyreResult<()>>;
|
||||||
fn pre_terminate(&self) -> SendPinBoxFutureLifetime<'_, ()>;
|
fn pre_terminate(&self) -> PinBoxFuture<'_, ()>;
|
||||||
fn terminate(&self) -> SendPinBoxFutureLifetime<'_, ()>;
|
fn terminate(&self) -> PinBoxFuture<'_, ()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait VeilidComponentRegistryAccessor {
|
pub trait VeilidComponentRegistryAccessor {
|
||||||
@ -171,7 +171,7 @@ impl VeilidComponentRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Event bus starts up early
|
// Event bus starts up early
|
||||||
self.event_bus.startup().await?;
|
self.event_bus.startup()?;
|
||||||
|
|
||||||
// Process components in initialization order
|
// Process components in initialization order
|
||||||
let init_order = self.get_init_order();
|
let init_order = self.get_init_order();
|
||||||
@ -320,19 +320,19 @@ macro_rules! impl_veilid_component {
|
|||||||
stringify!($component_name)
|
stringify!($component_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(&self) -> SendPinBoxFutureLifetime<'_, EyreResult<()>> {
|
fn init(&self) -> PinBoxFuture<'_, EyreResult<()>> {
|
||||||
Box::pin(async { self.init_async().await })
|
Box::pin(async { self.init_async().await })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn post_init(&self) -> SendPinBoxFutureLifetime<'_, EyreResult<()>> {
|
fn post_init(&self) -> PinBoxFuture<'_, EyreResult<()>> {
|
||||||
Box::pin(async { self.post_init_async().await })
|
Box::pin(async { self.post_init_async().await })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pre_terminate(&self) -> SendPinBoxFutureLifetime<'_, ()> {
|
fn pre_terminate(&self) -> PinBoxFuture<'_, ()> {
|
||||||
Box::pin(async { self.pre_terminate_async().await })
|
Box::pin(async { self.pre_terminate_async().await })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn terminate(&self) -> SendPinBoxFutureLifetime<'_, ()> {
|
fn terminate(&self) -> PinBoxFuture<'_, ()> {
|
||||||
Box::pin(async { self.terminate_async().await })
|
Box::pin(async { self.terminate_async().await })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ pub struct Envelope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Envelope {
|
impl Envelope {
|
||||||
|
#[must_use]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
version: EnvelopeVersion,
|
version: EnvelopeVersion,
|
||||||
crypto_kind: CryptoKind,
|
crypto_kind: CryptoKind,
|
||||||
@ -314,6 +315,7 @@ impl Envelope {
|
|||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn get_version(&self) -> u8 {
|
pub fn get_version(&self) -> u8 {
|
||||||
self.version
|
self.version
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// Guard to access a particular cryptosystem
|
/// Guard to access a particular cryptosystem
|
||||||
|
#[must_use]
|
||||||
pub struct CryptoSystemGuard<'a> {
|
pub struct CryptoSystemGuard<'a> {
|
||||||
crypto_system: Arc<dyn CryptoSystem + Send + Sync>,
|
crypto_system: Arc<dyn CryptoSystem + Send + Sync>,
|
||||||
_phantom: core::marker::PhantomData<&'a (dyn CryptoSystem + Send + Sync)>,
|
_phantom: core::marker::PhantomData<&'a (dyn CryptoSystem + Send + Sync)>,
|
||||||
@ -27,6 +28,7 @@ impl<'a> core::ops::Deref for CryptoSystemGuard<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Async cryptosystem guard to help break up heavy blocking operations
|
/// Async cryptosystem guard to help break up heavy blocking operations
|
||||||
|
#[must_use]
|
||||||
pub struct AsyncCryptoSystemGuard<'a> {
|
pub struct AsyncCryptoSystemGuard<'a> {
|
||||||
guard: CryptoSystemGuard<'a>,
|
guard: CryptoSystemGuard<'a>,
|
||||||
}
|
}
|
||||||
@ -42,6 +44,7 @@ impl<'a> AsyncCryptoSystemGuard<'a> {
|
|||||||
pub fn kind(&self) -> CryptoKind {
|
pub fn kind(&self) -> CryptoKind {
|
||||||
self.guard.kind()
|
self.guard.kind()
|
||||||
}
|
}
|
||||||
|
#[must_use]
|
||||||
pub fn crypto(&self) -> VeilidComponentGuard<'_, Crypto> {
|
pub fn crypto(&self) -> VeilidComponentGuard<'_, Crypto> {
|
||||||
self.guard.crypto()
|
self.guard.crypto()
|
||||||
}
|
}
|
||||||
@ -59,6 +62,7 @@ impl<'a> AsyncCryptoSystemGuard<'a> {
|
|||||||
pub async fn random_bytes(&self, len: u32) -> Vec<u8> {
|
pub async fn random_bytes(&self, len: u32) -> Vec<u8> {
|
||||||
yielding(|| self.guard.random_bytes(len)).await
|
yielding(|| self.guard.random_bytes(len)).await
|
||||||
}
|
}
|
||||||
|
#[must_use]
|
||||||
pub fn default_salt_length(&self) -> u32 {
|
pub fn default_salt_length(&self) -> u32 {
|
||||||
self.guard.default_salt_length()
|
self.guard.default_salt_length()
|
||||||
}
|
}
|
||||||
@ -160,6 +164,7 @@ impl<'a> AsyncCryptoSystemGuard<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AEAD Encrypt/Decrypt
|
// AEAD Encrypt/Decrypt
|
||||||
|
#[must_use]
|
||||||
pub fn aead_overhead(&self) -> usize {
|
pub fn aead_overhead(&self) -> usize {
|
||||||
self.guard.aead_overhead()
|
self.guard.aead_overhead()
|
||||||
}
|
}
|
||||||
|
@ -67,13 +67,14 @@ pub const VALID_ENVELOPE_VERSIONS: [EnvelopeVersion; 1] = [0u8];
|
|||||||
/// Number of envelope versions to keep on structures if many are present beyond the ones we consider valid
|
/// Number of envelope versions to keep on structures if many are present beyond the ones we consider valid
|
||||||
pub const MAX_ENVELOPE_VERSIONS: usize = 3;
|
pub const MAX_ENVELOPE_VERSIONS: usize = 3;
|
||||||
/// Return the best envelope version we support
|
/// Return the best envelope version we support
|
||||||
|
#[must_use]
|
||||||
pub fn best_envelope_version() -> EnvelopeVersion {
|
pub fn best_envelope_version() -> EnvelopeVersion {
|
||||||
VALID_ENVELOPE_VERSIONS[0]
|
VALID_ENVELOPE_VERSIONS[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CryptoInner {
|
struct CryptoInner {
|
||||||
dh_cache: DHCache,
|
dh_cache: DHCache,
|
||||||
flush_future: Option<SendPinBoxFuture<()>>,
|
flush_future: Option<PinBoxFutureStatic<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for CryptoInner {
|
impl fmt::Debug for CryptoInner {
|
||||||
@ -88,6 +89,7 @@ impl fmt::Debug for CryptoInner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Crypto factory implementation
|
/// Crypto factory implementation
|
||||||
|
#[must_use]
|
||||||
pub struct Crypto {
|
pub struct Crypto {
|
||||||
registry: VeilidComponentRegistry,
|
registry: VeilidComponentRegistry,
|
||||||
inner: Mutex<CryptoInner>,
|
inner: Mutex<CryptoInner>,
|
||||||
@ -221,6 +223,7 @@ impl Crypto {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
async fn terminate_async(&self) {
|
async fn terminate_async(&self) {
|
||||||
// Nothing to terminate at this time
|
// Nothing to terminate at this time
|
||||||
}
|
}
|
||||||
|
@ -196,6 +196,7 @@ impl Receipt {
|
|||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn get_version(&self) -> u8 {
|
pub fn get_version(&self) -> u8 {
|
||||||
self.version
|
self.version
|
||||||
}
|
}
|
||||||
@ -216,6 +217,7 @@ impl Receipt {
|
|||||||
TypedKey::new(self.crypto_kind, self.sender_id)
|
TypedKey::new(self.crypto_kind, self.sender_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn get_extra_data(&self) -> &[u8] {
|
pub fn get_extra_data(&self) -> &[u8] {
|
||||||
&self.extra_data
|
&self.extra_data
|
||||||
}
|
}
|
||||||
|
@ -221,11 +221,11 @@ pub async fn test_generation(vcrypto: &AsyncCryptoSystemGuard<'_>) {
|
|||||||
let pstr5 = vcrypto.hash_password(b"abc124", b"qwerasdg").await.unwrap();
|
let pstr5 = vcrypto.hash_password(b"abc124", b"qwerasdg").await.unwrap();
|
||||||
assert_ne!(pstr3, pstr5);
|
assert_ne!(pstr3, pstr5);
|
||||||
|
|
||||||
vcrypto
|
let _ = vcrypto
|
||||||
.hash_password(b"abc123", b"qwe")
|
.hash_password(b"abc123", b"qwe")
|
||||||
.await
|
.await
|
||||||
.expect_err("should reject short salt");
|
.expect_err("should reject short salt");
|
||||||
vcrypto
|
let _ = vcrypto
|
||||||
.hash_password(
|
.hash_password(
|
||||||
b"abc123",
|
b"abc123",
|
||||||
b"qwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerz",
|
b"qwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerz",
|
||||||
@ -249,11 +249,11 @@ pub async fn test_generation(vcrypto: &AsyncCryptoSystemGuard<'_>) {
|
|||||||
let ss5 = vcrypto.derive_shared_secret(b"abc124", b"qwerasdg").await;
|
let ss5 = vcrypto.derive_shared_secret(b"abc124", b"qwerasdg").await;
|
||||||
assert_ne!(ss3, ss5);
|
assert_ne!(ss3, ss5);
|
||||||
|
|
||||||
vcrypto
|
let _ = vcrypto
|
||||||
.derive_shared_secret(b"abc123", b"qwe")
|
.derive_shared_secret(b"abc123", b"qwe")
|
||||||
.await
|
.await
|
||||||
.expect_err("should reject short salt");
|
.expect_err("should reject short salt");
|
||||||
vcrypto
|
let _ = vcrypto
|
||||||
.derive_shared_secret(
|
.derive_shared_secret(
|
||||||
b"abc123",
|
b"abc123",
|
||||||
b"qwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerz",
|
b"qwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerz",
|
||||||
|
@ -91,7 +91,7 @@ pub async fn test_receipt_round_trip(
|
|||||||
|
|
||||||
// Should not validate even when a single bit is changed
|
// Should not validate even when a single bit is changed
|
||||||
enc_data[5] = 0x01;
|
enc_data[5] = 0x01;
|
||||||
Receipt::from_signed_data(&crypto, &enc_data)
|
let _ = Receipt::from_signed_data(&crypto, &enc_data)
|
||||||
.expect_err("should have failed to decrypt using wrong secret");
|
.expect_err("should have failed to decrypt using wrong secret");
|
||||||
|
|
||||||
// Compare receipts
|
// Compare receipts
|
||||||
|
@ -253,7 +253,7 @@ pub async fn test_encode_decode(vcrypto: &AsyncCryptoSystemGuard<'_>) {
|
|||||||
assert!(f2.is_err());
|
assert!(f2.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_typed_convert(vcrypto: &AsyncCryptoSystemGuard<'_>) {
|
pub fn test_typed_convert(vcrypto: &AsyncCryptoSystemGuard<'_>) {
|
||||||
let tks1 = format!(
|
let tks1 = format!(
|
||||||
"{}:7lxDEabK_qgjbe38RtBa3IZLrud84P6NhGP-pRTZzdQ",
|
"{}:7lxDEabK_qgjbe38RtBa3IZLrud84P6NhGP-pRTZzdQ",
|
||||||
vcrypto.kind()
|
vcrypto.kind()
|
||||||
@ -381,7 +381,7 @@ async fn test_operations(vcrypto: &AsyncCryptoSystemGuard<'_>) {
|
|||||||
assert_eq!(d4.first_nonzero_bit(), Some(0));
|
assert_eq!(d4.first_nonzero_bit(), Some(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_crypto_key_ordering() {
|
pub fn test_crypto_key_ordering() {
|
||||||
let k1 = CryptoKey::new([
|
let k1 = CryptoKey::new([
|
||||||
128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0,
|
0, 0,
|
||||||
@ -413,7 +413,7 @@ pub async fn test_all() {
|
|||||||
let api = crypto_tests_startup().await;
|
let api = crypto_tests_startup().await;
|
||||||
let crypto = api.crypto().unwrap();
|
let crypto = api.crypto().unwrap();
|
||||||
|
|
||||||
test_crypto_key_ordering().await;
|
test_crypto_key_ordering();
|
||||||
|
|
||||||
// Test versions
|
// Test versions
|
||||||
for v in VALID_CRYPTO_KINDS {
|
for v in VALID_CRYPTO_KINDS {
|
||||||
@ -423,7 +423,7 @@ pub async fn test_all() {
|
|||||||
test_sign_and_verify(&vcrypto).await;
|
test_sign_and_verify(&vcrypto).await;
|
||||||
test_key_conversions(&vcrypto).await;
|
test_key_conversions(&vcrypto).await;
|
||||||
test_encode_decode(&vcrypto).await;
|
test_encode_decode(&vcrypto).await;
|
||||||
test_typed_convert(&vcrypto).await;
|
test_typed_convert(&vcrypto);
|
||||||
test_hash(&vcrypto).await;
|
test_hash(&vcrypto).await;
|
||||||
test_operations(&vcrypto).await;
|
test_operations(&vcrypto).await;
|
||||||
}
|
}
|
||||||
|
@ -83,6 +83,7 @@ macro_rules! byte_array_type {
|
|||||||
derive(Tsify),
|
derive(Tsify),
|
||||||
tsify(into_wasm_abi)
|
tsify(into_wasm_abi)
|
||||||
)]
|
)]
|
||||||
|
#[must_use]
|
||||||
pub struct $name {
|
pub struct $name {
|
||||||
pub bytes: [u8; $size],
|
pub bytes: [u8; $size],
|
||||||
}
|
}
|
||||||
@ -124,6 +125,7 @@ macro_rules! byte_array_type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Big endian bit ordering
|
// Big endian bit ordering
|
||||||
|
#[must_use]
|
||||||
pub fn bit(&self, index: usize) -> bool {
|
pub fn bit(&self, index: usize) -> bool {
|
||||||
assert!(index < ($size * 8));
|
assert!(index < ($size * 8));
|
||||||
let bi = index / 8;
|
let bi = index / 8;
|
||||||
@ -131,6 +133,7 @@ macro_rules! byte_array_type {
|
|||||||
((self.bytes[bi] >> ti) & 1) != 0
|
((self.bytes[bi] >> ti) & 1) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn first_nonzero_bit(&self) -> Option<usize> {
|
pub fn first_nonzero_bit(&self) -> Option<usize> {
|
||||||
for i in 0..$size {
|
for i in 0..$size {
|
||||||
let b = self.bytes[i];
|
let b = self.bytes[i];
|
||||||
@ -147,6 +150,7 @@ macro_rules! byte_array_type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Big endian nibble ordering
|
// Big endian nibble ordering
|
||||||
|
#[must_use]
|
||||||
pub fn nibble(&self, index: usize) -> u8 {
|
pub fn nibble(&self, index: usize) -> u8 {
|
||||||
assert!(index < ($size * 2));
|
assert!(index < ($size * 2));
|
||||||
let bi = index / 2;
|
let bi = index / 2;
|
||||||
@ -157,6 +161,7 @@ macro_rules! byte_array_type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn first_nonzero_nibble(&self) -> Option<(usize, u8)> {
|
pub fn first_nonzero_nibble(&self) -> Option<(usize, u8)> {
|
||||||
for i in 0..($size * 2) {
|
for i in 0..($size * 2) {
|
||||||
let n = self.nibble(i);
|
let n = self.nibble(i);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
|
#[must_use]
|
||||||
pub struct CryptoTyped<K>
|
pub struct CryptoTyped<K>
|
||||||
where
|
where
|
||||||
K: Clone
|
K: Clone
|
||||||
|
@ -33,9 +33,11 @@ where
|
|||||||
+ Hash
|
+ Hash
|
||||||
+ Encodable,
|
+ Encodable,
|
||||||
{
|
{
|
||||||
|
#[must_use]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self { items: Vec::new() }
|
Self { items: Vec::new() }
|
||||||
}
|
}
|
||||||
|
#[must_use]
|
||||||
pub fn with_capacity(cap: usize) -> Self {
|
pub fn with_capacity(cap: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
items: Vec::with_capacity(cap),
|
items: Vec::with_capacity(cap),
|
||||||
@ -49,6 +51,7 @@ where
|
|||||||
out.sort_by(compare_crypto_kind);
|
out.sort_by(compare_crypto_kind);
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
#[must_use]
|
||||||
pub fn keys(&self) -> Vec<K> {
|
pub fn keys(&self) -> Vec<K> {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
for tk in &self.items {
|
for tk in &self.items {
|
||||||
@ -56,6 +59,7 @@ where
|
|||||||
}
|
}
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
#[must_use]
|
||||||
pub fn get(&self, kind: CryptoKind) -> Option<CryptoTyped<K>> {
|
pub fn get(&self, kind: CryptoKind) -> Option<CryptoTyped<K>> {
|
||||||
self.items.iter().find(|x| x.kind == kind).copied()
|
self.items.iter().find(|x| x.kind == kind).copied()
|
||||||
}
|
}
|
||||||
@ -93,15 +97,18 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Return preferred typed key of our supported crypto kinds
|
/// Return preferred typed key of our supported crypto kinds
|
||||||
|
#[must_use]
|
||||||
pub fn best(&self) -> Option<CryptoTyped<K>> {
|
pub fn best(&self) -> Option<CryptoTyped<K>> {
|
||||||
self.items
|
self.items
|
||||||
.first()
|
.first()
|
||||||
.copied()
|
.copied()
|
||||||
.filter(|k| VALID_CRYPTO_KINDS.contains(&k.kind))
|
.filter(|k| VALID_CRYPTO_KINDS.contains(&k.kind))
|
||||||
}
|
}
|
||||||
|
#[must_use]
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.items.is_empty()
|
self.items.is_empty()
|
||||||
}
|
}
|
||||||
|
#[must_use]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.items.len()
|
self.items.len()
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ use super::*;
|
|||||||
derive(Tsify),
|
derive(Tsify),
|
||||||
tsify(from_wasm_abi, into_wasm_abi)
|
tsify(from_wasm_abi, into_wasm_abi)
|
||||||
)]
|
)]
|
||||||
|
#[must_use]
|
||||||
pub struct KeyPair {
|
pub struct KeyPair {
|
||||||
pub key: PublicKey,
|
pub key: PublicKey,
|
||||||
pub secret: SecretKey,
|
pub secret: SecretKey,
|
||||||
|
@ -11,6 +11,7 @@ pub type CryptoKind = FourCC;
|
|||||||
|
|
||||||
/// Sort best crypto kinds first
|
/// Sort best crypto kinds first
|
||||||
/// Better crypto kinds are 'less', ordered toward the front of a list
|
/// Better crypto kinds are 'less', ordered toward the front of a list
|
||||||
|
#[must_use]
|
||||||
pub fn compare_crypto_kind(a: &CryptoKind, b: &CryptoKind) -> cmp::Ordering {
|
pub fn compare_crypto_kind(a: &CryptoKind, b: &CryptoKind) -> cmp::Ordering {
|
||||||
let a_idx = VALID_CRYPTO_KINDS.iter().position(|k| k == a);
|
let a_idx = VALID_CRYPTO_KINDS.iter().position(|k| k == a);
|
||||||
let b_idx = VALID_CRYPTO_KINDS.iter().position(|k| k == b);
|
let b_idx = VALID_CRYPTO_KINDS.iter().position(|k| k == b);
|
||||||
@ -32,6 +33,7 @@ pub fn compare_crypto_kind(a: &CryptoKind, b: &CryptoKind) -> cmp::Ordering {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Intersection of crypto kind vectors
|
/// Intersection of crypto kind vectors
|
||||||
|
#[must_use]
|
||||||
pub fn common_crypto_kinds(a: &[CryptoKind], b: &[CryptoKind]) -> Vec<CryptoKind> {
|
pub fn common_crypto_kinds(a: &[CryptoKind], b: &[CryptoKind]) -> Vec<CryptoKind> {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
for ack in a {
|
for ack in a {
|
||||||
|
@ -52,6 +52,7 @@ pub struct CryptoSystemVLD0 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CryptoSystemVLD0 {
|
impl CryptoSystemVLD0 {
|
||||||
|
#[must_use]
|
||||||
pub fn new(registry: VeilidComponentRegistry) -> Self {
|
pub fn new(registry: VeilidComponentRegistry) -> Self {
|
||||||
Self { registry }
|
Self { registry }
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ impl fmt::Debug for BlockStoreInner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[must_use]
|
||||||
pub struct BlockStore {
|
pub struct BlockStore {
|
||||||
registry: VeilidComponentRegistry,
|
registry: VeilidComponentRegistry,
|
||||||
inner: Mutex<BlockStoreInner>,
|
inner: Mutex<BlockStoreInner>,
|
||||||
@ -31,12 +32,19 @@ impl BlockStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn init_async(&self) -> EyreResult<()> {
|
async fn init_async(&self) -> EyreResult<()> {
|
||||||
// Ensure permissions are correct
|
|
||||||
// ensure_file_private_owner(&dbpath)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self), err)]
|
||||||
|
async fn post_init_async(&self) -> EyreResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self))]
|
||||||
|
async fn pre_terminate_async(&self) {}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn terminate_async(&self) {}
|
async fn terminate_async(&self) {}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ impl fmt::Debug for ProtectedStoreInner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[must_use]
|
||||||
pub struct ProtectedStore {
|
pub struct ProtectedStore {
|
||||||
registry: VeilidComponentRegistry,
|
registry: VeilidComponentRegistry,
|
||||||
inner: Mutex<ProtectedStoreInner>,
|
inner: Mutex<ProtectedStoreInner>,
|
||||||
@ -37,9 +38,9 @@ impl ProtectedStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self), err)]
|
#[instrument(level = "trace", skip(self), err)]
|
||||||
pub async fn delete_all(&self) -> EyreResult<()> {
|
pub fn delete_all(&self) -> EyreResult<()> {
|
||||||
for kpsk in &KNOWN_PROTECTED_STORE_KEYS {
|
for kpsk in &KNOWN_PROTECTED_STORE_KEYS {
|
||||||
if let Err(e) = self.remove_user_secret(kpsk).await {
|
if let Err(e) = self.remove_user_secret(kpsk) {
|
||||||
error!("failed to delete '{}': {}", kpsk, e);
|
error!("failed to delete '{}': {}", kpsk, e);
|
||||||
} else {
|
} else {
|
||||||
veilid_log!(self debug "deleted table '{}'", kpsk);
|
veilid_log!(self debug "deleted table '{}'", kpsk);
|
||||||
@ -103,7 +104,7 @@ impl ProtectedStore {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if delete {
|
if delete {
|
||||||
self.delete_all().await?;
|
self.delete_all()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -133,7 +134,7 @@ impl ProtectedStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self, value), ret, err)]
|
#[instrument(level = "trace", skip(self, value), ret, err)]
|
||||||
pub async fn save_user_secret_string<K: AsRef<str> + fmt::Debug, V: AsRef<str> + fmt::Debug>(
|
pub fn save_user_secret_string<K: AsRef<str> + fmt::Debug, V: AsRef<str> + fmt::Debug>(
|
||||||
&self,
|
&self,
|
||||||
key: K,
|
key: K,
|
||||||
value: V,
|
value: V,
|
||||||
@ -152,7 +153,7 @@ impl ProtectedStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self), err)]
|
#[instrument(level = "trace", skip(self), err)]
|
||||||
pub async fn load_user_secret_string<K: AsRef<str> + fmt::Debug>(
|
pub fn load_user_secret_string<K: AsRef<str> + fmt::Debug>(
|
||||||
&self,
|
&self,
|
||||||
key: K,
|
key: K,
|
||||||
) -> EyreResult<Option<String>> {
|
) -> EyreResult<Option<String>> {
|
||||||
@ -170,22 +171,22 @@ impl ProtectedStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self, value))]
|
#[instrument(level = "trace", skip(self, value))]
|
||||||
pub async fn save_user_secret_json<K, T>(&self, key: K, value: &T) -> EyreResult<bool>
|
pub fn save_user_secret_json<K, T>(&self, key: K, value: &T) -> EyreResult<bool>
|
||||||
where
|
where
|
||||||
K: AsRef<str> + fmt::Debug,
|
K: AsRef<str> + fmt::Debug,
|
||||||
T: serde::Serialize,
|
T: serde::Serialize,
|
||||||
{
|
{
|
||||||
let v = serde_json::to_vec(value)?;
|
let v = serde_json::to_vec(value)?;
|
||||||
self.save_user_secret(&key, &v).await
|
self.save_user_secret(&key, &v)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self))]
|
#[instrument(level = "trace", skip(self))]
|
||||||
pub async fn load_user_secret_json<K, T>(&self, key: K) -> EyreResult<Option<T>>
|
pub fn load_user_secret_json<K, T>(&self, key: K) -> EyreResult<Option<T>>
|
||||||
where
|
where
|
||||||
K: AsRef<str> + fmt::Debug,
|
K: AsRef<str> + fmt::Debug,
|
||||||
T: for<'de> serde::de::Deserialize<'de>,
|
T: for<'de> serde::de::Deserialize<'de>,
|
||||||
{
|
{
|
||||||
let out = self.load_user_secret(key).await?;
|
let out = self.load_user_secret(key)?;
|
||||||
let b = match out {
|
let b = match out {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => {
|
None => {
|
||||||
@ -198,7 +199,7 @@ impl ProtectedStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self, value), ret, err)]
|
#[instrument(level = "trace", skip(self, value), ret, err)]
|
||||||
pub async fn save_user_secret<K: AsRef<str> + fmt::Debug>(
|
pub fn save_user_secret<K: AsRef<str> + fmt::Debug>(
|
||||||
&self,
|
&self,
|
||||||
key: K,
|
key: K,
|
||||||
value: &[u8],
|
value: &[u8],
|
||||||
@ -206,15 +207,15 @@ impl ProtectedStore {
|
|||||||
let mut s = BASE64URL_NOPAD.encode(value);
|
let mut s = BASE64URL_NOPAD.encode(value);
|
||||||
s.push('!');
|
s.push('!');
|
||||||
|
|
||||||
self.save_user_secret_string(key, s.as_str()).await
|
self.save_user_secret_string(key, s.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self), err)]
|
#[instrument(level = "trace", skip(self), err)]
|
||||||
pub async fn load_user_secret<K: AsRef<str> + fmt::Debug>(
|
pub fn load_user_secret<K: AsRef<str> + fmt::Debug>(
|
||||||
&self,
|
&self,
|
||||||
key: K,
|
key: K,
|
||||||
) -> EyreResult<Option<Vec<u8>>> {
|
) -> EyreResult<Option<Vec<u8>>> {
|
||||||
let mut s = match self.load_user_secret_string(key).await? {
|
let mut s = match self.load_user_secret_string(key)? {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
None => {
|
None => {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
@ -244,7 +245,7 @@ impl ProtectedStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self), ret, err)]
|
#[instrument(level = "trace", skip(self), ret, err)]
|
||||||
pub async fn remove_user_secret<K: AsRef<str> + fmt::Debug>(&self, key: K) -> EyreResult<bool> {
|
pub fn remove_user_secret<K: AsRef<str> + fmt::Debug>(&self, key: K) -> EyreResult<bool> {
|
||||||
let inner = self.inner.lock();
|
let inner = self.inner.lock();
|
||||||
match inner
|
match inner
|
||||||
.keyring_manager
|
.keyring_manager
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
pub async fn get_outbound_relay_peer(
|
pub async fn get_outbound_relay_peer(
|
||||||
_routing_domain: routing_table::RoutingDomain,
|
_routing_domain: routing_table::RoutingDomain,
|
||||||
) -> Option<Arc<routing_table::PeerInfo>> {
|
) -> Option<Arc<routing_table::PeerInfo>> {
|
||||||
@ -22,6 +23,7 @@ cfg_if! {
|
|||||||
} else if #[cfg(feature="rt-tokio")] {
|
} else if #[cfg(feature="rt-tokio")] {
|
||||||
use hickory_resolver::{config, TokioAsyncResolver as AsyncResolver, system_conf::read_system_conf};
|
use hickory_resolver::{config, TokioAsyncResolver as AsyncResolver, system_conf::read_system_conf};
|
||||||
|
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
async fn resolver(
|
async fn resolver(
|
||||||
config: config::ResolverConfig,
|
config: config::ResolverConfig,
|
||||||
options: config::ResolverOpts,
|
options: config::ResolverOpts,
|
||||||
@ -48,7 +50,7 @@ cfg_if! {
|
|||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(not(target_os = "windows"))] {
|
if #[cfg(not(target_os = "windows"))] {
|
||||||
|
|
||||||
async fn with_resolvers<R, F: FnOnce(Arc<Resolvers>) -> SendPinBoxFuture<R>>(closure: F) -> R {
|
async fn with_resolvers<R, F: FnOnce(Arc<Resolvers>) -> PinBoxFutureStatic<R>>(closure: F) -> R {
|
||||||
let mut resolvers_lock = RESOLVERS.lock().await;
|
let mut resolvers_lock = RESOLVERS.lock().await;
|
||||||
if let Some(r) = &*resolvers_lock {
|
if let Some(r) = &*resolvers_lock {
|
||||||
return closure(r.clone()).await;
|
return closure(r.clone()).await;
|
||||||
@ -232,6 +234,7 @@ pub async fn ptr_lookup(ip_addr: IpAddr) -> EyreResult<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn env_variable_is_defined<S: AsRef<str>>(s: S) -> bool {
|
pub fn env_variable_is_defined<S: AsRef<str>>(s: S) -> bool {
|
||||||
match std::env::var(s.as_ref()) {
|
match std::env::var(s.as_ref()) {
|
||||||
Ok(v) => !v.is_empty(),
|
Ok(v) => !v.is_empty(),
|
||||||
|
@ -13,6 +13,7 @@ impl fmt::Debug for BlockStoreInner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[must_use]
|
||||||
pub struct BlockStore {
|
pub struct BlockStore {
|
||||||
registry: VeilidComponentRegistry,
|
registry: VeilidComponentRegistry,
|
||||||
inner: Mutex<BlockStoreInner>,
|
inner: Mutex<BlockStoreInner>,
|
||||||
@ -31,9 +32,19 @@ impl BlockStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn init_async(&self) -> EyreResult<()> {
|
async fn init_async(&self) -> EyreResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self), err)]
|
||||||
|
async fn post_init_async(&self) -> EyreResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self))]
|
||||||
|
async fn pre_terminate_async(&self) {}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn terminate_async(&self) {}
|
async fn terminate_async(&self) {}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ use web_sys::*;
|
|||||||
impl_veilid_log_facility!("pstore");
|
impl_veilid_log_facility!("pstore");
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[must_use]
|
||||||
pub struct ProtectedStore {
|
pub struct ProtectedStore {
|
||||||
registry: VeilidComponentRegistry,
|
registry: VeilidComponentRegistry,
|
||||||
}
|
}
|
||||||
@ -18,9 +19,9 @@ impl ProtectedStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self), err)]
|
#[instrument(level = "trace", skip(self), err)]
|
||||||
pub async fn delete_all(&self) -> EyreResult<()> {
|
pub fn delete_all(&self) -> EyreResult<()> {
|
||||||
for kpsk in &KNOWN_PROTECTED_STORE_KEYS {
|
for kpsk in &KNOWN_PROTECTED_STORE_KEYS {
|
||||||
if let Err(e) = self.remove_user_secret(kpsk).await {
|
if let Err(e) = self.remove_user_secret(kpsk) {
|
||||||
error!("failed to delete '{}': {}", kpsk, e);
|
error!("failed to delete '{}': {}", kpsk, e);
|
||||||
} else {
|
} else {
|
||||||
veilid_log!(self debug "deleted table '{}'", kpsk);
|
veilid_log!(self debug "deleted table '{}'", kpsk);
|
||||||
@ -30,20 +31,20 @@ impl ProtectedStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self), err)]
|
#[instrument(level = "debug", skip(self), err)]
|
||||||
pub(crate) async fn init_async(&self) -> EyreResult<()> {
|
async fn init_async(&self) -> EyreResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self), err)]
|
#[instrument(level = "debug", skip(self), err)]
|
||||||
pub(crate) async fn post_init_async(&self) -> EyreResult<()> {
|
async fn post_init_async(&self) -> EyreResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
pub(crate) async fn pre_terminate_async(&self) {}
|
async fn pre_terminate_async(&self) {}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
pub(crate) async fn terminate_async(&self) {}
|
async fn terminate_async(&self) {}
|
||||||
|
|
||||||
fn browser_key_name(&self, key: &str) -> String {
|
fn browser_key_name(&self, key: &str) -> String {
|
||||||
let config = self.config();
|
let config = self.config();
|
||||||
@ -55,8 +56,8 @@ impl ProtectedStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#[instrument(level = "trace", skip(self, value), ret, err)]
|
#[instrument(level = "trace", skip(self, key, value))]
|
||||||
pub async fn save_user_secret_string<K: AsRef<str> + fmt::Debug, V: AsRef<str> + fmt::Debug>(
|
pub fn save_user_secret_string<K: AsRef<str> + fmt::Debug, V: AsRef<str> + fmt::Debug>(
|
||||||
&self,
|
&self,
|
||||||
key: K,
|
key: K,
|
||||||
value: V,
|
value: V,
|
||||||
@ -98,8 +99,8 @@ impl ProtectedStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self), err)]
|
#[instrument(level = "trace", skip(self, key))]
|
||||||
pub async fn load_user_secret_string<K: AsRef<str> + fmt::Debug>(
|
pub fn load_user_secret_string<K: AsRef<str> + fmt::Debug>(
|
||||||
&self,
|
&self,
|
||||||
key: K,
|
key: K,
|
||||||
) -> EyreResult<Option<String>> {
|
) -> EyreResult<Option<String>> {
|
||||||
@ -133,22 +134,22 @@ impl ProtectedStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self, value))]
|
#[instrument(level = "trace", skip(self, value))]
|
||||||
pub async fn save_user_secret_json<K, T>(&self, key: K, value: &T) -> EyreResult<bool>
|
pub fn save_user_secret_json<K, T>(&self, key: K, value: &T) -> EyreResult<bool>
|
||||||
where
|
where
|
||||||
K: AsRef<str> + fmt::Debug,
|
K: AsRef<str> + fmt::Debug,
|
||||||
T: serde::Serialize,
|
T: serde::Serialize,
|
||||||
{
|
{
|
||||||
let v = serde_json::to_vec(value)?;
|
let v = serde_json::to_vec(value)?;
|
||||||
self.save_user_secret(key, &v).await
|
self.save_user_secret(key, &v)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self))]
|
#[instrument(level = "trace", skip(self))]
|
||||||
pub async fn load_user_secret_json<K, T>(&self, key: K) -> EyreResult<Option<T>>
|
pub fn load_user_secret_json<K, T>(&self, key: K) -> EyreResult<Option<T>>
|
||||||
where
|
where
|
||||||
K: AsRef<str> + fmt::Debug,
|
K: AsRef<str> + fmt::Debug,
|
||||||
T: for<'de> serde::de::Deserialize<'de>,
|
T: for<'de> serde::de::Deserialize<'de>,
|
||||||
{
|
{
|
||||||
let out = self.load_user_secret(key).await?;
|
let out = self.load_user_secret(key)?;
|
||||||
let b = match out {
|
let b = match out {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => {
|
None => {
|
||||||
@ -161,7 +162,7 @@ impl ProtectedStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self, value), ret, err)]
|
#[instrument(level = "trace", skip(self, value), ret, err)]
|
||||||
pub async fn save_user_secret<K: AsRef<str> + fmt::Debug>(
|
pub fn save_user_secret<K: AsRef<str> + fmt::Debug>(
|
||||||
&self,
|
&self,
|
||||||
key: K,
|
key: K,
|
||||||
value: &[u8],
|
value: &[u8],
|
||||||
@ -169,15 +170,15 @@ impl ProtectedStore {
|
|||||||
let mut s = BASE64URL_NOPAD.encode(value);
|
let mut s = BASE64URL_NOPAD.encode(value);
|
||||||
s.push('!');
|
s.push('!');
|
||||||
|
|
||||||
self.save_user_secret_string(key, s.as_str()).await
|
self.save_user_secret_string(key, s.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self), err)]
|
#[instrument(level = "trace", skip(self), err)]
|
||||||
pub async fn load_user_secret<K: AsRef<str> + fmt::Debug>(
|
pub fn load_user_secret<K: AsRef<str> + fmt::Debug>(
|
||||||
&self,
|
&self,
|
||||||
key: K,
|
key: K,
|
||||||
) -> EyreResult<Option<Vec<u8>>> {
|
) -> EyreResult<Option<Vec<u8>>> {
|
||||||
let mut s = match self.load_user_secret_string(key).await? {
|
let mut s = match self.load_user_secret_string(key)? {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
None => {
|
None => {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
@ -207,7 +208,7 @@ impl ProtectedStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self), ret, err)]
|
#[instrument(level = "trace", skip(self), ret, err)]
|
||||||
pub async fn remove_user_secret<K: AsRef<str> + fmt::Debug>(&self, key: K) -> EyreResult<bool> {
|
pub fn remove_user_secret<K: AsRef<str> + fmt::Debug>(&self, key: K) -> EyreResult<bool> {
|
||||||
if is_browser() {
|
if is_browser() {
|
||||||
let win = match window() {
|
let win = match window() {
|
||||||
Some(w) => w,
|
Some(w) => w,
|
||||||
|
@ -2,6 +2,7 @@ use super::*;
|
|||||||
|
|
||||||
//use js_sys::*;
|
//use js_sys::*;
|
||||||
|
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
pub async fn get_outbound_relay_peer(
|
pub async fn get_outbound_relay_peer(
|
||||||
_routing_domain: routing_table::RoutingDomain,
|
_routing_domain: routing_table::RoutingDomain,
|
||||||
) -> Option<Arc<routing_table::PeerInfo>> {
|
) -> Option<Arc<routing_table::PeerInfo>> {
|
||||||
@ -34,14 +35,17 @@ pub async fn get_outbound_relay_peer(
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
pub async fn txt_lookup<S: AsRef<str>>(_host: S) -> EyreResult<Vec<String>> {
|
pub async fn txt_lookup<S: AsRef<str>>(_host: S) -> EyreResult<Vec<String>> {
|
||||||
bail!("wasm does not support txt lookup")
|
bail!("wasm does not support txt lookup")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
pub async fn ptr_lookup(_ip_addr: IpAddr) -> EyreResult<String> {
|
pub async fn ptr_lookup(_ip_addr: IpAddr) -> EyreResult<String> {
|
||||||
bail!("wasm does not support ptr lookup")
|
bail!("wasm does not support ptr lookup")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn env_variable_is_defined<S: AsRef<str>>(_s: S) -> bool {
|
pub fn env_variable_is_defined<S: AsRef<str>>(_s: S) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,6 @@
|
|||||||
//! * `default-wasm` - When building for the `wasm32` architecture, use this to enable `wasm-bindgen-futures` as the async runtime.
|
//! * `default-wasm` - When building for the `wasm32` architecture, use this to enable `wasm-bindgen-futures` as the async runtime.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
#![deny(clippy::all)]
|
|
||||||
#![allow(clippy::comparison_chain, clippy::upper_case_acronyms)]
|
|
||||||
#![deny(unused_must_use)]
|
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
@ -73,6 +70,16 @@ pub use veilid_tools as tools;
|
|||||||
|
|
||||||
/// The on-the-wire serialization format for Veilid RPC.
|
/// The on-the-wire serialization format for Veilid RPC.
|
||||||
pub mod veilid_capnp {
|
pub mod veilid_capnp {
|
||||||
|
#![allow(
|
||||||
|
clippy::all,
|
||||||
|
clippy::must_use_candidate,
|
||||||
|
clippy::large_futures,
|
||||||
|
clippy::large_stack_arrays,
|
||||||
|
clippy::large_stack_frames,
|
||||||
|
clippy::large_types_passed_by_value,
|
||||||
|
clippy::unused_async,
|
||||||
|
clippy::ptr_cast_constness
|
||||||
|
)]
|
||||||
include!("../proto/veilid_capnp.rs");
|
include!("../proto/veilid_capnp.rs");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,11 +87,13 @@ pub mod veilid_capnp {
|
|||||||
pub mod tests;
|
pub mod tests;
|
||||||
|
|
||||||
/// Return the cargo package version of veilid-core in string format.
|
/// Return the cargo package version of veilid-core in string format.
|
||||||
|
#[must_use]
|
||||||
pub fn veilid_version_string() -> String {
|
pub fn veilid_version_string() -> String {
|
||||||
env!("CARGO_PKG_VERSION").to_owned()
|
env!("CARGO_PKG_VERSION").to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the cargo package version of veilid-core in tuple format.
|
/// Return the cargo package version of veilid-core in tuple format.
|
||||||
|
#[must_use]
|
||||||
pub fn veilid_version() -> (u32, u32, u32) {
|
pub fn veilid_version() -> (u32, u32, u32) {
|
||||||
(
|
(
|
||||||
u32::from_str(env!("CARGO_PKG_VERSION_MAJOR")).unwrap(),
|
u32::from_str(env!("CARGO_PKG_VERSION_MAJOR")).unwrap(),
|
||||||
|
@ -20,6 +20,7 @@ struct ApiTracingLayerInner {
|
|||||||
/// with many copies of Veilid running.
|
/// with many copies of Veilid running.
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
#[must_use]
|
||||||
pub struct ApiTracingLayer {}
|
pub struct ApiTracingLayer {}
|
||||||
|
|
||||||
static API_LOGGER_INNER: Mutex<Option<ApiTracingLayerInner>> = Mutex::new(None);
|
static API_LOGGER_INNER: Mutex<Option<ApiTracingLayerInner>> = Mutex::new(None);
|
||||||
|
@ -7,6 +7,7 @@ use tracing_subscriber::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub struct FmtStripFields {
|
pub struct FmtStripFields {
|
||||||
/// The inner formatter that will be used to format fields
|
/// The inner formatter that will be used to format fields
|
||||||
fmt: DefaultFields,
|
fmt: DefaultFields,
|
||||||
|
@ -11,6 +11,7 @@ struct VeilidLayerFilterInner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidLayerFilter {
|
pub struct VeilidLayerFilter {
|
||||||
inner: Arc<RwLock<VeilidLayerFilterInner>>,
|
inner: Arc<RwLock<VeilidLayerFilterInner>>,
|
||||||
}
|
}
|
||||||
@ -19,6 +20,7 @@ pub const VEILID_LOG_KEY_FIELD: &str = "__VEILID_LOG_KEY";
|
|||||||
pub type VeilidLayerLogKeyFilter = Arc<dyn Fn(&str) -> bool + Send + Sync>;
|
pub type VeilidLayerLogKeyFilter = Arc<dyn Fn(&str) -> bool + Send + Sync>;
|
||||||
|
|
||||||
impl VeilidLayerFilter {
|
impl VeilidLayerFilter {
|
||||||
|
#[must_use]
|
||||||
pub fn make_veilid_log_key(program_name: &str, namespace: &str) -> &'static str {
|
pub fn make_veilid_log_key(program_name: &str, namespace: &str) -> &'static str {
|
||||||
if namespace.is_empty() {
|
if namespace.is_empty() {
|
||||||
program_name.to_static_str()
|
program_name.to_static_str()
|
||||||
@ -66,6 +68,7 @@ impl VeilidLayerFilter {
|
|||||||
VeilidConfigLogLevel::from_tracing_level_filter(inner.max_level)
|
VeilidConfigLogLevel::from_tracing_level_filter(inner.max_level)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn ignore_list(&self) -> Vec<String> {
|
pub fn ignore_list(&self) -> Vec<String> {
|
||||||
let inner = self.inner.read();
|
let inner = self.inner.read();
|
||||||
inner.ignore_list.clone()
|
inner.ignore_list.clone()
|
||||||
@ -113,6 +116,7 @@ impl VeilidLayerFilter {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn apply_ignore_change(ignore_list: &[String], target_change: String) -> Vec<String> {
|
pub fn apply_ignore_change(ignore_list: &[String], target_change: String) -> Vec<String> {
|
||||||
let mut ignore_list = ignore_list.to_vec();
|
let mut ignore_list = ignore_list.to_vec();
|
||||||
let target_change = target_change
|
let target_change = target_change
|
||||||
|
@ -131,7 +131,7 @@ impl ConnectionManager {
|
|||||||
self.arc.connection_inactivity_timeout_ms
|
self.arc.connection_inactivity_timeout_ms
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn startup(&self) -> EyreResult<()> {
|
pub fn startup(&self) -> EyreResult<()> {
|
||||||
let guard = self.arc.startup_lock.startup()?;
|
let guard = self.arc.startup_lock.startup()?;
|
||||||
|
|
||||||
veilid_log!(self debug "startup connection manager");
|
veilid_log!(self debug "startup connection manager");
|
||||||
@ -158,7 +158,7 @@ impl ConnectionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Spawn the reconnection processor
|
// Spawn the reconnection processor
|
||||||
self.arc.reconnection_processor.init().await;
|
self.arc.reconnection_processor.init();
|
||||||
|
|
||||||
guard.success();
|
guard.success();
|
||||||
|
|
||||||
@ -696,7 +696,7 @@ impl ConnectionManager {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn debug_print(&self) -> String {
|
pub fn debug_print(&self) -> String {
|
||||||
//let inner = self.arc.inner.lock();
|
//let inner = self.arc.inner.lock();
|
||||||
format!(
|
format!(
|
||||||
"Connection Table:\n\n{}",
|
"Connection Table:\n\n{}",
|
||||||
|
@ -455,13 +455,16 @@ impl ConnectionTable {
|
|||||||
let conn = inner.conn_by_id[protocol_index].remove(&id).unwrap();
|
let conn = inner.conn_by_id[protocol_index].remove(&id).unwrap();
|
||||||
// id_by_flow
|
// id_by_flow
|
||||||
let flow = conn.flow();
|
let flow = conn.flow();
|
||||||
inner.id_by_flow.remove(&flow).unwrap();
|
let _ = inner
|
||||||
|
.id_by_flow
|
||||||
|
.remove(&flow)
|
||||||
|
.expect("must have removed something here");
|
||||||
// ids_by_remote
|
// ids_by_remote
|
||||||
let remote = flow.remote();
|
let remote = flow.remote();
|
||||||
let ids = inner.ids_by_remote.get_mut(&remote).unwrap();
|
let ids = inner.ids_by_remote.get_mut(&remote).unwrap();
|
||||||
for (n, elem) in ids.iter().enumerate() {
|
for (n, elem) in ids.iter().enumerate() {
|
||||||
if *elem == id {
|
if *elem == id {
|
||||||
ids.remove(n);
|
let _ = ids.remove(n);
|
||||||
if ids.is_empty() {
|
if ids.is_empty() {
|
||||||
inner.ids_by_remote.remove(&remote).unwrap();
|
inner.ids_by_remote.remove(&remote).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,8 @@ impl NetworkManager {
|
|||||||
let json_bytes = serialize_json(bootstrap_peerinfo).as_bytes().to_vec();
|
let json_bytes = serialize_json(bootstrap_peerinfo).as_bytes().to_vec();
|
||||||
|
|
||||||
// Reply with a chunk of signed routing table
|
// Reply with a chunk of signed routing table
|
||||||
match self
|
let net = self.net();
|
||||||
.net()
|
match pin_future_closure!(net.send_data_to_existing_flow(flow, json_bytes)).await? {
|
||||||
.send_data_to_existing_flow(flow, json_bytes)
|
|
||||||
.await?
|
|
||||||
{
|
|
||||||
SendDataToExistingFlowResult::Sent(_) => {
|
SendDataToExistingFlowResult::Sent(_) => {
|
||||||
// Bootstrap reply was sent
|
// Bootstrap reply was sent
|
||||||
Ok(NetworkResult::value(()))
|
Ok(NetworkResult::value(()))
|
||||||
|
@ -12,6 +12,7 @@ mod connection_manager;
|
|||||||
mod connection_table;
|
mod connection_table;
|
||||||
mod direct_boot;
|
mod direct_boot;
|
||||||
mod network_connection;
|
mod network_connection;
|
||||||
|
mod node_contact_method_cache;
|
||||||
mod receipt_manager;
|
mod receipt_manager;
|
||||||
mod send_data;
|
mod send_data;
|
||||||
mod stats;
|
mod stats;
|
||||||
@ -25,6 +26,7 @@ pub mod tests;
|
|||||||
|
|
||||||
pub use connection_manager::*;
|
pub use connection_manager::*;
|
||||||
pub use network_connection::*;
|
pub use network_connection::*;
|
||||||
|
pub(crate) use node_contact_method_cache::*;
|
||||||
pub use receipt_manager::*;
|
pub use receipt_manager::*;
|
||||||
pub use stats::*;
|
pub use stats::*;
|
||||||
pub(crate) use types::*;
|
pub(crate) use types::*;
|
||||||
@ -55,7 +57,6 @@ 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 =
|
pub const IPADDR_MAX_INACTIVE_DURATION_US: TimestampDuration =
|
||||||
TimestampDuration::new(300_000_000u64); // 5 minutes
|
TimestampDuration::new(300_000_000u64); // 5 minutes
|
||||||
pub const NODE_CONTACT_METHOD_CACHE_SIZE: usize = 1024;
|
|
||||||
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";
|
||||||
pub const HOLE_PUNCH_DELAY_MS: u32 = 100;
|
pub const HOLE_PUNCH_DELAY_MS: u32 = 100;
|
||||||
@ -75,20 +76,32 @@ struct ClientAllowlistEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SendDataMethod {
|
pub struct SendDataResult {
|
||||||
/// How the data was sent, possibly to a relay
|
/// How the data was sent, possibly to a relay
|
||||||
pub contact_method: NodeContactMethod,
|
opt_contact_method: Option<NodeContactMethod>,
|
||||||
/// Pre-relayed contact method
|
/// Original contact method for the destination if it was relayed
|
||||||
pub opt_relayed_contact_method: Option<NodeContactMethod>,
|
opt_relayed_contact_method: Option<NodeContactMethod>,
|
||||||
/// The specific flow used to send the data
|
/// The specific flow used to send the data
|
||||||
pub unique_flow: UniqueFlow,
|
unique_flow: UniqueFlow,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SendDataResult {
|
||||||
|
pub fn is_direct(&self) -> bool {
|
||||||
|
self.opt_relayed_contact_method.is_none()
|
||||||
|
&& matches!(
|
||||||
|
&self.opt_contact_method,
|
||||||
|
Some(ncm) if ncm.is_direct()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unique_flow(&self) -> UniqueFlow {
|
||||||
|
self.unique_flow
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mechanism required to contact another node
|
/// Mechanism required to contact another node
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum NodeContactMethod {
|
pub enum NodeContactMethodKind {
|
||||||
/// Node is not reachable by any means
|
|
||||||
Unreachable,
|
|
||||||
/// Connection should have already existed
|
/// Connection should have already existed
|
||||||
Existing,
|
Existing,
|
||||||
/// Contact the node directly
|
/// Contact the node directly
|
||||||
@ -102,14 +115,29 @@ pub enum NodeContactMethod {
|
|||||||
/// Must use outbound relay to reach the node
|
/// Must use outbound relay to reach the node
|
||||||
OutboundRelay(FilteredNodeRef),
|
OutboundRelay(FilteredNodeRef),
|
||||||
}
|
}
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
|
|
||||||
struct NodeContactMethodCacheKey {
|
#[derive(Clone, Debug)]
|
||||||
node_ids: TypedKeyGroup,
|
pub struct NodeContactMethod {
|
||||||
own_node_info_ts: Timestamp,
|
ncm_key: NodeContactMethodCacheKey,
|
||||||
target_node_info_ts: Timestamp,
|
ncm_kind: NodeContactMethodKind,
|
||||||
target_node_ref_filter: NodeRefFilter,
|
}
|
||||||
target_node_ref_sequencing: Sequencing,
|
|
||||||
dial_info_failures_map: BTreeMap<DialInfo, Timestamp>,
|
impl NodeContactMethod {
|
||||||
|
pub fn is_direct(&self) -> bool {
|
||||||
|
matches!(self.ncm_kind, NodeContactMethodKind::Direct(_))
|
||||||
|
}
|
||||||
|
pub fn direct_dial_info(&self) -> Option<DialInfo> {
|
||||||
|
match &self.ncm_kind {
|
||||||
|
NodeContactMethodKind::Direct(v) => Some(v.clone()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// pub fn kind(&self) -> &NodeContactMethodKind {
|
||||||
|
// &self.ncm_kind
|
||||||
|
// }
|
||||||
|
// pub fn into_kind(self) -> NodeContactMethodKind {
|
||||||
|
// self.ncm_kind
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SendDataToExistingFlowResult {
|
enum SendDataToExistingFlowResult {
|
||||||
@ -146,7 +174,7 @@ impl Default for NetworkManagerStartupContext {
|
|||||||
struct NetworkManagerInner {
|
struct NetworkManagerInner {
|
||||||
stats: NetworkManagerStats,
|
stats: NetworkManagerStats,
|
||||||
client_allowlist: LruCache<TypedKey, ClientAllowlistEntry>,
|
client_allowlist: LruCache<TypedKey, ClientAllowlistEntry>,
|
||||||
node_contact_method_cache: LruCache<NodeContactMethodCacheKey, NodeContactMethod>,
|
node_contact_method_cache: NodeContactMethodCache,
|
||||||
address_check: Option<AddressCheck>,
|
address_check: Option<AddressCheck>,
|
||||||
peer_info_change_subscription: Option<EventBusSubscription>,
|
peer_info_change_subscription: Option<EventBusSubscription>,
|
||||||
socket_address_change_subscription: Option<EventBusSubscription>,
|
socket_address_change_subscription: Option<EventBusSubscription>,
|
||||||
@ -181,9 +209,6 @@ impl fmt::Debug for NetworkManager {
|
|||||||
//.field("registry", &self.registry)
|
//.field("registry", &self.registry)
|
||||||
.field("inner", &self.inner)
|
.field("inner", &self.inner)
|
||||||
.field("address_filter", &self.address_filter)
|
.field("address_filter", &self.address_filter)
|
||||||
// .field("components", &self.components)
|
|
||||||
// .field("rolling_transfers_task", &self.rolling_transfers_task)
|
|
||||||
// .field("address_filter_task", &self.address_filter_task)
|
|
||||||
.field("network_key", &self.network_key)
|
.field("network_key", &self.network_key)
|
||||||
.field("startup_context", &self.startup_context)
|
.field("startup_context", &self.startup_context)
|
||||||
.finish()
|
.finish()
|
||||||
@ -195,7 +220,7 @@ impl NetworkManager {
|
|||||||
NetworkManagerInner {
|
NetworkManagerInner {
|
||||||
stats: NetworkManagerStats::default(),
|
stats: NetworkManagerStats::default(),
|
||||||
client_allowlist: LruCache::new_unbounded(),
|
client_allowlist: LruCache::new_unbounded(),
|
||||||
node_contact_method_cache: LruCache::new(NODE_CONTACT_METHOD_CACHE_SIZE),
|
node_contact_method_cache: NodeContactMethodCache::new(),
|
||||||
address_check: None,
|
address_check: None,
|
||||||
peer_info_change_subscription: None,
|
peer_info_change_subscription: None,
|
||||||
socket_address_change_subscription: None,
|
socket_address_change_subscription: None,
|
||||||
@ -300,10 +325,12 @@ impl NetworkManager {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
async fn post_init_async(&self) -> EyreResult<()> {
|
async fn post_init_async(&self) -> EyreResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
async fn pre_terminate_async(&self) {}
|
async fn pre_terminate_async(&self) {}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip_all)]
|
#[instrument(level = "debug", skip_all)]
|
||||||
@ -347,7 +374,7 @@ impl NetworkManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start network components
|
// Start network components
|
||||||
connection_manager.startup().await?;
|
connection_manager.startup()?;
|
||||||
match net.startup().await? {
|
match net.startup().await? {
|
||||||
StartupDisposition::Success => {}
|
StartupDisposition::Success => {}
|
||||||
StartupDisposition::BindRetry => {
|
StartupDisposition::BindRetry => {
|
||||||
@ -355,7 +382,7 @@ impl NetworkManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
receipt_manager.startup().await?;
|
receipt_manager.startup()?;
|
||||||
|
|
||||||
veilid_log!(self trace "NetworkManager::internal_startup end");
|
veilid_log!(self trace "NetworkManager::internal_startup end");
|
||||||
|
|
||||||
@ -823,7 +850,7 @@ impl NetworkManager {
|
|||||||
node_ref: FilteredNodeRef,
|
node_ref: FilteredNodeRef,
|
||||||
destination_node_ref: Option<NodeRef>,
|
destination_node_ref: Option<NodeRef>,
|
||||||
body: B,
|
body: B,
|
||||||
) -> EyreResult<NetworkResult<SendDataMethod>> {
|
) -> EyreResult<NetworkResult<SendDataResult>> {
|
||||||
let Ok(_guard) = self.startup_context.startup_lock.enter() else {
|
let Ok(_guard) = self.startup_context.startup_lock.enter() else {
|
||||||
return Ok(NetworkResult::no_connection_other("network is not started"));
|
return Ok(NetworkResult::no_connection_other("network is not started"));
|
||||||
};
|
};
|
||||||
@ -890,7 +917,7 @@ impl NetworkManager {
|
|||||||
// Called when a packet potentially containing an RPC envelope is received by a low-level
|
// Called when a packet potentially containing an RPC envelope is received by a low-level
|
||||||
// network protocol handler. Processes the envelope, authenticates and decrypts the RPC message
|
// network protocol handler. Processes the envelope, authenticates and decrypts the RPC message
|
||||||
// and passes it to the RPC handler
|
// and passes it to the RPC handler
|
||||||
#[instrument(level = "trace", target = "net", skip_all)]
|
//#[instrument(level = "trace", target = "net", skip_all)]
|
||||||
async fn on_recv_envelope(&self, data: &mut [u8], flow: Flow) -> EyreResult<bool> {
|
async fn on_recv_envelope(&self, data: &mut [u8], flow: Flow) -> EyreResult<bool> {
|
||||||
let Ok(_guard) = self.startup_context.startup_lock.enter() else {
|
let Ok(_guard) = self.startup_context.startup_lock.enter() else {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
@ -931,13 +958,13 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// Is this a direct bootstrap request instead of an envelope?
|
// Is this a direct bootstrap request instead of an envelope?
|
||||||
if data[0..4] == *BOOT_MAGIC {
|
if data[0..4] == *BOOT_MAGIC {
|
||||||
network_result_value_or_log!(self self.handle_boot_request(flow).await? => [ format!(": flow={:?}", flow) ] {});
|
network_result_value_or_log!(self pin_future!(self.handle_boot_request(flow)).await? => [ format!(": flow={:?}", flow) ] {});
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is this an out-of-band receipt instead of an envelope?
|
// Is this an out-of-band receipt instead of an envelope?
|
||||||
if data[0..3] == *RECEIPT_MAGIC {
|
if data[0..3] == *RECEIPT_MAGIC {
|
||||||
network_result_value_or_log!(self self.handle_out_of_band_receipt(data).await => [ format!(": data.len={}", data.len()) ] {});
|
network_result_value_or_log!(self pin_future!(self.handle_out_of_band_receipt(data)).await => [ format!(": data.len={}", data.len()) ] {});
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1071,18 +1098,9 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// Relay the packet to the desired destination
|
// Relay the packet to the desired destination
|
||||||
veilid_log!(self trace "relaying {} bytes to {}", data.len(), relay_nr);
|
veilid_log!(self trace "relaying {} bytes to {}", data.len(), relay_nr);
|
||||||
|
if let Err(e) = pin_future!(self.send_data(relay_nr, data.to_vec())).await {
|
||||||
network_result_value_or_log!(self match self.send_data(relay_nr, data.to_vec())
|
veilid_log!(self debug "failed to relay envelope: {}" ,e);
|
||||||
.await {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => {
|
|
||||||
veilid_log!(self debug "failed to forward envelope: {}" ,e);
|
|
||||||
return Ok(false);
|
|
||||||
}
|
}
|
||||||
} => [ format!(": relay_nr={}, data.len={}", relay_nr, data.len()) ] {
|
|
||||||
return Ok(false);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
// Inform caller that we dealt with the envelope, but did not process it locally
|
// Inform caller that we dealt with the envelope, but did not process it locally
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
|
@ -3,12 +3,15 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use futures_util::stream::FuturesUnordered;
|
use futures_util::stream::FuturesUnordered;
|
||||||
use igd_manager::{IGDAddressType, IGDProtocolType};
|
use igd_manager::{IGDAddressType, IGDProtocolType};
|
||||||
|
use stop_token::future::FutureExt as _;
|
||||||
|
|
||||||
impl_veilid_log_facility!("net");
|
impl_veilid_log_facility!("net");
|
||||||
|
|
||||||
const PORT_MAP_VALIDATE_TRY_COUNT: usize = 3;
|
const PORT_MAP_VALIDATE_TRY_COUNT: usize = 3;
|
||||||
const PORT_MAP_VALIDATE_DELAY_MS: u32 = 500;
|
const PORT_MAP_VALIDATE_DELAY_MS: u32 = 500;
|
||||||
const PORT_MAP_TRY_COUNT: usize = 3;
|
const PORT_MAP_TRY_COUNT: usize = 3;
|
||||||
|
const EXTERNAL_INFO_NODE_COUNT: usize = 20;
|
||||||
|
const EXTERNAL_INFO_CONCURRENCY: usize = 20;
|
||||||
const EXTERNAL_INFO_VALIDATIONS: usize = 5;
|
const EXTERNAL_INFO_VALIDATIONS: usize = 5;
|
||||||
|
|
||||||
// Detection result of dial info detection futures
|
// Detection result of dial info detection futures
|
||||||
@ -26,6 +29,82 @@ pub struct DetectionResult {
|
|||||||
pub external_address_types: AddressTypeSet,
|
pub external_address_types: AddressTypeSet,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
enum DetectionResultKind {
|
||||||
|
Result {
|
||||||
|
result: DetectionResult,
|
||||||
|
possibilities: Vec<DialInfoClassPossibility>,
|
||||||
|
},
|
||||||
|
Failure {
|
||||||
|
possibilities: Vec<DialInfoClassPossibility>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
type DialInfoClassPossibility = (DialInfoClass, usize);
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct DialInfoClassAllPossibilities {
|
||||||
|
remaining: BTreeMap<DialInfoClass, usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DialInfoClassAllPossibilities {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
remaining: BTreeMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add(&mut self, possibilities: &[DialInfoClassPossibility]) {
|
||||||
|
for (k, v) in possibilities {
|
||||||
|
*self.remaining.entry(*k).or_default() += v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn remove(&mut self, possibilities: &[DialInfoClassPossibility]) {
|
||||||
|
for (k, v) in possibilities {
|
||||||
|
*self.remaining.entry(*k).or_default() -= v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn any_better(&mut self, dial_info_class: DialInfoClass) -> bool {
|
||||||
|
let best_available_order: [DialInfoClassSet; 4] = [
|
||||||
|
DialInfoClass::Mapped.into(),
|
||||||
|
DialInfoClass::Direct | DialInfoClass::Blocked,
|
||||||
|
DialInfoClass::FullConeNAT.into(),
|
||||||
|
DialInfoClass::AddressRestrictedNAT | DialInfoClass::PortRestrictedNAT,
|
||||||
|
];
|
||||||
|
|
||||||
|
for bestdicset in best_available_order {
|
||||||
|
// Already got the best we've checked so far?
|
||||||
|
if bestdicset.contains(dial_info_class) {
|
||||||
|
// We can just stop here since nothing else is going to be better
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the total remaining possibilities left at this level
|
||||||
|
let mut remaining = 0usize;
|
||||||
|
for bestdic in bestdicset {
|
||||||
|
remaining += self.remaining.get(&bestdic).copied().unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
|
if remaining > 0 {
|
||||||
|
// There's some things worth waiting for that could be better than dial_info_class
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing left to wait for
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DialInfoClassAllPossibilities {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct DiscoveryContextConfig {
|
pub struct DiscoveryContextConfig {
|
||||||
pub protocol_type: ProtocolType,
|
pub protocol_type: ProtocolType,
|
||||||
@ -57,6 +136,7 @@ pub(super) struct DiscoveryContext {
|
|||||||
registry: VeilidComponentRegistry,
|
registry: VeilidComponentRegistry,
|
||||||
unlocked_inner: Arc<DiscoveryContextUnlockedInner>,
|
unlocked_inner: Arc<DiscoveryContextUnlockedInner>,
|
||||||
inner: Arc<Mutex<DiscoveryContextInner>>,
|
inner: Arc<Mutex<DiscoveryContextInner>>,
|
||||||
|
stop_token: StopToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_veilid_component_registry_accessor!(DiscoveryContext);
|
impl_veilid_component_registry_accessor!(DiscoveryContext);
|
||||||
@ -70,7 +150,11 @@ impl core::ops::Deref for DiscoveryContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DiscoveryContext {
|
impl DiscoveryContext {
|
||||||
pub fn new(registry: VeilidComponentRegistry, config: DiscoveryContextConfig) -> Self {
|
pub fn new(
|
||||||
|
registry: VeilidComponentRegistry,
|
||||||
|
config: DiscoveryContextConfig,
|
||||||
|
stop_token: StopToken,
|
||||||
|
) -> Self {
|
||||||
let routing_table = registry.routing_table();
|
let routing_table = registry.routing_table();
|
||||||
let intf_addrs =
|
let intf_addrs =
|
||||||
Self::get_local_addresses(&routing_table, config.protocol_type, config.address_type);
|
Self::get_local_addresses(&routing_table, config.protocol_type, config.address_type);
|
||||||
@ -81,6 +165,7 @@ impl DiscoveryContext {
|
|||||||
inner: Arc::new(Mutex::new(DiscoveryContextInner {
|
inner: Arc::new(Mutex::new(DiscoveryContextInner {
|
||||||
external_info: Vec::new(),
|
external_info: Vec::new(),
|
||||||
})),
|
})),
|
||||||
|
stop_token,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,9 +232,7 @@ impl DiscoveryContext {
|
|||||||
// This is done over the normal port using RPC
|
// This is done over the normal port using RPC
|
||||||
#[instrument(level = "trace", skip(self), ret)]
|
#[instrument(level = "trace", skip(self), ret)]
|
||||||
async fn discover_external_addresses(&self) -> bool {
|
async fn discover_external_addresses(&self) -> bool {
|
||||||
let node_count = self
|
let node_count = EXTERNAL_INFO_NODE_COUNT;
|
||||||
.config()
|
|
||||||
.with(|c| c.network.dht.max_find_node_count as usize);
|
|
||||||
let routing_domain = RoutingDomain::PublicInternet;
|
let routing_domain = RoutingDomain::PublicInternet;
|
||||||
|
|
||||||
let protocol_type = self.config.protocol_type;
|
let protocol_type = self.config.protocol_type;
|
||||||
@ -211,7 +294,6 @@ impl DiscoveryContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For each peer, ask them for our public address, filtering on desired dial info
|
// For each peer, ask them for our public address, filtering on desired dial info
|
||||||
|
|
||||||
let get_public_address_func = |node: NodeRef| {
|
let get_public_address_func = |node: NodeRef| {
|
||||||
let this = self.clone();
|
let this = self.clone();
|
||||||
let node = node.custom_filtered(
|
let node = node.custom_filtered(
|
||||||
@ -242,24 +324,55 @@ impl DiscoveryContext {
|
|||||||
unord.push(gpa_future);
|
unord.push(gpa_future);
|
||||||
|
|
||||||
// Always process N at a time so we get all addresses in parallel if possible
|
// Always process N at a time so we get all addresses in parallel if possible
|
||||||
if unord.len() == EXTERNAL_INFO_VALIDATIONS {
|
if unord.len() == EXTERNAL_INFO_CONCURRENCY {
|
||||||
// Process one
|
// Process one
|
||||||
if let Some(Some(ei)) = unord.next().in_current_span().await {
|
match unord
|
||||||
|
.next()
|
||||||
|
.timeout_at(self.stop_token.clone())
|
||||||
|
.in_current_span()
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(Some(Some(ei))) => {
|
||||||
external_address_infos.push(ei);
|
external_address_infos.push(ei);
|
||||||
if external_address_infos.len() == EXTERNAL_INFO_VALIDATIONS {
|
if external_address_infos.len() == EXTERNAL_INFO_VALIDATIONS {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(Some(None)) => {
|
||||||
|
// Found no public address from this node
|
||||||
|
}
|
||||||
|
Ok(None) => {
|
||||||
|
// Should never happen in this loop
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
// stop requested
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Finish whatever is left if we need to
|
// Finish whatever is left if we need to
|
||||||
if external_address_infos.len() < EXTERNAL_INFO_VALIDATIONS {
|
while external_address_infos.len() < EXTERNAL_INFO_VALIDATIONS {
|
||||||
while let Some(res) = unord.next().in_current_span().await {
|
match unord
|
||||||
if let Some(ei) = res {
|
.next()
|
||||||
|
.timeout_at(self.stop_token.clone())
|
||||||
|
.in_current_span()
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(Some(Some(ei))) => {
|
||||||
external_address_infos.push(ei);
|
external_address_infos.push(ei);
|
||||||
if external_address_infos.len() == EXTERNAL_INFO_VALIDATIONS {
|
}
|
||||||
|
Ok(Some(None)) => {
|
||||||
|
// Found no public address from this node
|
||||||
|
}
|
||||||
|
Ok(None) => {
|
||||||
|
// No nodes left to wait for
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Err(_) => {
|
||||||
|
// stop requested
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -414,16 +527,21 @@ impl DiscoveryContext {
|
|||||||
|
|
||||||
// If we know we are not behind NAT, check our firewall status
|
// If we know we are not behind NAT, check our firewall status
|
||||||
#[instrument(level = "trace", skip(self), ret)]
|
#[instrument(level = "trace", skip(self), ret)]
|
||||||
async fn protocol_process_no_nat(
|
fn protocol_process_no_nat(
|
||||||
&self,
|
&self,
|
||||||
unord: &mut FuturesUnordered<SendPinBoxFuture<Option<DetectionResult>>>,
|
all_possibilities: &mut DialInfoClassAllPossibilities,
|
||||||
|
unord: &mut FuturesUnordered<PinBoxFutureStatic<DetectionResultKind>>,
|
||||||
) {
|
) {
|
||||||
let external_infos = self.inner.lock().external_info.clone();
|
let external_infos = self.inner.lock().external_info.clone();
|
||||||
|
|
||||||
// Have all the external validator nodes check us
|
// Have all the external validator nodes check us
|
||||||
for external_info in external_infos {
|
for external_info in external_infos {
|
||||||
let this = self.clone();
|
let this = self.clone();
|
||||||
let do_no_nat_fut: SendPinBoxFuture<Option<DetectionResult>> = Box::pin(async move {
|
|
||||||
|
let possibilities = vec![(DialInfoClass::Direct, 1), (DialInfoClass::Blocked, 1)];
|
||||||
|
all_possibilities.add(&possibilities);
|
||||||
|
|
||||||
|
let do_no_nat_fut: PinBoxFutureStatic<DetectionResultKind> = Box::pin(async move {
|
||||||
// Do a validate_dial_info on the external address from a redirected node
|
// Do a validate_dial_info on the external address from a redirected node
|
||||||
if this
|
if this
|
||||||
.validate_dial_info(
|
.validate_dial_info(
|
||||||
@ -434,7 +552,9 @@ impl DiscoveryContext {
|
|||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
// Add public dial info with Direct dialinfo class
|
// Add public dial info with Direct dialinfo class
|
||||||
Some(DetectionResult {
|
DetectionResultKind::Result {
|
||||||
|
possibilities,
|
||||||
|
result: DetectionResult {
|
||||||
config: this.config,
|
config: this.config,
|
||||||
ddi: DetectedDialInfo::Detected(DialInfoDetail {
|
ddi: DetectedDialInfo::Detected(DialInfoDetail {
|
||||||
dial_info: external_info.dial_info.clone(),
|
dial_info: external_info.dial_info.clone(),
|
||||||
@ -443,10 +563,13 @@ impl DiscoveryContext {
|
|||||||
external_address_types: AddressTypeSet::only(
|
external_address_types: AddressTypeSet::only(
|
||||||
external_info.address.address_type(),
|
external_info.address.address_type(),
|
||||||
),
|
),
|
||||||
})
|
},
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Add public dial info with Blocked dialinfo class
|
// Add public dial info with Blocked dialinfo class
|
||||||
Some(DetectionResult {
|
DetectionResultKind::Result {
|
||||||
|
possibilities,
|
||||||
|
result: DetectionResult {
|
||||||
config: this.config,
|
config: this.config,
|
||||||
ddi: DetectedDialInfo::Detected(DialInfoDetail {
|
ddi: DetectedDialInfo::Detected(DialInfoDetail {
|
||||||
dial_info: external_info.dial_info.clone(),
|
dial_info: external_info.dial_info.clone(),
|
||||||
@ -455,26 +578,29 @@ impl DiscoveryContext {
|
|||||||
external_address_types: AddressTypeSet::only(
|
external_address_types: AddressTypeSet::only(
|
||||||
external_info.address.address_type(),
|
external_info.address.address_type(),
|
||||||
),
|
),
|
||||||
})
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
unord.push(do_no_nat_fut);
|
unord.push(do_no_nat_fut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we know we are behind NAT check what kind
|
// If we know we are behind NAT check what kind
|
||||||
#[instrument(level = "trace", skip(self), ret)]
|
#[instrument(level = "trace", skip(self), ret)]
|
||||||
async fn protocol_process_nat(
|
fn protocol_process_nat(
|
||||||
&self,
|
&self,
|
||||||
unord: &mut FuturesUnordered<SendPinBoxFuture<Option<DetectionResult>>>,
|
all_possibilities: &mut DialInfoClassAllPossibilities,
|
||||||
|
unord: &mut FuturesUnordered<PinBoxFutureStatic<DetectionResultKind>>,
|
||||||
) {
|
) {
|
||||||
|
// Get the external dial info histogram for our use here
|
||||||
let external_info = {
|
let external_info = {
|
||||||
let inner = self.inner.lock();
|
let inner = self.inner.lock();
|
||||||
inner.external_info.clone()
|
inner.external_info.clone()
|
||||||
};
|
};
|
||||||
let local_port = self.config.port;
|
let local_port = self.config.port;
|
||||||
|
|
||||||
// Get the external dial info histogram for our use here
|
|
||||||
let mut external_info_addr_port_hist = HashMap::<SocketAddress, usize>::new();
|
let mut external_info_addr_port_hist = HashMap::<SocketAddress, usize>::new();
|
||||||
let mut external_info_addr_hist = HashMap::<Address, usize>::new();
|
let mut external_info_addr_hist = HashMap::<Address, usize>::new();
|
||||||
for ei in &external_info {
|
for ei in &external_info {
|
||||||
@ -525,15 +651,21 @@ impl DiscoveryContext {
|
|||||||
// then we consider this a symmetric NAT
|
// then we consider this a symmetric NAT
|
||||||
if different_addresses || !same_address_has_popular_port {
|
if different_addresses || !same_address_has_popular_port {
|
||||||
let this = self.clone();
|
let this = self.clone();
|
||||||
let do_symmetric_nat_fut: SendPinBoxFuture<Option<DetectionResult>> =
|
let do_symmetric_nat_fut: PinBoxFutureStatic<DetectionResultKind> =
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
Some(DetectionResult {
|
DetectionResultKind::Result {
|
||||||
|
// Don't bother tracking possibilities for SymmetricNAT
|
||||||
|
// it's never going to be 'better than' anything else
|
||||||
|
possibilities: vec![],
|
||||||
|
result: DetectionResult {
|
||||||
config: this.config,
|
config: this.config,
|
||||||
ddi: DetectedDialInfo::SymmetricNAT,
|
ddi: DetectedDialInfo::SymmetricNAT,
|
||||||
external_address_types,
|
external_address_types,
|
||||||
})
|
},
|
||||||
|
}
|
||||||
});
|
});
|
||||||
unord.push(do_symmetric_nat_fut);
|
unord.push(do_symmetric_nat_fut);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -545,8 +677,11 @@ impl DiscoveryContext {
|
|||||||
if local_port_matching_external_info.is_none() && best_external_info.is_some() {
|
if local_port_matching_external_info.is_none() && best_external_info.is_some() {
|
||||||
let c_external_1 = best_external_info.as_ref().unwrap().clone();
|
let c_external_1 = best_external_info.as_ref().unwrap().clone();
|
||||||
let c_this = this.clone();
|
let c_this = this.clone();
|
||||||
let do_manual_map_fut: SendPinBoxFuture<Option<DetectionResult>> =
|
|
||||||
Box::pin(async move {
|
let possibilities = vec![(DialInfoClass::Direct, 1)];
|
||||||
|
all_possibilities.add(&possibilities);
|
||||||
|
|
||||||
|
let do_manual_map_fut: PinBoxFutureStatic<DetectionResultKind> = Box::pin(async move {
|
||||||
// Do a validate_dial_info on the external address, but with the same port as the local port of local interface, from a redirected node
|
// Do a validate_dial_info on the external address, but with the same port as the local port of local interface, from a redirected node
|
||||||
// This test is to see if a node had manual port forwarding done with the same port number as the local listener
|
// This test is to see if a node had manual port forwarding done with the same port number as the local listener
|
||||||
let mut external_1_dial_info_with_local_port = c_external_1.dial_info.clone();
|
let mut external_1_dial_info_with_local_port = c_external_1.dial_info.clone();
|
||||||
@ -561,7 +696,9 @@ impl DiscoveryContext {
|
|||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
// Add public dial info with Direct dialinfo class
|
// Add public dial info with Direct dialinfo class
|
||||||
return Some(DetectionResult {
|
return DetectionResultKind::Result {
|
||||||
|
possibilities,
|
||||||
|
result: DetectionResult {
|
||||||
config: c_this.config,
|
config: c_this.config,
|
||||||
ddi: DetectedDialInfo::Detected(DialInfoDetail {
|
ddi: DetectedDialInfo::Detected(DialInfoDetail {
|
||||||
dial_info: external_1_dial_info_with_local_port,
|
dial_info: external_1_dial_info_with_local_port,
|
||||||
@ -570,10 +707,11 @@ impl DiscoveryContext {
|
|||||||
external_address_types: AddressTypeSet::only(
|
external_address_types: AddressTypeSet::only(
|
||||||
c_external_1.address.address_type(),
|
c_external_1.address.address_type(),
|
||||||
),
|
),
|
||||||
});
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
DetectionResultKind::Failure { possibilities }
|
||||||
});
|
});
|
||||||
unord.push(do_manual_map_fut);
|
unord.push(do_manual_map_fut);
|
||||||
}
|
}
|
||||||
@ -581,22 +719,21 @@ impl DiscoveryContext {
|
|||||||
// NAT Detection
|
// NAT Detection
|
||||||
///////////
|
///////////
|
||||||
|
|
||||||
|
let retry_count = self.config().with(|c| c.network.restricted_nat_retries);
|
||||||
|
|
||||||
// Full Cone NAT Detection
|
// Full Cone NAT Detection
|
||||||
///////////
|
///////////
|
||||||
let this = self.clone();
|
|
||||||
let do_nat_detect_fut: SendPinBoxFuture<Option<DetectionResult>> = Box::pin(async move {
|
|
||||||
let mut retry_count = this.config().with(|c| c.network.restricted_nat_retries);
|
|
||||||
|
|
||||||
// Loop for restricted NAT retries
|
let c_this = self.clone();
|
||||||
loop {
|
|
||||||
let mut ord = FuturesOrdered::new();
|
|
||||||
|
|
||||||
let c_this = this.clone();
|
|
||||||
let c_external_1 = external_info.first().cloned().unwrap();
|
let c_external_1 = external_info.first().cloned().unwrap();
|
||||||
let do_full_cone_fut: SendPinBoxFuture<Option<DetectionResult>> =
|
let possibilities = vec![(DialInfoClass::FullConeNAT, 1)];
|
||||||
Box::pin(async move {
|
all_possibilities.add(&possibilities);
|
||||||
|
let do_full_cone_fut: PinBoxFutureStatic<DetectionResultKind> = Box::pin(async move {
|
||||||
|
let mut retry_count = retry_count;
|
||||||
|
|
||||||
// Let's see what kind of NAT we have
|
// Let's see what kind of NAT we have
|
||||||
// Does a redirected dial info validation from a different address and a random port find us?
|
// Does a redirected dial info validation from a different address and a random port find us?
|
||||||
|
loop {
|
||||||
if c_this
|
if c_this
|
||||||
.validate_dial_info(
|
.validate_dial_info(
|
||||||
c_external_1.node.clone(),
|
c_external_1.node.clone(),
|
||||||
@ -608,7 +745,9 @@ impl DiscoveryContext {
|
|||||||
// Yes, another machine can use the dial info directly, so Full Cone
|
// Yes, another machine can use the dial info directly, so Full Cone
|
||||||
// Add public dial info with full cone NAT network class
|
// Add public dial info with full cone NAT network class
|
||||||
|
|
||||||
return Some(DetectionResult {
|
return DetectionResultKind::Result {
|
||||||
|
possibilities,
|
||||||
|
result: DetectionResult {
|
||||||
config: c_this.config,
|
config: c_this.config,
|
||||||
ddi: DetectedDialInfo::Detected(DialInfoDetail {
|
ddi: DetectedDialInfo::Detected(DialInfoDetail {
|
||||||
dial_info: c_external_1.dial_info,
|
dial_info: c_external_1.dial_info,
|
||||||
@ -617,22 +756,37 @@ impl DiscoveryContext {
|
|||||||
external_address_types: AddressTypeSet::only(
|
external_address_types: AddressTypeSet::only(
|
||||||
c_external_1.address.address_type(),
|
c_external_1.address.address_type(),
|
||||||
),
|
),
|
||||||
});
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if retry_count == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
retry_count -= 1;
|
||||||
}
|
}
|
||||||
None
|
|
||||||
});
|
|
||||||
ord.push_back(do_full_cone_fut);
|
|
||||||
|
|
||||||
let c_this = this.clone();
|
DetectionResultKind::Failure { possibilities }
|
||||||
|
});
|
||||||
|
unord.push(do_full_cone_fut);
|
||||||
|
|
||||||
|
let c_this = self.clone();
|
||||||
let c_external_1 = external_info.first().cloned().unwrap();
|
let c_external_1 = external_info.first().cloned().unwrap();
|
||||||
let c_external_2 = external_info.get(1).cloned().unwrap();
|
let c_external_2 = external_info.get(1).cloned().unwrap();
|
||||||
let do_restricted_cone_fut: SendPinBoxFuture<Option<DetectionResult>> =
|
let possibilities = vec![
|
||||||
|
(DialInfoClass::AddressRestrictedNAT, 1),
|
||||||
|
(DialInfoClass::PortRestrictedNAT, 1),
|
||||||
|
];
|
||||||
|
all_possibilities.add(&possibilities);
|
||||||
|
let do_restricted_cone_fut: PinBoxFutureStatic<DetectionResultKind> =
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
|
let mut retry_count = retry_count;
|
||||||
|
|
||||||
// We are restricted, determine what kind of restriction
|
// We are restricted, determine what kind of restriction
|
||||||
|
|
||||||
// If we're going to end up as a restricted NAT of some sort
|
// If we're going to end up as a restricted NAT of some sort
|
||||||
// Address is the same, so it's address or port restricted
|
// Address is the same, so it's address or port restricted
|
||||||
|
|
||||||
|
loop {
|
||||||
// Do a validate_dial_info on the external address from a random port
|
// Do a validate_dial_info on the external address from a random port
|
||||||
if c_this
|
if c_this
|
||||||
.validate_dial_info(
|
.validate_dial_info(
|
||||||
@ -643,7 +797,9 @@ impl DiscoveryContext {
|
|||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
// Got a reply from a non-default port, which means we're only address restricted
|
// Got a reply from a non-default port, which means we're only address restricted
|
||||||
return Some(DetectionResult {
|
return DetectionResultKind::Result {
|
||||||
|
possibilities,
|
||||||
|
result: DetectionResult {
|
||||||
config: c_this.config,
|
config: c_this.config,
|
||||||
ddi: DetectedDialInfo::Detected(DialInfoDetail {
|
ddi: DetectedDialInfo::Detected(DialInfoDetail {
|
||||||
dial_info: c_external_1.dial_info.clone(),
|
dial_info: c_external_1.dial_info.clone(),
|
||||||
@ -652,10 +808,20 @@ impl DiscoveryContext {
|
|||||||
external_address_types: AddressTypeSet::only(
|
external_address_types: AddressTypeSet::only(
|
||||||
c_external_1.address.address_type(),
|
c_external_1.address.address_type(),
|
||||||
),
|
),
|
||||||
});
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if retry_count == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
retry_count -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Didn't get a reply from a non-default port, which means we are also port restricted
|
// Didn't get a reply from a non-default port, which means we are also port restricted
|
||||||
Some(DetectionResult {
|
DetectionResultKind::Result {
|
||||||
|
possibilities,
|
||||||
|
result: DetectionResult {
|
||||||
config: c_this.config,
|
config: c_this.config,
|
||||||
ddi: DetectedDialInfo::Detected(DialInfoDetail {
|
ddi: DetectedDialInfo::Detected(DialInfoDetail {
|
||||||
dial_info: c_external_1.dial_info.clone(),
|
dial_info: c_external_1.dial_info.clone(),
|
||||||
@ -664,64 +830,51 @@ impl DiscoveryContext {
|
|||||||
external_address_types: AddressTypeSet::only(
|
external_address_types: AddressTypeSet::only(
|
||||||
c_external_1.address.address_type(),
|
c_external_1.address.address_type(),
|
||||||
),
|
),
|
||||||
})
|
},
|
||||||
|
}
|
||||||
});
|
});
|
||||||
ord.push_back(do_restricted_cone_fut);
|
unord.push(do_restricted_cone_fut);
|
||||||
|
|
||||||
// Return the first result we get
|
|
||||||
let mut some_dr = None;
|
|
||||||
while let Some(res) = ord.next().await {
|
|
||||||
if let Some(dr) = res {
|
|
||||||
some_dr = Some(dr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(dr) = some_dr {
|
/// Run a discovery for a particular context
|
||||||
if let DetectedDialInfo::Detected(did) = &dr.ddi {
|
/// Returns None if no detection was possible
|
||||||
// If we got something better than restricted NAT or we're done retrying
|
/// Returns Some(DetectionResult) with the best detection result for this context
|
||||||
if did.class < DialInfoClass::AddressRestrictedNAT || retry_count == 0 {
|
|
||||||
return Some(dr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if retry_count == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
retry_count -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
});
|
|
||||||
unord.push(do_nat_detect_fut);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add discovery futures to an unordered set that may detect dialinfo when they complete
|
|
||||||
#[instrument(level = "trace", skip(self))]
|
#[instrument(level = "trace", skip(self))]
|
||||||
pub async fn discover(
|
pub async fn discover(self) -> Option<DetectionResult> {
|
||||||
&self,
|
|
||||||
unord: &mut FuturesUnordered<SendPinBoxFuture<Option<DetectionResult>>>,
|
|
||||||
) {
|
|
||||||
let enable_upnp = self.config().with(|c| c.network.upnp);
|
|
||||||
|
|
||||||
// Do this right away because it's fast and every detection is going to need it
|
// Do this right away because it's fast and every detection is going to need it
|
||||||
// Get our external addresses from two fast nodes
|
// Get our external addresses from a bunch of fast nodes
|
||||||
if !self.discover_external_addresses().await {
|
if !self.discover_external_addresses().await {
|
||||||
// If we couldn't get an external address, then we should just try the whole network class detection again later
|
// If we couldn't get an external address, then we should just try the whole network class detection again later
|
||||||
return;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The set of futures we're going to wait on to determine dial info class for this context
|
||||||
|
let mut unord = FuturesUnordered::<PinBoxFutureStatic<DetectionResultKind>>::new();
|
||||||
|
|
||||||
|
// Used to determine what is still worth waiting for since we always want to return the
|
||||||
|
// best available dial info class. Once there are no better options in our waiting set
|
||||||
|
// we can just return what we've got.
|
||||||
|
let mut all_possibilities = DialInfoClassAllPossibilities::new();
|
||||||
|
|
||||||
// UPNP Automatic Mapping
|
// UPNP Automatic Mapping
|
||||||
///////////
|
///////////
|
||||||
|
|
||||||
|
let enable_upnp = self.config().with(|c| c.network.upnp);
|
||||||
if enable_upnp {
|
if enable_upnp {
|
||||||
let this = self.clone();
|
let this = self.clone();
|
||||||
let do_mapped_fut: SendPinBoxFuture<Option<DetectionResult>> = Box::pin(async move {
|
|
||||||
|
let possibilities = vec![(DialInfoClass::Mapped, 1)];
|
||||||
|
all_possibilities.add(&possibilities);
|
||||||
|
|
||||||
|
let do_mapped_fut: PinBoxFutureStatic<DetectionResultKind> = Box::pin(async move {
|
||||||
// Attempt a port mapping via all available and enabled mechanisms
|
// Attempt a port mapping via all available and enabled mechanisms
|
||||||
// Try this before the direct mapping in the event that we are restarting
|
// Try this before the direct mapping in the event that we are restarting
|
||||||
// and may not have recorded a mapping created the last time
|
// and may not have recorded a mapping created the last time
|
||||||
if let Some(external_mapped_dial_info) = this.try_upnp_port_mapping().await {
|
if let Some(external_mapped_dial_info) = this.try_upnp_port_mapping().await {
|
||||||
// Got a port mapping, let's use it
|
// Got a port mapping, let's use it
|
||||||
return Some(DetectionResult {
|
return DetectionResultKind::Result {
|
||||||
|
possibilities,
|
||||||
|
result: DetectionResult {
|
||||||
config: this.config,
|
config: this.config,
|
||||||
ddi: DetectedDialInfo::Detected(DialInfoDetail {
|
ddi: DetectedDialInfo::Detected(DialInfoDetail {
|
||||||
dial_info: external_mapped_dial_info.clone(),
|
dial_info: external_mapped_dial_info.clone(),
|
||||||
@ -730,9 +883,10 @@ impl DiscoveryContext {
|
|||||||
external_address_types: AddressTypeSet::only(
|
external_address_types: AddressTypeSet::only(
|
||||||
external_mapped_dial_info.address_type(),
|
external_mapped_dial_info.address_type(),
|
||||||
),
|
),
|
||||||
});
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
None
|
DetectionResultKind::Failure { possibilities }
|
||||||
});
|
});
|
||||||
unord.push(do_mapped_fut);
|
unord.push(do_mapped_fut);
|
||||||
}
|
}
|
||||||
@ -750,9 +904,84 @@ impl DiscoveryContext {
|
|||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
if local_address_in_external_info {
|
if local_address_in_external_info {
|
||||||
self.protocol_process_no_nat(unord).await;
|
self.protocol_process_no_nat(&mut all_possibilities, &mut unord);
|
||||||
} else {
|
} else {
|
||||||
self.protocol_process_nat(unord).await;
|
self.protocol_process_nat(&mut all_possibilities, &mut unord);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the best detection result to roll in
|
||||||
|
let mut opt_best_detection_result: Option<DetectionResult> = None;
|
||||||
|
loop {
|
||||||
|
match unord
|
||||||
|
.next()
|
||||||
|
.timeout_at(self.stop_token.clone())
|
||||||
|
.in_current_span()
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(Some(DetectionResultKind::Result {
|
||||||
|
result,
|
||||||
|
possibilities,
|
||||||
|
})) => {
|
||||||
|
// Remove possible dial info classes from our available set
|
||||||
|
all_possibilities.remove(&possibilities);
|
||||||
|
|
||||||
|
// Get best detection result for each discovery context config
|
||||||
|
if let Some(best_detection_result) = &mut opt_best_detection_result {
|
||||||
|
let ddi = &mut best_detection_result.ddi;
|
||||||
|
// Upgrade existing dialinfo
|
||||||
|
match ddi {
|
||||||
|
DetectedDialInfo::SymmetricNAT => {
|
||||||
|
// Whatever we got is better than or equal to symmetric
|
||||||
|
*ddi = result.ddi;
|
||||||
|
}
|
||||||
|
DetectedDialInfo::Detected(cur_did) => match result.ddi {
|
||||||
|
DetectedDialInfo::SymmetricNAT => {
|
||||||
|
// Nothing is worse than this
|
||||||
|
}
|
||||||
|
DetectedDialInfo::Detected(did) => {
|
||||||
|
// Pick the best dial info class we detected
|
||||||
|
// because some nodes could be degenerate and if any node can validate a
|
||||||
|
// better dial info class we should go with it and leave the
|
||||||
|
// degenerate nodes in the dust to fade into obscurity
|
||||||
|
if did.class < cur_did.class {
|
||||||
|
cur_did.class = did.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
best_detection_result.external_address_types |=
|
||||||
|
result.external_address_types;
|
||||||
|
} else {
|
||||||
|
opt_best_detection_result = Some(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Some(DetectionResultKind::Failure { possibilities })) => {
|
||||||
|
// Found no dial info for this protocol/address combination
|
||||||
|
|
||||||
|
// Remove possible dial info classes from our available set
|
||||||
|
all_possibilities.remove(&possibilities);
|
||||||
|
}
|
||||||
|
Ok(None) => {
|
||||||
|
// All done, normally
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
// Stop token, exit early without error propagation
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if there's any better results worth waiting for
|
||||||
|
if let Some(best_detection_result) = &opt_best_detection_result {
|
||||||
|
if let DetectedDialInfo::Detected(did) = &best_detection_result.ddi {
|
||||||
|
// If nothing else is going to be a better result, just stop here
|
||||||
|
if !all_possibilities.any_better(did.class) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
opt_best_detection_result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -318,7 +318,7 @@ impl Network {
|
|||||||
.routing_table()
|
.routing_table()
|
||||||
.routing_domain_for_address(dial_info.address());
|
.routing_domain_for_address(dial_info.address());
|
||||||
|
|
||||||
let network_result = fut.await?;
|
let network_result = pin_future_closure!(fut).await?;
|
||||||
if matches!(network_result, NetworkResult::NoConnection(_)) {
|
if matches!(network_result, NetworkResult::NoConnection(_)) {
|
||||||
// Dial info failure
|
// Dial info failure
|
||||||
self.network_manager()
|
self.network_manager()
|
||||||
|
@ -211,7 +211,7 @@ impl ProtocolAcceptHandler for RawTcpProtocolHandler {
|
|||||||
stream: AsyncPeekStream,
|
stream: AsyncPeekStream,
|
||||||
peer_addr: SocketAddr,
|
peer_addr: SocketAddr,
|
||||||
local_addr: SocketAddr,
|
local_addr: SocketAddr,
|
||||||
) -> SendPinBoxFuture<io::Result<Option<ProtocolNetworkConnection>>> {
|
) -> PinBoxFutureStatic<io::Result<Option<ProtocolNetworkConnection>>> {
|
||||||
Box::pin(self.clone().on_accept_async(stream, peer_addr, local_addr))
|
Box::pin(self.clone().on_accept_async(stream, peer_addr, local_addr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -410,7 +410,7 @@ impl ProtocolAcceptHandler for WebsocketProtocolHandler {
|
|||||||
stream: AsyncPeekStream,
|
stream: AsyncPeekStream,
|
||||||
peer_addr: SocketAddr,
|
peer_addr: SocketAddr,
|
||||||
local_addr: SocketAddr,
|
local_addr: SocketAddr,
|
||||||
) -> SendPinBoxFuture<io::Result<Option<ProtocolNetworkConnection>>> {
|
) -> PinBoxFutureStatic<io::Result<Option<ProtocolNetworkConnection>>> {
|
||||||
Box::pin(self.clone().on_accept_async(stream, peer_addr, local_addr))
|
Box::pin(self.clone().on_accept_async(stream, peer_addr, local_addr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,9 +11,9 @@ impl Network {
|
|||||||
// Network lock ensures only one task operating on the low level network state
|
// Network lock ensures only one task operating on the low level network state
|
||||||
// can happen at the same time. Try lock is here to give preference to other longer
|
// can happen at the same time. Try lock is here to give preference to other longer
|
||||||
// running processes like update_network_class_task.
|
// running processes like update_network_class_task.
|
||||||
let _guard = match self.network_task_lock.try_lock() {
|
let _guard = match asyncmutex_try_lock!(self.network_task_lock) {
|
||||||
Ok(v) => v,
|
Some(v) => v,
|
||||||
Err(_) => {
|
None => {
|
||||||
// If we can't get the lock right now, then
|
// If we can't get the lock right now, then
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ impl Network {
|
|||||||
&self,
|
&self,
|
||||||
stop_token: StopToken,
|
stop_token: StopToken,
|
||||||
_l: Timestamp,
|
_l: Timestamp,
|
||||||
_t: Timestamp,
|
cur_ts: Timestamp,
|
||||||
) -> EyreResult<bool> {
|
) -> EyreResult<bool> {
|
||||||
// Figure out if we can optimize TCP/WS checking since they are often on the same port
|
// Figure out if we can optimize TCP/WS checking since they are often on the same port
|
||||||
let (protocol_config, inbound_protocol_map) = {
|
let (protocol_config, inbound_protocol_map) = {
|
||||||
@ -153,8 +153,8 @@ impl Network {
|
|||||||
port,
|
port,
|
||||||
};
|
};
|
||||||
context_configs.insert(dcc);
|
context_configs.insert(dcc);
|
||||||
let discovery_context = DiscoveryContext::new(self.registry(), dcc);
|
let discovery_context = DiscoveryContext::new(self.registry(), dcc, stop_token.clone());
|
||||||
discovery_context.discover(&mut unord).await;
|
unord.push(discovery_context.discover());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for all discovery futures to complete and apply discoverycontexts
|
// Wait for all discovery futures to complete and apply discoverycontexts
|
||||||
@ -174,35 +174,9 @@ impl Network {
|
|||||||
// Add the external address kinds to the set we've seen
|
// Add the external address kinds to the set we've seen
|
||||||
external_address_types |= dr.external_address_types;
|
external_address_types |= dr.external_address_types;
|
||||||
|
|
||||||
// Get best detection result for each discovery context config
|
// Save best detection result for each discovery context config
|
||||||
if let Some(cur_dr) = detection_results.get_mut(&dr.config) {
|
|
||||||
let ddi = &mut cur_dr.ddi;
|
|
||||||
// Upgrade existing dialinfo
|
|
||||||
match ddi {
|
|
||||||
DetectedDialInfo::SymmetricNAT => {
|
|
||||||
// Whatever we got is better than or equal to symmetric
|
|
||||||
*ddi = dr.ddi;
|
|
||||||
}
|
|
||||||
DetectedDialInfo::Detected(cur_did) => match dr.ddi {
|
|
||||||
DetectedDialInfo::SymmetricNAT => {
|
|
||||||
// Nothing is worse than this
|
|
||||||
}
|
|
||||||
DetectedDialInfo::Detected(did) => {
|
|
||||||
// Pick the best dial info class we detected
|
|
||||||
// because some nodes could be degenerate and if any node can validate a
|
|
||||||
// better dial info class we should go with it and leave the
|
|
||||||
// degenerate nodes in the dust to fade into obscurity
|
|
||||||
if did.class < cur_did.class {
|
|
||||||
cur_did.class = did.class;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
cur_dr.external_address_types |= dr.external_address_types;
|
|
||||||
} else {
|
|
||||||
detection_results.insert(dr.config, dr);
|
detection_results.insert(dr.config, dr);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(Some(None)) => {
|
Ok(Some(None)) => {
|
||||||
// Found no dial info for this protocol/address combination
|
// Found no dial info for this protocol/address combination
|
||||||
}
|
}
|
||||||
@ -223,9 +197,11 @@ impl Network {
|
|||||||
self.update_with_detection_result(&mut editor, &inbound_protocol_map, dr);
|
self.update_with_detection_result(&mut editor, &inbound_protocol_map, dr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let end_ts = Timestamp::now();
|
||||||
|
|
||||||
// If we got no external address types, try again
|
// If we got no external address types, try again
|
||||||
if external_address_types.is_empty() {
|
if external_address_types.is_empty() {
|
||||||
veilid_log!(self debug "Network class discovery failed, trying again, got no external address types");
|
veilid_log!(self debug "Network class discovery failed in {}, trying again, got no external address types", end_ts - cur_ts);
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,12 +216,12 @@ impl Network {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !success {
|
if !success {
|
||||||
veilid_log!(self debug "Network class discovery failed, trying again, needed {:?}", context_configs);
|
veilid_log!(self debug "Network class discovery failed in {}, trying again, needed {:?}", end_ts - cur_ts, context_configs);
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// All done
|
// All done
|
||||||
veilid_log!(self debug "Network class discovery finished with address_types {:?}", external_address_types);
|
veilid_log!(self debug "Network class discovery finished in {} with address_types {:?}", end_ts - cur_ts, external_address_types);
|
||||||
|
|
||||||
// Set the address types we've seen and confirm the network class
|
// Set the address types we've seen and confirm the network class
|
||||||
editor.setup_network(
|
editor.setup_network(
|
||||||
|
@ -17,7 +17,7 @@ cfg_if::cfg_if! {
|
|||||||
stream: AsyncPeekStream,
|
stream: AsyncPeekStream,
|
||||||
peer_addr: SocketAddr,
|
peer_addr: SocketAddr,
|
||||||
local_addr: SocketAddr,
|
local_addr: SocketAddr,
|
||||||
) -> SendPinBoxFuture<io::Result<Option<ProtocolNetworkConnection>>>;
|
) -> PinBoxFutureStatic<io::Result<Option<ProtocolNetworkConnection>>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait ProtocolAcceptHandlerClone {
|
pub(crate) trait ProtocolAcceptHandlerClone {
|
||||||
@ -328,7 +328,7 @@ impl NetworkConnection {
|
|||||||
receiver: flume::Receiver<(Option<Id>, Vec<u8>)>,
|
receiver: flume::Receiver<(Option<Id>, Vec<u8>)>,
|
||||||
protocol_connection: ProtocolNetworkConnection,
|
protocol_connection: ProtocolNetworkConnection,
|
||||||
stats: Arc<Mutex<NetworkConnectionStats>>,
|
stats: Arc<Mutex<NetworkConnectionStats>>,
|
||||||
) -> SendPinBoxFuture<()> {
|
) -> PinBoxFutureStatic<()> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let registry = connection_manager.registry();
|
let registry = connection_manager.registry();
|
||||||
|
|
||||||
|
132
veilid-core/src/network_manager/node_contact_method_cache.rs
Normal file
132
veilid-core/src/network_manager/node_contact_method_cache.rs
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub const NODE_CONTACT_METHOD_CACHE_SIZE: usize = 1024;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
|
||||||
|
pub struct NodeContactMethodCacheKey {
|
||||||
|
pub node_ids: TypedKeyGroup,
|
||||||
|
pub own_node_info_ts: Timestamp,
|
||||||
|
pub target_node_info_ts: Timestamp,
|
||||||
|
pub target_node_ref_filter: NodeRefFilter,
|
||||||
|
pub target_node_ref_sequencing: Sequencing,
|
||||||
|
pub dial_info_failures_map: BTreeMap<DialInfo, Timestamp>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Default, Debug)]
|
||||||
|
pub struct HitMissStats {
|
||||||
|
pub hit: usize,
|
||||||
|
pub miss: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
|
enum ContactMethodKind {
|
||||||
|
Unreachable,
|
||||||
|
Existing,
|
||||||
|
Direct,
|
||||||
|
SignalReverse,
|
||||||
|
SignalHolePunch,
|
||||||
|
InboundRelay,
|
||||||
|
OutboundRelay,
|
||||||
|
}
|
||||||
|
impl From<Option<&NodeContactMethodKind>> for ContactMethodKind {
|
||||||
|
fn from(value: Option<&NodeContactMethodKind>) -> Self {
|
||||||
|
match value {
|
||||||
|
None => ContactMethodKind::Unreachable,
|
||||||
|
Some(NodeContactMethodKind::Existing) => ContactMethodKind::Existing,
|
||||||
|
Some(NodeContactMethodKind::Direct(_)) => ContactMethodKind::Direct,
|
||||||
|
Some(NodeContactMethodKind::SignalReverse(_, _)) => ContactMethodKind::SignalReverse,
|
||||||
|
Some(NodeContactMethodKind::SignalHolePunch(_, _)) => {
|
||||||
|
ContactMethodKind::SignalHolePunch
|
||||||
|
}
|
||||||
|
Some(NodeContactMethodKind::InboundRelay(_)) => ContactMethodKind::InboundRelay,
|
||||||
|
Some(NodeContactMethodKind::OutboundRelay(_)) => ContactMethodKind::OutboundRelay,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HitMissStats {
|
||||||
|
pub fn percentage(&self) -> f32 {
|
||||||
|
(self.hit as f32 * 100.0f32) / ((self.hit + self.miss) as f32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for HitMissStats {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}/{} {:.2}%",
|
||||||
|
self.hit,
|
||||||
|
self.hit + self.miss,
|
||||||
|
self.percentage()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NodeContactMethodCache {
|
||||||
|
cache: LruCache<NodeContactMethodCacheKey, NodeContactMethodKind>,
|
||||||
|
|
||||||
|
// Statistics for cache hits/misses
|
||||||
|
cache_stats: HitMissStats,
|
||||||
|
|
||||||
|
// Recorded stats for contact method success
|
||||||
|
contact_method_kind_stats: HashMap<ContactMethodKind, HitMissStats>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for NodeContactMethodCache {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("NodeContactMethodCache")
|
||||||
|
//.field("cache", &self.cache)
|
||||||
|
.field("cache_stats", &self.cache_stats)
|
||||||
|
.field("contact_method_kind_stats", &self.contact_method_kind_stats)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NodeContactMethodCache {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
cache: LruCache::new(NODE_CONTACT_METHOD_CACHE_SIZE),
|
||||||
|
cache_stats: HitMissStats::default(),
|
||||||
|
contact_method_kind_stats: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn insert(&mut self, ncm_key: NodeContactMethodCacheKey, ncm_kind: NodeContactMethodKind) {
|
||||||
|
// Cache this
|
||||||
|
self.cache.insert(ncm_key, ncm_kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&mut self, ncm_key: &NodeContactMethodCacheKey) -> Option<NodeContactMethodKind> {
|
||||||
|
if let Some(ncm_kind) = self.cache.get(ncm_key) {
|
||||||
|
self.cache_stats.hit += 1;
|
||||||
|
|
||||||
|
return Some(ncm_kind.clone());
|
||||||
|
}
|
||||||
|
// Record miss
|
||||||
|
self.cache_stats.miss += 1;
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn record_contact_method_success(&mut self, ncm_kind: Option<&NodeContactMethodKind>) {
|
||||||
|
let cmk = ContactMethodKind::from(ncm_kind);
|
||||||
|
self.contact_method_kind_stats.entry(cmk).or_default().hit += 1;
|
||||||
|
}
|
||||||
|
pub fn record_contact_method_failure(&mut self, ncm_kind: Option<&NodeContactMethodKind>) {
|
||||||
|
let cmk = ContactMethodKind::from(ncm_kind);
|
||||||
|
self.contact_method_kind_stats.entry(cmk).or_default().miss += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn debug(&self) -> String {
|
||||||
|
let mut out = format!(
|
||||||
|
"Cache size: {}\nCache hits: {}\nContact methods:\n",
|
||||||
|
self.cache.len(),
|
||||||
|
self.cache_stats
|
||||||
|
);
|
||||||
|
let mut sorted_kinds: Vec<_> = self.contact_method_kind_stats.keys().collect();
|
||||||
|
sorted_kinds.sort();
|
||||||
|
for kind in sorted_kinds {
|
||||||
|
let kindstats = self.contact_method_kind_stats.get(kind).unwrap();
|
||||||
|
out += &format!(" {:?}: {}\n", kind, kindstats);
|
||||||
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
|
}
|
@ -38,7 +38,7 @@ pub trait ReceiptCallback: Send + 'static {
|
|||||||
receipt: Receipt,
|
receipt: Receipt,
|
||||||
returns_so_far: u32,
|
returns_so_far: u32,
|
||||||
expected_returns: u32,
|
expected_returns: u32,
|
||||||
) -> SendPinBoxFuture<()>;
|
) -> PinBoxFutureStatic<()>;
|
||||||
}
|
}
|
||||||
impl<F, T> ReceiptCallback for T
|
impl<F, T> ReceiptCallback for T
|
||||||
where
|
where
|
||||||
@ -51,7 +51,7 @@ where
|
|||||||
receipt: Receipt,
|
receipt: Receipt,
|
||||||
returns_so_far: u32,
|
returns_so_far: u32,
|
||||||
expected_returns: u32,
|
expected_returns: u32,
|
||||||
) -> SendPinBoxFuture<()> {
|
) -> PinBoxFutureStatic<()> {
|
||||||
Box::pin(self(event, receipt, returns_so_far, expected_returns))
|
Box::pin(self(event, receipt, returns_so_far, expected_returns))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -184,17 +184,12 @@ impl ReceiptManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn startup(&self) -> EyreResult<()> {
|
pub fn startup(&self) -> EyreResult<()> {
|
||||||
let guard = self.unlocked_inner.startup_lock.startup()?;
|
let guard = self.unlocked_inner.startup_lock.startup()?;
|
||||||
veilid_log!(self debug "startup receipt manager");
|
veilid_log!(self debug "startup receipt manager");
|
||||||
|
|
||||||
// Retrieve config
|
|
||||||
{
|
|
||||||
// let config = self.core().config();
|
|
||||||
// let c = config.get();
|
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
inner.stop_source = Some(StopSource::new());
|
inner.stop_source = Some(StopSource::new());
|
||||||
}
|
|
||||||
|
|
||||||
guard.success();
|
guard.success();
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -204,7 +199,7 @@ impl ReceiptManager {
|
|||||||
fn perform_callback(
|
fn perform_callback(
|
||||||
evt: ReceiptEvent,
|
evt: ReceiptEvent,
|
||||||
record_mut: &mut ReceiptRecord,
|
record_mut: &mut ReceiptRecord,
|
||||||
) -> Option<SendPinBoxFuture<()>> {
|
) -> Option<PinBoxFutureStatic<()>> {
|
||||||
match &mut record_mut.receipt_callback {
|
match &mut record_mut.receipt_callback {
|
||||||
ReceiptRecordCallbackType::Normal(callback) => Some(callback.call(
|
ReceiptRecordCallbackType::Normal(callback) => Some(callback.call(
|
||||||
evt,
|
evt,
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use stop_token::future::FutureExt as _;
|
use stop_token::future::FutureExt as _;
|
||||||
|
|
||||||
// global debugging statistics for hole punch success
|
|
||||||
static HOLE_PUNCH_SUCCESS: AtomicUsize = AtomicUsize::new(0);
|
|
||||||
static HOLE_PUNCH_FAILURE: AtomicUsize = AtomicUsize::new(0);
|
|
||||||
static REVERSE_CONNECT_SUCCESS: AtomicUsize = AtomicUsize::new(0);
|
|
||||||
static REVERSE_CONNECT_FAILURE: AtomicUsize = AtomicUsize::new(0);
|
|
||||||
|
|
||||||
impl NetworkManager {
|
impl NetworkManager {
|
||||||
/// Send raw data to a node
|
/// Send raw data to a node
|
||||||
///
|
///
|
||||||
@ -20,50 +14,161 @@ impl NetworkManager {
|
|||||||
&self,
|
&self,
|
||||||
destination_node_ref: FilteredNodeRef,
|
destination_node_ref: FilteredNodeRef,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
) -> EyreResult<NetworkResult<SendDataMethod>> {
|
) -> EyreResult<NetworkResult<SendDataResult>> {
|
||||||
// Get the best way to contact this node
|
// Get the best way to contact this node
|
||||||
let possibly_relayed_contact_method =
|
let mut opt_node_contact_method =
|
||||||
self.get_node_contact_method(destination_node_ref.clone())?;
|
self.get_node_contact_method(destination_node_ref.clone())?;
|
||||||
|
|
||||||
self.try_possibly_relayed_contact_method(
|
// Retry loop
|
||||||
possibly_relayed_contact_method,
|
loop {
|
||||||
destination_node_ref,
|
// Boxed because calling rpc_call_signal() is recursive to send_data()
|
||||||
data,
|
let nres = pin_future_closure!(self.try_node_contact_method(
|
||||||
)
|
opt_node_contact_method.clone(),
|
||||||
.await
|
destination_node_ref.clone(),
|
||||||
|
data.clone(),
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
match &nres {
|
||||||
|
NetworkResult::Timeout => {
|
||||||
|
// Record contact method failure statistics
|
||||||
|
self.inner
|
||||||
|
.lock()
|
||||||
|
.node_contact_method_cache
|
||||||
|
.record_contact_method_failure(
|
||||||
|
opt_node_contact_method.as_ref().map(|x| &x.ncm_kind),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Timeouts may retry with a different method
|
||||||
|
match opt_node_contact_method {
|
||||||
|
Some(NodeContactMethod {
|
||||||
|
ncm_key,
|
||||||
|
ncm_kind:
|
||||||
|
NodeContactMethodKind::SignalReverse(relay_nr, _target_node_ref),
|
||||||
|
}) => {
|
||||||
|
// Try again with a different method
|
||||||
|
opt_node_contact_method = Some(NodeContactMethod {
|
||||||
|
ncm_key,
|
||||||
|
ncm_kind: NodeContactMethodKind::InboundRelay(relay_nr),
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Some(NodeContactMethod {
|
||||||
|
ncm_key,
|
||||||
|
ncm_kind:
|
||||||
|
NodeContactMethodKind::SignalHolePunch(relay_nr, _target_node_ref),
|
||||||
|
}) => {
|
||||||
|
// Try again with a different method
|
||||||
|
opt_node_contact_method = Some(NodeContactMethod {
|
||||||
|
ncm_key,
|
||||||
|
ncm_kind: NodeContactMethodKind::InboundRelay(relay_nr),
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// Don't retry any other contact methods, and don't cache a timeout
|
||||||
|
break Ok(nres);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NetworkResult::ServiceUnavailable(_)
|
||||||
|
| NetworkResult::NoConnection(_)
|
||||||
|
| NetworkResult::AlreadyExists(_)
|
||||||
|
| NetworkResult::InvalidMessage(_) => {
|
||||||
|
// Record contact method failure statistics
|
||||||
|
self.inner
|
||||||
|
.lock()
|
||||||
|
.node_contact_method_cache
|
||||||
|
.record_contact_method_failure(
|
||||||
|
opt_node_contact_method.as_ref().map(|x| &x.ncm_kind),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Other network results don't cache, just directly return the result
|
||||||
|
break Ok(nres);
|
||||||
|
}
|
||||||
|
NetworkResult::Value(v) => {
|
||||||
|
// Successful network result gets to cache the node contact method
|
||||||
|
if let Some(ncm) = &v.opt_contact_method {
|
||||||
|
// Cache the contact method
|
||||||
|
self.cache_node_contact_method(ncm.clone());
|
||||||
|
}
|
||||||
|
if let Some(ncm) = &v.opt_relayed_contact_method {
|
||||||
|
// Cache the relayed contact method
|
||||||
|
self.cache_node_contact_method(ncm.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record cache insertion as a success
|
||||||
|
self.inner
|
||||||
|
.lock()
|
||||||
|
.node_contact_method_cache
|
||||||
|
.record_contact_method_success(
|
||||||
|
v.opt_contact_method.as_ref().map(|x| &x.ncm_kind),
|
||||||
|
);
|
||||||
|
// If relayed contact method was specified, then it wasn't unreachable
|
||||||
|
// (must have been relay type or it wouldnt be here, and if this is None
|
||||||
|
// then the contact method was not relayed)
|
||||||
|
if v.opt_relayed_contact_method.is_some() {
|
||||||
|
self.inner
|
||||||
|
.lock()
|
||||||
|
.node_contact_method_cache
|
||||||
|
.record_contact_method_success(
|
||||||
|
v.opt_relayed_contact_method.as_ref().map(|x| &x.ncm_kind),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
break Ok(nres);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", target = "net", skip_all)]
|
#[instrument(level = "trace", target = "net", skip_all)]
|
||||||
pub fn try_possibly_relayed_contact_method(
|
async fn try_node_contact_method(
|
||||||
&self,
|
&self,
|
||||||
possibly_relayed_contact_method: NodeContactMethod,
|
opt_node_contact_method: Option<NodeContactMethod>,
|
||||||
destination_node_ref: FilteredNodeRef,
|
destination_node_ref: FilteredNodeRef,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
) -> SendPinBoxFuture<EyreResult<NetworkResult<SendDataMethod>>> {
|
) -> EyreResult<NetworkResult<SendDataResult>> {
|
||||||
let registry = self.registry();
|
|
||||||
Box::pin(
|
|
||||||
async move {
|
|
||||||
let this = registry.network_manager();
|
|
||||||
|
|
||||||
// If we need to relay, do it
|
// If we need to relay, do it
|
||||||
let (contact_method, target_node_ref, opt_relayed_contact_method) = match possibly_relayed_contact_method.clone() {
|
let (opt_contact_method, target_node_ref, opt_relayed_contact_method) =
|
||||||
NodeContactMethod::OutboundRelay(relay_nr)
|
match opt_node_contact_method.clone().map(|x| x.ncm_kind) {
|
||||||
| NodeContactMethod::InboundRelay(relay_nr) => {
|
Some(NodeContactMethodKind::OutboundRelay(relay_nr))
|
||||||
let cm = this.get_node_contact_method(relay_nr.clone())?;
|
| Some(NodeContactMethodKind::InboundRelay(relay_nr)) => {
|
||||||
(cm, relay_nr, Some(possibly_relayed_contact_method))
|
let opt_contact_method = self.get_node_contact_method(relay_nr.clone())?;
|
||||||
|
(opt_contact_method, relay_nr, opt_node_contact_method)
|
||||||
}
|
}
|
||||||
cm => (cm, destination_node_ref.clone(), None),
|
_ => (opt_node_contact_method, destination_node_ref.clone(), None),
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "verbose-tracing")]
|
#[cfg(feature = "verbose-tracing")]
|
||||||
veilid_log!(self debug
|
veilid_log!(self debug
|
||||||
"ContactMethod: {:?} for {:?}",
|
"ContactMethod: {:?} for {:?}",
|
||||||
contact_method, destination_node_ref
|
opt_contact_method, destination_node_ref
|
||||||
);
|
);
|
||||||
|
|
||||||
// Try the contact method
|
// Try the contact method
|
||||||
let mut send_data_method = match contact_method {
|
let unique_flow = match &opt_contact_method {
|
||||||
NodeContactMethod::OutboundRelay(relay_nr) => {
|
None => {
|
||||||
|
// If a node is unreachable it may still have an existing inbound connection
|
||||||
|
// Try that, but don't cache anything
|
||||||
|
network_result_try!(
|
||||||
|
pin_future_closure!(self.send_data_ncm_existing(target_node_ref, data)).await?
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Some(NodeContactMethod {
|
||||||
|
ncm_key: _,
|
||||||
|
ncm_kind: NodeContactMethodKind::Existing,
|
||||||
|
}) => {
|
||||||
|
// The node must have an existing connection, for example connecting to your own
|
||||||
|
// relay is something that must always have a connection already
|
||||||
|
network_result_try!(
|
||||||
|
pin_future_closure!(self.send_data_ncm_existing(target_node_ref, data)).await?
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Some(NodeContactMethod {
|
||||||
|
ncm_key: _,
|
||||||
|
ncm_kind: NodeContactMethodKind::OutboundRelay(relay_nr),
|
||||||
|
}) => {
|
||||||
// Relay loop or multiple relays
|
// Relay loop or multiple relays
|
||||||
bail!(
|
bail!(
|
||||||
"Outbound relay loop or multiple relays detected: destination {} resolved to target {} via extraneous relay {}",
|
"Outbound relay loop or multiple relays detected: destination {} resolved to target {} via extraneous relay {}",
|
||||||
@ -72,7 +177,10 @@ impl NetworkManager {
|
|||||||
relay_nr,
|
relay_nr,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
| NodeContactMethod::InboundRelay(relay_nr) => {
|
Some(NodeContactMethod {
|
||||||
|
ncm_key: _,
|
||||||
|
ncm_kind: NodeContactMethodKind::InboundRelay(relay_nr),
|
||||||
|
}) => {
|
||||||
// Relay loop or multiple relays
|
// Relay loop or multiple relays
|
||||||
bail!(
|
bail!(
|
||||||
"Inbound relay loop or multiple relays detected: destination {} resolved to target {} via extraneous relay {}",
|
"Inbound relay loop or multiple relays detected: destination {} resolved to target {} via extraneous relay {}",
|
||||||
@ -81,80 +189,52 @@ impl NetworkManager {
|
|||||||
relay_nr,
|
relay_nr,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
NodeContactMethod::Direct(dial_info) => {
|
Some(NodeContactMethod {
|
||||||
|
ncm_key: _,
|
||||||
|
ncm_kind: NodeContactMethodKind::Direct(dial_info),
|
||||||
|
}) => {
|
||||||
network_result_try!(
|
network_result_try!(
|
||||||
this.send_data_ncm_direct(target_node_ref, dial_info, data).await?
|
pin_future_closure!(self.send_data_ncm_direct(
|
||||||
|
target_node_ref,
|
||||||
|
dial_info.clone(),
|
||||||
|
data
|
||||||
|
))
|
||||||
|
.await?
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
NodeContactMethod::SignalReverse(relay_nr, target_node_ref) => {
|
Some(NodeContactMethod {
|
||||||
let nres =
|
ncm_key: _,
|
||||||
this.send_data_ncm_signal_reverse(relay_nr.clone(), target_node_ref.clone(), data.clone())
|
ncm_kind: NodeContactMethodKind::SignalReverse(relay_nr, target_node_ref),
|
||||||
.await?;
|
}) => {
|
||||||
if matches!(nres, NetworkResult::Timeout) {
|
|
||||||
// Failed to reverse-connect, fallback to inbound relay
|
|
||||||
let success = REVERSE_CONNECT_SUCCESS.load(Ordering::Acquire);
|
|
||||||
let failure = REVERSE_CONNECT_FAILURE.fetch_add(1, Ordering::AcqRel) + 1;
|
|
||||||
let rate = (success as f64 * 100.0) / ((success + failure) as f64);
|
|
||||||
|
|
||||||
veilid_log!(this debug target:"network_result", "Reverse connection failed ({:.2}% success) to {}, falling back to inbound relay via {}", rate, target_node_ref, relay_nr);
|
|
||||||
network_result_try!(this.try_possibly_relayed_contact_method(NodeContactMethod::InboundRelay(relay_nr), destination_node_ref, data).await?)
|
|
||||||
} else {
|
|
||||||
if let NetworkResult::Value(sdm) = &nres {
|
|
||||||
if matches!(sdm.contact_method, NodeContactMethod::SignalReverse(_,_)) {
|
|
||||||
|
|
||||||
let success = REVERSE_CONNECT_SUCCESS.fetch_add(1, Ordering::AcqRel) + 1;
|
|
||||||
let failure = REVERSE_CONNECT_FAILURE.load(Ordering::Acquire);
|
|
||||||
let rate = (success as f64 * 100.0) / ((success + failure) as f64);
|
|
||||||
|
|
||||||
veilid_log!(this debug target:"network_result", "Reverse connection successful ({:.2}% success) to {} via {}", rate, target_node_ref, relay_nr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
network_result_try!(nres)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NodeContactMethod::SignalHolePunch(relay_nr, target_node_ref) => {
|
|
||||||
let nres =
|
|
||||||
this.send_data_ncm_signal_hole_punch(relay_nr.clone(), target_node_ref.clone(), data.clone())
|
|
||||||
.await?;
|
|
||||||
if matches!(nres, NetworkResult::Timeout) {
|
|
||||||
// Failed to holepunch, fallback to inbound relay
|
|
||||||
let success = HOLE_PUNCH_SUCCESS.load(Ordering::Acquire);
|
|
||||||
let failure = HOLE_PUNCH_FAILURE.fetch_add(1, Ordering::AcqRel) + 1;
|
|
||||||
let rate = (success as f64 * 100.0) / ((success + failure) as f64);
|
|
||||||
|
|
||||||
veilid_log!(this debug target:"network_result", "Hole punch failed ({:.2}% success) to {} , falling back to inbound relay via {}", rate, target_node_ref , relay_nr);
|
|
||||||
network_result_try!(this.try_possibly_relayed_contact_method(NodeContactMethod::InboundRelay(relay_nr), destination_node_ref, data).await?)
|
|
||||||
} else {
|
|
||||||
if let NetworkResult::Value(sdm) = &nres {
|
|
||||||
if matches!(sdm.contact_method, NodeContactMethod::SignalHolePunch(_,_)) {
|
|
||||||
let success = HOLE_PUNCH_SUCCESS.fetch_add(1, Ordering::AcqRel) + 1;
|
|
||||||
let failure = HOLE_PUNCH_FAILURE.load(Ordering::Acquire);
|
|
||||||
let rate = (success as f64 * 100.0) / ((success + failure) as f64);
|
|
||||||
|
|
||||||
veilid_log!(this debug target:"network_result", "Hole punch successful ({:.2}% success) to {} via {}", rate, target_node_ref, relay_nr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
network_result_try!(nres)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NodeContactMethod::Existing => {
|
|
||||||
network_result_try!(
|
network_result_try!(
|
||||||
this.send_data_ncm_existing(target_node_ref, data).await?
|
pin_future_closure!(self.send_data_ncm_signal_reverse(
|
||||||
|
relay_nr.clone(),
|
||||||
|
target_node_ref.clone(),
|
||||||
|
data.clone()
|
||||||
|
))
|
||||||
|
.await?
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
NodeContactMethod::Unreachable => {
|
Some(NodeContactMethod {
|
||||||
|
ncm_key: _,
|
||||||
|
ncm_kind: NodeContactMethodKind::SignalHolePunch(relay_nr, target_node_ref),
|
||||||
|
}) => {
|
||||||
network_result_try!(
|
network_result_try!(
|
||||||
this.send_data_ncm_unreachable(target_node_ref, data)
|
pin_future_closure!(self.send_data_ncm_signal_hole_punch(
|
||||||
|
relay_nr.clone(),
|
||||||
|
target_node_ref.clone(),
|
||||||
|
data.clone()
|
||||||
|
))
|
||||||
.await?
|
.await?
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
send_data_method.opt_relayed_contact_method = opt_relayed_contact_method;
|
|
||||||
|
|
||||||
Ok(NetworkResult::value(send_data_method))
|
Ok(NetworkResult::value(SendDataResult {
|
||||||
}
|
opt_contact_method,
|
||||||
.in_current_span()
|
opt_relayed_contact_method,
|
||||||
)
|
unique_flow,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send data using NodeContactMethod::Existing
|
/// Send data using NodeContactMethod::Existing
|
||||||
@ -163,7 +243,7 @@ impl NetworkManager {
|
|||||||
&self,
|
&self,
|
||||||
target_node_ref: FilteredNodeRef,
|
target_node_ref: FilteredNodeRef,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
) -> EyreResult<NetworkResult<SendDataMethod>> {
|
) -> EyreResult<NetworkResult<UniqueFlow>> {
|
||||||
// First try to send data to the last connection we've seen this peer on
|
// First try to send data to the last connection we've seen this peer on
|
||||||
let Some(flow) = target_node_ref.last_flow() else {
|
let Some(flow) = target_node_ref.last_flow() else {
|
||||||
return Ok(NetworkResult::no_connection_other(format!(
|
return Ok(NetworkResult::no_connection_other(format!(
|
||||||
@ -172,7 +252,8 @@ impl NetworkManager {
|
|||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
|
|
||||||
let unique_flow = match self.net().send_data_to_existing_flow(flow, data).await? {
|
let net = self.net();
|
||||||
|
let unique_flow = match pin_future!(net.send_data_to_existing_flow(flow, data)).await? {
|
||||||
SendDataToExistingFlowResult::Sent(unique_flow) => unique_flow,
|
SendDataToExistingFlowResult::Sent(unique_flow) => unique_flow,
|
||||||
SendDataToExistingFlowResult::NotSent(_) => {
|
SendDataToExistingFlowResult::NotSent(_) => {
|
||||||
return Ok(NetworkResult::no_connection_other(
|
return Ok(NetworkResult::no_connection_other(
|
||||||
@ -184,46 +265,7 @@ impl NetworkManager {
|
|||||||
// Update timestamp for this last connection since we just sent to it
|
// Update timestamp for this last connection since we just sent to it
|
||||||
self.set_last_flow(target_node_ref.unfiltered(), flow, Timestamp::now());
|
self.set_last_flow(target_node_ref.unfiltered(), flow, Timestamp::now());
|
||||||
|
|
||||||
Ok(NetworkResult::value(SendDataMethod {
|
Ok(NetworkResult::value(unique_flow))
|
||||||
contact_method: NodeContactMethod::Existing,
|
|
||||||
opt_relayed_contact_method: None,
|
|
||||||
unique_flow,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Send data using NodeContactMethod::Unreachable
|
|
||||||
#[instrument(level = "trace", target = "net", skip_all, err)]
|
|
||||||
async fn send_data_ncm_unreachable(
|
|
||||||
&self,
|
|
||||||
target_node_ref: FilteredNodeRef,
|
|
||||||
data: Vec<u8>,
|
|
||||||
) -> EyreResult<NetworkResult<SendDataMethod>> {
|
|
||||||
// Try to send data to the last flow we've seen this peer on
|
|
||||||
let Some(flow) = target_node_ref.last_flow() else {
|
|
||||||
return Ok(NetworkResult::no_connection_other(format!(
|
|
||||||
"Node is not reachable and has no existing connection: {}",
|
|
||||||
target_node_ref
|
|
||||||
)));
|
|
||||||
};
|
|
||||||
|
|
||||||
let unique_flow = match self.net().send_data_to_existing_flow(flow, data).await? {
|
|
||||||
SendDataToExistingFlowResult::Sent(unique_flow) => unique_flow,
|
|
||||||
SendDataToExistingFlowResult::NotSent(_) => {
|
|
||||||
return Ok(NetworkResult::no_connection_other(format!(
|
|
||||||
"failed to send to unreachable node over existing connection: {:?}",
|
|
||||||
flow
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Update timestamp for this last connection since we just sent to it
|
|
||||||
self.set_last_flow(target_node_ref.unfiltered(), flow, Timestamp::now());
|
|
||||||
|
|
||||||
Ok(NetworkResult::value(SendDataMethod {
|
|
||||||
contact_method: NodeContactMethod::Existing,
|
|
||||||
opt_relayed_contact_method: None,
|
|
||||||
unique_flow,
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send data using NodeContactMethod::SignalReverse
|
/// Send data using NodeContactMethod::SignalReverse
|
||||||
@ -233,7 +275,7 @@ impl NetworkManager {
|
|||||||
relay_nr: FilteredNodeRef,
|
relay_nr: FilteredNodeRef,
|
||||||
target_node_ref: FilteredNodeRef,
|
target_node_ref: FilteredNodeRef,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
) -> EyreResult<NetworkResult<SendDataMethod>> {
|
) -> EyreResult<NetworkResult<UniqueFlow>> {
|
||||||
// Make a noderef that meets the sequencing requirements
|
// Make a noderef that meets the sequencing requirements
|
||||||
// But is not protocol-specific, or address-family-specific
|
// But is not protocol-specific, or address-family-specific
|
||||||
// as a signalled node gets to choose its own dial info for the reverse connection.
|
// as a signalled node gets to choose its own dial info for the reverse connection.
|
||||||
@ -252,16 +294,13 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// First try to send data to the last flow we've seen this peer on
|
// First try to send data to the last flow we've seen this peer on
|
||||||
let data = if let Some(flow) = seq_target_node_ref.last_flow() {
|
let data = if let Some(flow) = seq_target_node_ref.last_flow() {
|
||||||
match self.net().send_data_to_existing_flow(flow, data).await? {
|
let net = self.net();
|
||||||
|
match pin_future!(net.send_data_to_existing_flow(flow, data)).await? {
|
||||||
SendDataToExistingFlowResult::Sent(unique_flow) => {
|
SendDataToExistingFlowResult::Sent(unique_flow) => {
|
||||||
// Update timestamp for this last connection since we just sent to it
|
// Update timestamp for this last connection since we just sent to it
|
||||||
self.set_last_flow(target_node_ref.unfiltered(), flow, Timestamp::now());
|
self.set_last_flow(target_node_ref.unfiltered(), flow, Timestamp::now());
|
||||||
|
|
||||||
return Ok(NetworkResult::value(SendDataMethod {
|
return Ok(NetworkResult::value(unique_flow));
|
||||||
contact_method: NodeContactMethod::Existing,
|
|
||||||
opt_relayed_contact_method: None,
|
|
||||||
unique_flow,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
SendDataToExistingFlowResult::NotSent(data) => {
|
SendDataToExistingFlowResult::NotSent(data) => {
|
||||||
// Couldn't send data to existing connection
|
// Couldn't send data to existing connection
|
||||||
@ -281,14 +320,10 @@ impl NetworkManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let unique_flow = network_result_try!(
|
let unique_flow = network_result_try!(
|
||||||
self.do_reverse_connect(relay_nr.clone(), target_node_ref.clone(), data)
|
pin_future!(self.do_reverse_connect(relay_nr.clone(), target_node_ref.clone(), data))
|
||||||
.await?
|
.await?
|
||||||
);
|
);
|
||||||
Ok(NetworkResult::value(SendDataMethod {
|
Ok(NetworkResult::value(unique_flow))
|
||||||
contact_method: NodeContactMethod::SignalReverse(relay_nr, target_node_ref),
|
|
||||||
opt_relayed_contact_method: None,
|
|
||||||
unique_flow,
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send data using NodeContactMethod::SignalHolePunch
|
/// Send data using NodeContactMethod::SignalHolePunch
|
||||||
@ -298,19 +333,16 @@ impl NetworkManager {
|
|||||||
relay_nr: FilteredNodeRef,
|
relay_nr: FilteredNodeRef,
|
||||||
target_node_ref: FilteredNodeRef,
|
target_node_ref: FilteredNodeRef,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
) -> EyreResult<NetworkResult<SendDataMethod>> {
|
) -> EyreResult<NetworkResult<UniqueFlow>> {
|
||||||
// First try to send data to the last flow we've seen this peer on
|
// First try to send data to the last flow we've seen this peer on
|
||||||
let data = if let Some(flow) = target_node_ref.last_flow() {
|
let data = if let Some(flow) = target_node_ref.last_flow() {
|
||||||
match self.net().send_data_to_existing_flow(flow, data).await? {
|
let net = self.net();
|
||||||
|
match pin_future!(net.send_data_to_existing_flow(flow, data)).await? {
|
||||||
SendDataToExistingFlowResult::Sent(unique_flow) => {
|
SendDataToExistingFlowResult::Sent(unique_flow) => {
|
||||||
// Update timestamp for this last connection since we just sent to it
|
// Update timestamp for this last connection since we just sent to it
|
||||||
self.set_last_flow(target_node_ref.unfiltered(), flow, Timestamp::now());
|
self.set_last_flow(target_node_ref.unfiltered(), flow, Timestamp::now());
|
||||||
|
|
||||||
return Ok(NetworkResult::value(SendDataMethod {
|
return Ok(NetworkResult::value(unique_flow));
|
||||||
contact_method: NodeContactMethod::Existing,
|
|
||||||
opt_relayed_contact_method: None,
|
|
||||||
unique_flow,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
SendDataToExistingFlowResult::NotSent(data) => {
|
SendDataToExistingFlowResult::NotSent(data) => {
|
||||||
// Couldn't send data to existing connection
|
// Couldn't send data to existing connection
|
||||||
@ -330,14 +362,11 @@ impl NetworkManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let unique_flow = network_result_try!(
|
let unique_flow = network_result_try!(
|
||||||
self.do_hole_punch(relay_nr.clone(), target_node_ref.clone(), data)
|
pin_future!(self.do_hole_punch(relay_nr.clone(), target_node_ref.clone(), data))
|
||||||
.await?
|
.await?
|
||||||
);
|
);
|
||||||
Ok(NetworkResult::value(SendDataMethod {
|
|
||||||
contact_method: NodeContactMethod::SignalHolePunch(relay_nr, target_node_ref),
|
Ok(NetworkResult::value(unique_flow))
|
||||||
opt_relayed_contact_method: None,
|
|
||||||
unique_flow,
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send data using NodeContactMethod::Direct
|
/// Send data using NodeContactMethod::Direct
|
||||||
@ -347,7 +376,7 @@ impl NetworkManager {
|
|||||||
node_ref: FilteredNodeRef,
|
node_ref: FilteredNodeRef,
|
||||||
dial_info: DialInfo,
|
dial_info: DialInfo,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
) -> EyreResult<NetworkResult<SendDataMethod>> {
|
) -> EyreResult<NetworkResult<UniqueFlow>> {
|
||||||
// Since we have the best dial info already, we can find a connection to use by protocol type
|
// Since we have the best dial info already, we can find a connection to use by protocol type
|
||||||
let node_ref = node_ref.filtered_clone(NodeRefFilter::from(dial_info.make_filter()));
|
let node_ref = node_ref.filtered_clone(NodeRefFilter::from(dial_info.make_filter()));
|
||||||
|
|
||||||
@ -359,16 +388,13 @@ impl NetworkManager {
|
|||||||
flow, node_ref
|
flow, node_ref
|
||||||
);
|
);
|
||||||
|
|
||||||
match self.net().send_data_to_existing_flow(flow, data).await? {
|
let net = self.net();
|
||||||
|
match pin_future!(net.send_data_to_existing_flow(flow, data)).await? {
|
||||||
SendDataToExistingFlowResult::Sent(unique_flow) => {
|
SendDataToExistingFlowResult::Sent(unique_flow) => {
|
||||||
// Update timestamp for this last connection since we just sent to it
|
// Update timestamp for this last connection since we just sent to it
|
||||||
self.set_last_flow(node_ref.unfiltered(), flow, Timestamp::now());
|
self.set_last_flow(node_ref.unfiltered(), flow, Timestamp::now());
|
||||||
|
|
||||||
return Ok(NetworkResult::value(SendDataMethod {
|
return Ok(NetworkResult::value(unique_flow));
|
||||||
contact_method: NodeContactMethod::Existing,
|
|
||||||
opt_relayed_contact_method: None,
|
|
||||||
unique_flow,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
SendDataToExistingFlowResult::NotSent(d) => {
|
SendDataToExistingFlowResult::NotSent(d) => {
|
||||||
// Connection couldn't send, kill it
|
// Connection couldn't send, kill it
|
||||||
@ -381,27 +407,22 @@ impl NetworkManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// New direct connection was necessary for this dial info
|
// New direct connection was necessary for this dial info
|
||||||
|
let net = self.net();
|
||||||
let unique_flow = network_result_try!(
|
let unique_flow = network_result_try!(
|
||||||
self.net()
|
pin_future!(net.send_data_to_dial_info(dial_info.clone(), data)).await?
|
||||||
.send_data_to_dial_info(dial_info.clone(), data)
|
|
||||||
.await?
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// If we connected to this node directly, save off the last connection so we can use it again
|
// If we connected to this node directly, save off the last connection so we can use it again
|
||||||
self.set_last_flow(node_ref.unfiltered(), unique_flow.flow, Timestamp::now());
|
self.set_last_flow(node_ref.unfiltered(), unique_flow.flow, Timestamp::now());
|
||||||
|
|
||||||
Ok(NetworkResult::value(SendDataMethod {
|
Ok(NetworkResult::value(unique_flow))
|
||||||
contact_method: NodeContactMethod::Direct(dial_info),
|
|
||||||
opt_relayed_contact_method: None,
|
|
||||||
unique_flow,
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", target = "net", skip_all, err)]
|
#[instrument(level = "trace", target = "net", skip(self), err)]
|
||||||
pub fn get_node_contact_method(
|
pub fn get_node_contact_method(
|
||||||
&self,
|
&self,
|
||||||
target_node_ref: FilteredNodeRef,
|
target_node_ref: FilteredNodeRef,
|
||||||
) -> EyreResult<NodeContactMethod> {
|
) -> EyreResult<Option<NodeContactMethod>> {
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
|
|
||||||
// If a node is punished, then don't try to contact it
|
// If a node is punished, then don't try to contact it
|
||||||
@ -410,7 +431,7 @@ impl NetworkManager {
|
|||||||
.iter()
|
.iter()
|
||||||
.any(|nid| self.address_filter().is_node_id_punished(*nid))
|
.any(|nid| self.address_filter().is_node_id_punished(*nid))
|
||||||
{
|
{
|
||||||
return Ok(NodeContactMethod::Unreachable);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Figure out the best routing domain to get the contact method over
|
// Figure out the best routing domain to get the contact method over
|
||||||
@ -418,7 +439,7 @@ impl NetworkManager {
|
|||||||
Some(rd) => rd,
|
Some(rd) => rd,
|
||||||
None => {
|
None => {
|
||||||
veilid_log!(self trace "no routing domain for node {:?}", target_node_ref);
|
veilid_log!(self trace "no routing domain for node {:?}", target_node_ref);
|
||||||
return Ok(NodeContactMethod::Unreachable);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -430,7 +451,7 @@ impl NetworkManager {
|
|||||||
// Peer B is the target node, get the whole peer info now
|
// Peer B is the target node, get the whole peer info now
|
||||||
let Some(peer_b) = target_node_ref.get_peer_info(routing_domain) else {
|
let Some(peer_b) = target_node_ref.get_peer_info(routing_domain) else {
|
||||||
veilid_log!(self trace "no node info for node {:?}", target_node_ref);
|
veilid_log!(self trace "no node info for node {:?}", target_node_ref);
|
||||||
return Ok(NodeContactMethod::Unreachable);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Calculate the dial info failures map
|
// Calculate the dial info failures map
|
||||||
@ -458,42 +479,47 @@ impl NetworkManager {
|
|||||||
target_node_ref_sequencing: target_node_ref.sequencing(),
|
target_node_ref_sequencing: target_node_ref.sequencing(),
|
||||||
dial_info_failures_map,
|
dial_info_failures_map,
|
||||||
};
|
};
|
||||||
if let Some(ncm) = self.inner.lock().node_contact_method_cache.get(&ncm_key) {
|
if let Some(ncm_kind) = self.inner.lock().node_contact_method_cache.get(&ncm_key) {
|
||||||
return Ok(ncm.clone());
|
return Ok(Some(NodeContactMethod { ncm_key, ncm_kind }));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the node contact method
|
// Calculate the node contact method
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
let ncm = Self::get_node_contact_method_uncached(
|
let Some(ncm_kind) = Self::get_node_contact_method_kind(
|
||||||
&routing_table,
|
&routing_table,
|
||||||
routing_domain,
|
routing_domain,
|
||||||
target_node_ref,
|
target_node_ref,
|
||||||
peer_a,
|
peer_a,
|
||||||
peer_b,
|
peer_b,
|
||||||
&ncm_key,
|
&ncm_key,
|
||||||
)?;
|
)?
|
||||||
|
else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Some(NodeContactMethod { ncm_key, ncm_kind }))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cache_node_contact_method(&self, ncm: NodeContactMethod) {
|
||||||
// Cache this
|
// Cache this
|
||||||
self.inner
|
self.inner
|
||||||
.lock()
|
.lock()
|
||||||
.node_contact_method_cache
|
.node_contact_method_cache
|
||||||
.insert(ncm_key, ncm.clone());
|
.insert(ncm.ncm_key, ncm.ncm_kind);
|
||||||
|
|
||||||
Ok(ncm)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Figure out how to reach a node from our own node over the best routing domain and reference the nodes we want to access
|
/// Figure out how to reach a node from our own node over the best routing domain and reference the nodes we want to access
|
||||||
/// Uses NodeRefs to ensure nodes are referenced, this is not a part of 'RoutingTable' because RoutingTable is not
|
/// Uses NodeRefs to ensure nodes are referenced, this is not a part of 'RoutingTable' because RoutingTable is not
|
||||||
/// allowed to use NodeRefs due to recursive locking
|
/// allowed to use NodeRefs due to recursive locking
|
||||||
#[instrument(level = "trace", target = "net", skip_all, err)]
|
#[instrument(level = "trace", target = "net", skip_all, err)]
|
||||||
fn get_node_contact_method_uncached(
|
fn get_node_contact_method_kind(
|
||||||
routing_table: &RoutingTable,
|
routing_table: &RoutingTable,
|
||||||
routing_domain: RoutingDomain,
|
routing_domain: RoutingDomain,
|
||||||
target_node_ref: FilteredNodeRef,
|
target_node_ref: FilteredNodeRef,
|
||||||
peer_a: Arc<PeerInfo>,
|
peer_a: Arc<PeerInfo>,
|
||||||
peer_b: Arc<PeerInfo>,
|
peer_b: Arc<PeerInfo>,
|
||||||
ncm_key: &NodeContactMethodCacheKey,
|
ncm_key: &NodeContactMethodCacheKey,
|
||||||
) -> EyreResult<NodeContactMethod> {
|
) -> EyreResult<Option<NodeContactMethodKind>> {
|
||||||
// Dial info filter comes from the target node ref but must be filtered by this node's outbound capabilities
|
// Dial info filter comes from the target node ref but must be filtered by this node's outbound capabilities
|
||||||
let dial_info_filter = target_node_ref.dial_info_filter().filtered(
|
let dial_info_filter = target_node_ref.dial_info_filter().filtered(
|
||||||
DialInfoFilter::all()
|
DialInfoFilter::all()
|
||||||
@ -542,9 +568,9 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// Translate the raw contact method to a referenced contact method
|
// Translate the raw contact method to a referenced contact method
|
||||||
let ncm = match cm {
|
let ncm = match cm {
|
||||||
ContactMethod::Unreachable => NodeContactMethod::Unreachable,
|
ContactMethod::Unreachable => None,
|
||||||
ContactMethod::Existing => NodeContactMethod::Existing,
|
ContactMethod::Existing => Some(NodeContactMethodKind::Existing),
|
||||||
ContactMethod::Direct(di) => NodeContactMethod::Direct(di),
|
ContactMethod::Direct(di) => Some(NodeContactMethodKind::Direct(di)),
|
||||||
ContactMethod::SignalReverse(relay_key, target_key) => {
|
ContactMethod::SignalReverse(relay_key, target_key) => {
|
||||||
let mut relay_nr = routing_table
|
let mut relay_nr = routing_table
|
||||||
.lookup_and_filter_noderef(relay_key, routing_domain.into(), dial_info_filter)?
|
.lookup_and_filter_noderef(relay_key, routing_domain.into(), dial_info_filter)?
|
||||||
@ -595,7 +621,10 @@ impl NetworkManager {
|
|||||||
if tighten {
|
if tighten {
|
||||||
target_node_ref.set_sequencing(Sequencing::EnsureOrdered);
|
target_node_ref.set_sequencing(Sequencing::EnsureOrdered);
|
||||||
}
|
}
|
||||||
NodeContactMethod::SignalReverse(relay_nr, target_node_ref)
|
Some(NodeContactMethodKind::SignalReverse(
|
||||||
|
relay_nr,
|
||||||
|
target_node_ref,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
ContactMethod::SignalHolePunch(relay_key, target_key) => {
|
ContactMethod::SignalHolePunch(relay_key, target_key) => {
|
||||||
let mut relay_nr = routing_table
|
let mut relay_nr = routing_table
|
||||||
@ -622,7 +651,10 @@ impl NetworkManager {
|
|||||||
.with_protocol_type(ProtocolType::UDP),
|
.with_protocol_type(ProtocolType::UDP),
|
||||||
);
|
);
|
||||||
|
|
||||||
NodeContactMethod::SignalHolePunch(relay_nr, udp_target_node_ref)
|
Some(NodeContactMethodKind::SignalHolePunch(
|
||||||
|
relay_nr,
|
||||||
|
udp_target_node_ref,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
ContactMethod::InboundRelay(relay_key) => {
|
ContactMethod::InboundRelay(relay_key) => {
|
||||||
let mut relay_nr = routing_table
|
let mut relay_nr = routing_table
|
||||||
@ -635,7 +667,7 @@ impl NetworkManager {
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
relay_nr.set_sequencing(sequencing);
|
relay_nr.set_sequencing(sequencing);
|
||||||
NodeContactMethod::InboundRelay(relay_nr)
|
Some(NodeContactMethodKind::InboundRelay(relay_nr))
|
||||||
}
|
}
|
||||||
ContactMethod::OutboundRelay(relay_key) => {
|
ContactMethod::OutboundRelay(relay_key) => {
|
||||||
let mut relay_nr = routing_table
|
let mut relay_nr = routing_table
|
||||||
@ -648,7 +680,7 @@ impl NetworkManager {
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
relay_nr.set_sequencing(sequencing);
|
relay_nr.set_sequencing(sequencing);
|
||||||
NodeContactMethod::OutboundRelay(relay_nr)
|
Some(NodeContactMethodKind::OutboundRelay(relay_nr))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -695,14 +727,13 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// Issue the signal
|
// Issue the signal
|
||||||
let rpc = self.rpc_processor();
|
let rpc = self.rpc_processor();
|
||||||
network_result_try!(rpc
|
network_result_try!(pin_future!(rpc.rpc_call_signal(
|
||||||
.rpc_call_signal(
|
|
||||||
Destination::relay(relay_nr.clone(), target_nr.unfiltered()),
|
Destination::relay(relay_nr.clone(), target_nr.unfiltered()),
|
||||||
SignalInfo::ReverseConnect {
|
SignalInfo::ReverseConnect {
|
||||||
receipt,
|
receipt,
|
||||||
peer_info: published_peer_info
|
peer_info: published_peer_info
|
||||||
},
|
},
|
||||||
)
|
))
|
||||||
.await
|
.await
|
||||||
.wrap_err("failed to send signal")?);
|
.wrap_err("failed to send signal")?);
|
||||||
|
|
||||||
@ -747,7 +778,8 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// And now use the existing connection to send over
|
// And now use the existing connection to send over
|
||||||
if let Some(flow) = inbound_nr.last_flow() {
|
if let Some(flow) = inbound_nr.last_flow() {
|
||||||
match self.net().send_data_to_existing_flow(flow, data).await? {
|
let net = self.net();
|
||||||
|
match pin_future!(net.send_data_to_existing_flow(flow, data)).await? {
|
||||||
SendDataToExistingFlowResult::Sent(unique_flow) => {
|
SendDataToExistingFlowResult::Sent(unique_flow) => {
|
||||||
Ok(NetworkResult::value(unique_flow))
|
Ok(NetworkResult::value(unique_flow))
|
||||||
}
|
}
|
||||||
@ -817,9 +849,9 @@ impl NetworkManager {
|
|||||||
// Both sides will do this and then the receipt will get sent over the punched hole
|
// Both sides will do this and then the receipt will get sent over the punched hole
|
||||||
// Don't bother storing the returned flow as the 'last flow' because the other side of the hole
|
// Don't bother storing the returned flow as the 'last flow' because the other side of the hole
|
||||||
// punch should come through and create a real 'last connection' for us if this succeeds
|
// punch should come through and create a real 'last connection' for us if this succeeds
|
||||||
|
let net = self.net();
|
||||||
network_result_try!(
|
network_result_try!(
|
||||||
self.net()
|
pin_future!(net.send_data_to_dial_info(hole_punch_did.dial_info.clone(), Vec::new()))
|
||||||
.send_data_to_dial_info(hole_punch_did.dial_info.clone(), Vec::new())
|
|
||||||
.await?
|
.await?
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -828,22 +860,20 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// Issue the signal
|
// Issue the signal
|
||||||
let rpc = self.rpc_processor();
|
let rpc = self.rpc_processor();
|
||||||
network_result_try!(rpc
|
network_result_try!(pin_future!(rpc.rpc_call_signal(
|
||||||
.rpc_call_signal(
|
|
||||||
Destination::relay(relay_nr, target_nr.unfiltered()),
|
Destination::relay(relay_nr, target_nr.unfiltered()),
|
||||||
SignalInfo::HolePunch {
|
SignalInfo::HolePunch {
|
||||||
receipt,
|
receipt,
|
||||||
peer_info: published_peer_info
|
peer_info: published_peer_info
|
||||||
},
|
},
|
||||||
)
|
))
|
||||||
.await
|
.await
|
||||||
.wrap_err("failed to send signal")?);
|
.wrap_err("failed to send signal")?);
|
||||||
|
|
||||||
// Another hole punch after the signal for UDP redundancy
|
// Another hole punch after the signal for UDP redundancy
|
||||||
|
let net = self.net();
|
||||||
network_result_try!(
|
network_result_try!(
|
||||||
self.net()
|
pin_future!(net.send_data_to_dial_info(hole_punch_did.dial_info, Vec::new())).await?
|
||||||
.send_data_to_dial_info(hole_punch_did.dial_info, Vec::new())
|
|
||||||
.await?
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Wait for the return receipt
|
// Wait for the return receipt
|
||||||
|
@ -69,12 +69,28 @@ impl NetworkManager {
|
|||||||
.add_down(bytes);
|
.add_down(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[expect(dead_code)]
|
|
||||||
pub fn get_stats(&self) -> NetworkManagerStats {
|
pub fn get_stats(&self) -> NetworkManagerStats {
|
||||||
let inner = self.inner.lock();
|
let inner = self.inner.lock();
|
||||||
inner.stats.clone()
|
inner.stats.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn debug(&self) -> String {
|
||||||
|
let stats = self.get_stats();
|
||||||
|
|
||||||
|
let mut out = String::new();
|
||||||
|
out += "Network Manager\n";
|
||||||
|
out += "---------------\n";
|
||||||
|
let mut out = format!(
|
||||||
|
"Transfer stats:\n{}\n",
|
||||||
|
indent_all_string(&stats.self_stats.transfer_stats)
|
||||||
|
);
|
||||||
|
out += "Node Contact Method Cache\n";
|
||||||
|
out += "-------------------------\n";
|
||||||
|
out += &self.inner.lock().node_contact_method_cache.debug();
|
||||||
|
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_veilid_state(&self) -> Box<VeilidStateNetwork> {
|
pub fn get_veilid_state(&self) -> Box<VeilidStateNetwork> {
|
||||||
if !self.network_is_started() {
|
if !self.network_is_started() {
|
||||||
return Box::new(VeilidStateNetwork {
|
return Box::new(VeilidStateNetwork {
|
||||||
|
@ -54,7 +54,7 @@ pub async fn test_signed_node_info() {
|
|||||||
sni.timestamp(),
|
sni.timestamp(),
|
||||||
sni.signatures().to_vec(),
|
sni.signatures().to_vec(),
|
||||||
);
|
);
|
||||||
sdni.validate(&tks1, &crypto).unwrap_err();
|
let _ = sdni.validate(&tks1, &crypto).unwrap_err();
|
||||||
|
|
||||||
// Test unsupported cryptosystem validation
|
// Test unsupported cryptosystem validation
|
||||||
let fake_crypto_kind: CryptoKind = FourCC::from([0, 1, 2, 3]);
|
let fake_crypto_kind: CryptoKind = FourCC::from([0, 1, 2, 3]);
|
||||||
@ -119,7 +119,7 @@ pub async fn test_signed_node_info() {
|
|||||||
sni2.timestamp(),
|
sni2.timestamp(),
|
||||||
sni2.signatures().to_vec(),
|
sni2.signatures().to_vec(),
|
||||||
);
|
);
|
||||||
srni.validate(&tks3, &crypto).unwrap_err();
|
assert_err!(srni.validate(&tks3, &crypto));
|
||||||
|
|
||||||
// Test unsupported cryptosystem validation
|
// Test unsupported cryptosystem validation
|
||||||
let fake_crypto_kind: CryptoKind = FourCC::from([0, 1, 2, 3]);
|
let fake_crypto_kind: CryptoKind = FourCC::from([0, 1, 2, 3]);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
// Keep member order appropriate for sorting < preference
|
// Keep member order appropriate for sorting < preference
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
|
#[derive(Debug, Ord, PartialOrd, Hash, Serialize, Deserialize, EnumSetType)]
|
||||||
pub(crate) enum DialInfoClass {
|
pub(crate) enum DialInfoClass {
|
||||||
Direct = 0, // D = Directly reachable with public IP and no firewall, with statically configured port
|
Direct = 0, // D = Directly reachable with public IP and no firewall, with statically configured port
|
||||||
Mapped = 1, // M = Directly reachable with via portmap behind any NAT or firewalled with dynamically negotiated port
|
Mapped = 1, // M = Directly reachable with via portmap behind any NAT or firewalled with dynamically negotiated port
|
||||||
@ -33,3 +33,6 @@ impl DialInfoClass {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), expect(dead_code))]
|
||||||
|
pub(crate) type DialInfoClassSet = EnumSet<DialInfoClass>;
|
||||||
|
@ -516,5 +516,6 @@ impl Network {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
pub async fn cancel_tasks(&self) {}
|
pub async fn cancel_tasks(&self) {}
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,7 @@ const CACHE_VALIDITY_KEY: &[u8] = b"cache_validity_key";
|
|||||||
type LowLevelProtocolPorts = BTreeSet<(LowLevelProtocolType, AddressType, u16)>;
|
type LowLevelProtocolPorts = BTreeSet<(LowLevelProtocolType, AddressType, u16)>;
|
||||||
type ProtocolToPortMapping = BTreeMap<(ProtocolType, AddressType), (LowLevelProtocolType, u16)>;
|
type ProtocolToPortMapping = BTreeMap<(ProtocolType, AddressType), (LowLevelProtocolType, u16)>;
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
#[must_use]
|
||||||
pub struct LowLevelPortInfo {
|
pub struct LowLevelPortInfo {
|
||||||
pub low_level_protocol_ports: LowLevelProtocolPorts,
|
pub low_level_protocol_ports: LowLevelProtocolPorts,
|
||||||
pub protocol_to_port: ProtocolToPortMapping,
|
pub protocol_to_port: ProtocolToPortMapping,
|
||||||
@ -71,6 +72,7 @@ type SerializedBuckets = Vec<Vec<u8>>;
|
|||||||
type SerializedBucketMap = BTreeMap<CryptoKind, SerializedBuckets>;
|
type SerializedBucketMap = BTreeMap<CryptoKind, SerializedBuckets>;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||||
|
#[must_use]
|
||||||
pub struct RoutingTableHealth {
|
pub struct RoutingTableHealth {
|
||||||
/// Number of reliable (long-term responsive) entries in the routing table
|
/// Number of reliable (long-term responsive) entries in the routing table
|
||||||
pub reliable_entry_count: usize,
|
pub reliable_entry_count: usize,
|
||||||
@ -89,10 +91,12 @@ pub struct RoutingTableHealth {
|
|||||||
pub type BucketIndex = (CryptoKind, usize);
|
pub type BucketIndex = (CryptoKind, usize);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
#[must_use]
|
||||||
pub struct RecentPeersEntry {
|
pub struct RecentPeersEntry {
|
||||||
pub last_connection: Flow,
|
pub last_connection: Flow,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub(crate) struct RoutingTable {
|
pub(crate) struct RoutingTable {
|
||||||
registry: VeilidComponentRegistry,
|
registry: VeilidComponentRegistry,
|
||||||
inner: RwLock<RoutingTableInner>,
|
inner: RwLock<RoutingTableInner>,
|
||||||
@ -231,10 +235,12 @@ impl RoutingTable {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
async fn post_init_async(&self) -> EyreResult<()> {
|
async fn post_init_async(&self) -> EyreResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
pub(crate) async fn startup(&self) -> EyreResult<()> {
|
pub(crate) async fn startup(&self) -> EyreResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -245,6 +251,7 @@ impl RoutingTable {
|
|||||||
self.cancel_tasks().await;
|
self.cancel_tasks().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
async fn pre_terminate_async(&self) {}
|
async fn pre_terminate_async(&self) {}
|
||||||
|
|
||||||
/// Called to shut down the routing table
|
/// Called to shut down the routing table
|
||||||
@ -1091,7 +1098,7 @@ impl RoutingTable {
|
|||||||
capabilities: Vec<Capability>,
|
capabilities: Vec<Capability>,
|
||||||
) {
|
) {
|
||||||
// Ask node for nodes closest to our own node
|
// Ask node for nodes closest to our own node
|
||||||
let closest_nodes = network_result_value_or_log!(self match self.find_nodes_close_to_self(crypto_kind, node_ref.clone(), capabilities.clone()).await {
|
let closest_nodes = network_result_value_or_log!(self match pin_future!(self.find_nodes_close_to_self(crypto_kind, node_ref.clone(), capabilities.clone())).await {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
veilid_log!(self error
|
veilid_log!(self error
|
||||||
"find_self failed for {:?}: {:?}",
|
"find_self failed for {:?}: {:?}",
|
||||||
@ -1107,7 +1114,7 @@ impl RoutingTable {
|
|||||||
// Ask each node near us to find us as well
|
// Ask each node near us to find us as well
|
||||||
if wide {
|
if wide {
|
||||||
for closest_nr in closest_nodes {
|
for closest_nr in closest_nodes {
|
||||||
network_result_value_or_log!(self match self.find_nodes_close_to_self(crypto_kind, closest_nr.clone(), capabilities.clone()).await {
|
network_result_value_or_log!(self match pin_future!(self.find_nodes_close_to_self(crypto_kind, closest_nr.clone(), capabilities.clone())).await {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
veilid_log!(self error
|
veilid_log!(self error
|
||||||
"find_self failed for {:?}: {:?}",
|
"find_self failed for {:?}: {:?}",
|
||||||
|
@ -38,6 +38,7 @@ struct RouteSpecStoreInner {
|
|||||||
|
|
||||||
/// The routing table's storage for private/safety routes
|
/// The routing table's storage for private/safety routes
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[must_use]
|
||||||
pub(crate) struct RouteSpecStore {
|
pub(crate) struct RouteSpecStore {
|
||||||
registry: VeilidComponentRegistry,
|
registry: VeilidComponentRegistry,
|
||||||
inner: Mutex<RouteSpecStoreInner>,
|
inner: Mutex<RouteSpecStoreInner>,
|
||||||
|
@ -157,12 +157,7 @@ impl RouteSpecStoreCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// add remote private route to caches
|
/// add remote private route to caches
|
||||||
/// returns a remote private route set id
|
fn add_remote_private_route(&mut self, id: RouteId, rprinfo: RemotePrivateRouteInfo) {
|
||||||
fn add_remote_private_route(
|
|
||||||
&mut self,
|
|
||||||
id: RouteId,
|
|
||||||
rprinfo: RemotePrivateRouteInfo,
|
|
||||||
) -> RouteId {
|
|
||||||
// also store in id by key table
|
// also store in id by key table
|
||||||
for private_route in rprinfo.get_private_routes() {
|
for private_route in rprinfo.get_private_routes() {
|
||||||
self.remote_private_routes_by_key
|
self.remote_private_routes_by_key
|
||||||
@ -182,15 +177,14 @@ impl RouteSpecStoreCache {
|
|||||||
// If anything LRUs out, remove from the by-key table
|
// If anything LRUs out, remove from the by-key table
|
||||||
// Follow the same logic as 'remove_remote_private_route' here
|
// Follow the same logic as 'remove_remote_private_route' here
|
||||||
for dead_private_route in dead_rpri.get_private_routes() {
|
for dead_private_route in dead_rpri.get_private_routes() {
|
||||||
self.remote_private_routes_by_key
|
let _ = self
|
||||||
|
.remote_private_routes_by_key
|
||||||
.remove(&dead_private_route.public_key.value)
|
.remove(&dead_private_route.public_key.value)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.invalidate_compiled_route_cache(&dead_private_route.public_key.value);
|
self.invalidate_compiled_route_cache(&dead_private_route.public_key.value);
|
||||||
}
|
}
|
||||||
self.dead_remote_routes.push(dead_id);
|
self.dead_remote_routes.push(dead_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// iterate all of the remote private routes we have in the cache
|
/// iterate all of the remote private routes we have in the cache
|
||||||
@ -311,7 +305,8 @@ impl RouteSpecStoreCache {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
for private_route in rprinfo.get_private_routes() {
|
for private_route in rprinfo.get_private_routes() {
|
||||||
self.remote_private_routes_by_key
|
let _ = self
|
||||||
|
.remote_private_routes_by_key
|
||||||
.remove(&private_route.public_key.value)
|
.remove(&private_route.public_key.value)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.invalidate_compiled_route_cache(&private_route.public_key.value);
|
self.invalidate_compiled_route_cache(&private_route.public_key.value);
|
||||||
|
@ -75,7 +75,7 @@ impl RouteSpecStoreContent {
|
|||||||
pub fn remove_detail(&mut self, id: &RouteId) -> Option<RouteSetSpecDetail> {
|
pub fn remove_detail(&mut self, id: &RouteId) -> Option<RouteSetSpecDetail> {
|
||||||
let detail = self.details.remove(id)?;
|
let detail = self.details.remove(id)?;
|
||||||
for (pk, _) in detail.iter_route_set() {
|
for (pk, _) in detail.iter_route_set() {
|
||||||
self.id_by_key.remove(pk).unwrap();
|
let _ = self.id_by_key.remove(pk).unwrap();
|
||||||
}
|
}
|
||||||
Some(detail)
|
Some(detail)
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ pub type EntryCounts = BTreeMap<(RoutingDomain, CryptoKind), usize>;
|
|||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/// RoutingTable rwlock-internal data
|
/// RoutingTable rwlock-internal data
|
||||||
|
#[must_use]
|
||||||
pub struct RoutingTableInner {
|
pub struct RoutingTableInner {
|
||||||
/// Convenience accessor for the global component registry
|
/// Convenience accessor for the global component registry
|
||||||
pub(super) registry: VeilidComponentRegistry,
|
pub(super) registry: VeilidComponentRegistry,
|
||||||
|
@ -17,8 +17,8 @@ pub trait RoutingDomainEditorCommonTrait {
|
|||||||
capabilities: Vec<Capability>,
|
capabilities: Vec<Capability>,
|
||||||
confirmed: bool,
|
confirmed: bool,
|
||||||
) -> &mut Self;
|
) -> &mut Self;
|
||||||
fn commit(&mut self, pause_tasks: bool) -> SendPinBoxFutureLifetime<'_, bool>;
|
fn commit(&mut self, pause_tasks: bool) -> PinBoxFuture<'_, bool>;
|
||||||
fn shutdown(&mut self) -> SendPinBoxFutureLifetime<'_, ()>;
|
fn shutdown(&mut self) -> PinBoxFuture<'_, ()>;
|
||||||
fn publish(&mut self);
|
fn publish(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ impl<'a> RoutingDomainEditorCommonTrait for RoutingDomainEditorLocalNetwork<'a>
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
fn commit(&mut self, pause_tasks: bool) -> SendPinBoxFutureLifetime<'_, bool> {
|
fn commit(&mut self, pause_tasks: bool) -> PinBoxFuture<'_, bool> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
// No locking if we have nothing to do
|
// No locking if we have nothing to do
|
||||||
if self.changes.is_empty() {
|
if self.changes.is_empty() {
|
||||||
@ -254,7 +254,7 @@ impl<'a> RoutingDomainEditorCommonTrait for RoutingDomainEditorLocalNetwork<'a>
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
fn shutdown(&mut self) -> SendPinBoxFutureLifetime<'_, ()> {
|
fn shutdown(&mut self) -> PinBoxFuture<'_, ()> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
self.clear_dial_info_details(None, None)
|
self.clear_dial_info_details(None, None)
|
||||||
.set_relay_node(None)
|
.set_relay_node(None)
|
||||||
|
@ -116,7 +116,7 @@ impl<'a> RoutingDomainEditorCommonTrait for RoutingDomainEditorPublicInternet<'a
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
fn commit(&mut self, pause_tasks: bool) -> SendPinBoxFutureLifetime<'_, bool> {
|
fn commit(&mut self, pause_tasks: bool) -> PinBoxFuture<'_, bool> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
// No locking if we have nothing to do
|
// No locking if we have nothing to do
|
||||||
if self.changes.is_empty() {
|
if self.changes.is_empty() {
|
||||||
@ -270,7 +270,7 @@ impl<'a> RoutingDomainEditorCommonTrait for RoutingDomainEditorPublicInternet<'a
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
fn shutdown(&mut self) -> SendPinBoxFutureLifetime<'_, ()> {
|
fn shutdown(&mut self) -> PinBoxFuture<'_, ()> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
self.clear_dial_info_details(None, None)
|
self.clear_dial_info_details(None, None)
|
||||||
.set_relay_node(None)
|
.set_relay_node(None)
|
||||||
|
@ -33,7 +33,7 @@ impl BootstrapRecord {
|
|||||||
|
|
||||||
impl RoutingTable {
|
impl RoutingTable {
|
||||||
/// Process bootstrap version 0
|
/// Process bootstrap version 0
|
||||||
async fn process_bootstrap_records_v0(
|
fn process_bootstrap_records_v0(
|
||||||
&self,
|
&self,
|
||||||
records: Vec<String>,
|
records: Vec<String>,
|
||||||
) -> EyreResult<Option<BootstrapRecord>> {
|
) -> EyreResult<Option<BootstrapRecord>> {
|
||||||
@ -195,7 +195,7 @@ impl RoutingTable {
|
|||||||
};
|
};
|
||||||
let bootstrap_record = match txt_version {
|
let bootstrap_record = match txt_version {
|
||||||
BOOTSTRAP_TXT_VERSION_0 => {
|
BOOTSTRAP_TXT_VERSION_0 => {
|
||||||
match self.process_bootstrap_records_v0(records).await {
|
match self.process_bootstrap_records_v0(records) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
veilid_log!(self error
|
veilid_log!(self error
|
||||||
"couldn't process v0 bootstrap records from {}: {}",
|
"couldn't process v0 bootstrap records from {}: {}",
|
||||||
@ -260,7 +260,7 @@ impl RoutingTable {
|
|||||||
&self,
|
&self,
|
||||||
crypto_kinds: Vec<CryptoKind>,
|
crypto_kinds: Vec<CryptoKind>,
|
||||||
pi: Arc<PeerInfo>,
|
pi: Arc<PeerInfo>,
|
||||||
unord: &FuturesUnordered<SendPinBoxFuture<()>>,
|
unord: &FuturesUnordered<PinBoxFutureStatic<()>>,
|
||||||
) {
|
) {
|
||||||
veilid_log!(self trace
|
veilid_log!(self trace
|
||||||
"--- bootstrapping {} with {:?}",
|
"--- bootstrapping {} with {:?}",
|
||||||
@ -291,7 +291,7 @@ impl RoutingTable {
|
|||||||
let bsdi = match network_manager
|
let bsdi = match network_manager
|
||||||
.get_node_contact_method(nr.default_filtered())
|
.get_node_contact_method(nr.default_filtered())
|
||||||
{
|
{
|
||||||
Ok(NodeContactMethod::Direct(v)) => v,
|
Ok(Some(ncm)) if ncm.is_direct() => ncm.direct_dial_info().unwrap(),
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
veilid_log!(nr debug "invalid contact method for bootstrap, ignoring peer: {:?}", v);
|
veilid_log!(nr debug "invalid contact method for bootstrap, ignoring peer: {:?}", v);
|
||||||
// let _ =
|
// let _ =
|
||||||
@ -342,7 +342,7 @@ impl RoutingTable {
|
|||||||
veilid_log!(self debug " bootstrap crypto kinds: {:?}", &crypto_kinds);
|
veilid_log!(self debug " bootstrap crypto kinds: {:?}", &crypto_kinds);
|
||||||
|
|
||||||
// Run all bootstrap operations concurrently
|
// Run all bootstrap operations concurrently
|
||||||
let mut unord = FuturesUnordered::<SendPinBoxFuture<()>>::new();
|
let mut unord = FuturesUnordered::<PinBoxFutureStatic<()>>::new();
|
||||||
for peer in peers {
|
for peer in peers {
|
||||||
self.bootstrap_with_peer(crypto_kinds.clone(), peer, &unord);
|
self.bootstrap_with_peer(crypto_kinds.clone(), peer, &unord);
|
||||||
}
|
}
|
||||||
@ -367,7 +367,7 @@ impl RoutingTable {
|
|||||||
crypto_kinds
|
crypto_kinds
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self), err)]
|
#[instrument(level = "trace", skip_all, err)]
|
||||||
pub async fn bootstrap_task_routine(
|
pub async fn bootstrap_task_routine(
|
||||||
&self,
|
&self,
|
||||||
stop_token: StopToken,
|
stop_token: StopToken,
|
||||||
@ -403,7 +403,7 @@ impl RoutingTable {
|
|||||||
let mut peer_map = HashMap::<TypedKeyGroup, Arc<PeerInfo>>::new();
|
let mut peer_map = HashMap::<TypedKeyGroup, Arc<PeerInfo>>::new();
|
||||||
for bootstrap_di in bootstrap_dialinfos {
|
for bootstrap_di in bootstrap_dialinfos {
|
||||||
veilid_log!(self debug "direct bootstrap with: {}", bootstrap_di);
|
veilid_log!(self debug "direct bootstrap with: {}", bootstrap_di);
|
||||||
let peers = network_manager.boot_request(bootstrap_di).await?;
|
let peers = pin_future!(network_manager.boot_request(bootstrap_di)).await?;
|
||||||
for peer in peers {
|
for peer in peers {
|
||||||
if !peer_map.contains_key(peer.node_ids()) {
|
if !peer_map.contains_key(peer.node_ids()) {
|
||||||
peer_map.insert(peer.node_ids().clone(), peer);
|
peer_map.insert(peer.node_ids().clone(), peer);
|
||||||
@ -413,9 +413,9 @@ impl RoutingTable {
|
|||||||
peer_map.into_values().collect()
|
peer_map.into_values().collect()
|
||||||
} else {
|
} else {
|
||||||
// If not direct, resolve bootstrap servers and recurse their TXT entries
|
// If not direct, resolve bootstrap servers and recurse their TXT entries
|
||||||
let bsrecs = match self
|
let bsrecs = match pin_future!(self
|
||||||
.resolve_bootstrap(bootstrap)
|
.resolve_bootstrap(bootstrap)
|
||||||
.timeout_at(stop_token.clone())
|
.timeout_at(stop_token.clone()))
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(v) => v?,
|
Ok(v) => v?,
|
||||||
|
@ -14,7 +14,7 @@ const ACTIVE_WATCH_KEEPALIVE_PING_INTERVAL_SECS: u32 = 10;
|
|||||||
/// Ping queue processing depth per validator
|
/// Ping queue processing depth per validator
|
||||||
const MAX_PARALLEL_PINGS: usize = 8;
|
const MAX_PARALLEL_PINGS: usize = 8;
|
||||||
|
|
||||||
type PingValidatorFuture = SendPinBoxFuture<Result<(), RPCError>>;
|
type PingValidatorFuture = PinBoxFutureStatic<Result<(), RPCError>>;
|
||||||
|
|
||||||
impl RoutingTable {
|
impl RoutingTable {
|
||||||
// Task routine for PublicInternet status pings
|
// Task routine for PublicInternet status pings
|
||||||
@ -258,7 +258,7 @@ impl RoutingTable {
|
|||||||
futurequeue.push_back(
|
futurequeue.push_back(
|
||||||
async move {
|
async move {
|
||||||
#[cfg(feature = "verbose-tracing")]
|
#[cfg(feature = "verbose-tracing")]
|
||||||
veilid_log!(self debug "--> PublicInternet Validator ping to {:?}", nr);
|
veilid_log!(nr debug "--> PublicInternet Validator ping to {:?}", nr);
|
||||||
let rpc_processor = nr.rpc_processor();
|
let rpc_processor = nr.rpc_processor();
|
||||||
let _ = rpc_processor
|
let _ = rpc_processor
|
||||||
.rpc_call_status(Destination::direct(nr))
|
.rpc_call_status(Destination::direct(nr))
|
||||||
@ -291,7 +291,7 @@ impl RoutingTable {
|
|||||||
futurequeue.push_back(
|
futurequeue.push_back(
|
||||||
async move {
|
async move {
|
||||||
#[cfg(feature = "verbose-tracing")]
|
#[cfg(feature = "verbose-tracing")]
|
||||||
veilid_log!(self debug "--> LocalNetwork Validator ping to {:?}", nr);
|
veilid_log!(nr debug "--> LocalNetwork Validator ping to {:?}", nr);
|
||||||
let rpc_processor = nr.rpc_processor();
|
let rpc_processor = nr.rpc_processor();
|
||||||
let _ = rpc_processor
|
let _ = rpc_processor
|
||||||
.rpc_call_status(Destination::direct(nr))
|
.rpc_call_status(Destination::direct(nr))
|
||||||
|
@ -57,7 +57,7 @@ pub async fn test_routingtable_buckets_round_trip() {
|
|||||||
mock_registry::terminate(copy_registry).await;
|
mock_registry::terminate(copy_registry).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_round_trip_peerinfo() {
|
pub fn test_round_trip_peerinfo() {
|
||||||
let mut tks = TypedKeyGroup::new();
|
let mut tks = TypedKeyGroup::new();
|
||||||
tks.add(TypedKey::new(
|
tks.add(TypedKey::new(
|
||||||
CRYPTO_KIND_VLD0,
|
CRYPTO_KIND_VLD0,
|
||||||
@ -93,5 +93,5 @@ pub async fn test_round_trip_peerinfo() {
|
|||||||
|
|
||||||
pub async fn test_all() {
|
pub async fn test_all() {
|
||||||
test_routingtable_buckets_round_trip().await;
|
test_routingtable_buckets_round_trip().await;
|
||||||
test_round_trip_peerinfo().await;
|
test_round_trip_peerinfo();
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,10 @@ pub struct FanoutCallOutput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub type FanoutCallResult = RPCNetworkResult<FanoutCallOutput>;
|
pub type FanoutCallResult = RPCNetworkResult<FanoutCallOutput>;
|
||||||
pub type FanoutNodeInfoFilter = Arc<dyn Fn(&[TypedKey], &NodeInfo) -> bool + Send + Sync>;
|
pub type FanoutNodeInfoFilter = Arc<dyn (Fn(&[TypedKey], &NodeInfo) -> bool) + Send + Sync>;
|
||||||
|
pub type FanoutCheckDone<R> = Arc<dyn (Fn(&[NodeRef]) -> Option<R>) + Send + Sync>;
|
||||||
|
pub type FanoutCallRoutine =
|
||||||
|
Arc<dyn (Fn(NodeRef) -> PinBoxFutureStatic<FanoutCallResult>) + Send + Sync>;
|
||||||
|
|
||||||
pub fn empty_fanout_node_info_filter() -> FanoutNodeInfoFilter {
|
pub fn empty_fanout_node_info_filter() -> FanoutNodeInfoFilter {
|
||||||
Arc::new(|_, _| true)
|
Arc::new(|_, _| true)
|
||||||
@ -91,12 +94,9 @@ pub fn capability_fanout_node_info_filter(caps: Vec<Capability>) -> FanoutNodeIn
|
|||||||
/// If the algorithm times out, a Timeout result is returned, however operations will still have been performed and a
|
/// If the algorithm times out, a Timeout result is returned, however operations will still have been performed and a
|
||||||
/// timeout is not necessarily indicative of an algorithmic 'failure', just that no definitive stopping condition was found
|
/// timeout is not necessarily indicative of an algorithmic 'failure', just that no definitive stopping condition was found
|
||||||
/// in the given time
|
/// in the given time
|
||||||
pub(crate) struct FanoutCall<'a, R, F, C, D>
|
pub(crate) struct FanoutCall<'a, R>
|
||||||
where
|
where
|
||||||
R: Unpin,
|
R: Unpin,
|
||||||
F: Future<Output = FanoutCallResult>,
|
|
||||||
C: Fn(NodeRef) -> F,
|
|
||||||
D: Fn(&[NodeRef]) -> Option<R>,
|
|
||||||
{
|
{
|
||||||
routing_table: &'a RoutingTable,
|
routing_table: &'a RoutingTable,
|
||||||
node_id: TypedKey,
|
node_id: TypedKey,
|
||||||
@ -105,16 +105,13 @@ where
|
|||||||
fanout: usize,
|
fanout: usize,
|
||||||
timeout_us: TimestampDuration,
|
timeout_us: TimestampDuration,
|
||||||
node_info_filter: FanoutNodeInfoFilter,
|
node_info_filter: FanoutNodeInfoFilter,
|
||||||
call_routine: C,
|
call_routine: FanoutCallRoutine,
|
||||||
check_done: D,
|
check_done: FanoutCheckDone<R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, R, F, C, D> FanoutCall<'a, R, F, C, D>
|
impl<'a, R> FanoutCall<'a, R>
|
||||||
where
|
where
|
||||||
R: Unpin,
|
R: Unpin,
|
||||||
F: Future<Output = FanoutCallResult>,
|
|
||||||
C: Fn(NodeRef) -> F,
|
|
||||||
D: Fn(&[NodeRef]) -> Option<R>,
|
|
||||||
{
|
{
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
@ -124,8 +121,8 @@ where
|
|||||||
fanout: usize,
|
fanout: usize,
|
||||||
timeout_us: TimestampDuration,
|
timeout_us: TimestampDuration,
|
||||||
node_info_filter: FanoutNodeInfoFilter,
|
node_info_filter: FanoutNodeInfoFilter,
|
||||||
call_routine: C,
|
call_routine: FanoutCallRoutine,
|
||||||
check_done: D,
|
check_done: FanoutCheckDone<R>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let context = Mutex::new(FanoutContext {
|
let context = Mutex::new(FanoutContext {
|
||||||
fanout_queue: FanoutQueue::new(node_id.kind),
|
fanout_queue: FanoutQueue::new(node_id.kind),
|
||||||
|
@ -68,12 +68,13 @@ impl_veilid_log_facility!("rpc");
|
|||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[must_use]
|
||||||
struct WaitableReply {
|
struct WaitableReply {
|
||||||
handle: OperationWaitHandle<Message, Option<QuestionContext>>,
|
handle: OperationWaitHandle<Message, Option<QuestionContext>>,
|
||||||
timeout_us: TimestampDuration,
|
timeout_us: TimestampDuration,
|
||||||
node_ref: NodeRef,
|
node_ref: NodeRef,
|
||||||
send_ts: Timestamp,
|
send_ts: Timestamp,
|
||||||
send_data_method: SendDataMethod,
|
send_data_method: SendDataResult,
|
||||||
safety_route: Option<PublicKey>,
|
safety_route: Option<PublicKey>,
|
||||||
remote_private_route: Option<PublicKey>,
|
remote_private_route: Option<PublicKey>,
|
||||||
reply_private_route: Option<PublicKey>,
|
reply_private_route: Option<PublicKey>,
|
||||||
@ -83,6 +84,7 @@ struct WaitableReply {
|
|||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
#[must_use]
|
||||||
enum RPCKind {
|
enum RPCKind {
|
||||||
Question,
|
Question,
|
||||||
Statement,
|
Statement,
|
||||||
@ -92,6 +94,7 @@ enum RPCKind {
|
|||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
#[must_use]
|
||||||
pub struct RPCProcessorStartupContext {
|
pub struct RPCProcessorStartupContext {
|
||||||
pub startup_lock: Arc<StartupLock>,
|
pub startup_lock: Arc<StartupLock>,
|
||||||
}
|
}
|
||||||
@ -111,6 +114,7 @@ impl Default for RPCProcessorStartupContext {
|
|||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[must_use]
|
||||||
struct RPCProcessorInner {
|
struct RPCProcessorInner {
|
||||||
send_channel: Option<flume::Sender<(Span, MessageEncoded)>>,
|
send_channel: Option<flume::Sender<(Span, MessageEncoded)>>,
|
||||||
stop_source: Option<StopSource>,
|
stop_source: Option<StopSource>,
|
||||||
@ -118,6 +122,7 @@ struct RPCProcessorInner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[must_use]
|
||||||
pub(crate) struct RPCProcessor {
|
pub(crate) struct RPCProcessor {
|
||||||
registry: VeilidComponentRegistry,
|
registry: VeilidComponentRegistry,
|
||||||
inner: Mutex<RPCProcessorInner>,
|
inner: Mutex<RPCProcessorInner>,
|
||||||
@ -183,14 +188,17 @@ impl RPCProcessor {
|
|||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
/// Initialization
|
/// Initialization
|
||||||
|
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
async fn init_async(&self) -> EyreResult<()> {
|
async fn init_async(&self) -> EyreResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
async fn post_init_async(&self) -> EyreResult<()> {
|
async fn post_init_async(&self) -> EyreResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
async fn pre_terminate_async(&self) {
|
async fn pre_terminate_async(&self) {
|
||||||
// Ensure things have shut down
|
// Ensure things have shut down
|
||||||
assert!(
|
assert!(
|
||||||
@ -199,6 +207,7 @@ impl RPCProcessor {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
async fn terminate_async(&self) {}
|
async fn terminate_async(&self) {}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
@ -223,7 +232,7 @@ impl RPCProcessor {
|
|||||||
let stop_token = inner.stop_source.as_ref().unwrap().token();
|
let stop_token = inner.stop_source.as_ref().unwrap().token();
|
||||||
let jh = spawn(&format!("rpc worker {}", task_n), async move {
|
let jh = spawn(&format!("rpc worker {}", task_n), async move {
|
||||||
let this = registry.rpc_processor();
|
let this = registry.rpc_processor();
|
||||||
this.rpc_worker(stop_token, receiver).await
|
Box::pin(this.rpc_worker(stop_token, receiver)).await
|
||||||
});
|
});
|
||||||
inner.worker_join_handles.push(jh);
|
inner.worker_join_handles.push(jh);
|
||||||
}
|
}
|
||||||
@ -368,9 +377,10 @@ impl RPCProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Routine to call to generate fanout
|
// Routine to call to generate fanout
|
||||||
let call_routine = |next_node: NodeRef| {
|
|
||||||
let registry = self.registry();
|
let registry = self.registry();
|
||||||
async move {
|
let call_routine = Arc::new(move |next_node: NodeRef| {
|
||||||
|
let registry = registry.clone();
|
||||||
|
Box::pin(async move {
|
||||||
let this = registry.rpc_processor();
|
let this = registry.rpc_processor();
|
||||||
let v = network_result_try!(
|
let v = network_result_try!(
|
||||||
this.rpc_call_find_node(
|
this.rpc_call_find_node(
|
||||||
@ -384,11 +394,11 @@ impl RPCProcessor {
|
|||||||
Ok(NetworkResult::value(FanoutCallOutput {
|
Ok(NetworkResult::value(FanoutCallOutput {
|
||||||
peer_info_list: v.answer,
|
peer_info_list: v.answer,
|
||||||
}))
|
}))
|
||||||
}
|
}) as PinBoxFuture<FanoutCallResult>
|
||||||
};
|
});
|
||||||
|
|
||||||
// Routine to call to check if we're done at each step
|
// Routine to call to check if we're done at each step
|
||||||
let check_done = |_: &[NodeRef]| {
|
let check_done = Arc::new(move |_: &[NodeRef]| {
|
||||||
let Ok(Some(nr)) = routing_table.lookup_node_ref(node_id) else {
|
let Ok(Some(nr)) = routing_table.lookup_node_ref(node_id) else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
@ -401,7 +411,7 @@ impl RPCProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
};
|
});
|
||||||
|
|
||||||
// Call the fanout
|
// Call the fanout
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
@ -421,13 +431,13 @@ impl RPCProcessor {
|
|||||||
|
|
||||||
/// Search the DHT for a specific node corresponding to a key unless we
|
/// Search the DHT for a specific node corresponding to a key unless we
|
||||||
/// have that node in our routing table already, and return the node reference
|
/// have that node in our routing table already, and return the node reference
|
||||||
/// Note: This routine can possibly be recursive, hence the SendPinBoxFuture async form
|
/// Note: This routine can possibly be recursive, hence the PinBoxFuture async form
|
||||||
#[instrument(level = "trace", target = "rpc", skip_all)]
|
#[instrument(level = "trace", target = "rpc", skip_all)]
|
||||||
pub fn resolve_node(
|
pub fn resolve_node(
|
||||||
&self,
|
&self,
|
||||||
node_id: TypedKey,
|
node_id: TypedKey,
|
||||||
safety_selection: SafetySelection,
|
safety_selection: SafetySelection,
|
||||||
) -> SendPinBoxFuture<Result<Option<NodeRef>, RPCError>> {
|
) -> PinBoxFuture<Result<Option<NodeRef>, RPCError>> {
|
||||||
let registry = self.registry();
|
let registry = self.registry();
|
||||||
Box::pin(
|
Box::pin(
|
||||||
async move {
|
async move {
|
||||||
@ -1165,7 +1175,8 @@ impl RPCProcessor {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Ref the connection so it doesn't go away until we're done with the waitable reply
|
// Ref the connection so it doesn't go away until we're done with the waitable reply
|
||||||
let opt_connection_ref_scope = send_data_method.unique_flow.connection_id.and_then(|id| {
|
let opt_connection_ref_scope =
|
||||||
|
send_data_method.unique_flow().connection_id.and_then(|id| {
|
||||||
self.network_manager()
|
self.network_manager()
|
||||||
.connection_manager()
|
.connection_manager()
|
||||||
.try_connection_ref_scope(id)
|
.try_connection_ref_scope(id)
|
||||||
@ -1506,35 +1517,75 @@ impl RPCProcessor {
|
|||||||
|
|
||||||
// Process specific message kind
|
// Process specific message kind
|
||||||
match msg.operation.kind() {
|
match msg.operation.kind() {
|
||||||
RPCOperationKind::Question(q) => match q.detail() {
|
RPCOperationKind::Question(q) => {
|
||||||
RPCQuestionDetail::StatusQ(_) => self.process_status_q(msg).await,
|
let res = match q.detail() {
|
||||||
RPCQuestionDetail::FindNodeQ(_) => self.process_find_node_q(msg).await,
|
RPCQuestionDetail::StatusQ(_) => {
|
||||||
RPCQuestionDetail::AppCallQ(_) => self.process_app_call_q(msg).await,
|
pin_dyn_future_closure!(self.process_status_q(msg))
|
||||||
RPCQuestionDetail::GetValueQ(_) => self.process_get_value_q(msg).await,
|
}
|
||||||
RPCQuestionDetail::SetValueQ(_) => self.process_set_value_q(msg).await,
|
RPCQuestionDetail::FindNodeQ(_) => {
|
||||||
RPCQuestionDetail::WatchValueQ(_) => self.process_watch_value_q(msg).await,
|
pin_dyn_future_closure!(self.process_find_node_q(msg))
|
||||||
RPCQuestionDetail::InspectValueQ(_) => self.process_inspect_value_q(msg).await,
|
}
|
||||||
#[cfg(feature = "unstable-blockstore")]
|
RPCQuestionDetail::AppCallQ(_) => {
|
||||||
RPCQuestionDetail::SupplyBlockQ(_) => self.process_supply_block_q(msg).await,
|
pin_dyn_future_closure!(self.process_app_call_q(msg))
|
||||||
#[cfg(feature = "unstable-blockstore")]
|
}
|
||||||
RPCQuestionDetail::FindBlockQ(_) => self.process_find_block_q(msg).await,
|
RPCQuestionDetail::GetValueQ(_) => {
|
||||||
#[cfg(feature = "unstable-tunnels")]
|
pin_dyn_future_closure!(self.process_get_value_q(msg))
|
||||||
RPCQuestionDetail::StartTunnelQ(_) => self.process_start_tunnel_q(msg).await,
|
}
|
||||||
#[cfg(feature = "unstable-tunnels")]
|
RPCQuestionDetail::SetValueQ(_) => {
|
||||||
RPCQuestionDetail::CompleteTunnelQ(_) => self.process_complete_tunnel_q(msg).await,
|
pin_dyn_future_closure!(self.process_set_value_q(msg))
|
||||||
#[cfg(feature = "unstable-tunnels")]
|
}
|
||||||
RPCQuestionDetail::CancelTunnelQ(_) => self.process_cancel_tunnel_q(msg).await,
|
RPCQuestionDetail::WatchValueQ(_) => {
|
||||||
},
|
pin_dyn_future_closure!(self.process_watch_value_q(msg))
|
||||||
RPCOperationKind::Statement(s) => match s.detail() {
|
}
|
||||||
RPCStatementDetail::ValidateDialInfo(_) => {
|
RPCQuestionDetail::InspectValueQ(_) => {
|
||||||
self.process_validate_dial_info(msg).await
|
pin_dyn_future_closure!(self.process_inspect_value_q(msg))
|
||||||
|
}
|
||||||
|
#[cfg(feature = "unstable-blockstore")]
|
||||||
|
RPCQuestionDetail::SupplyBlockQ(_) => {
|
||||||
|
pin_dyn_future_closure!(self.process_supply_block_q(msg))
|
||||||
|
}
|
||||||
|
#[cfg(feature = "unstable-blockstore")]
|
||||||
|
RPCQuestionDetail::FindBlockQ(_) => {
|
||||||
|
pin_dyn_future_closure!(self.process_find_block_q(msg))
|
||||||
|
}
|
||||||
|
#[cfg(feature = "unstable-tunnels")]
|
||||||
|
RPCQuestionDetail::StartTunnelQ(_) => {
|
||||||
|
pin_dyn_future_closure!(self.process_start_tunnel_q(msg))
|
||||||
|
}
|
||||||
|
#[cfg(feature = "unstable-tunnels")]
|
||||||
|
RPCQuestionDetail::CompleteTunnelQ(_) => {
|
||||||
|
pin_dyn_future_closure!(self.process_complete_tunnel_q(msg))
|
||||||
|
}
|
||||||
|
#[cfg(feature = "unstable-tunnels")]
|
||||||
|
RPCQuestionDetail::CancelTunnelQ(_) => {
|
||||||
|
pin_dyn_future_closure!(self.process_cancel_tunnel_q(msg))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
res.await
|
||||||
|
}
|
||||||
|
RPCOperationKind::Statement(s) => {
|
||||||
|
let res = match s.detail() {
|
||||||
|
RPCStatementDetail::ValidateDialInfo(_) => {
|
||||||
|
pin_dyn_future_closure!(self.process_validate_dial_info(msg))
|
||||||
|
}
|
||||||
|
RPCStatementDetail::Route(_) => {
|
||||||
|
pin_dyn_future_closure!(self.process_route(msg))
|
||||||
|
}
|
||||||
|
RPCStatementDetail::ValueChanged(_) => {
|
||||||
|
pin_dyn_future_closure!(self.process_value_changed(msg))
|
||||||
|
}
|
||||||
|
RPCStatementDetail::Signal(_) => {
|
||||||
|
pin_dyn_future_closure!(self.process_signal(msg))
|
||||||
|
}
|
||||||
|
RPCStatementDetail::ReturnReceipt(_) => {
|
||||||
|
pin_dyn_future_closure!(self.process_return_receipt(msg))
|
||||||
|
}
|
||||||
|
RPCStatementDetail::AppMessage(_) => {
|
||||||
|
pin_dyn_future_closure!(self.process_app_message(msg))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
res.await
|
||||||
}
|
}
|
||||||
RPCStatementDetail::Route(_) => self.process_route(msg).await,
|
|
||||||
RPCStatementDetail::ValueChanged(_) => self.process_value_changed(msg).await,
|
|
||||||
RPCStatementDetail::Signal(_) => self.process_signal(msg).await,
|
|
||||||
RPCStatementDetail::ReturnReceipt(_) => self.process_return_receipt(msg).await,
|
|
||||||
RPCStatementDetail::AppMessage(_) => self.process_app_message(msg).await,
|
|
||||||
},
|
|
||||||
RPCOperationKind::Answer(_) => {
|
RPCOperationKind::Answer(_) => {
|
||||||
let op_id = msg.operation.op_id();
|
let op_id = msg.operation.op_id();
|
||||||
if let Err(e) = self.waiting_rpc_table.complete_op_waiter(op_id, msg) {
|
if let Err(e) = self.waiting_rpc_table.complete_op_waiter(op_id, msg) {
|
||||||
|
@ -115,18 +115,13 @@ impl RPCProcessor {
|
|||||||
} => {
|
} => {
|
||||||
if matches!(safety_selection, SafetySelection::Unsafe(_)) {
|
if matches!(safety_selection, SafetySelection::Unsafe(_)) {
|
||||||
if let Some(sender_info) = sender_info {
|
if let Some(sender_info) = sender_info {
|
||||||
if send_data_method.opt_relayed_contact_method.is_none()
|
if send_data_method.is_direct() {
|
||||||
&& matches!(
|
|
||||||
send_data_method.contact_method,
|
|
||||||
NodeContactMethod::Direct(_)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Directly requested status that actually gets sent directly and not over a relay will tell us what our IP address appears as
|
// Directly requested status that actually gets sent directly and not over a relay will tell us what our IP address appears as
|
||||||
// If this changes, we'd want to know about that to reset the networking stack
|
// If this changes, we'd want to know about that to reset the networking stack
|
||||||
opt_previous_sender_info = target.report_sender_info(
|
opt_previous_sender_info = target.report_sender_info(
|
||||||
routing_domain,
|
routing_domain,
|
||||||
send_data_method.unique_flow.flow.protocol_type(),
|
send_data_method.unique_flow().flow.protocol_type(),
|
||||||
send_data_method.unique_flow.flow.address_type(),
|
send_data_method.unique_flow().flow.address_type(),
|
||||||
sender_info,
|
sender_info,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -137,7 +132,7 @@ impl RPCProcessor {
|
|||||||
routing_domain,
|
routing_domain,
|
||||||
socket_address: sender_info.socket_address,
|
socket_address: sender_info.socket_address,
|
||||||
old_socket_address: opt_previous_sender_info.map(|s| s.socket_address),
|
old_socket_address: opt_previous_sender_info.map(|s| s.socket_address),
|
||||||
flow: send_data_method.unique_flow.flow,
|
flow: send_data_method.unique_flow().flow,
|
||||||
reporting_peer: target.unfiltered(),
|
reporting_peer: target.unfiltered(),
|
||||||
}) {
|
}) {
|
||||||
veilid_log!(self debug "Failed to post event: {}", e);
|
veilid_log!(self debug "Failed to post event: {}", e);
|
||||||
|
@ -82,7 +82,7 @@ impl RPCProcessor {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[instrument(level = "trace", target = "rpc", skip(self, msg), fields(msg.operation.op_id), ret, err)]
|
//#[instrument(level = "trace", target = "rpc", skip(self, msg), fields(msg.operation.op_id), ret, err)]
|
||||||
pub(super) async fn process_validate_dial_info(&self, msg: Message) -> RPCNetworkResult<()> {
|
pub(super) async fn process_validate_dial_info(&self, msg: Message) -> RPCNetworkResult<()> {
|
||||||
// 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
|
||||||
let detail = match msg.header.detail {
|
let detail = match msg.header.detail {
|
||||||
@ -187,7 +187,7 @@ impl RPCProcessor {
|
|||||||
|
|
||||||
// Send the validate_dial_info request
|
// Send the validate_dial_info request
|
||||||
// This can only be sent directly, as relays can not validate dial info
|
// This can only be sent directly, as relays can not validate dial info
|
||||||
network_result_value_or_log!(self self.statement(Destination::direct(peer.default_filtered()), statement)
|
network_result_value_or_log!(self pin_future_closure!(self.statement(Destination::direct(peer.default_filtered()), statement))
|
||||||
.await? => [ format!(": peer={} statement={:?}", peer, statement) ] {
|
.await? => [ format!(": peer={} statement={:?}", peer, statement) ] {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -33,11 +33,20 @@ impl StorageManager {
|
|||||||
}
|
}
|
||||||
format!("{}]\n", out)
|
format!("{}]\n", out)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn debug_offline_records(&self) -> String {
|
pub async fn debug_offline_records(&self) -> String {
|
||||||
let inner = self.inner.lock().await;
|
let inner = self.inner.lock().await;
|
||||||
|
let Some(local_record_store) = &inner.local_record_store else {
|
||||||
|
return "not initialized".to_owned();
|
||||||
|
};
|
||||||
|
|
||||||
let mut out = "[\n".to_owned();
|
let mut out = "[\n".to_owned();
|
||||||
for (k, v) in &inner.offline_subkey_writes {
|
for (k, v) in &inner.offline_subkey_writes {
|
||||||
out += &format!(" {}:{:?}\n", k, v);
|
let record_info = local_record_store
|
||||||
|
.peek_record(*k, |r| format!("{} nodes", r.detail().nodes.len()))
|
||||||
|
.unwrap_or("Not found".to_owned());
|
||||||
|
|
||||||
|
out += &format!(" {}:{:?}, {}\n", k, v, record_info);
|
||||||
}
|
}
|
||||||
format!("{}]\n", out)
|
format!("{}]\n", out)
|
||||||
}
|
}
|
||||||
|
@ -84,11 +84,11 @@ impl StorageManager {
|
|||||||
let call_routine = {
|
let call_routine = {
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
let registry = self.registry();
|
let registry = self.registry();
|
||||||
move |next_node: NodeRef| {
|
Arc::new(move |next_node: NodeRef| {
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let last_descriptor = last_get_result.opt_descriptor.clone();
|
let last_descriptor = last_get_result.opt_descriptor.clone();
|
||||||
async move {
|
Box::pin(async move {
|
||||||
let rpc_processor = registry.rpc_processor();
|
let rpc_processor = registry.rpc_processor();
|
||||||
let gva = network_result_try!(
|
let gva = network_result_try!(
|
||||||
rpc_processor
|
rpc_processor
|
||||||
@ -189,8 +189,8 @@ impl StorageManager {
|
|||||||
veilid_log!(registry debug target:"network_result", "GetValue fanout call returned peers {}", gva.answer.peers.len());
|
veilid_log!(registry debug target:"network_result", "GetValue fanout call returned peers {}", gva.answer.peers.len());
|
||||||
|
|
||||||
Ok(NetworkResult::value(FanoutCallOutput{peer_info_list: gva.answer.peers}))
|
Ok(NetworkResult::value(FanoutCallOutput{peer_info_list: gva.answer.peers}))
|
||||||
}.instrument(tracing::trace_span!("outbound_get_value fanout routine"))
|
}.instrument(tracing::trace_span!("outbound_get_value fanout routine"))) as PinBoxFuture<FanoutCallResult>
|
||||||
}
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
// Routine to call to check if we're done at each step
|
// Routine to call to check if we're done at each step
|
||||||
@ -198,7 +198,7 @@ impl StorageManager {
|
|||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
let out_tx = out_tx.clone();
|
let out_tx = out_tx.clone();
|
||||||
let registry = self.registry();
|
let registry = self.registry();
|
||||||
move |_closest_nodes: &[NodeRef]| {
|
Arc::new(move |_closest_nodes: &[NodeRef]| {
|
||||||
let mut ctx = context.lock();
|
let mut ctx = context.lock();
|
||||||
|
|
||||||
// send partial update if desired
|
// send partial update if desired
|
||||||
@ -229,7 +229,7 @@ impl StorageManager {
|
|||||||
return Some(());
|
return Some(());
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
// Call the fanout in a spawned task
|
// Call the fanout in a spawned task
|
||||||
@ -305,7 +305,7 @@ impl StorageManager {
|
|||||||
self.process_deferred_results(
|
self.process_deferred_results(
|
||||||
res_rx,
|
res_rx,
|
||||||
Box::new(
|
Box::new(
|
||||||
move |result: VeilidAPIResult<get_value::OutboundGetValueResult>| -> SendPinBoxFuture<bool> {
|
move |result: VeilidAPIResult<get_value::OutboundGetValueResult>| -> PinBoxFutureStatic<bool> {
|
||||||
let registry=registry.clone();
|
let registry=registry.clone();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let this = registry.storage_manager();
|
let this = registry.storage_manager();
|
||||||
|
@ -120,12 +120,12 @@ impl StorageManager {
|
|||||||
let call_routine = {
|
let call_routine = {
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
let registry = self.registry();
|
let registry = self.registry();
|
||||||
move |next_node: NodeRef| {
|
Arc::new(move |next_node: NodeRef| {
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let opt_descriptor = local_inspect_result.opt_descriptor.clone();
|
let opt_descriptor = local_inspect_result.opt_descriptor.clone();
|
||||||
let subkeys = subkeys.clone();
|
let subkeys = subkeys.clone();
|
||||||
async move {
|
Box::pin(async move {
|
||||||
let rpc_processor = registry.rpc_processor();
|
let rpc_processor = registry.rpc_processor();
|
||||||
|
|
||||||
let iva = network_result_try!(
|
let iva = network_result_try!(
|
||||||
@ -159,7 +159,7 @@ impl StorageManager {
|
|||||||
|
|
||||||
// Keep the value if we got one and it is newer and it passes schema validation
|
// Keep the value if we got one and it is newer and it passes schema validation
|
||||||
if !answer.seqs.is_empty() {
|
if !answer.seqs.is_empty() {
|
||||||
veilid_log!(self debug "Got seqs back: len={}", answer.seqs.len());
|
veilid_log!(registry debug "Got seqs back: len={}", answer.seqs.len());
|
||||||
let mut ctx = context.lock();
|
let mut ctx = context.lock();
|
||||||
|
|
||||||
// Ensure we have a schema and descriptor etc
|
// Ensure we have a schema and descriptor etc
|
||||||
@ -239,12 +239,15 @@ impl StorageManager {
|
|||||||
veilid_log!(registry debug target:"network_result", "InspectValue fanout call returned peers {}", answer.peers.len());
|
veilid_log!(registry debug target:"network_result", "InspectValue fanout call returned peers {}", answer.peers.len());
|
||||||
|
|
||||||
Ok(NetworkResult::value(FanoutCallOutput { peer_info_list: answer.peers}))
|
Ok(NetworkResult::value(FanoutCallOutput { peer_info_list: answer.peers}))
|
||||||
}.instrument(tracing::trace_span!("outbound_inspect_value fanout call"))
|
}.instrument(tracing::trace_span!("outbound_inspect_value fanout call"))) as PinBoxFuture<FanoutCallResult>
|
||||||
}
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
// Routine to call to check if we're done at each step
|
// Routine to call to check if we're done at each step
|
||||||
let check_done = |_closest_nodes: &[NodeRef]| {
|
|
||||||
|
let check_done = {
|
||||||
|
let context = context.clone();
|
||||||
|
Arc::new(move |_closest_nodes: &[NodeRef]| {
|
||||||
// If we have reached sufficient consensus on all subkeys, return done
|
// If we have reached sufficient consensus on all subkeys, return done
|
||||||
let ctx = context.lock();
|
let ctx = context.lock();
|
||||||
let mut has_consensus = true;
|
let mut has_consensus = true;
|
||||||
@ -258,6 +261,7 @@ impl StorageManager {
|
|||||||
return Some(());
|
return Some(());
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
// Call the fanout
|
// Call the fanout
|
||||||
|
@ -62,7 +62,7 @@ struct StorageManagerInner {
|
|||||||
/// Storage manager metadata that is persistent, including copy of offline subkey writes
|
/// Storage manager metadata that is persistent, including copy of offline subkey writes
|
||||||
pub metadata_db: Option<TableDB>,
|
pub metadata_db: Option<TableDB>,
|
||||||
/// Background processing task (not part of attachment manager tick tree so it happens when detached too)
|
/// Background processing task (not part of attachment manager tick tree so it happens when detached too)
|
||||||
pub tick_future: Option<SendPinBoxFuture<()>>,
|
pub tick_future: Option<PinBoxFutureStatic<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for StorageManagerInner {
|
impl fmt::Debug for StorageManagerInner {
|
||||||
@ -237,7 +237,7 @@ impl StorageManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start deferred results processors
|
// Start deferred results processors
|
||||||
self.deferred_result_processor.init().await;
|
self.deferred_result_processor.init();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -966,9 +966,8 @@ impl StorageManager {
|
|||||||
|
|
||||||
// Update the watch. This just calls through to the above watch_values() function
|
// Update the watch. This just calls through to the above watch_values() function
|
||||||
// This will update the active_watch so we don't need to do that in this routine.
|
// This will update the active_watch so we don't need to do that in this routine.
|
||||||
let expiration_ts = self
|
let expiration_ts =
|
||||||
.watch_values(key, subkeys, active_watch.expiration_ts, count)
|
pin_future!(self.watch_values(key, subkeys, active_watch.expiration_ts, count)).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
// A zero expiration time returned from watch_value() means the watch is done
|
// A zero expiration time returned from watch_value() means the watch is done
|
||||||
// or no subkeys are left, and the watch is no longer active
|
// or no subkeys are left, and the watch is no longer active
|
||||||
@ -1739,7 +1738,7 @@ impl StorageManager {
|
|||||||
pub(super) fn process_deferred_results<T: Send + 'static>(
|
pub(super) fn process_deferred_results<T: Send + 'static>(
|
||||||
&self,
|
&self,
|
||||||
receiver: flume::Receiver<T>,
|
receiver: flume::Receiver<T>,
|
||||||
handler: impl FnMut(T) -> SendPinBoxFuture<bool> + Send + 'static,
|
handler: impl FnMut(T) -> PinBoxFutureStatic<bool> + Send + 'static,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
self.deferred_result_processor
|
self.deferred_result_processor
|
||||||
.add(receiver.into_stream(), handler)
|
.add(receiver.into_stream(), handler)
|
||||||
|
@ -82,11 +82,11 @@ impl StorageManager {
|
|||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
let registry = self.registry();
|
let registry = self.registry();
|
||||||
|
|
||||||
move |next_node: NodeRef| {
|
Arc::new(move |next_node: NodeRef| {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
let descriptor = descriptor.clone();
|
let descriptor = descriptor.clone();
|
||||||
async move {
|
Box::pin(async move {
|
||||||
let rpc_processor = registry.rpc_processor();
|
let rpc_processor = registry.rpc_processor();
|
||||||
|
|
||||||
let send_descriptor = true; // xxx check if next_node needs the descriptor or not, see issue #203
|
let send_descriptor = true; // xxx check if next_node needs the descriptor or not, see issue #203
|
||||||
@ -187,8 +187,8 @@ impl StorageManager {
|
|||||||
ctx.send_partial_update = true;
|
ctx.send_partial_update = true;
|
||||||
|
|
||||||
Ok(NetworkResult::value(FanoutCallOutput{peer_info_list:sva.answer.peers}))
|
Ok(NetworkResult::value(FanoutCallOutput{peer_info_list:sva.answer.peers}))
|
||||||
}.instrument(tracing::trace_span!("fanout call_routine"))
|
}.instrument(tracing::trace_span!("fanout call_routine"))) as PinBoxFuture<FanoutCallResult>
|
||||||
}
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
// Routine to call to check if we're done at each step
|
// Routine to call to check if we're done at each step
|
||||||
@ -196,7 +196,7 @@ impl StorageManager {
|
|||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
let out_tx = out_tx.clone();
|
let out_tx = out_tx.clone();
|
||||||
let registry = self.registry();
|
let registry = self.registry();
|
||||||
move |_closest_nodes: &[NodeRef]| {
|
Arc::new(move |_closest_nodes: &[NodeRef]| {
|
||||||
let mut ctx = context.lock();
|
let mut ctx = context.lock();
|
||||||
|
|
||||||
// send partial update if desired
|
// send partial update if desired
|
||||||
@ -233,7 +233,7 @@ impl StorageManager {
|
|||||||
return Some(());
|
return Some(());
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
// Call the fanout in a spawned task
|
// Call the fanout in a spawned task
|
||||||
@ -308,7 +308,7 @@ impl StorageManager {
|
|||||||
self.process_deferred_results(
|
self.process_deferred_results(
|
||||||
res_rx,
|
res_rx,
|
||||||
Box::new(
|
Box::new(
|
||||||
move |result: VeilidAPIResult<set_value::OutboundSetValueResult>| -> SendPinBoxFuture<bool> {
|
move |result: VeilidAPIResult<set_value::OutboundSetValueResult>| -> PinBoxFutureStatic<bool> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let last_value_data = last_value_data.clone();
|
let last_value_data = last_value_data.clone();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
|
@ -26,7 +26,7 @@ impl SignedValueDescriptor {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
// validate schema
|
// validate schema
|
||||||
DHTSchema::try_from(self.schema_data.as_slice())?;
|
let _ = DHTSchema::try_from(self.schema_data.as_slice())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,8 +99,7 @@ impl StorageManager {
|
|||||||
opt_watcher.unwrap_or_else(|| self.anonymous_watch_keys.get(key.kind).unwrap().value);
|
opt_watcher.unwrap_or_else(|| self.anonymous_watch_keys.get(key.kind).unwrap().value);
|
||||||
|
|
||||||
let wva = VeilidAPIError::from_network_result(
|
let wva = VeilidAPIError::from_network_result(
|
||||||
self.rpc_processor()
|
pin_future!(self.rpc_processor().rpc_call_watch_value(
|
||||||
.rpc_call_watch_value(
|
|
||||||
Destination::direct(watch_node.routing_domain_filtered(routing_domain))
|
Destination::direct(watch_node.routing_domain_filtered(routing_domain))
|
||||||
.with_safety(safety_selection),
|
.with_safety(safety_selection),
|
||||||
key,
|
key,
|
||||||
@ -109,7 +108,7 @@ impl StorageManager {
|
|||||||
count,
|
count,
|
||||||
watcher,
|
watcher,
|
||||||
Some(watch_id),
|
Some(watch_id),
|
||||||
)
|
))
|
||||||
.await?,
|
.await?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -233,13 +232,13 @@ impl StorageManager {
|
|||||||
let call_routine = {
|
let call_routine = {
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
let registry = self.registry();
|
let registry = self.registry();
|
||||||
move |next_node: NodeRef| {
|
Arc::new(move |next_node: NodeRef| {
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
|
|
||||||
let subkeys = subkeys.clone();
|
let subkeys = subkeys.clone();
|
||||||
|
|
||||||
async move {
|
Box::pin(async move {
|
||||||
let rpc_processor = registry.rpc_processor();
|
let rpc_processor = registry.rpc_processor();
|
||||||
let wva = network_result_try!(
|
let wva = network_result_try!(
|
||||||
rpc_processor
|
rpc_processor
|
||||||
@ -282,18 +281,21 @@ impl StorageManager {
|
|||||||
veilid_log!(registry debug target:"network_result", "WatchValue fanout call returned peers {} ({})", wva.answer.peers.len(), next_node);
|
veilid_log!(registry debug target:"network_result", "WatchValue fanout call returned peers {} ({})", wva.answer.peers.len(), next_node);
|
||||||
|
|
||||||
Ok(NetworkResult::value(FanoutCallOutput{peer_info_list: wva.answer.peers}))
|
Ok(NetworkResult::value(FanoutCallOutput{peer_info_list: wva.answer.peers}))
|
||||||
}.instrument(tracing::trace_span!("outbound_watch_value call routine"))
|
}.instrument(tracing::trace_span!("outbound_watch_value call routine"))) as PinBoxFuture<FanoutCallResult>
|
||||||
}
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
// Routine to call to check if we're done at each step
|
// Routine to call to check if we're done at each step
|
||||||
let check_done = |_closest_nodes: &[NodeRef]| {
|
let check_done = {
|
||||||
|
let context = context.clone();
|
||||||
|
Arc::new(move |_closest_nodes: &[NodeRef]| {
|
||||||
// If a watch has succeeded, return done
|
// If a watch has succeeded, return done
|
||||||
let ctx = context.lock();
|
let ctx = context.lock();
|
||||||
if ctx.opt_watch_value_result.is_some() {
|
if ctx.opt_watch_value_result.is_some() {
|
||||||
return Some(());
|
return Some(());
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
// Call the fanout
|
// Call the fanout
|
||||||
|
@ -23,6 +23,7 @@ const ALL_TABLE_NAMES: &[u8] = b"all_table_names";
|
|||||||
/// Description of column
|
/// Description of column
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct ColumnInfo {
|
pub struct ColumnInfo {
|
||||||
pub key_count: AlignedU64,
|
pub key_count: AlignedU64,
|
||||||
}
|
}
|
||||||
@ -30,6 +31,7 @@ pub struct ColumnInfo {
|
|||||||
/// IO Stats for table
|
/// IO Stats for table
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct IOStatsInfo {
|
pub struct IOStatsInfo {
|
||||||
/// Number of transaction.
|
/// Number of transaction.
|
||||||
pub transactions: AlignedU64,
|
pub transactions: AlignedU64,
|
||||||
@ -54,6 +56,7 @@ pub struct IOStatsInfo {
|
|||||||
/// Description of table
|
/// Description of table
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct TableInfo {
|
pub struct TableInfo {
|
||||||
/// Internal table name
|
/// Internal table name
|
||||||
pub table_name: String,
|
pub table_name: String,
|
||||||
@ -67,6 +70,7 @@ pub struct TableInfo {
|
|||||||
pub columns: Vec<ColumnInfo>,
|
pub columns: Vec<ColumnInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
struct TableStoreInner {
|
struct TableStoreInner {
|
||||||
opened: BTreeMap<String, Weak<TableDBUnlockedInner>>,
|
opened: BTreeMap<String, Weak<TableDBUnlockedInner>>,
|
||||||
encryption_key: Option<TypedSharedSecret>,
|
encryption_key: Option<TypedSharedSecret>,
|
||||||
@ -87,6 +91,7 @@ impl fmt::Debug for TableStoreInner {
|
|||||||
|
|
||||||
/// Veilid Table Storage.
|
/// Veilid Table Storage.
|
||||||
/// Database for storing key value pairs persistently and securely across runs.
|
/// Database for storing key value pairs persistently and securely across runs.
|
||||||
|
#[must_use]
|
||||||
pub struct TableStore {
|
pub struct TableStore {
|
||||||
registry: VeilidComponentRegistry,
|
registry: VeilidComponentRegistry,
|
||||||
inner: Mutex<TableStoreInner>, // Sync mutex here because TableDB drops can happen at any time
|
inner: Mutex<TableStoreInner>, // Sync mutex here because TableDB drops can happen at any time
|
||||||
@ -160,7 +165,7 @@ impl TableStore {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn name_get_or_create(&self, table: &str) -> VeilidAPIResult<String> {
|
fn name_get_or_create(&self, table: &str) -> VeilidAPIResult<String> {
|
||||||
let name = self.namespaced_name(table)?;
|
let name = self.namespaced_name(table)?;
|
||||||
|
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
@ -356,8 +361,7 @@ impl TableStore {
|
|||||||
async fn load_device_encryption_key(&self) -> EyreResult<Option<TypedSharedSecret>> {
|
async fn load_device_encryption_key(&self) -> EyreResult<Option<TypedSharedSecret>> {
|
||||||
let dek_bytes: Option<Vec<u8>> = self
|
let dek_bytes: Option<Vec<u8>> = self
|
||||||
.protected_store()
|
.protected_store()
|
||||||
.load_user_secret("device_encryption_key")
|
.load_user_secret("device_encryption_key")?;
|
||||||
.await?;
|
|
||||||
let Some(dek_bytes) = dek_bytes else {
|
let Some(dek_bytes) = dek_bytes else {
|
||||||
veilid_log!(self debug "no device encryption key");
|
veilid_log!(self debug "no device encryption key");
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
@ -383,8 +387,7 @@ impl TableStore {
|
|||||||
// Remove the device encryption key
|
// Remove the device encryption key
|
||||||
let existed = self
|
let existed = self
|
||||||
.protected_store()
|
.protected_store()
|
||||||
.remove_user_secret("device_encryption_key")
|
.remove_user_secret("device_encryption_key")?;
|
||||||
.await?;
|
|
||||||
veilid_log!(self debug "removed device encryption key. existed: {}", existed);
|
veilid_log!(self debug "removed device encryption key. existed: {}", existed);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
@ -423,8 +426,7 @@ impl TableStore {
|
|||||||
// Save the new device encryption key
|
// Save the new device encryption key
|
||||||
let existed = self
|
let existed = self
|
||||||
.protected_store()
|
.protected_store()
|
||||||
.save_user_secret("device_encryption_key", &dek_bytes)
|
.save_user_secret("device_encryption_key", &dek_bytes)?;
|
||||||
.await?;
|
|
||||||
veilid_log!(self debug "saving device encryption key. existed: {}", existed);
|
veilid_log!(self debug "saving device encryption key. existed: {}", existed);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -560,7 +562,7 @@ impl TableStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let table_name = self.name_get_or_create(name).await?;
|
let table_name = self.name_get_or_create(name)?;
|
||||||
|
|
||||||
// See if this table is already opened, if so the column count must be the same
|
// See if this table is already opened, if so the column count must be the same
|
||||||
{
|
{
|
||||||
|
@ -3,6 +3,7 @@ pub use keyvaluedb_sqlite::*;
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
#[must_use]
|
||||||
pub(in crate::table_store) struct TableStoreDriver {
|
pub(in crate::table_store) struct TableStoreDriver {
|
||||||
registry: VeilidComponentRegistry,
|
registry: VeilidComponentRegistry,
|
||||||
}
|
}
|
||||||
@ -31,6 +32,7 @@ impl TableStoreDriver {
|
|||||||
Ok(dbpath)
|
Ok(dbpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
pub async fn open(&self, table_name: &str, column_count: u32) -> VeilidAPIResult<Database> {
|
pub async fn open(&self, table_name: &str, column_count: u32) -> VeilidAPIResult<Database> {
|
||||||
let dbpath = self.get_dbpath(table_name)?;
|
let dbpath = self.get_dbpath(table_name)?;
|
||||||
|
|
||||||
@ -52,6 +54,7 @@ impl TableStoreDriver {
|
|||||||
Ok(db)
|
Ok(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
pub async fn delete(&self, table_name: &str) -> VeilidAPIResult<bool> {
|
pub async fn delete(&self, table_name: &str) -> VeilidAPIResult<bool> {
|
||||||
let dbpath = self.get_dbpath(table_name)?;
|
let dbpath = self.get_dbpath(table_name)?;
|
||||||
if !dbpath.exists() {
|
if !dbpath.exists() {
|
||||||
|
@ -12,6 +12,7 @@ cfg_if! {
|
|||||||
|
|
||||||
impl_veilid_log_facility!("tstore");
|
impl_veilid_log_facility!("tstore");
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
struct CryptInfo {
|
struct CryptInfo {
|
||||||
typed_key: TypedSharedSecret,
|
typed_key: TypedSharedSecret,
|
||||||
}
|
}
|
||||||
@ -21,6 +22,7 @@ impl CryptInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub struct TableDBUnlockedInner {
|
pub struct TableDBUnlockedInner {
|
||||||
registry: VeilidComponentRegistry,
|
registry: VeilidComponentRegistry,
|
||||||
table: String,
|
table: String,
|
||||||
@ -44,6 +46,7 @@ impl Drop for TableDBUnlockedInner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
#[must_use]
|
||||||
pub struct TableDB {
|
pub struct TableDB {
|
||||||
opened_column_count: u32,
|
opened_column_count: u32,
|
||||||
unlocked_inner: Arc<TableDBUnlockedInner>,
|
unlocked_inner: Arc<TableDBUnlockedInner>,
|
||||||
@ -107,6 +110,7 @@ impl TableDB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the internal name of the table
|
/// Get the internal name of the table
|
||||||
|
#[must_use]
|
||||||
pub fn table_name(&self) -> String {
|
pub fn table_name(&self) -> String {
|
||||||
self.unlocked_inner.table.clone()
|
self.unlocked_inner.table.clone()
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ use super::*;
|
|||||||
pub use keyvaluedb_web::*;
|
pub use keyvaluedb_web::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
#[must_use]
|
||||||
pub(in crate::table_store) struct TableStoreDriver {
|
pub(in crate::table_store) struct TableStoreDriver {
|
||||||
registry: VeilidComponentRegistry,
|
registry: VeilidComponentRegistry,
|
||||||
}
|
}
|
||||||
|
@ -15,73 +15,55 @@ async fn shutdown(api: VeilidAPI) {
|
|||||||
trace!("test_table_store: finished");
|
trace!("test_table_store: finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_protected_store(ps: &ProtectedStore) {
|
pub fn test_protected_store(ps: &ProtectedStore) {
|
||||||
info!("testing protected store");
|
info!("testing protected store");
|
||||||
|
|
||||||
let _ = ps.remove_user_secret("_test_key").await;
|
let _ = ps.remove_user_secret("_test_key");
|
||||||
let _ = ps.remove_user_secret("_test_broken").await;
|
let _ = ps.remove_user_secret("_test_broken");
|
||||||
|
|
||||||
let d1: [u8; 0] = [];
|
let d1: [u8; 0] = [];
|
||||||
|
|
||||||
assert!(!ps
|
assert!(!ps.save_user_secret("_test_key", &[2u8, 3u8, 4u8]).unwrap());
|
||||||
.save_user_secret("_test_key", &[2u8, 3u8, 4u8])
|
|
||||||
.await
|
|
||||||
.unwrap());
|
|
||||||
info!("testing saving user secret");
|
info!("testing saving user secret");
|
||||||
assert!(ps.save_user_secret("_test_key", &d1).await.unwrap());
|
assert!(ps.save_user_secret("_test_key", &d1).unwrap());
|
||||||
info!("testing loading user secret");
|
info!("testing loading user secret");
|
||||||
assert_eq!(
|
assert_eq!(ps.load_user_secret("_test_key").unwrap(), Some(d1.to_vec()));
|
||||||
ps.load_user_secret("_test_key").await.unwrap(),
|
|
||||||
Some(d1.to_vec())
|
|
||||||
);
|
|
||||||
info!("testing loading user secret again");
|
info!("testing loading user secret again");
|
||||||
assert_eq!(
|
assert_eq!(ps.load_user_secret("_test_key").unwrap(), Some(d1.to_vec()));
|
||||||
ps.load_user_secret("_test_key").await.unwrap(),
|
|
||||||
Some(d1.to_vec())
|
|
||||||
);
|
|
||||||
info!("testing loading broken user secret");
|
info!("testing loading broken user secret");
|
||||||
assert_eq!(ps.load_user_secret("_test_broken").await.unwrap(), None);
|
assert_eq!(ps.load_user_secret("_test_broken").unwrap(), None);
|
||||||
info!("testing loading broken user secret again");
|
info!("testing loading broken user secret again");
|
||||||
assert_eq!(ps.load_user_secret("_test_broken").await.unwrap(), None);
|
assert_eq!(ps.load_user_secret("_test_broken").unwrap(), None);
|
||||||
info!("testing remove user secret");
|
info!("testing remove user secret");
|
||||||
assert!(ps.remove_user_secret("_test_key").await.unwrap());
|
assert!(ps.remove_user_secret("_test_key").unwrap());
|
||||||
info!("testing remove user secret again");
|
info!("testing remove user secret again");
|
||||||
assert!(!ps.remove_user_secret("_test_key").await.unwrap());
|
assert!(!ps.remove_user_secret("_test_key").unwrap());
|
||||||
info!("testing remove broken user secret");
|
info!("testing remove broken user secret");
|
||||||
assert!(!ps.remove_user_secret("_test_broken").await.unwrap());
|
assert!(!ps.remove_user_secret("_test_broken").unwrap());
|
||||||
info!("testing remove broken user secret again");
|
info!("testing remove broken user secret again");
|
||||||
assert!(!ps.remove_user_secret("_test_broken").await.unwrap());
|
assert!(!ps.remove_user_secret("_test_broken").unwrap());
|
||||||
|
|
||||||
let d2: [u8; 10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
let d2: [u8; 10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||||
|
|
||||||
assert!(!ps
|
assert!(!ps.save_user_secret("_test_key", &[2u8, 3u8, 4u8]).unwrap());
|
||||||
.save_user_secret("_test_key", &[2u8, 3u8, 4u8])
|
assert!(ps.save_user_secret("_test_key", &d2).unwrap());
|
||||||
.await
|
assert_eq!(ps.load_user_secret("_test_key").unwrap(), Some(d2.to_vec()));
|
||||||
.unwrap());
|
assert_eq!(ps.load_user_secret("_test_key").unwrap(), Some(d2.to_vec()));
|
||||||
assert!(ps.save_user_secret("_test_key", &d2).await.unwrap());
|
assert_eq!(ps.load_user_secret("_test_broken").unwrap(), None);
|
||||||
assert_eq!(
|
assert_eq!(ps.load_user_secret("_test_broken").unwrap(), None);
|
||||||
ps.load_user_secret("_test_key").await.unwrap(),
|
assert!(ps.remove_user_secret("_test_key").unwrap());
|
||||||
Some(d2.to_vec())
|
assert!(!ps.remove_user_secret("_test_key").unwrap());
|
||||||
);
|
assert!(!ps.remove_user_secret("_test_key").unwrap());
|
||||||
assert_eq!(
|
assert!(!ps.remove_user_secret("_test_broken").unwrap());
|
||||||
ps.load_user_secret("_test_key").await.unwrap(),
|
|
||||||
Some(d2.to_vec())
|
|
||||||
);
|
|
||||||
assert_eq!(ps.load_user_secret("_test_broken").await.unwrap(), None);
|
|
||||||
assert_eq!(ps.load_user_secret("_test_broken").await.unwrap(), None);
|
|
||||||
assert!(ps.remove_user_secret("_test_key").await.unwrap());
|
|
||||||
assert!(!ps.remove_user_secret("_test_key").await.unwrap());
|
|
||||||
assert!(!ps.remove_user_secret("_test_key").await.unwrap());
|
|
||||||
assert!(!ps.remove_user_secret("_test_broken").await.unwrap());
|
|
||||||
|
|
||||||
let _ = ps.remove_user_secret("_test_key").await;
|
let _ = ps.remove_user_secret("_test_key");
|
||||||
let _ = ps.remove_user_secret("_test_broken").await;
|
let _ = ps.remove_user_secret("_test_broken");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_all() {
|
pub async fn test_all() {
|
||||||
let api = startup().await;
|
let api = startup().await;
|
||||||
let ps = api.protected_store().unwrap();
|
let ps = api.protected_store().unwrap();
|
||||||
test_protected_store(&ps).await;
|
test_protected_store(&ps);
|
||||||
|
|
||||||
shutdown(api).await;
|
shutdown(api).await;
|
||||||
}
|
}
|
||||||
|
@ -62,25 +62,25 @@ wFAbkZY9eS/x6P7qrpd7dUA=
|
|||||||
cfg_if! {
|
cfg_if! {
|
||||||
|
|
||||||
if #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] {
|
if #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] {
|
||||||
pub fn get_table_store_path() -> String {
|
#[must_use]pub fn get_table_store_path() -> String {
|
||||||
String::new()
|
String::new()
|
||||||
}
|
}
|
||||||
pub fn get_block_store_path() -> String {
|
#[must_use]pub fn get_block_store_path() -> String {
|
||||||
String::new()
|
String::new()
|
||||||
}
|
}
|
||||||
pub fn get_protected_store_path() -> String {
|
#[must_use]pub fn get_protected_store_path() -> String {
|
||||||
String::new()
|
String::new()
|
||||||
}
|
}
|
||||||
pub fn get_certfile_path() -> String {
|
#[must_use]pub fn get_certfile_path() -> String {
|
||||||
String::new()
|
String::new()
|
||||||
}
|
}
|
||||||
pub fn get_keyfile_path() -> String {
|
#[must_use]pub fn get_keyfile_path() -> String {
|
||||||
String::new()
|
String::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
fn get_data_dir() -> PathBuf {
|
#[must_use] fn get_data_dir() -> PathBuf {
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(target_os = "android")] {
|
if #[cfg(target_os = "android")] {
|
||||||
PathBuf::from(crate::intf::android::get_files_dir())
|
PathBuf::from(crate::intf::android::get_files_dir())
|
||||||
@ -96,7 +96,7 @@ cfg_if! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_table_store_path() -> String {
|
#[must_use] pub fn get_table_store_path() -> String {
|
||||||
let mut out = get_data_dir();
|
let mut out = get_data_dir();
|
||||||
std::fs::create_dir_all(&out).unwrap();
|
std::fs::create_dir_all(&out).unwrap();
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ cfg_if! {
|
|||||||
out.into_os_string().into_string().unwrap()
|
out.into_os_string().into_string().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_block_store_path() -> String {
|
#[must_use] pub fn get_block_store_path() -> String {
|
||||||
let mut out = get_data_dir();
|
let mut out = get_data_dir();
|
||||||
std::fs::create_dir_all(&out).unwrap();
|
std::fs::create_dir_all(&out).unwrap();
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ cfg_if! {
|
|||||||
out.into_os_string().into_string().unwrap()
|
out.into_os_string().into_string().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_protected_store_path() -> String {
|
#[must_use] pub fn get_protected_store_path() -> String {
|
||||||
let mut out = get_data_dir();
|
let mut out = get_data_dir();
|
||||||
std::fs::create_dir_all(&out).unwrap();
|
std::fs::create_dir_all(&out).unwrap();
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ cfg_if! {
|
|||||||
out.into_os_string().into_string().unwrap()
|
out.into_os_string().into_string().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_certfile_path() -> String {
|
#[must_use]pub fn get_certfile_path() -> String {
|
||||||
let mut out = get_data_dir();
|
let mut out = get_data_dir();
|
||||||
std::fs::create_dir_all(&out).unwrap();
|
std::fs::create_dir_all(&out).unwrap();
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ cfg_if! {
|
|||||||
out.into_os_string().into_string().unwrap()
|
out.into_os_string().into_string().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_keyfile_path() -> String {
|
#[must_use]pub fn get_keyfile_path() -> String {
|
||||||
let mut out = get_data_dir();
|
let mut out = get_data_dir();
|
||||||
std::fs::create_dir_all(&out).unwrap();
|
std::fs::create_dir_all(&out).unwrap();
|
||||||
|
|
||||||
@ -307,7 +307,7 @@ pub fn get_config() -> VeilidConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_config() {
|
pub fn test_config() {
|
||||||
let vc = get_config();
|
let vc = get_config();
|
||||||
|
|
||||||
let inner = vc.get();
|
let inner = vc.get();
|
||||||
@ -426,6 +426,7 @@ pub async fn test_config() {
|
|||||||
assert_eq!(inner.network.virtual_network.server_address, "");
|
assert_eq!(inner.network.virtual_network.server_address, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
pub async fn test_all() {
|
pub async fn test_all() {
|
||||||
test_config().await;
|
test_config();
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ impl Drop for VeilidAPIInner {
|
|||||||
/// * Create and import private routes.
|
/// * Create and import private routes.
|
||||||
/// * Reply to `AppCall` RPCs.
|
/// * Reply to `AppCall` RPCs.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidAPI {
|
pub struct VeilidAPI {
|
||||||
inner: Arc<Mutex<VeilidAPIInner>>,
|
inner: Arc<Mutex<VeilidAPIInner>>,
|
||||||
}
|
}
|
||||||
@ -69,6 +70,7 @@ impl VeilidAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Check to see if Veilid is already shut down.
|
/// Check to see if Veilid is already shut down.
|
||||||
|
#[must_use]
|
||||||
pub fn is_shutdown(&self) -> bool {
|
pub fn is_shutdown(&self) -> bool {
|
||||||
self.inner.lock().context.is_none()
|
self.inner.lock().context.is_none()
|
||||||
}
|
}
|
||||||
@ -154,6 +156,7 @@ impl VeilidAPI {
|
|||||||
// Attach/Detach
|
// Attach/Detach
|
||||||
|
|
||||||
/// Get a full copy of the current state of Veilid.
|
/// Get a full copy of the current state of Veilid.
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
pub async fn get_state(&self) -> VeilidAPIResult<VeilidState> {
|
pub async fn get_state(&self) -> VeilidAPIResult<VeilidState> {
|
||||||
let attachment_manager = self.core_context()?.attachment_manager();
|
let attachment_manager = self.core_context()?.attachment_manager();
|
||||||
let network_manager = attachment_manager.network_manager();
|
let network_manager = attachment_manager.network_manager();
|
||||||
@ -177,7 +180,7 @@ impl VeilidAPI {
|
|||||||
"VeilidAPI::attach()");
|
"VeilidAPI::attach()");
|
||||||
|
|
||||||
let attachment_manager = self.core_context()?.attachment_manager();
|
let attachment_manager = self.core_context()?.attachment_manager();
|
||||||
if !attachment_manager.attach().await {
|
if !Box::pin(attachment_manager.attach()).await {
|
||||||
apibail_generic!("Already attached");
|
apibail_generic!("Already attached");
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -190,7 +193,7 @@ impl VeilidAPI {
|
|||||||
"VeilidAPI::detach()");
|
"VeilidAPI::detach()");
|
||||||
|
|
||||||
let attachment_manager = self.core_context()?.attachment_manager();
|
let attachment_manager = self.core_context()?.attachment_manager();
|
||||||
if !attachment_manager.detach().await {
|
if !Box::pin(attachment_manager.detach()).await {
|
||||||
apibail_generic!("Already detached");
|
apibail_generic!("Already detached");
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -253,11 +256,11 @@ impl VeilidAPI {
|
|||||||
/// imported by another Veilid node.
|
/// imported by another Veilid node.
|
||||||
//#[instrument(target = "veilid_api", level = "debug", skip(self), ret, err)]
|
//#[instrument(target = "veilid_api", level = "debug", skip(self), ret, err)]
|
||||||
pub async fn new_private_route(&self) -> VeilidAPIResult<(RouteId, Vec<u8>)> {
|
pub async fn new_private_route(&self) -> VeilidAPIResult<(RouteId, Vec<u8>)> {
|
||||||
self.new_custom_private_route(
|
Box::pin(self.new_custom_private_route(
|
||||||
&VALID_CRYPTO_KINDS,
|
&VALID_CRYPTO_KINDS,
|
||||||
Stability::Reliable,
|
Stability::Reliable,
|
||||||
Sequencing::PreferOrdered,
|
Sequencing::PreferOrdered,
|
||||||
)
|
))
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +306,7 @@ impl VeilidAPI {
|
|||||||
let rss = routing_table.route_spec_store();
|
let rss = routing_table.route_spec_store();
|
||||||
let route_id =
|
let route_id =
|
||||||
rss.allocate_route(crypto_kinds, &safety_spec, DirectionSet::all(), &[], false)?;
|
rss.allocate_route(crypto_kinds, &safety_spec, DirectionSet::all(), &[], false)?;
|
||||||
match rss.test_route(route_id).await? {
|
match Box::pin(rss.test_route(route_id)).await? {
|
||||||
Some(true) => {
|
Some(true) => {
|
||||||
// route tested okay
|
// route tested okay
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ pub(crate) struct DebugCache {
|
|||||||
pub opened_record_contexts: Lazy<LinkedHashMap<TypedKey, RoutingContext>>,
|
pub opened_record_contexts: Lazy<LinkedHashMap<TypedKey, RoutingContext>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn format_opt_ts(ts: Option<TimestampDuration>) -> String {
|
pub fn format_opt_ts(ts: Option<TimestampDuration>) -> String {
|
||||||
let Some(ts) = ts else {
|
let Some(ts) = ts else {
|
||||||
return "---".to_owned();
|
return "---".to_owned();
|
||||||
@ -30,6 +31,7 @@ pub fn format_opt_ts(ts: Option<TimestampDuration>) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn format_opt_bps(bps: Option<ByteCount>) -> String {
|
pub fn format_opt_bps(bps: Option<ByteCount>) -> String {
|
||||||
let Some(bps) = bps else {
|
let Some(bps) = bps else {
|
||||||
return "---".to_owned();
|
return "---".to_owned();
|
||||||
@ -288,7 +290,7 @@ fn get_dht_key(
|
|||||||
fn resolve_node_ref(
|
fn resolve_node_ref(
|
||||||
registry: VeilidComponentRegistry,
|
registry: VeilidComponentRegistry,
|
||||||
safety_selection: SafetySelection,
|
safety_selection: SafetySelection,
|
||||||
) -> impl FnOnce(&str) -> SendPinBoxFuture<Option<NodeRef>> {
|
) -> impl FnOnce(&str) -> PinBoxFutureStatic<Option<NodeRef>> {
|
||||||
move |text| {
|
move |text| {
|
||||||
let text = text.to_owned();
|
let text = text.to_owned();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
@ -318,7 +320,7 @@ fn resolve_node_ref(
|
|||||||
fn resolve_filtered_node_ref(
|
fn resolve_filtered_node_ref(
|
||||||
registry: VeilidComponentRegistry,
|
registry: VeilidComponentRegistry,
|
||||||
safety_selection: SafetySelection,
|
safety_selection: SafetySelection,
|
||||||
) -> impl FnOnce(&str) -> SendPinBoxFuture<Option<FilteredNodeRef>> {
|
) -> impl FnOnce(&str) -> PinBoxFutureStatic<Option<FilteredNodeRef>> {
|
||||||
move |text| {
|
move |text| {
|
||||||
let text = text.to_owned();
|
let text = text.to_owned();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
@ -503,7 +505,7 @@ fn get_debug_argument<T, G: FnOnce(&str) -> Option<T>>(
|
|||||||
Ok(val)
|
Ok(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn async_get_debug_argument<T, G: FnOnce(&str) -> SendPinBoxFuture<Option<T>>>(
|
async fn async_get_debug_argument<T, G: FnOnce(&str) -> PinBoxFutureStatic<Option<T>>>(
|
||||||
value: &str,
|
value: &str,
|
||||||
context: &str,
|
context: &str,
|
||||||
argument: &str,
|
argument: &str,
|
||||||
@ -532,7 +534,7 @@ fn get_debug_argument_at<T, G: FnOnce(&str) -> Option<T>>(
|
|||||||
Ok(val)
|
Ok(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn async_get_debug_argument_at<T, G: FnOnce(&str) -> SendPinBoxFuture<Option<T>>>(
|
async fn async_get_debug_argument_at<T, G: FnOnce(&str) -> PinBoxFutureStatic<Option<T>>>(
|
||||||
debug_args: &[String],
|
debug_args: &[String],
|
||||||
pos: usize,
|
pos: usize,
|
||||||
context: &str,
|
context: &str,
|
||||||
@ -549,6 +551,7 @@ async fn async_get_debug_argument_at<T, G: FnOnce(&str) -> SendPinBoxFuture<Opti
|
|||||||
Ok(val)
|
Ok(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn print_data(data: &[u8], truncate_len: Option<usize>) -> String {
|
pub fn print_data(data: &[u8], truncate_len: Option<usize>) -> String {
|
||||||
// check if message body is ascii printable
|
// check if message body is ascii printable
|
||||||
let mut printable = true;
|
let mut printable = true;
|
||||||
@ -588,7 +591,7 @@ pub fn print_data(data: &[u8], truncate_len: Option<usize>) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl VeilidAPI {
|
impl VeilidAPI {
|
||||||
async fn debug_buckets(&self, args: String) -> VeilidAPIResult<String> {
|
fn debug_buckets(&self, args: String) -> VeilidAPIResult<String> {
|
||||||
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
||||||
let mut min_state = BucketEntryState::Unreliable;
|
let mut min_state = BucketEntryState::Unreliable;
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
@ -604,12 +607,12 @@ impl VeilidAPI {
|
|||||||
Ok(routing_table.debug_info_buckets(min_state))
|
Ok(routing_table.debug_info_buckets(min_state))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn debug_dialinfo(&self, _args: String) -> VeilidAPIResult<String> {
|
fn debug_dialinfo(&self, _args: String) -> VeilidAPIResult<String> {
|
||||||
// Dump routing table dialinfo
|
// Dump routing table dialinfo
|
||||||
let routing_table = self.core_context()?.routing_table();
|
let routing_table = self.core_context()?.routing_table();
|
||||||
Ok(routing_table.debug_info_dialinfo())
|
Ok(routing_table.debug_info_dialinfo())
|
||||||
}
|
}
|
||||||
async fn debug_peerinfo(&self, args: String) -> VeilidAPIResult<String> {
|
fn debug_peerinfo(&self, args: String) -> VeilidAPIResult<String> {
|
||||||
// Dump routing table peerinfo
|
// Dump routing table peerinfo
|
||||||
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
||||||
let routing_table = self.core_context()?.routing_table();
|
let routing_table = self.core_context()?.routing_table();
|
||||||
@ -647,7 +650,7 @@ impl VeilidAPI {
|
|||||||
Ok(routing_table.debug_info_txtrecord().await)
|
Ok(routing_table.debug_info_txtrecord().await)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn debug_keypair(&self, args: String) -> VeilidAPIResult<String> {
|
fn debug_keypair(&self, args: String) -> VeilidAPIResult<String> {
|
||||||
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
||||||
let crypto = self.crypto()?;
|
let crypto = self.crypto()?;
|
||||||
|
|
||||||
@ -665,7 +668,7 @@ impl VeilidAPI {
|
|||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn debug_entries(&self, args: String) -> VeilidAPIResult<String> {
|
fn debug_entries(&self, args: String) -> VeilidAPIResult<String> {
|
||||||
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
||||||
|
|
||||||
let mut min_state = BucketEntryState::Unreliable;
|
let mut min_state = BucketEntryState::Unreliable;
|
||||||
@ -695,7 +698,7 @@ impl VeilidAPI {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn debug_entry(&self, args: String) -> VeilidAPIResult<String> {
|
fn debug_entry(&self, args: String) -> VeilidAPIResult<String> {
|
||||||
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
||||||
let registry = self.core_context()?.registry();
|
let registry = self.core_context()?.registry();
|
||||||
|
|
||||||
@ -782,7 +785,7 @@ impl VeilidAPI {
|
|||||||
// Dump connection table
|
// Dump connection table
|
||||||
let connman =
|
let connman =
|
||||||
if let Some(connection_manager) = registry.network_manager().opt_connection_manager() {
|
if let Some(connection_manager) = registry.network_manager().opt_connection_manager() {
|
||||||
connection_manager.debug_print().await
|
connection_manager.debug_print()
|
||||||
} else {
|
} else {
|
||||||
"Connection manager unavailable when detached".to_owned()
|
"Connection manager unavailable when detached".to_owned()
|
||||||
};
|
};
|
||||||
@ -790,7 +793,7 @@ impl VeilidAPI {
|
|||||||
Ok(format!("{}\n{}\n{}\n", nodeinfo, peertable, connman))
|
Ok(format!("{}\n{}\n{}\n", nodeinfo, peertable, connman))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn debug_nodeid(&self, _args: String) -> VeilidAPIResult<String> {
|
fn debug_nodeid(&self, _args: String) -> VeilidAPIResult<String> {
|
||||||
// Dump routing table entry
|
// Dump routing table entry
|
||||||
let registry = self.core_context()?.registry();
|
let registry = self.core_context()?.registry();
|
||||||
let nodeid = registry.routing_table().debug_info_nodeid();
|
let nodeid = registry.routing_table().debug_info_nodeid();
|
||||||
@ -833,15 +836,15 @@ impl VeilidAPI {
|
|||||||
Ok("Config value set".to_owned())
|
Ok("Config value set".to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn debug_restart(&self, args: String) -> VeilidAPIResult<String> {
|
async fn debug_network(&self, args: String) -> VeilidAPIResult<String> {
|
||||||
let args = args.trim_start();
|
let args = args.trim_start();
|
||||||
if args.is_empty() {
|
if args.is_empty() {
|
||||||
apibail_missing_argument!("debug_restart", "arg_0");
|
apibail_missing_argument!("debug_network", "arg_0");
|
||||||
}
|
}
|
||||||
let (arg, _rest) = args.split_once(' ').unwrap_or((args, ""));
|
let (arg, _rest) = args.split_once(' ').unwrap_or((args, ""));
|
||||||
// let rest = rest.trim_start().to_owned();
|
// let rest = rest.trim_start().to_owned();
|
||||||
|
|
||||||
if arg == "network" {
|
if arg == "restart" {
|
||||||
// Must be attached
|
// Must be attached
|
||||||
if matches!(
|
if matches!(
|
||||||
self.get_state().await?.attachment.state,
|
self.get_state().await?.attachment.state,
|
||||||
@ -854,6 +857,11 @@ impl VeilidAPI {
|
|||||||
registry.network_manager().restart_network();
|
registry.network_manager().restart_network();
|
||||||
|
|
||||||
Ok("Network restarted".to_owned())
|
Ok("Network restarted".to_owned())
|
||||||
|
} else if arg == "stats" {
|
||||||
|
let registry = self.core_context()?.registry();
|
||||||
|
let debug_stats = registry.network_manager().debug();
|
||||||
|
|
||||||
|
Ok(debug_stats)
|
||||||
} else {
|
} else {
|
||||||
apibail_invalid_argument!("debug_restart", "arg_1", arg);
|
apibail_invalid_argument!("debug_restart", "arg_1", arg);
|
||||||
}
|
}
|
||||||
@ -888,7 +896,6 @@ impl VeilidAPI {
|
|||||||
if let Some(connection_manager) = &opt_connection_manager {
|
if let Some(connection_manager) = &opt_connection_manager {
|
||||||
connection_manager
|
connection_manager
|
||||||
.startup()
|
.startup()
|
||||||
.await
|
|
||||||
.map_err(VeilidAPIError::internal)?;
|
.map_err(VeilidAPIError::internal)?;
|
||||||
}
|
}
|
||||||
Ok("Connections purged".to_owned())
|
Ok("Connections purged".to_owned())
|
||||||
@ -942,7 +949,7 @@ impl VeilidAPI {
|
|||||||
Ok("Detached".to_owned())
|
Ok("Detached".to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn debug_contact(&self, args: String) -> VeilidAPIResult<String> {
|
fn debug_contact(&self, args: String) -> VeilidAPIResult<String> {
|
||||||
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
||||||
|
|
||||||
let registry = self.core_context()?.registry();
|
let registry = self.core_context()?.registry();
|
||||||
@ -1153,7 +1160,7 @@ impl VeilidAPI {
|
|||||||
Ok(format!("Replied with {} bytes", data_len))
|
Ok(format!("Replied with {} bytes", data_len))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn debug_route_allocate(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
fn debug_route_allocate(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
||||||
// [ord|*ord] [rel] [<count>] [in|out] [avoid_node_id]
|
// [ord|*ord] [rel] [<count>] [in|out] [avoid_node_id]
|
||||||
|
|
||||||
let registry = self.core_context()?.registry();
|
let registry = self.core_context()?.registry();
|
||||||
@ -1212,7 +1219,7 @@ impl VeilidAPI {
|
|||||||
|
|
||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
async fn debug_route_release(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
fn debug_route_release(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
||||||
// <route id>
|
// <route id>
|
||||||
let registry = self.core_context()?.registry();
|
let registry = self.core_context()?.registry();
|
||||||
let routing_table = registry.routing_table();
|
let routing_table = registry.routing_table();
|
||||||
@ -1233,7 +1240,7 @@ impl VeilidAPI {
|
|||||||
self.with_debug_cache(|dc| {
|
self.with_debug_cache(|dc| {
|
||||||
for (n, ir) in dc.imported_routes.iter().enumerate() {
|
for (n, ir) in dc.imported_routes.iter().enumerate() {
|
||||||
if *ir == route_id {
|
if *ir == route_id {
|
||||||
dc.imported_routes.remove(n);
|
let _ = dc.imported_routes.remove(n);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1245,7 +1252,7 @@ impl VeilidAPI {
|
|||||||
|
|
||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
async fn debug_route_publish(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
fn debug_route_publish(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
||||||
// <route id> [full]
|
// <route id> [full]
|
||||||
let registry = self.core_context()?.registry();
|
let registry = self.core_context()?.registry();
|
||||||
let routing_table = registry.routing_table();
|
let routing_table = registry.routing_table();
|
||||||
@ -1297,7 +1304,7 @@ impl VeilidAPI {
|
|||||||
|
|
||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
async fn debug_route_unpublish(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
fn debug_route_unpublish(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
||||||
// <route id>
|
// <route id>
|
||||||
let registry = self.core_context()?.registry();
|
let registry = self.core_context()?.registry();
|
||||||
let routing_table = registry.routing_table();
|
let routing_table = registry.routing_table();
|
||||||
@ -1319,7 +1326,7 @@ impl VeilidAPI {
|
|||||||
};
|
};
|
||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
async fn debug_route_print(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
fn debug_route_print(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
||||||
// <route id>
|
// <route id>
|
||||||
let registry = self.core_context()?.registry();
|
let registry = self.core_context()?.registry();
|
||||||
let routing_table = registry.routing_table();
|
let routing_table = registry.routing_table();
|
||||||
@ -1338,7 +1345,7 @@ impl VeilidAPI {
|
|||||||
None => Ok("Route does not exist".to_owned()),
|
None => Ok("Route does not exist".to_owned()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async fn debug_route_list(&self, _args: Vec<String>) -> VeilidAPIResult<String> {
|
fn debug_route_list(&self, _args: Vec<String>) -> VeilidAPIResult<String> {
|
||||||
//
|
//
|
||||||
let registry = self.core_context()?.registry();
|
let registry = self.core_context()?.registry();
|
||||||
let routing_table = registry.routing_table();
|
let routing_table = registry.routing_table();
|
||||||
@ -1361,7 +1368,7 @@ impl VeilidAPI {
|
|||||||
|
|
||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
async fn debug_route_import(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
fn debug_route_import(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
||||||
// <blob>
|
// <blob>
|
||||||
let registry = self.core_context()?.registry();
|
let registry = self.core_context()?.registry();
|
||||||
let routing_table = registry.routing_table();
|
let routing_table = registry.routing_table();
|
||||||
@ -1420,19 +1427,19 @@ impl VeilidAPI {
|
|||||||
let command = get_debug_argument_at(&args, 0, "debug_route", "command", get_string)?;
|
let command = get_debug_argument_at(&args, 0, "debug_route", "command", get_string)?;
|
||||||
|
|
||||||
if command == "allocate" {
|
if command == "allocate" {
|
||||||
self.debug_route_allocate(args).await
|
self.debug_route_allocate(args)
|
||||||
} else if command == "release" {
|
} else if command == "release" {
|
||||||
self.debug_route_release(args).await
|
self.debug_route_release(args)
|
||||||
} else if command == "publish" {
|
} else if command == "publish" {
|
||||||
self.debug_route_publish(args).await
|
self.debug_route_publish(args)
|
||||||
} else if command == "unpublish" {
|
} else if command == "unpublish" {
|
||||||
self.debug_route_unpublish(args).await
|
self.debug_route_unpublish(args)
|
||||||
} else if command == "print" {
|
} else if command == "print" {
|
||||||
self.debug_route_print(args).await
|
self.debug_route_print(args)
|
||||||
} else if command == "list" {
|
} else if command == "list" {
|
||||||
self.debug_route_list(args).await
|
self.debug_route_list(args)
|
||||||
} else if command == "import" {
|
} else if command == "import" {
|
||||||
self.debug_route_import(args).await
|
self.debug_route_import(args)
|
||||||
} else if command == "test" {
|
} else if command == "test" {
|
||||||
self.debug_route_test(args).await
|
self.debug_route_test(args).await
|
||||||
} else {
|
} else {
|
||||||
@ -1953,7 +1960,7 @@ impl VeilidAPI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn debug_table_list(&self, _args: Vec<String>) -> VeilidAPIResult<String> {
|
fn debug_table_list(&self, _args: Vec<String>) -> VeilidAPIResult<String> {
|
||||||
//
|
//
|
||||||
let table_store = self.table_store()?;
|
let table_store = self.table_store()?;
|
||||||
let table_names = table_store.list_all();
|
let table_names = table_store.list_all();
|
||||||
@ -2012,7 +2019,7 @@ impl VeilidAPI {
|
|||||||
let command = get_debug_argument_at(&args, 0, "debug_table", "command", get_string)?;
|
let command = get_debug_argument_at(&args, 0, "debug_table", "command", get_string)?;
|
||||||
|
|
||||||
if command == "list" {
|
if command == "list" {
|
||||||
self.debug_table_list(args).await
|
self.debug_table_list(args)
|
||||||
} else if command == "info" {
|
} else if command == "info" {
|
||||||
self.debug_table_info(args).await
|
self.debug_table_info(args).await
|
||||||
} else {
|
} else {
|
||||||
@ -2020,7 +2027,7 @@ impl VeilidAPI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn debug_punish_list(&self, _args: Vec<String>) -> VeilidAPIResult<String> {
|
fn debug_punish_list(&self, _args: Vec<String>) -> VeilidAPIResult<String> {
|
||||||
//
|
//
|
||||||
let registry = self.core_context()?.registry();
|
let registry = self.core_context()?.registry();
|
||||||
let network_manager = registry.network_manager();
|
let network_manager = registry.network_manager();
|
||||||
@ -2030,7 +2037,7 @@ impl VeilidAPI {
|
|||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn debug_punish_clear(&self, _args: Vec<String>) -> VeilidAPIResult<String> {
|
fn debug_punish_clear(&self, _args: Vec<String>) -> VeilidAPIResult<String> {
|
||||||
//
|
//
|
||||||
let registry = self.core_context()?.registry();
|
let registry = self.core_context()?.registry();
|
||||||
let network_manager = registry.network_manager();
|
let network_manager = registry.network_manager();
|
||||||
@ -2041,23 +2048,23 @@ impl VeilidAPI {
|
|||||||
Ok("Address Filter punishments cleared\n".to_owned())
|
Ok("Address Filter punishments cleared\n".to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn debug_punish(&self, args: String) -> VeilidAPIResult<String> {
|
fn debug_punish(&self, args: String) -> VeilidAPIResult<String> {
|
||||||
let args: Vec<String> =
|
let args: Vec<String> =
|
||||||
shell_words::split(&args).map_err(|e| VeilidAPIError::parse_error(e, args))?;
|
shell_words::split(&args).map_err(|e| VeilidAPIError::parse_error(e, args))?;
|
||||||
|
|
||||||
let command = get_debug_argument_at(&args, 0, "debug_punish", "command", get_string)?;
|
let command = get_debug_argument_at(&args, 0, "debug_punish", "command", get_string)?;
|
||||||
|
|
||||||
if command == "list" {
|
if command == "list" {
|
||||||
self.debug_punish_list(args).await
|
self.debug_punish_list(args)
|
||||||
} else if command == "clear" {
|
} else if command == "clear" {
|
||||||
self.debug_punish_clear(args).await
|
self.debug_punish_clear(args)
|
||||||
} else {
|
} else {
|
||||||
Ok(">>> Unknown command\n".to_owned())
|
Ok(">>> Unknown command\n".to_owned())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the help text for 'internal debug' commands.
|
/// Get the help text for 'internal debug' commands.
|
||||||
pub async fn debug_help(&self, _args: String) -> VeilidAPIResult<String> {
|
pub fn debug_help(&self, _args: String) -> VeilidAPIResult<String> {
|
||||||
Ok(r#"Node Information:
|
Ok(r#"Node Information:
|
||||||
nodeid - display a node's id(s)
|
nodeid - display a node's id(s)
|
||||||
nodeinfo - display detailed information about this node
|
nodeinfo - display detailed information about this node
|
||||||
@ -2089,9 +2096,12 @@ Utilities:
|
|||||||
txtrecord - Generate a TXT record for making this node into a bootstrap node capable of DNS bootstrap
|
txtrecord - Generate a TXT record for making this node into a bootstrap node capable of DNS bootstrap
|
||||||
keypair [cryptokind] - Generate and display a random public/private keypair
|
keypair [cryptokind] - Generate and display a random public/private keypair
|
||||||
purge <buckets|connections|routes> - Throw away the node's routing table, connections, or routes
|
purge <buckets|connections|routes> - Throw away the node's routing table, connections, or routes
|
||||||
|
|
||||||
|
Network:
|
||||||
attach - Attach the node to the network if it is detached
|
attach - Attach the node to the network if it is detached
|
||||||
detach - Detach the node from the network if it is attached
|
detach - Detach the node from the network if it is attached
|
||||||
restart network - Restart the low level network
|
network restart - Restart the low level network
|
||||||
|
stats - Print network manager statistics
|
||||||
|
|
||||||
RPC Operations:
|
RPC Operations:
|
||||||
ping <destination> - Send a 'Status' RPC question to a destination node and display the returned ping status
|
ping <destination> - Send a 'Status' RPC question to a destination node and display the returned ping status
|
||||||
@ -2177,67 +2187,70 @@ TableDB Operations:
|
|||||||
let args = args.trim_start();
|
let args = args.trim_start();
|
||||||
if args.is_empty() {
|
if args.is_empty() {
|
||||||
// No arguments runs help command
|
// No arguments runs help command
|
||||||
return self.debug_help("".to_owned()).await;
|
return self.debug_help("".to_owned());
|
||||||
}
|
}
|
||||||
let (arg, rest) = args.split_once(' ').unwrap_or((args, ""));
|
let (arg, rest) = args.split_once(' ').unwrap_or((args, ""));
|
||||||
let rest = rest.trim_start().to_owned();
|
let rest = rest.trim_start().to_owned();
|
||||||
|
|
||||||
if arg == "help" {
|
if arg == "help" {
|
||||||
self.debug_help(rest).await
|
self.debug_help(rest)
|
||||||
} else if arg == "nodeid" {
|
} else if arg == "nodeid" {
|
||||||
self.debug_nodeid(rest).await
|
self.debug_nodeid(rest)
|
||||||
} else if arg == "buckets" {
|
} else if arg == "buckets" {
|
||||||
self.debug_buckets(rest).await
|
self.debug_buckets(rest)
|
||||||
} else if arg == "dialinfo" {
|
} else if arg == "dialinfo" {
|
||||||
self.debug_dialinfo(rest).await
|
self.debug_dialinfo(rest)
|
||||||
} else if arg == "peerinfo" {
|
} else if arg == "peerinfo" {
|
||||||
self.debug_peerinfo(rest).await
|
self.debug_peerinfo(rest)
|
||||||
} else if arg == "txtrecord" {
|
|
||||||
self.debug_txtrecord(rest).await
|
|
||||||
} else if arg == "keypair" {
|
|
||||||
self.debug_keypair(rest).await
|
|
||||||
} else if arg == "entries" {
|
|
||||||
self.debug_entries(rest).await
|
|
||||||
} else if arg == "entry" {
|
|
||||||
self.debug_entry(rest).await
|
|
||||||
} else if arg == "relay" {
|
|
||||||
self.debug_relay(rest).await
|
|
||||||
} else if arg == "ping" {
|
|
||||||
self.debug_ping(rest).await
|
|
||||||
} else if arg == "appmessage" {
|
|
||||||
self.debug_app_message(rest).await
|
|
||||||
} else if arg == "appcall" {
|
|
||||||
self.debug_app_call(rest).await
|
|
||||||
} else if arg == "appreply" {
|
|
||||||
self.debug_app_reply(rest).await
|
|
||||||
} else if arg == "resolve" {
|
|
||||||
self.debug_resolve(rest).await
|
|
||||||
} else if arg == "contact" {
|
} else if arg == "contact" {
|
||||||
self.debug_contact(rest).await
|
self.debug_contact(rest)
|
||||||
} else if arg == "nodeinfo" {
|
} else if arg == "keypair" {
|
||||||
self.debug_nodeinfo(rest).await
|
self.debug_keypair(rest)
|
||||||
} else if arg == "purge" {
|
} else if arg == "entries" {
|
||||||
self.debug_purge(rest).await
|
self.debug_entries(rest)
|
||||||
} else if arg == "attach" {
|
} else if arg == "entry" {
|
||||||
self.debug_attach(rest).await
|
self.debug_entry(rest)
|
||||||
} else if arg == "detach" {
|
|
||||||
self.debug_detach(rest).await
|
|
||||||
} else if arg == "config" {
|
|
||||||
self.debug_config(rest).await
|
|
||||||
} else if arg == "restart" {
|
|
||||||
self.debug_restart(rest).await
|
|
||||||
} else if arg == "route" {
|
|
||||||
self.debug_route(rest).await
|
|
||||||
} else if arg == "record" {
|
|
||||||
self.debug_record(rest).await
|
|
||||||
} else if arg == "punish" {
|
} else if arg == "punish" {
|
||||||
self.debug_punish(rest).await
|
self.debug_punish(rest)
|
||||||
} else if arg == "table" {
|
|
||||||
self.debug_table(rest).await
|
|
||||||
} else if arg == "uptime" {
|
|
||||||
self.debug_uptime(rest).await
|
|
||||||
} else {
|
} else {
|
||||||
Err(VeilidAPIError::generic("Unknown debug command"))
|
let fut = if arg == "txtrecord" {
|
||||||
|
pin_dyn_future!(self.debug_txtrecord(rest))
|
||||||
|
} else if arg == "relay" {
|
||||||
|
pin_dyn_future!(self.debug_relay(rest))
|
||||||
|
} else if arg == "ping" {
|
||||||
|
pin_dyn_future!(self.debug_ping(rest))
|
||||||
|
} else if arg == "appmessage" {
|
||||||
|
pin_dyn_future!(self.debug_app_message(rest))
|
||||||
|
} else if arg == "appcall" {
|
||||||
|
pin_dyn_future!(self.debug_app_call(rest))
|
||||||
|
} else if arg == "appreply" {
|
||||||
|
pin_dyn_future!(self.debug_app_reply(rest))
|
||||||
|
} else if arg == "resolve" {
|
||||||
|
pin_dyn_future!(self.debug_resolve(rest))
|
||||||
|
} else if arg == "nodeinfo" {
|
||||||
|
pin_dyn_future!(self.debug_nodeinfo(rest))
|
||||||
|
} else if arg == "purge" {
|
||||||
|
pin_dyn_future!(self.debug_purge(rest))
|
||||||
|
} else if arg == "attach" {
|
||||||
|
pin_dyn_future!(self.debug_attach(rest))
|
||||||
|
} else if arg == "detach" {
|
||||||
|
pin_dyn_future!(self.debug_detach(rest))
|
||||||
|
} else if arg == "config" {
|
||||||
|
pin_dyn_future!(self.debug_config(rest))
|
||||||
|
} else if arg == "network" {
|
||||||
|
pin_dyn_future!(self.debug_network(rest))
|
||||||
|
} else if arg == "route" {
|
||||||
|
pin_dyn_future!(self.debug_route(rest))
|
||||||
|
} else if arg == "record" {
|
||||||
|
pin_dyn_future!(self.debug_record(rest))
|
||||||
|
} else if arg == "table" {
|
||||||
|
pin_dyn_future!(self.debug_table(rest))
|
||||||
|
} else if arg == "uptime" {
|
||||||
|
pin_dyn_future!(self.debug_uptime(rest))
|
||||||
|
} else {
|
||||||
|
return Err(VeilidAPIError::generic("Unknown debug command"));
|
||||||
|
};
|
||||||
|
fut.await
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
res
|
res
|
||||||
@ -2246,7 +2259,7 @@ TableDB Operations:
|
|||||||
fn get_destination(
|
fn get_destination(
|
||||||
self,
|
self,
|
||||||
registry: VeilidComponentRegistry,
|
registry: VeilidComponentRegistry,
|
||||||
) -> impl FnOnce(&str) -> SendPinBoxFuture<Option<Destination>> {
|
) -> impl FnOnce(&str) -> PinBoxFutureStatic<Option<Destination>> {
|
||||||
move |text| {
|
move |text| {
|
||||||
let text = text.to_owned();
|
let text = text.to_owned();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
@ -2278,7 +2291,7 @@ TableDB Operations:
|
|||||||
let prid = *dc.imported_routes.get(n)?;
|
let prid = *dc.imported_routes.get(n)?;
|
||||||
let Some(private_route) = rss.best_remote_private_route(&prid) else {
|
let Some(private_route) = rss.best_remote_private_route(&prid) else {
|
||||||
// Remove imported route
|
// Remove imported route
|
||||||
dc.imported_routes.remove(n);
|
let _ = dc.imported_routes.remove(n);
|
||||||
veilid_log!(registry info "removed dead imported route {}", n);
|
veilid_log!(registry info "removed dead imported route {}", n);
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
@ -113,6 +113,7 @@ macro_rules! apibail_already_initialized {
|
|||||||
tsify(into_wasm_abi)
|
tsify(into_wasm_abi)
|
||||||
)]
|
)]
|
||||||
#[serde(tag = "kind")]
|
#[serde(tag = "kind")]
|
||||||
|
#[must_use]
|
||||||
pub enum VeilidAPIError {
|
pub enum VeilidAPIError {
|
||||||
#[error("Not initialized")]
|
#[error("Not initialized")]
|
||||||
NotInitialized,
|
NotInitialized,
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use futures_util::FutureExt;
|
|
||||||
|
|
||||||
pub fn to_json_api_result<T: Clone + fmt::Debug + JsonSchema>(
|
pub fn to_json_api_result<T: Clone + fmt::Debug + JsonSchema>(
|
||||||
r: VeilidAPIResult<T>,
|
r: VeilidAPIResult<T>,
|
||||||
@ -37,6 +36,7 @@ pub fn to_json_api_result_with_opt_vec_string<T: Clone + fmt::Debug>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn to_json_api_result_with_vec_u8(r: VeilidAPIResult<Vec<u8>>) -> json_api::ApiResultWithVecU8 {
|
pub fn to_json_api_result_with_vec_u8(r: VeilidAPIResult<Vec<u8>>) -> json_api::ApiResultWithVecU8 {
|
||||||
match r {
|
match r {
|
||||||
Err(e) => json_api::ApiResultWithVecU8::Err { error: e },
|
Err(e) => json_api::ApiResultWithVecU8::Err { error: e },
|
||||||
@ -44,6 +44,7 @@ pub fn to_json_api_result_with_vec_u8(r: VeilidAPIResult<Vec<u8>>) -> json_api::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn to_json_api_result_with_vec_vec_u8(
|
pub fn to_json_api_result_with_vec_vec_u8(
|
||||||
r: VeilidAPIResult<Vec<Vec<u8>>>,
|
r: VeilidAPIResult<Vec<Vec<u8>>>,
|
||||||
) -> json_api::ApiResultWithVecVecU8 {
|
) -> json_api::ApiResultWithVecVecU8 {
|
||||||
@ -69,6 +70,7 @@ pub struct JsonRequestProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl JsonRequestProcessor {
|
impl JsonRequestProcessor {
|
||||||
|
#[must_use]
|
||||||
pub fn new(api: VeilidAPI) -> Self {
|
pub fn new(api: VeilidAPI) -> Self {
|
||||||
Self {
|
Self {
|
||||||
api,
|
api,
|
||||||
@ -212,7 +214,7 @@ impl JsonRequestProcessor {
|
|||||||
// Target
|
// Target
|
||||||
|
|
||||||
// Parse target
|
// Parse target
|
||||||
async fn parse_target(&self, s: String) -> VeilidAPIResult<Target> {
|
fn parse_target(&self, s: String) -> VeilidAPIResult<Target> {
|
||||||
// Is this a route id?
|
// Is this a route id?
|
||||||
if let Ok(rrid) = RouteId::from_str(&s) {
|
if let Ok(rrid) = RouteId::from_str(&s) {
|
||||||
let routing_table = self.api.core_context()?.routing_table();
|
let routing_table = self.api.core_context()?.routing_table();
|
||||||
@ -277,8 +279,11 @@ impl JsonRequestProcessor {
|
|||||||
RoutingContextRequestOp::AppCall { target, message } => {
|
RoutingContextRequestOp::AppCall { target, message } => {
|
||||||
RoutingContextResponseOp::AppCall {
|
RoutingContextResponseOp::AppCall {
|
||||||
result: to_json_api_result_with_vec_u8(
|
result: to_json_api_result_with_vec_u8(
|
||||||
self.parse_target(target)
|
async {
|
||||||
.then(|tr| async { routing_context.app_call(tr?, message).await })
|
routing_context
|
||||||
|
.app_call(self.parse_target(target)?, message)
|
||||||
|
.await
|
||||||
|
}
|
||||||
.await,
|
.await,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@ -286,8 +291,11 @@ impl JsonRequestProcessor {
|
|||||||
RoutingContextRequestOp::AppMessage { target, message } => {
|
RoutingContextRequestOp::AppMessage { target, message } => {
|
||||||
RoutingContextResponseOp::AppMessage {
|
RoutingContextResponseOp::AppMessage {
|
||||||
result: to_json_api_result(
|
result: to_json_api_result(
|
||||||
self.parse_target(target)
|
async {
|
||||||
.then(|tr| async { routing_context.app_message(tr?, message).await })
|
routing_context
|
||||||
|
.app_message(self.parse_target(target)?, message)
|
||||||
|
.await
|
||||||
|
}
|
||||||
.await,
|
.await,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ use super::*;
|
|||||||
|
|
||||||
/// Valid destinations for a message sent over a routing context.
|
/// Valid destinations for a message sent over a routing context.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Hash, Copy, PartialOrd, Ord)]
|
#[derive(Clone, Debug, Eq, PartialEq, Hash, Copy, PartialOrd, Ord)]
|
||||||
|
#[must_use]
|
||||||
pub enum Target {
|
pub enum Target {
|
||||||
/// Node by its public key.
|
/// Node by its public key.
|
||||||
NodeId(TypedKey),
|
NodeId(TypedKey),
|
||||||
@ -25,6 +26,7 @@ pub struct RoutingContextUnlockedInner {
|
|||||||
/// To enable receiver privacy, you should send to a private route RouteId that you have imported, rather than directly to a NodeId.
|
/// To enable receiver privacy, you should send to a private route RouteId that you have imported, rather than directly to a NodeId.
|
||||||
///
|
///
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
#[must_use]
|
||||||
pub struct RoutingContext {
|
pub struct RoutingContext {
|
||||||
/// Veilid API handle.
|
/// Veilid API handle.
|
||||||
api: VeilidAPI,
|
api: VeilidAPI,
|
||||||
@ -144,8 +146,10 @@ impl RoutingContext {
|
|||||||
"RoutingContext::get_destination(self: {:?}, target: {:?})", self, target);
|
"RoutingContext::get_destination(self: {:?}, target: {:?})", self, target);
|
||||||
|
|
||||||
let rpc_processor = self.api.core_context()?.rpc_processor();
|
let rpc_processor = self.api.core_context()?.rpc_processor();
|
||||||
|
Box::pin(
|
||||||
rpc_processor
|
rpc_processor
|
||||||
.resolve_target_to_destination(target, self.unlocked_inner.safety_selection)
|
.resolve_target_to_destination(target, self.unlocked_inner.safety_selection),
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(VeilidAPIError::invalid_target)
|
.map_err(VeilidAPIError::invalid_target)
|
||||||
}
|
}
|
||||||
@ -172,7 +176,7 @@ impl RoutingContext {
|
|||||||
let dest = self.get_destination(target).await?;
|
let dest = self.get_destination(target).await?;
|
||||||
|
|
||||||
// Send app message
|
// Send app message
|
||||||
let answer = match rpc_processor.rpc_call_app_call(dest, message).await {
|
let answer = match Box::pin(rpc_processor.rpc_call_app_call(dest, message)).await {
|
||||||
Ok(NetworkResult::Value(v)) => v,
|
Ok(NetworkResult::Value(v)) => v,
|
||||||
Ok(NetworkResult::Timeout) => apibail_timeout!(),
|
Ok(NetworkResult::Timeout) => apibail_timeout!(),
|
||||||
Ok(NetworkResult::ServiceUnavailable(e)) => apibail_invalid_target!(e),
|
Ok(NetworkResult::ServiceUnavailable(e)) => apibail_invalid_target!(e),
|
||||||
@ -206,7 +210,7 @@ impl RoutingContext {
|
|||||||
let dest = self.get_destination(target).await?;
|
let dest = self.get_destination(target).await?;
|
||||||
|
|
||||||
// Send app message
|
// Send app message
|
||||||
match rpc_processor.rpc_call_app_message(dest, message).await {
|
match Box::pin(rpc_processor.rpc_call_app_message(dest, message)).await {
|
||||||
Ok(NetworkResult::Value(())) => {}
|
Ok(NetworkResult::Value(())) => {}
|
||||||
Ok(NetworkResult::Timeout) => apibail_timeout!(),
|
Ok(NetworkResult::Timeout) => apibail_timeout!(),
|
||||||
Ok(NetworkResult::ServiceUnavailable(e)) => apibail_invalid_target!(e),
|
Ok(NetworkResult::ServiceUnavailable(e)) => apibail_invalid_target!(e),
|
||||||
@ -267,8 +271,12 @@ impl RoutingContext {
|
|||||||
Crypto::validate_crypto_kind(kind)?;
|
Crypto::validate_crypto_kind(kind)?;
|
||||||
|
|
||||||
let storage_manager = self.api.core_context()?.storage_manager();
|
let storage_manager = self.api.core_context()?.storage_manager();
|
||||||
storage_manager
|
Box::pin(storage_manager.create_record(
|
||||||
.create_record(kind, schema, owner, self.unlocked_inner.safety_selection)
|
kind,
|
||||||
|
schema,
|
||||||
|
owner,
|
||||||
|
self.unlocked_inner.safety_selection,
|
||||||
|
))
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,7 +319,7 @@ impl RoutingContext {
|
|||||||
Crypto::validate_crypto_kind(key.kind)?;
|
Crypto::validate_crypto_kind(key.kind)?;
|
||||||
|
|
||||||
let storage_manager = self.api.core_context()?.storage_manager();
|
let storage_manager = self.api.core_context()?.storage_manager();
|
||||||
storage_manager.close_record(key).await
|
Box::pin(storage_manager.close_record(key)).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deletes a DHT record at a specific key.
|
/// Deletes a DHT record at a specific key.
|
||||||
@ -327,7 +335,7 @@ impl RoutingContext {
|
|||||||
Crypto::validate_crypto_kind(key.kind)?;
|
Crypto::validate_crypto_kind(key.kind)?;
|
||||||
|
|
||||||
let storage_manager = self.api.core_context()?.storage_manager();
|
let storage_manager = self.api.core_context()?.storage_manager();
|
||||||
storage_manager.delete_record(key).await
|
Box::pin(storage_manager.delete_record(key)).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the latest value of a subkey.
|
/// Gets the latest value of a subkey.
|
||||||
@ -349,7 +357,7 @@ impl RoutingContext {
|
|||||||
Crypto::validate_crypto_kind(key.kind)?;
|
Crypto::validate_crypto_kind(key.kind)?;
|
||||||
|
|
||||||
let storage_manager = self.api.core_context()?.storage_manager();
|
let storage_manager = self.api.core_context()?.storage_manager();
|
||||||
storage_manager.get_value(key, subkey, force_refresh).await
|
Box::pin(storage_manager.get_value(key, subkey, force_refresh)).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes a changed subkey value to the network.
|
/// Pushes a changed subkey value to the network.
|
||||||
@ -373,7 +381,7 @@ impl RoutingContext {
|
|||||||
Crypto::validate_crypto_kind(key.kind)?;
|
Crypto::validate_crypto_kind(key.kind)?;
|
||||||
|
|
||||||
let storage_manager = self.api.core_context()?.storage_manager();
|
let storage_manager = self.api.core_context()?.storage_manager();
|
||||||
storage_manager.set_value(key, subkey, data, writer).await
|
Box::pin(storage_manager.set_value(key, subkey, data, writer)).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add or update a watch to a DHT value that informs the user via an VeilidUpdate::ValueChange callback when the record has subkeys change.
|
/// Add or update a watch to a DHT value that informs the user via an VeilidUpdate::ValueChange callback when the record has subkeys change.
|
||||||
@ -410,9 +418,7 @@ impl RoutingContext {
|
|||||||
Crypto::validate_crypto_kind(key.kind)?;
|
Crypto::validate_crypto_kind(key.kind)?;
|
||||||
|
|
||||||
let storage_manager = self.api.core_context()?.storage_manager();
|
let storage_manager = self.api.core_context()?.storage_manager();
|
||||||
storage_manager
|
Box::pin(storage_manager.watch_values(key, subkeys, expiration, count)).await
|
||||||
.watch_values(key, subkeys, expiration, count)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cancels a watch early.
|
/// Cancels a watch early.
|
||||||
@ -436,7 +442,7 @@ impl RoutingContext {
|
|||||||
Crypto::validate_crypto_kind(key.kind)?;
|
Crypto::validate_crypto_kind(key.kind)?;
|
||||||
|
|
||||||
let storage_manager = self.api.core_context()?.storage_manager();
|
let storage_manager = self.api.core_context()?.storage_manager();
|
||||||
storage_manager.cancel_watch_values(key, subkeys).await
|
Box::pin(storage_manager.cancel_watch_values(key, subkeys)).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inspects a DHT record for subkey state.
|
/// Inspects a DHT record for subkey state.
|
||||||
@ -491,7 +497,7 @@ impl RoutingContext {
|
|||||||
Crypto::validate_crypto_kind(key.kind)?;
|
Crypto::validate_crypto_kind(key.kind)?;
|
||||||
|
|
||||||
let storage_manager = self.api.core_context()?.storage_manager();
|
let storage_manager = self.api.core_context()?.storage_manager();
|
||||||
storage_manager.inspect_record(key, subkeys, scope).await
|
Box::pin(storage_manager.inspect_record(key, subkeys, scope)).await
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////
|
///////////////////////////////////
|
||||||
|
@ -2,49 +2,50 @@ use super::test_types::*;
|
|||||||
use super::test_types_dht::*;
|
use super::test_types_dht::*;
|
||||||
use super::test_types_dht_schema::*;
|
use super::test_types_dht_schema::*;
|
||||||
|
|
||||||
|
#[expect(clippy::unused_async)]
|
||||||
pub async fn test_all() {
|
pub async fn test_all() {
|
||||||
// test_types
|
// test_types
|
||||||
test_alignedu64().await;
|
test_alignedu64();
|
||||||
test_veilidappmessage().await;
|
test_veilidappmessage();
|
||||||
test_veilidappcall().await;
|
test_veilidappcall();
|
||||||
test_fourcc().await;
|
test_fourcc();
|
||||||
test_sequencing().await;
|
test_sequencing();
|
||||||
test_stability().await;
|
test_stability();
|
||||||
test_safetyselection().await;
|
test_safetyselection();
|
||||||
test_safetyspec().await;
|
test_safetyspec();
|
||||||
test_latencystats().await;
|
test_latencystats();
|
||||||
test_transferstats().await;
|
test_transferstats();
|
||||||
test_transferstatsdownup().await;
|
test_transferstatsdownup();
|
||||||
test_rpcstats().await;
|
test_rpcstats();
|
||||||
test_peerstats().await;
|
test_peerstats();
|
||||||
#[cfg(feature = "unstable-tunnels")]
|
#[cfg(feature = "unstable-tunnels")]
|
||||||
test_tunnelmode().await;
|
test_tunnelmode();
|
||||||
#[cfg(feature = "unstable-tunnels")]
|
#[cfg(feature = "unstable-tunnels")]
|
||||||
test_tunnelerror().await;
|
test_tunnelerror();
|
||||||
#[cfg(feature = "unstable-tunnels")]
|
#[cfg(feature = "unstable-tunnels")]
|
||||||
test_tunnelendpoint().await;
|
test_tunnelendpoint();
|
||||||
#[cfg(feature = "unstable-tunnels")]
|
#[cfg(feature = "unstable-tunnels")]
|
||||||
test_fulltunnel().await;
|
test_fulltunnel();
|
||||||
#[cfg(feature = "unstable-tunnels")]
|
#[cfg(feature = "unstable-tunnels")]
|
||||||
test_partialtunnel().await;
|
test_partialtunnel();
|
||||||
test_veilidloglevel().await;
|
test_veilidloglevel();
|
||||||
test_veilidlog().await;
|
test_veilidlog();
|
||||||
test_attachmentstate().await;
|
test_attachmentstate();
|
||||||
test_veilidstateattachment().await;
|
test_veilidstateattachment();
|
||||||
test_peertabledata().await;
|
test_peertabledata();
|
||||||
test_veilidstatenetwork().await;
|
test_veilidstatenetwork();
|
||||||
test_veilidroutechange().await;
|
test_veilidroutechange();
|
||||||
test_veilidstateconfig().await;
|
test_veilidstateconfig();
|
||||||
test_veilidvaluechange().await;
|
test_veilidvaluechange();
|
||||||
test_veilidupdate().await;
|
test_veilidupdate();
|
||||||
test_veilidstate().await;
|
test_veilidstate();
|
||||||
// test_types_dht
|
// test_types_dht
|
||||||
test_dhtrecorddescriptor().await;
|
test_dhtrecorddescriptor();
|
||||||
test_valuedata().await;
|
test_valuedata();
|
||||||
test_valuesubkeyrangeset().await;
|
test_valuesubkeyrangeset();
|
||||||
// test_types_dht_schema
|
// test_types_dht_schema
|
||||||
test_dhtschemadflt().await;
|
test_dhtschemadflt();
|
||||||
test_dhtschema().await;
|
test_dhtschema();
|
||||||
test_dhtschemasmplmember().await;
|
test_dhtschemasmplmember();
|
||||||
test_dhtschemasmpl().await;
|
test_dhtschemasmpl();
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use crate::*;
|
|||||||
|
|
||||||
// aligned_u64
|
// aligned_u64
|
||||||
|
|
||||||
pub async fn test_alignedu64() {
|
pub fn test_alignedu64() {
|
||||||
let orig = AlignedU64::new(0x0123456789abcdef);
|
let orig = AlignedU64::new(0x0123456789abcdef);
|
||||||
let copy = deserialize_json(&serialize_json(orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(orig)).unwrap();
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ pub async fn test_alignedu64() {
|
|||||||
|
|
||||||
// app_messsage_call
|
// app_messsage_call
|
||||||
|
|
||||||
pub async fn test_veilidappmessage() {
|
pub fn test_veilidappmessage() {
|
||||||
let orig = VeilidAppMessage::new(
|
let orig = VeilidAppMessage::new(
|
||||||
Some(fix_typedkey()),
|
Some(fix_typedkey()),
|
||||||
Some(fix_cryptokey()),
|
Some(fix_cryptokey()),
|
||||||
@ -23,7 +23,7 @@ pub async fn test_veilidappmessage() {
|
|||||||
assert_eq!(orig, copy);
|
assert_eq!(orig, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_veilidappcall() {
|
pub fn test_veilidappcall() {
|
||||||
let orig = VeilidAppCall::new(
|
let orig = VeilidAppCall::new(
|
||||||
Some(fix_typedkey()),
|
Some(fix_typedkey()),
|
||||||
Some(fix_cryptokey()),
|
Some(fix_cryptokey()),
|
||||||
@ -37,7 +37,7 @@ pub async fn test_veilidappcall() {
|
|||||||
|
|
||||||
// fourcc
|
// fourcc
|
||||||
|
|
||||||
pub async fn test_fourcc() {
|
pub fn test_fourcc() {
|
||||||
let orig = FourCC::from_str("D34D").unwrap();
|
let orig = FourCC::from_str("D34D").unwrap();
|
||||||
let copy = deserialize_json(&serialize_json(orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(orig)).unwrap();
|
||||||
|
|
||||||
@ -46,28 +46,28 @@ pub async fn test_fourcc() {
|
|||||||
|
|
||||||
// safety
|
// safety
|
||||||
|
|
||||||
pub async fn test_sequencing() {
|
pub fn test_sequencing() {
|
||||||
let orig = Sequencing::PreferOrdered;
|
let orig = Sequencing::PreferOrdered;
|
||||||
let copy = deserialize_json(&serialize_json(orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(orig)).unwrap();
|
||||||
|
|
||||||
assert_eq!(orig, copy);
|
assert_eq!(orig, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_stability() {
|
pub fn test_stability() {
|
||||||
let orig = Stability::Reliable;
|
let orig = Stability::Reliable;
|
||||||
let copy = deserialize_json(&serialize_json(orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(orig)).unwrap();
|
||||||
|
|
||||||
assert_eq!(orig, copy);
|
assert_eq!(orig, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_safetyselection() {
|
pub fn test_safetyselection() {
|
||||||
let orig = SafetySelection::Unsafe(Sequencing::EnsureOrdered);
|
let orig = SafetySelection::Unsafe(Sequencing::EnsureOrdered);
|
||||||
let copy = deserialize_json(&serialize_json(orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(orig)).unwrap();
|
||||||
|
|
||||||
assert_eq!(orig, copy);
|
assert_eq!(orig, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_safetyspec() {
|
pub fn test_safetyspec() {
|
||||||
let orig = SafetySpec {
|
let orig = SafetySpec {
|
||||||
preferred_route: Some(fix_cryptokey()),
|
preferred_route: Some(fix_cryptokey()),
|
||||||
hop_count: 23,
|
hop_count: 23,
|
||||||
@ -81,35 +81,35 @@ pub async fn test_safetyspec() {
|
|||||||
|
|
||||||
// stats
|
// stats
|
||||||
|
|
||||||
pub async fn test_latencystats() {
|
pub fn test_latencystats() {
|
||||||
let orig = fix_latencystats();
|
let orig = fix_latencystats();
|
||||||
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
||||||
|
|
||||||
assert_eq!(orig, copy);
|
assert_eq!(orig, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_transferstats() {
|
pub fn test_transferstats() {
|
||||||
let orig = fix_transferstats();
|
let orig = fix_transferstats();
|
||||||
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
||||||
|
|
||||||
assert_eq!(orig, copy);
|
assert_eq!(orig, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_transferstatsdownup() {
|
pub fn test_transferstatsdownup() {
|
||||||
let orig = fix_transferstatsdownup();
|
let orig = fix_transferstatsdownup();
|
||||||
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
||||||
|
|
||||||
assert_eq!(orig, copy);
|
assert_eq!(orig, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_rpcstats() {
|
pub fn test_rpcstats() {
|
||||||
let orig = fix_rpcstats();
|
let orig = fix_rpcstats();
|
||||||
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
||||||
|
|
||||||
assert_eq!(orig, copy);
|
assert_eq!(orig, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_peerstats() {
|
pub fn test_peerstats() {
|
||||||
let orig = fix_peerstats();
|
let orig = fix_peerstats();
|
||||||
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ pub async fn test_peerstats() {
|
|||||||
// tunnel
|
// tunnel
|
||||||
|
|
||||||
#[cfg(feature = "unstable-tunnels")]
|
#[cfg(feature = "unstable-tunnels")]
|
||||||
pub async fn test_tunnelmode() {
|
pub fn test_tunnelmode() {
|
||||||
let orig = TunnelMode::Raw;
|
let orig = TunnelMode::Raw;
|
||||||
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ pub async fn test_tunnelmode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unstable-tunnels")]
|
#[cfg(feature = "unstable-tunnels")]
|
||||||
pub async fn test_tunnelerror() {
|
pub fn test_tunnelerror() {
|
||||||
let orig = TunnelError::NoCapacity;
|
let orig = TunnelError::NoCapacity;
|
||||||
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
||||||
|
|
||||||
@ -135,7 +135,7 @@ pub async fn test_tunnelerror() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unstable-tunnels")]
|
#[cfg(feature = "unstable-tunnels")]
|
||||||
pub async fn test_tunnelendpoint() {
|
pub fn test_tunnelendpoint() {
|
||||||
let orig = TunnelEndpoint {
|
let orig = TunnelEndpoint {
|
||||||
mode: TunnelMode::Raw,
|
mode: TunnelMode::Raw,
|
||||||
description: "Here there be tygers.".to_string(),
|
description: "Here there be tygers.".to_string(),
|
||||||
@ -146,7 +146,7 @@ pub async fn test_tunnelendpoint() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unstable-tunnels")]
|
#[cfg(feature = "unstable-tunnels")]
|
||||||
pub async fn test_fulltunnel() {
|
pub fn test_fulltunnel() {
|
||||||
let orig = FullTunnel {
|
let orig = FullTunnel {
|
||||||
id: AlignedU64::from(42),
|
id: AlignedU64::from(42),
|
||||||
timeout: AlignedU64::from(3_000_000),
|
timeout: AlignedU64::from(3_000_000),
|
||||||
@ -165,7 +165,7 @@ pub async fn test_fulltunnel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unstable-tunnels")]
|
#[cfg(feature = "unstable-tunnels")]
|
||||||
pub async fn test_partialtunnel() {
|
pub fn test_partialtunnel() {
|
||||||
let orig = PartialTunnel {
|
let orig = PartialTunnel {
|
||||||
id: AlignedU64::from(42),
|
id: AlignedU64::from(42),
|
||||||
timeout: AlignedU64::from(3_000_000),
|
timeout: AlignedU64::from(3_000_000),
|
||||||
@ -181,14 +181,14 @@ pub async fn test_partialtunnel() {
|
|||||||
|
|
||||||
// veilid_log
|
// veilid_log
|
||||||
|
|
||||||
pub async fn test_veilidloglevel() {
|
pub fn test_veilidloglevel() {
|
||||||
let orig = VeilidLogLevel::Info;
|
let orig = VeilidLogLevel::Info;
|
||||||
let copy = deserialize_json(&serialize_json(orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(orig)).unwrap();
|
||||||
|
|
||||||
assert_eq!(orig, copy);
|
assert_eq!(orig, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_veilidlog() {
|
pub fn test_veilidlog() {
|
||||||
let orig = VeilidLog {
|
let orig = VeilidLog {
|
||||||
log_level: VeilidLogLevel::Debug,
|
log_level: VeilidLogLevel::Debug,
|
||||||
message: "A log! A log!".to_string(),
|
message: "A log! A log!".to_string(),
|
||||||
@ -201,14 +201,14 @@ pub async fn test_veilidlog() {
|
|||||||
|
|
||||||
// veilid_state
|
// veilid_state
|
||||||
|
|
||||||
pub async fn test_attachmentstate() {
|
pub fn test_attachmentstate() {
|
||||||
let orig = AttachmentState::FullyAttached;
|
let orig = AttachmentState::FullyAttached;
|
||||||
let copy = deserialize_json(&serialize_json(orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(orig)).unwrap();
|
||||||
|
|
||||||
assert_eq!(orig, copy);
|
assert_eq!(orig, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_veilidstateattachment() {
|
pub fn test_veilidstateattachment() {
|
||||||
let orig = VeilidStateAttachment {
|
let orig = VeilidStateAttachment {
|
||||||
state: AttachmentState::OverAttached,
|
state: AttachmentState::OverAttached,
|
||||||
public_internet_ready: true,
|
public_internet_ready: true,
|
||||||
@ -221,14 +221,14 @@ pub async fn test_veilidstateattachment() {
|
|||||||
assert_eq!(orig, copy);
|
assert_eq!(orig, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_peertabledata() {
|
pub fn test_peertabledata() {
|
||||||
let orig = fix_peertabledata();
|
let orig = fix_peertabledata();
|
||||||
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
||||||
|
|
||||||
assert_eq!(orig, copy);
|
assert_eq!(orig, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_veilidstatenetwork() {
|
pub fn test_veilidstatenetwork() {
|
||||||
let orig = VeilidStateNetwork {
|
let orig = VeilidStateNetwork {
|
||||||
started: true,
|
started: true,
|
||||||
bps_down: ByteCount::from(14_400),
|
bps_down: ByteCount::from(14_400),
|
||||||
@ -240,7 +240,7 @@ pub async fn test_veilidstatenetwork() {
|
|||||||
assert_eq!(orig, copy);
|
assert_eq!(orig, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_veilidroutechange() {
|
pub fn test_veilidroutechange() {
|
||||||
let orig = VeilidRouteChange {
|
let orig = VeilidRouteChange {
|
||||||
dead_routes: vec![fix_cryptokey()],
|
dead_routes: vec![fix_cryptokey()],
|
||||||
dead_remote_routes: vec![fix_cryptokey()],
|
dead_remote_routes: vec![fix_cryptokey()],
|
||||||
@ -250,7 +250,7 @@ pub async fn test_veilidroutechange() {
|
|||||||
assert_eq!(orig, copy);
|
assert_eq!(orig, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_veilidstateconfig() {
|
pub fn test_veilidstateconfig() {
|
||||||
let orig = VeilidStateConfig {
|
let orig = VeilidStateConfig {
|
||||||
config: fix_veilidconfiginner(),
|
config: fix_veilidconfiginner(),
|
||||||
};
|
};
|
||||||
@ -259,21 +259,21 @@ pub async fn test_veilidstateconfig() {
|
|||||||
assert_eq!(orig, copy);
|
assert_eq!(orig, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_veilidvaluechange() {
|
pub fn test_veilidvaluechange() {
|
||||||
let orig = fix_veilidvaluechange();
|
let orig = fix_veilidvaluechange();
|
||||||
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
||||||
|
|
||||||
assert_eq!(orig, copy);
|
assert_eq!(orig, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_veilidupdate() {
|
pub fn test_veilidupdate() {
|
||||||
let orig = VeilidUpdate::ValueChange(Box::new(fix_veilidvaluechange()));
|
let orig = VeilidUpdate::ValueChange(Box::new(fix_veilidvaluechange()));
|
||||||
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
||||||
|
|
||||||
assert_eq!(orig, copy);
|
assert_eq!(orig, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_veilidstate() {
|
pub fn test_veilidstate() {
|
||||||
let orig = VeilidState {
|
let orig = VeilidState {
|
||||||
attachment: Box::new(VeilidStateAttachment {
|
attachment: Box::new(VeilidStateAttachment {
|
||||||
state: AttachmentState::OverAttached,
|
state: AttachmentState::OverAttached,
|
||||||
|
@ -4,7 +4,7 @@ use range_set_blaze::*;
|
|||||||
|
|
||||||
// dht_record_descriptors
|
// dht_record_descriptors
|
||||||
|
|
||||||
pub async fn test_dhtrecorddescriptor() {
|
pub fn test_dhtrecorddescriptor() {
|
||||||
let orig = DHTRecordDescriptor::new(
|
let orig = DHTRecordDescriptor::new(
|
||||||
fix_typedkey(),
|
fix_typedkey(),
|
||||||
fix_cryptokey(),
|
fix_cryptokey(),
|
||||||
@ -18,7 +18,7 @@ pub async fn test_dhtrecorddescriptor() {
|
|||||||
|
|
||||||
// value_data
|
// value_data
|
||||||
|
|
||||||
pub async fn test_valuedata() {
|
pub fn test_valuedata() {
|
||||||
let orig = ValueData::new_with_seq(42, b"Brent Spiner".to_vec(), fix_cryptokey());
|
let orig = ValueData::new_with_seq(42, b"Brent Spiner".to_vec(), fix_cryptokey());
|
||||||
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ pub async fn test_valuedata() {
|
|||||||
|
|
||||||
// value_subkey_range_set
|
// value_subkey_range_set
|
||||||
|
|
||||||
pub async fn test_valuesubkeyrangeset() {
|
pub fn test_valuesubkeyrangeset() {
|
||||||
let orig = ValueSubkeyRangeSet::new_with_data(RangeSetBlaze::from_iter([20..=30]));
|
let orig = ValueSubkeyRangeSet::new_with_data(RangeSetBlaze::from_iter([20..=30]));
|
||||||
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ use crate::*;
|
|||||||
|
|
||||||
// dlft
|
// dlft
|
||||||
|
|
||||||
pub async fn test_dhtschemadflt() {
|
pub fn test_dhtschemadflt() {
|
||||||
let orig = DHTSchemaDFLT::new(9);
|
let orig = DHTSchemaDFLT::new(9);
|
||||||
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
let copy = deserialize_json(&serialize_json(&orig)).unwrap();
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ pub async fn test_dhtschemadflt() {
|
|||||||
|
|
||||||
// mod
|
// mod
|
||||||
|
|
||||||
pub async fn test_dhtschema() {
|
pub fn test_dhtschema() {
|
||||||
let orig = DHTSchema::SMPL(
|
let orig = DHTSchema::SMPL(
|
||||||
DHTSchemaSMPL::new(
|
DHTSchemaSMPL::new(
|
||||||
91,
|
91,
|
||||||
@ -36,7 +36,7 @@ pub async fn test_dhtschema() {
|
|||||||
|
|
||||||
// smpl
|
// smpl
|
||||||
|
|
||||||
pub async fn test_dhtschemasmplmember() {
|
pub fn test_dhtschemasmplmember() {
|
||||||
let orig = DHTSchemaSMPLMember {
|
let orig = DHTSchemaSMPLMember {
|
||||||
m_key: fix_cryptokey(),
|
m_key: fix_cryptokey(),
|
||||||
m_cnt: 7,
|
m_cnt: 7,
|
||||||
@ -46,7 +46,7 @@ pub async fn test_dhtschemasmplmember() {
|
|||||||
assert_eq!(orig, copy);
|
assert_eq!(orig, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_dhtschemasmpl() {
|
pub fn test_dhtschemasmpl() {
|
||||||
let orig = DHTSchemaSMPL::new(
|
let orig = DHTSchemaSMPL::new(
|
||||||
91,
|
91,
|
||||||
vec![
|
vec![
|
||||||
|
@ -24,6 +24,7 @@ macro_rules! aligned_u64_type {
|
|||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
#[repr(C, align(8))]
|
#[repr(C, align(8))]
|
||||||
#[serde(transparent)]
|
#[serde(transparent)]
|
||||||
|
#[must_use]
|
||||||
pub struct $name(
|
pub struct $name(
|
||||||
#[serde(with = "as_human_string")]
|
#[serde(with = "as_human_string")]
|
||||||
#[schemars(with = "String")]
|
#[schemars(with = "String")]
|
||||||
@ -49,6 +50,7 @@ macro_rules! aligned_u64_type {
|
|||||||
pub const fn new(v: u64) -> Self {
|
pub const fn new(v: u64) -> Self {
|
||||||
Self(v)
|
Self(v)
|
||||||
}
|
}
|
||||||
|
#[must_use]
|
||||||
pub fn as_u64(self) -> u64 {
|
pub fn as_u64(self) -> u64 {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ use super::*;
|
|||||||
/// Direct statement blob passed to hosting application for processing.
|
/// Direct statement blob passed to hosting application for processing.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidAppMessage {
|
pub struct VeilidAppMessage {
|
||||||
#[serde(with = "as_human_opt_string")]
|
#[serde(with = "as_human_opt_string")]
|
||||||
#[schemars(with = "Option<String>")]
|
#[schemars(with = "Option<String>")]
|
||||||
@ -43,16 +44,19 @@ impl VeilidAppMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Some(sender) if the message was sent directly, None if received via a private/safety route.
|
/// Some(sender) if the message was sent directly, None if received via a private/safety route.
|
||||||
|
#[must_use]
|
||||||
pub fn sender(&self) -> Option<&TypedKey> {
|
pub fn sender(&self) -> Option<&TypedKey> {
|
||||||
self.sender.as_ref()
|
self.sender.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Some(route_id) if the message was received over a private route, None if received only a safety route or directly.
|
/// Some(route_id) if the message was received over a private route, None if received only a safety route or directly.
|
||||||
|
#[must_use]
|
||||||
pub fn route_id(&self) -> Option<&RouteId> {
|
pub fn route_id(&self) -> Option<&RouteId> {
|
||||||
self.route_id.as_ref()
|
self.route_id.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The content of the message to deliver to the application.
|
/// The content of the message to deliver to the application.
|
||||||
|
#[must_use]
|
||||||
pub fn message(&self) -> &[u8] {
|
pub fn message(&self) -> &[u8] {
|
||||||
&self.message
|
&self.message
|
||||||
}
|
}
|
||||||
@ -61,6 +65,7 @@ impl VeilidAppMessage {
|
|||||||
/// Direct question blob passed to hosting application for processing to send an eventual AppReply.
|
/// Direct question blob passed to hosting application for processing to send an eventual AppReply.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidAppCall {
|
pub struct VeilidAppCall {
|
||||||
#[serde(with = "as_human_opt_string")]
|
#[serde(with = "as_human_opt_string")]
|
||||||
#[schemars(with = "Option<String>")]
|
#[schemars(with = "Option<String>")]
|
||||||
@ -108,16 +113,19 @@ impl VeilidAppCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Some(sender) if the request was sent directly, None if received via a private/safety route.
|
/// Some(sender) if the request was sent directly, None if received via a private/safety route.
|
||||||
|
#[must_use]
|
||||||
pub fn sender(&self) -> Option<&TypedKey> {
|
pub fn sender(&self) -> Option<&TypedKey> {
|
||||||
self.sender.as_ref()
|
self.sender.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Some(route_id) if the request was received over a private route, None if received only a safety route or directly.
|
/// Some(route_id) if the request was received over a private route, None if received only a safety route or directly.
|
||||||
|
#[must_use]
|
||||||
pub fn route_id(&self) -> Option<&RouteId> {
|
pub fn route_id(&self) -> Option<&RouteId> {
|
||||||
self.route_id.as_ref()
|
self.route_id.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The content of the request to deliver to the application.
|
/// The content of the request to deliver to the application.
|
||||||
|
#[must_use]
|
||||||
pub fn message(&self) -> &[u8] {
|
pub fn message(&self) -> &[u8] {
|
||||||
&self.message
|
&self.message
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ use super::*;
|
|||||||
derive(Tsify),
|
derive(Tsify),
|
||||||
tsify(from_wasm_abi, into_wasm_abi)
|
tsify(from_wasm_abi, into_wasm_abi)
|
||||||
)]
|
)]
|
||||||
|
#[must_use]
|
||||||
pub struct DHTRecordDescriptor {
|
pub struct DHTRecordDescriptor {
|
||||||
/// DHT Key = Hash(ownerKeyKind) of: [ ownerKeyValue, schema ]
|
/// DHT Key = Hash(ownerKeyKind) of: [ ownerKeyValue, schema ]
|
||||||
#[schemars(with = "String")]
|
#[schemars(with = "String")]
|
||||||
@ -46,6 +47,7 @@ impl DHTRecordDescriptor {
|
|||||||
&self.owner
|
&self.owner
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn owner_secret(&self) -> Option<&SecretKey> {
|
pub fn owner_secret(&self) -> Option<&SecretKey> {
|
||||||
self.owner_secret.as_ref()
|
self.owner_secret.as_ref()
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ use super::*;
|
|||||||
derive(Tsify),
|
derive(Tsify),
|
||||||
tsify(from_wasm_abi, into_wasm_abi)
|
tsify(from_wasm_abi, into_wasm_abi)
|
||||||
)]
|
)]
|
||||||
|
#[must_use]
|
||||||
pub struct DHTRecordReport {
|
pub struct DHTRecordReport {
|
||||||
/// The actual subkey range within the schema being reported on
|
/// The actual subkey range within the schema being reported on
|
||||||
/// This may be a subset of the requested range if it exceeds the schema limits
|
/// This may be a subset of the requested range if it exceeds the schema limits
|
||||||
@ -42,9 +43,11 @@ impl DHTRecordReport {
|
|||||||
pub fn offline_subkeys(&self) -> &ValueSubkeyRangeSet {
|
pub fn offline_subkeys(&self) -> &ValueSubkeyRangeSet {
|
||||||
&self.offline_subkeys
|
&self.offline_subkeys
|
||||||
}
|
}
|
||||||
|
#[must_use]
|
||||||
pub fn local_seqs(&self) -> &[ValueSeqNum] {
|
pub fn local_seqs(&self) -> &[ValueSeqNum] {
|
||||||
&self.local_seqs
|
&self.local_seqs
|
||||||
}
|
}
|
||||||
|
#[must_use]
|
||||||
pub fn network_seqs(&self) -> &[ValueSeqNum] {
|
pub fn network_seqs(&self) -> &[ValueSeqNum] {
|
||||||
&self.network_seqs
|
&self.network_seqs
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ use crate::storage_manager::{MAX_RECORD_DATA_SIZE, MAX_SUBKEY_SIZE};
|
|||||||
derive(Tsify),
|
derive(Tsify),
|
||||||
tsify(from_wasm_abi)
|
tsify(from_wasm_abi)
|
||||||
)]
|
)]
|
||||||
|
#[must_use]
|
||||||
pub struct DHTSchemaDFLT {
|
pub struct DHTSchemaDFLT {
|
||||||
/// Owner subkey count
|
/// Owner subkey count
|
||||||
o_cnt: u16,
|
o_cnt: u16,
|
||||||
@ -33,11 +34,13 @@ impl DHTSchemaDFLT {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the owner subkey count
|
/// Get the owner subkey count
|
||||||
|
#[must_use]
|
||||||
pub fn o_cnt(&self) -> u16 {
|
pub fn o_cnt(&self) -> u16 {
|
||||||
self.o_cnt
|
self.o_cnt
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build the data representation of the schema
|
/// Build the data representation of the schema
|
||||||
|
#[must_use]
|
||||||
pub fn compile(&self) -> Vec<u8> {
|
pub fn compile(&self) -> Vec<u8> {
|
||||||
let mut out = Vec::<u8>::with_capacity(Self::FIXED_SIZE);
|
let mut out = Vec::<u8>::with_capacity(Self::FIXED_SIZE);
|
||||||
// kind
|
// kind
|
||||||
@ -48,15 +51,18 @@ impl DHTSchemaDFLT {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the maximum subkey this schema allocates
|
/// Get the maximum subkey this schema allocates
|
||||||
|
#[must_use]
|
||||||
pub fn max_subkey(&self) -> ValueSubkey {
|
pub fn max_subkey(&self) -> ValueSubkey {
|
||||||
self.o_cnt as ValueSubkey - 1
|
self.o_cnt as ValueSubkey - 1
|
||||||
}
|
}
|
||||||
/// Get the data size of this schema beyond the size of the structure itself
|
/// Get the data size of this schema beyond the size of the structure itself
|
||||||
|
#[must_use]
|
||||||
pub fn data_size(&self) -> usize {
|
pub fn data_size(&self) -> usize {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check a subkey value data against the schema
|
/// Check a subkey value data against the schema
|
||||||
|
#[must_use]
|
||||||
pub fn check_subkey_value_data(
|
pub fn check_subkey_value_data(
|
||||||
&self,
|
&self,
|
||||||
owner: &PublicKey,
|
owner: &PublicKey,
|
||||||
@ -90,6 +96,7 @@ impl DHTSchemaDFLT {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Check if a key is a schema member
|
/// Check if a key is a schema member
|
||||||
|
#[must_use]
|
||||||
pub fn is_member(&self, _key: &PublicKey) -> bool {
|
pub fn is_member(&self, _key: &PublicKey) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ pub use smpl::*;
|
|||||||
derive(Tsify),
|
derive(Tsify),
|
||||||
tsify(from_wasm_abi)
|
tsify(from_wasm_abi)
|
||||||
)]
|
)]
|
||||||
|
#[must_use]
|
||||||
pub enum DHTSchema {
|
pub enum DHTSchema {
|
||||||
DFLT(DHTSchemaDFLT),
|
DFLT(DHTSchemaDFLT),
|
||||||
SMPL(DHTSchemaSMPL),
|
SMPL(DHTSchemaSMPL),
|
||||||
@ -36,6 +37,7 @@ impl DHTSchema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Build the data representation of the schema
|
/// Build the data representation of the schema
|
||||||
|
#[must_use]
|
||||||
pub fn compile(&self) -> Vec<u8> {
|
pub fn compile(&self) -> Vec<u8> {
|
||||||
match self {
|
match self {
|
||||||
DHTSchema::DFLT(d) => d.compile(),
|
DHTSchema::DFLT(d) => d.compile(),
|
||||||
@ -44,6 +46,7 @@ impl DHTSchema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get maximum subkey number for this schema
|
/// Get maximum subkey number for this schema
|
||||||
|
#[must_use]
|
||||||
pub fn max_subkey(&self) -> ValueSubkey {
|
pub fn max_subkey(&self) -> ValueSubkey {
|
||||||
match self {
|
match self {
|
||||||
DHTSchema::DFLT(d) => d.max_subkey(),
|
DHTSchema::DFLT(d) => d.max_subkey(),
|
||||||
@ -52,6 +55,7 @@ impl DHTSchema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the data size of this schema beyond the size of the structure itself
|
/// Get the data size of this schema beyond the size of the structure itself
|
||||||
|
#[must_use]
|
||||||
pub fn data_size(&self) -> usize {
|
pub fn data_size(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
DHTSchema::DFLT(d) => d.data_size(),
|
DHTSchema::DFLT(d) => d.data_size(),
|
||||||
@ -60,6 +64,7 @@ impl DHTSchema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Check a subkey value data against the schema
|
/// Check a subkey value data against the schema
|
||||||
|
#[must_use]
|
||||||
pub fn check_subkey_value_data(
|
pub fn check_subkey_value_data(
|
||||||
&self,
|
&self,
|
||||||
owner: &PublicKey,
|
owner: &PublicKey,
|
||||||
@ -73,6 +78,7 @@ impl DHTSchema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Check if a key is a schema member
|
/// Check if a key is a schema member
|
||||||
|
#[must_use]
|
||||||
pub fn is_member(&self, key: &PublicKey) -> bool {
|
pub fn is_member(&self, key: &PublicKey) -> bool {
|
||||||
match self {
|
match self {
|
||||||
DHTSchema::DFLT(d) => d.is_member(key),
|
DHTSchema::DFLT(d) => d.is_member(key),
|
||||||
|
@ -8,6 +8,7 @@ use crate::storage_manager::{MAX_RECORD_DATA_SIZE, MAX_SUBKEY_SIZE};
|
|||||||
derive(Tsify),
|
derive(Tsify),
|
||||||
tsify(from_wasm_abi)
|
tsify(from_wasm_abi)
|
||||||
)]
|
)]
|
||||||
|
#[must_use]
|
||||||
pub struct DHTSchemaSMPLMember {
|
pub struct DHTSchemaSMPLMember {
|
||||||
/// Member key
|
/// Member key
|
||||||
#[schemars(with = "String")]
|
#[schemars(with = "String")]
|
||||||
@ -23,6 +24,7 @@ pub struct DHTSchemaSMPLMember {
|
|||||||
derive(Tsify),
|
derive(Tsify),
|
||||||
tsify(from_wasm_abi)
|
tsify(from_wasm_abi)
|
||||||
)]
|
)]
|
||||||
|
#[must_use]
|
||||||
pub struct DHTSchemaSMPL {
|
pub struct DHTSchemaSMPL {
|
||||||
/// Owner subkey count
|
/// Owner subkey count
|
||||||
o_cnt: u16,
|
o_cnt: u16,
|
||||||
@ -58,6 +60,7 @@ impl DHTSchemaSMPL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the owner subkey count
|
/// Get the owner subkey count
|
||||||
|
#[must_use]
|
||||||
pub fn o_cnt(&self) -> u16 {
|
pub fn o_cnt(&self) -> u16 {
|
||||||
self.o_cnt
|
self.o_cnt
|
||||||
}
|
}
|
||||||
@ -68,6 +71,7 @@ impl DHTSchemaSMPL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Build the data representation of the schema
|
/// Build the data representation of the schema
|
||||||
|
#[must_use]
|
||||||
pub fn compile(&self) -> Vec<u8> {
|
pub fn compile(&self) -> Vec<u8> {
|
||||||
let mut out = Vec::<u8>::with_capacity(
|
let mut out = Vec::<u8>::with_capacity(
|
||||||
Self::FIXED_SIZE + (self.members.len() * (PUBLIC_KEY_LENGTH + 2)),
|
Self::FIXED_SIZE + (self.members.len() * (PUBLIC_KEY_LENGTH + 2)),
|
||||||
@ -87,6 +91,7 @@ impl DHTSchemaSMPL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the maximum subkey this schema allocates
|
/// Get the maximum subkey this schema allocates
|
||||||
|
#[must_use]
|
||||||
pub fn max_subkey(&self) -> ValueSubkey {
|
pub fn max_subkey(&self) -> ValueSubkey {
|
||||||
let subkey_count = self
|
let subkey_count = self
|
||||||
.members
|
.members
|
||||||
@ -96,11 +101,13 @@ impl DHTSchemaSMPL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the data size of this schema beyond the size of the structure itself
|
/// Get the data size of this schema beyond the size of the structure itself
|
||||||
|
#[must_use]
|
||||||
pub fn data_size(&self) -> usize {
|
pub fn data_size(&self) -> usize {
|
||||||
self.members.len() * mem::size_of::<DHTSchemaSMPLMember>()
|
self.members.len() * mem::size_of::<DHTSchemaSMPLMember>()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check a subkey value data against the schema
|
/// Check a subkey value data against the schema
|
||||||
|
#[must_use]
|
||||||
pub fn check_subkey_value_data(
|
pub fn check_subkey_value_data(
|
||||||
&self,
|
&self,
|
||||||
owner: &PublicKey,
|
owner: &PublicKey,
|
||||||
@ -156,6 +163,7 @@ impl DHTSchemaSMPL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Check if a key is a schema member
|
/// Check if a key is a schema member
|
||||||
|
#[must_use]
|
||||||
pub fn is_member(&self, key: &PublicKey) -> bool {
|
pub fn is_member(&self, key: &PublicKey) -> bool {
|
||||||
for m in &self.members {
|
for m in &self.members {
|
||||||
if m.m_key == *key {
|
if m.m_key == *key {
|
||||||
|
@ -7,6 +7,7 @@ use veilid_api::VeilidAPIResult;
|
|||||||
derive(Tsify),
|
derive(Tsify),
|
||||||
tsify(into_wasm_abi)
|
tsify(into_wasm_abi)
|
||||||
)]
|
)]
|
||||||
|
#[must_use]
|
||||||
pub struct ValueData {
|
pub struct ValueData {
|
||||||
/// An increasing sequence number to time-order the DHT record changes
|
/// An increasing sequence number to time-order the DHT record changes
|
||||||
seq: ValueSeqNum,
|
seq: ValueSeqNum,
|
||||||
@ -54,6 +55,7 @@ impl ValueData {
|
|||||||
Ok(Self { seq, data, writer })
|
Ok(Self { seq, data, writer })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn seq(&self) -> ValueSeqNum {
|
pub fn seq(&self) -> ValueSeqNum {
|
||||||
self.seq
|
self.seq
|
||||||
}
|
}
|
||||||
@ -62,14 +64,17 @@ impl ValueData {
|
|||||||
&self.writer
|
&self.writer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn data(&self) -> &[u8] {
|
pub fn data(&self) -> &[u8] {
|
||||||
&self.data
|
&self.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn data_size(&self) -> usize {
|
pub fn data_size(&self) -> usize {
|
||||||
self.data.len()
|
self.data.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn total_size(&self) -> usize {
|
pub fn total_size(&self) -> usize {
|
||||||
mem::size_of::<Self>() + self.data.len()
|
mem::size_of::<Self>() + self.data.len()
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ use range_set_blaze::*;
|
|||||||
tsify(from_wasm_abi, into_wasm_abi)
|
tsify(from_wasm_abi, into_wasm_abi)
|
||||||
)]
|
)]
|
||||||
#[serde(transparent)]
|
#[serde(transparent)]
|
||||||
|
#[must_use]
|
||||||
pub struct ValueSubkeyRangeSet {
|
pub struct ValueSubkeyRangeSet {
|
||||||
#[serde(with = "serialize_range_set_blaze")]
|
#[serde(with = "serialize_range_set_blaze")]
|
||||||
#[schemars(with = "Vec<(u32,u32)>")]
|
#[schemars(with = "Vec<(u32,u32)>")]
|
||||||
@ -52,13 +53,16 @@ impl ValueSubkeyRangeSet {
|
|||||||
Self::new_with_data(&self.data | &other.data)
|
Self::new_with_data(&self.data | &other.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn data(&self) -> &RangeSetBlaze<ValueSubkey> {
|
pub fn data(&self) -> &RangeSetBlaze<ValueSubkey> {
|
||||||
&self.data
|
&self.data
|
||||||
}
|
}
|
||||||
|
#[must_use]
|
||||||
pub fn into_data(self) -> RangeSetBlaze<ValueSubkey> {
|
pub fn into_data(self) -> RangeSetBlaze<ValueSubkey> {
|
||||||
self.data
|
self.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn nth_subkey(&self, idx: usize) -> Option<ValueSubkey> {
|
pub fn nth_subkey(&self, idx: usize) -> Option<ValueSubkey> {
|
||||||
let mut idxleft = idx;
|
let mut idxleft = idx;
|
||||||
for range in self.data.ranges() {
|
for range in self.data.ranges() {
|
||||||
@ -71,6 +75,7 @@ impl ValueSubkeyRangeSet {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn idx_of_subkey(&self, subkey: ValueSubkey) -> Option<usize> {
|
pub fn idx_of_subkey(&self, subkey: ValueSubkey) -> Option<usize> {
|
||||||
let mut idx = 0usize;
|
let mut idx = 0usize;
|
||||||
for range in self.data.ranges() {
|
for range in self.data.ranges() {
|
||||||
|
@ -6,6 +6,7 @@ use super::*;
|
|||||||
)]
|
)]
|
||||||
#[serde(try_from = "String")]
|
#[serde(try_from = "String")]
|
||||||
#[serde(into = "String")]
|
#[serde(into = "String")]
|
||||||
|
#[must_use]
|
||||||
pub struct FourCC(pub [u8; 4]);
|
pub struct FourCC(pub [u8; 4]);
|
||||||
|
|
||||||
impl From<[u8; 4]> for FourCC {
|
impl From<[u8; 4]> for FourCC {
|
||||||
|
@ -9,6 +9,7 @@ use super::*;
|
|||||||
derive(Tsify),
|
derive(Tsify),
|
||||||
tsify(from_wasm_abi, into_wasm_abi, namespace)
|
tsify(from_wasm_abi, into_wasm_abi, namespace)
|
||||||
)]
|
)]
|
||||||
|
#[must_use]
|
||||||
pub enum Sequencing {
|
pub enum Sequencing {
|
||||||
NoPreference = 0,
|
NoPreference = 0,
|
||||||
PreferOrdered = 1,
|
PreferOrdered = 1,
|
||||||
@ -31,6 +32,7 @@ impl Default for Sequencing {
|
|||||||
derive(Tsify),
|
derive(Tsify),
|
||||||
tsify(from_wasm_abi, into_wasm_abi, namespace)
|
tsify(from_wasm_abi, into_wasm_abi, namespace)
|
||||||
)]
|
)]
|
||||||
|
#[must_use]
|
||||||
pub enum Stability {
|
pub enum Stability {
|
||||||
LowLatency = 0,
|
LowLatency = 0,
|
||||||
Reliable = 1,
|
Reliable = 1,
|
||||||
@ -52,7 +54,7 @@ impl Default for Stability {
|
|||||||
derive(Tsify),
|
derive(Tsify),
|
||||||
tsify(from_wasm_abi, into_wasm_abi, namespace)
|
tsify(from_wasm_abi, into_wasm_abi, namespace)
|
||||||
)]
|
)]
|
||||||
|
#[must_use]
|
||||||
pub enum SafetySelection {
|
pub enum SafetySelection {
|
||||||
/// Don't use a safety route, only specify the sequencing preference.
|
/// Don't use a safety route, only specify the sequencing preference.
|
||||||
Unsafe(Sequencing),
|
Unsafe(Sequencing),
|
||||||
@ -80,6 +82,7 @@ impl Default for SafetySelection {
|
|||||||
Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema,
|
Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct SafetySpec {
|
pub struct SafetySpec {
|
||||||
/// Preferred safety route set id if it still exists.
|
/// Preferred safety route set id if it still exists.
|
||||||
#[schemars(with = "Option<String>")]
|
#[schemars(with = "Option<String>")]
|
||||||
|
@ -9,6 +9,7 @@ use super::*;
|
|||||||
derive(Tsify),
|
derive(Tsify),
|
||||||
tsify(namespace)
|
tsify(namespace)
|
||||||
)]
|
)]
|
||||||
|
#[must_use]
|
||||||
pub enum VeilidLogLevel {
|
pub enum VeilidLogLevel {
|
||||||
Error = 1,
|
Error = 1,
|
||||||
Warn = 2,
|
Warn = 2,
|
||||||
@ -36,6 +37,7 @@ impl VeilidLogLevel {
|
|||||||
log::Level::Trace => VeilidLogLevel::Trace,
|
log::Level::Trace => VeilidLogLevel::Trace,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[must_use]
|
||||||
pub fn to_tracing_level(&self) -> tracing::Level {
|
pub fn to_tracing_level(&self) -> tracing::Level {
|
||||||
match self {
|
match self {
|
||||||
Self::Error => tracing::Level::ERROR,
|
Self::Error => tracing::Level::ERROR,
|
||||||
@ -45,6 +47,7 @@ impl VeilidLogLevel {
|
|||||||
Self::Trace => tracing::Level::TRACE,
|
Self::Trace => tracing::Level::TRACE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[must_use]
|
||||||
pub fn to_log_level(&self) -> log::Level {
|
pub fn to_log_level(&self) -> log::Level {
|
||||||
match self {
|
match self {
|
||||||
Self::Error => log::Level::Error,
|
Self::Error => log::Level::Error,
|
||||||
|
@ -7,6 +7,7 @@ use super::*;
|
|||||||
derive(Tsify),
|
derive(Tsify),
|
||||||
tsify(namespace, from_wasm_abi, into_wasm_abi)
|
tsify(namespace, from_wasm_abi, into_wasm_abi)
|
||||||
)]
|
)]
|
||||||
|
#[must_use]
|
||||||
pub enum AttachmentState {
|
pub enum AttachmentState {
|
||||||
Detached = 0,
|
Detached = 0,
|
||||||
Attaching = 1,
|
Attaching = 1,
|
||||||
@ -18,9 +19,11 @@ pub enum AttachmentState {
|
|||||||
Detaching = 7,
|
Detaching = 7,
|
||||||
}
|
}
|
||||||
impl AttachmentState {
|
impl AttachmentState {
|
||||||
|
#[must_use]
|
||||||
pub fn is_detached(&self) -> bool {
|
pub fn is_detached(&self) -> bool {
|
||||||
matches!(self, Self::Detached)
|
matches!(self, Self::Detached)
|
||||||
}
|
}
|
||||||
|
#[must_use]
|
||||||
pub fn is_attached(&self) -> bool {
|
pub fn is_attached(&self) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
self,
|
self,
|
||||||
@ -78,6 +81,7 @@ impl TryFrom<&str> for AttachmentState {
|
|||||||
/// Describe the attachment state of the Veilid node
|
/// Describe the attachment state of the Veilid node
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidStateAttachment {
|
pub struct VeilidStateAttachment {
|
||||||
/// The overall quality of the routing table if attached, or the current state the attachment state machine.
|
/// The overall quality of the routing table if attached, or the current state the attachment state machine.
|
||||||
pub state: AttachmentState,
|
pub state: AttachmentState,
|
||||||
@ -95,6 +99,7 @@ pub struct VeilidStateAttachment {
|
|||||||
/// Describe a recently accessed peer
|
/// Describe a recently accessed peer
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct PeerTableData {
|
pub struct PeerTableData {
|
||||||
/// The node ids used by this peer
|
/// The node ids used by this peer
|
||||||
#[schemars(with = "Vec<String>")]
|
#[schemars(with = "Vec<String>")]
|
||||||
@ -112,6 +117,7 @@ pub struct PeerTableData {
|
|||||||
/// Describe the current network state of the Veilid node
|
/// Describe the current network state of the Veilid node
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidStateNetwork {
|
pub struct VeilidStateNetwork {
|
||||||
/// If the network has been started or not.
|
/// If the network has been started or not.
|
||||||
pub started: bool,
|
pub started: bool,
|
||||||
@ -127,6 +133,7 @@ pub struct VeilidStateNetwork {
|
|||||||
/// Describe a private route change that has happened
|
/// Describe a private route change that has happened
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidRouteChange {
|
pub struct VeilidRouteChange {
|
||||||
/// If a private route that was allocated has died, it is listed here.
|
/// If a private route that was allocated has died, it is listed here.
|
||||||
#[schemars(with = "Vec<String>")]
|
#[schemars(with = "Vec<String>")]
|
||||||
@ -142,6 +149,7 @@ pub struct VeilidRouteChange {
|
|||||||
/// itself during runtime.
|
/// itself during runtime.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidStateConfig {
|
pub struct VeilidStateConfig {
|
||||||
/// If the Veilid node configuration has changed the full new config will be here.
|
/// If the Veilid node configuration has changed the full new config will be here.
|
||||||
pub config: VeilidConfigInner,
|
pub config: VeilidConfigInner,
|
||||||
@ -150,6 +158,7 @@ pub struct VeilidStateConfig {
|
|||||||
/// Describe when DHT records have subkey values changed
|
/// Describe when DHT records have subkey values changed
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidValueChange {
|
pub struct VeilidValueChange {
|
||||||
/// The DHT Record key that changed
|
/// The DHT Record key that changed
|
||||||
#[schemars(with = "String")]
|
#[schemars(with = "String")]
|
||||||
@ -176,6 +185,7 @@ pub struct VeilidValueChange {
|
|||||||
tsify(into_wasm_abi)
|
tsify(into_wasm_abi)
|
||||||
)]
|
)]
|
||||||
#[serde(tag = "kind")]
|
#[serde(tag = "kind")]
|
||||||
|
#[must_use]
|
||||||
pub enum VeilidUpdate {
|
pub enum VeilidUpdate {
|
||||||
Log(Box<VeilidLog>),
|
Log(Box<VeilidLog>),
|
||||||
AppMessage(Box<VeilidAppMessage>),
|
AppMessage(Box<VeilidAppMessage>),
|
||||||
@ -196,6 +206,7 @@ from_impl_to_jsvalue!(VeilidUpdate);
|
|||||||
derive(Tsify),
|
derive(Tsify),
|
||||||
tsify(into_wasm_abi)
|
tsify(into_wasm_abi)
|
||||||
)]
|
)]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidState {
|
pub struct VeilidState {
|
||||||
pub attachment: Box<VeilidStateAttachment>,
|
pub attachment: Box<VeilidStateAttachment>,
|
||||||
pub network: Box<VeilidStateNetwork>,
|
pub network: Box<VeilidStateNetwork>,
|
||||||
|
@ -32,6 +32,7 @@ pub type ConfigCallback = Arc<dyn Fn(String) -> ConfigCallbackReturn + Send + Sy
|
|||||||
///
|
///
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigHTTPS {
|
pub struct VeilidConfigHTTPS {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub listen_address: String,
|
pub listen_address: String,
|
||||||
@ -63,6 +64,7 @@ impl Default for VeilidConfigHTTPS {
|
|||||||
///
|
///
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigHTTP {
|
pub struct VeilidConfigHTTP {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub listen_address: String,
|
pub listen_address: String,
|
||||||
@ -90,6 +92,7 @@ impl Default for VeilidConfigHTTP {
|
|||||||
///
|
///
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigApplication {
|
pub struct VeilidConfigApplication {
|
||||||
pub https: VeilidConfigHTTPS,
|
pub https: VeilidConfigHTTPS,
|
||||||
pub http: VeilidConfigHTTP,
|
pub http: VeilidConfigHTTP,
|
||||||
@ -107,6 +110,7 @@ pub struct VeilidConfigApplication {
|
|||||||
///
|
///
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigUDP {
|
pub struct VeilidConfigUDP {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub socket_pool_size: u32,
|
pub socket_pool_size: u32,
|
||||||
@ -145,6 +149,7 @@ impl Default for VeilidConfigUDP {
|
|||||||
///
|
///
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigTCP {
|
pub struct VeilidConfigTCP {
|
||||||
pub connect: bool,
|
pub connect: bool,
|
||||||
pub listen: bool,
|
pub listen: bool,
|
||||||
@ -188,6 +193,7 @@ impl Default for VeilidConfigTCP {
|
|||||||
///
|
///
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigWS {
|
pub struct VeilidConfigWS {
|
||||||
pub connect: bool,
|
pub connect: bool,
|
||||||
pub listen: bool,
|
pub listen: bool,
|
||||||
@ -233,6 +239,7 @@ impl Default for VeilidConfigWS {
|
|||||||
///
|
///
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigWSS {
|
pub struct VeilidConfigWSS {
|
||||||
pub connect: bool,
|
pub connect: bool,
|
||||||
pub listen: bool,
|
pub listen: bool,
|
||||||
@ -265,6 +272,7 @@ impl Default for VeilidConfigWSS {
|
|||||||
///
|
///
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigProtocol {
|
pub struct VeilidConfigProtocol {
|
||||||
pub udp: VeilidConfigUDP,
|
pub udp: VeilidConfigUDP,
|
||||||
pub tcp: VeilidConfigTCP,
|
pub tcp: VeilidConfigTCP,
|
||||||
@ -281,6 +289,7 @@ pub struct VeilidConfigProtocol {
|
|||||||
#[cfg(feature = "geolocation")]
|
#[cfg(feature = "geolocation")]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigPrivacy {
|
pub struct VeilidConfigPrivacy {
|
||||||
pub country_code_denylist: Vec<CountryCode>,
|
pub country_code_denylist: Vec<CountryCode>,
|
||||||
}
|
}
|
||||||
@ -304,6 +313,7 @@ impl Default for VeilidConfigPrivacy {
|
|||||||
#[cfg(feature = "virtual-network")]
|
#[cfg(feature = "virtual-network")]
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigVirtualNetwork {
|
pub struct VeilidConfigVirtualNetwork {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub server_address: String,
|
pub server_address: String,
|
||||||
@ -319,6 +329,7 @@ pub struct VeilidConfigVirtualNetwork {
|
|||||||
///
|
///
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigTLS {
|
pub struct VeilidConfigTLS {
|
||||||
pub certificate_path: String,
|
pub certificate_path: String,
|
||||||
pub private_key_path: String,
|
pub private_key_path: String,
|
||||||
@ -339,6 +350,7 @@ impl Default for VeilidConfigTLS {
|
|||||||
all(target_arch = "wasm32", target_os = "unknown"),
|
all(target_arch = "wasm32", target_os = "unknown"),
|
||||||
allow(unused_variables)
|
allow(unused_variables)
|
||||||
)]
|
)]
|
||||||
|
#[must_use]
|
||||||
pub fn get_default_ssl_directory(
|
pub fn get_default_ssl_directory(
|
||||||
program_name: &str,
|
program_name: &str,
|
||||||
organization: &str,
|
organization: &str,
|
||||||
@ -365,6 +377,7 @@ pub fn get_default_ssl_directory(
|
|||||||
/// for correct DHT operations.
|
/// for correct DHT operations.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigDHT {
|
pub struct VeilidConfigDHT {
|
||||||
pub max_find_node_count: u32,
|
pub max_find_node_count: u32,
|
||||||
pub resolve_node_timeout_ms: u32,
|
pub resolve_node_timeout_ms: u32,
|
||||||
@ -449,6 +462,7 @@ impl Default for VeilidConfigDHT {
|
|||||||
///
|
///
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigRPC {
|
pub struct VeilidConfigRPC {
|
||||||
pub concurrency: u32,
|
pub concurrency: u32,
|
||||||
pub queue_size: u32,
|
pub queue_size: u32,
|
||||||
@ -479,6 +493,7 @@ impl Default for VeilidConfigRPC {
|
|||||||
///
|
///
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigRoutingTable {
|
pub struct VeilidConfigRoutingTable {
|
||||||
#[schemars(with = "Vec<String>")]
|
#[schemars(with = "Vec<String>")]
|
||||||
pub node_id: TypedKeyGroup,
|
pub node_id: TypedKeyGroup,
|
||||||
@ -519,6 +534,7 @@ impl Default for VeilidConfigRoutingTable {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigNetwork {
|
pub struct VeilidConfigNetwork {
|
||||||
pub connection_initial_timeout_ms: u32,
|
pub connection_initial_timeout_ms: u32,
|
||||||
pub connection_inactivity_timeout_ms: u32,
|
pub connection_inactivity_timeout_ms: u32,
|
||||||
@ -578,6 +594,7 @@ impl Default for VeilidConfigNetwork {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigTableStore {
|
pub struct VeilidConfigTableStore {
|
||||||
pub directory: String,
|
pub directory: String,
|
||||||
pub delete: bool,
|
pub delete: bool,
|
||||||
@ -587,6 +604,7 @@ pub struct VeilidConfigTableStore {
|
|||||||
all(target_arch = "wasm32", target_os = "unknown"),
|
all(target_arch = "wasm32", target_os = "unknown"),
|
||||||
allow(unused_variables)
|
allow(unused_variables)
|
||||||
)]
|
)]
|
||||||
|
#[must_use]
|
||||||
fn get_default_store_path(
|
fn get_default_store_path(
|
||||||
program_name: &str,
|
program_name: &str,
|
||||||
organization: &str,
|
organization: &str,
|
||||||
@ -610,6 +628,7 @@ fn get_default_store_path(
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigBlockStore {
|
pub struct VeilidConfigBlockStore {
|
||||||
pub directory: String,
|
pub directory: String,
|
||||||
pub delete: bool,
|
pub delete: bool,
|
||||||
@ -626,6 +645,7 @@ impl Default for VeilidConfigBlockStore {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigProtectedStore {
|
pub struct VeilidConfigProtectedStore {
|
||||||
pub allow_insecure_fallback: bool,
|
pub allow_insecure_fallback: bool,
|
||||||
pub always_use_insecure_storage: bool,
|
pub always_use_insecure_storage: bool,
|
||||||
@ -651,6 +671,7 @@ impl Default for VeilidConfigProtectedStore {
|
|||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigCapabilities {
|
pub struct VeilidConfigCapabilities {
|
||||||
pub disable: Vec<FourCC>,
|
pub disable: Vec<FourCC>,
|
||||||
}
|
}
|
||||||
@ -661,6 +682,7 @@ pub struct VeilidConfigCapabilities {
|
|||||||
all(target_arch = "wasm32", target_os = "unknown"),
|
all(target_arch = "wasm32", target_os = "unknown"),
|
||||||
tsify(namespace, from_wasm_abi)
|
tsify(namespace, from_wasm_abi)
|
||||||
)]
|
)]
|
||||||
|
#[must_use]
|
||||||
pub enum VeilidConfigLogLevel {
|
pub enum VeilidConfigLogLevel {
|
||||||
Off,
|
Off,
|
||||||
Error,
|
Error,
|
||||||
@ -671,6 +693,7 @@ pub enum VeilidConfigLogLevel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl VeilidConfigLogLevel {
|
impl VeilidConfigLogLevel {
|
||||||
|
#[must_use]
|
||||||
pub fn to_veilid_log_level(&self) -> Option<VeilidLogLevel> {
|
pub fn to_veilid_log_level(&self) -> Option<VeilidLogLevel> {
|
||||||
match self {
|
match self {
|
||||||
Self::Off => None,
|
Self::Off => None,
|
||||||
@ -681,6 +704,7 @@ impl VeilidConfigLogLevel {
|
|||||||
Self::Trace => Some(VeilidLogLevel::Trace),
|
Self::Trace => Some(VeilidLogLevel::Trace),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[must_use]
|
||||||
pub fn to_tracing_level_filter(&self) -> level_filters::LevelFilter {
|
pub fn to_tracing_level_filter(&self) -> level_filters::LevelFilter {
|
||||||
match self {
|
match self {
|
||||||
Self::Off => level_filters::LevelFilter::OFF,
|
Self::Off => level_filters::LevelFilter::OFF,
|
||||||
@ -750,6 +774,7 @@ impl fmt::Display for VeilidConfigLogLevel {
|
|||||||
/// Top level of the Veilid configuration tree
|
/// Top level of the Veilid configuration tree
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfigInner {
|
pub struct VeilidConfigInner {
|
||||||
/// An identifier used to describe the program using veilid-core.
|
/// An identifier used to describe the program using veilid-core.
|
||||||
/// Used to partition storage locations in places like the ProtectedStore.
|
/// Used to partition storage locations in places like the ProtectedStore.
|
||||||
@ -857,6 +882,7 @@ impl VeilidConfigInner {
|
|||||||
|
|
||||||
/// The configuration built for each Veilid node during API startup
|
/// The configuration built for each Veilid node during API startup
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
#[must_use]
|
||||||
pub struct VeilidConfig {
|
pub struct VeilidConfig {
|
||||||
update_cb: UpdateCallback,
|
update_cb: UpdateCallback,
|
||||||
inner: Arc<RwLock<VeilidConfigInner>>,
|
inner: Arc<RwLock<VeilidConfigInner>>,
|
||||||
@ -879,18 +905,13 @@ impl VeilidConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new_from_callback(
|
fn get_config_key<T: 'static>(
|
||||||
|
inner_field: &mut T,
|
||||||
|
keyname: &str,
|
||||||
cb: ConfigCallback,
|
cb: ConfigCallback,
|
||||||
update_cb: UpdateCallback,
|
) -> VeilidAPIResult<()> {
|
||||||
) -> VeilidAPIResult<Self> {
|
|
||||||
let mut inner = VeilidConfigInner::default();
|
|
||||||
|
|
||||||
// Simple config transformation
|
|
||||||
macro_rules! get_config {
|
|
||||||
($key:expr) => {
|
|
||||||
let keyname = &stringify!($key)[6..];
|
|
||||||
let v = cb(keyname.to_owned())?;
|
let v = cb(keyname.to_owned())?;
|
||||||
$key = match v.downcast() {
|
*inner_field = match v.downcast() {
|
||||||
Ok(v) => *v,
|
Ok(v) => *v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
apibail_generic!(format!(
|
apibail_generic!(format!(
|
||||||
@ -900,6 +921,19 @@ impl VeilidConfig {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn new_from_callback(
|
||||||
|
cb: ConfigCallback,
|
||||||
|
update_cb: UpdateCallback,
|
||||||
|
) -> VeilidAPIResult<Self> {
|
||||||
|
let mut inner = VeilidConfigInner::default();
|
||||||
|
|
||||||
|
// Simple config transformation
|
||||||
|
macro_rules! get_config {
|
||||||
|
($key:expr) => {
|
||||||
|
Self::get_config_key(&mut $key, &stringify!($key)[6..], cb.clone())?;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1019,6 +1053,7 @@ impl VeilidConfig {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn update_callback(&self) -> UpdateCallback {
|
pub fn update_callback(&self) -> UpdateCallback {
|
||||||
self.update_cb.clone()
|
self.update_cb.clone()
|
||||||
}
|
}
|
||||||
@ -1298,6 +1333,7 @@ impl VeilidConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return the default veilid config as a json object.
|
/// Return the default veilid config as a json object.
|
||||||
|
#[must_use]
|
||||||
pub fn default_veilid_config() -> String {
|
pub fn default_veilid_config() -> String {
|
||||||
serialize_json(VeilidConfigInner::default())
|
serialize_json(VeilidConfigInner::default())
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user