mirror of
https://gitlab.com/veilid/veilid.git
synced 2024-10-01 01:26:08 -04:00
ffi work
This commit is contained in:
parent
d660d86884
commit
70960fa592
104
Cargo.lock
generated
104
Cargo.lock
generated
@ -125,15 +125,6 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ansi_term"
|
|
||||||
version = "0.12.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
|
||||||
dependencies = [
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.53"
|
version = "1.0.53"
|
||||||
@ -707,13 +698,9 @@ version = "2.34.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
|
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
|
||||||
"atty",
|
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"strsim 0.8.0",
|
|
||||||
"textwrap 0.11.0",
|
"textwrap 0.11.0",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
"vec_map",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -726,7 +713,7 @@ dependencies = [
|
|||||||
"bitflags",
|
"bitflags",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"os_str_bytes",
|
"os_str_bytes",
|
||||||
"strsim 0.10.0",
|
"strsim",
|
||||||
"termcolor",
|
"termcolor",
|
||||||
"textwrap 0.14.2",
|
"textwrap 0.14.2",
|
||||||
]
|
]
|
||||||
@ -1148,7 +1135,7 @@ dependencies = [
|
|||||||
"ident_case",
|
"ident_case",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"strsim 0.10.0",
|
"strsim",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1399,6 +1386,16 @@ dependencies = [
|
|||||||
"instant",
|
"instant",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ffi-support"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "27838c6815cfe9de2d3aeb145ffd19e565f577414b33f3bdbf42fe040e9e0ff6"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fixed-hash"
|
name = "fixed-hash"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
@ -1427,26 +1424,6 @@ dependencies = [
|
|||||||
"yansi",
|
"yansi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "flutter_rust_bridge"
|
|
||||||
version = "1.15.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "39ad509fe9fd3ac5a4d10a30a7de9224b74192c65c22338cc958ab0f93f0c834"
|
|
||||||
dependencies = [
|
|
||||||
"allo-isolate",
|
|
||||||
"anyhow",
|
|
||||||
"flutter_rust_bridge_macros",
|
|
||||||
"lazy_static",
|
|
||||||
"parking_lot 0.11.2",
|
|
||||||
"threadpool",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "flutter_rust_bridge_macros"
|
|
||||||
version = "1.15.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "99a2555456c9c12c5982543c61d79267327d522eaa1490ef4914f5ed87b16fe1"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
@ -1900,8 +1877,8 @@ dependencies = [
|
|||||||
"android_logger",
|
"android_logger",
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"cfg-if 0.1.10",
|
"cfg-if 1.0.0",
|
||||||
"clap 2.34.0",
|
"clap 3.0.13",
|
||||||
"core-foundation 0.9.2",
|
"core-foundation 0.9.2",
|
||||||
"core-foundation-sys 0.8.3",
|
"core-foundation-sys 0.8.3",
|
||||||
"directories",
|
"directories",
|
||||||
@ -1912,7 +1889,6 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"ndk",
|
"ndk",
|
||||||
"ndk-glue",
|
"ndk-glue",
|
||||||
"owning_ref",
|
|
||||||
"rpassword",
|
"rpassword",
|
||||||
"secret-service",
|
"secret-service",
|
||||||
"security-framework",
|
"security-framework",
|
||||||
@ -3518,12 +3494,6 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "strsim"
|
|
||||||
version = "0.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
@ -3644,15 +3614,6 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "threadpool"
|
|
||||||
version = "1.8.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
|
|
||||||
dependencies = [
|
|
||||||
"num_cpus",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.1.43"
|
version = "0.1.43"
|
||||||
@ -3871,12 +3832,6 @@ version = "0.2.15"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "vec_map"
|
|
||||||
version = "0.8.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "veilid-cli"
|
name = "veilid-cli"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -3990,13 +3945,26 @@ dependencies = [
|
|||||||
name = "veilid-flutter"
|
name = "veilid-flutter"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"allo-isolate",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-std",
|
"async-std",
|
||||||
|
"backtrace",
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"flutter_rust_bridge",
|
"console_error_panic_hook",
|
||||||
|
"ffi-support",
|
||||||
|
"futures",
|
||||||
|
"js-sys",
|
||||||
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
"parking_lot 0.12.0",
|
"parking_lot 0.12.0",
|
||||||
|
"serde 1.0.136",
|
||||||
|
"serde_json",
|
||||||
"veilid-core",
|
"veilid-core",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"wasm-bindgen-futures",
|
||||||
|
"wasm-bindgen-test",
|
||||||
|
"wasm-logger",
|
||||||
|
"wee_alloc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4030,6 +3998,22 @@ dependencies = [
|
|||||||
"windows-service",
|
"windows-service",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "veilid-wasm"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"console_error_panic_hook",
|
||||||
|
"js-sys",
|
||||||
|
"log",
|
||||||
|
"veilid-core",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"wasm-bindgen-futures",
|
||||||
|
"wasm-bindgen-test",
|
||||||
|
"wasm-logger",
|
||||||
|
"wee_alloc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
|
@ -4,7 +4,8 @@ members = [
|
|||||||
"veilid-core",
|
"veilid-core",
|
||||||
"veilid-server",
|
"veilid-server",
|
||||||
"veilid-cli",
|
"veilid-cli",
|
||||||
"veilid-flutter/rust"
|
"veilid-flutter/rust",
|
||||||
|
"veilid-wasm",
|
||||||
]
|
]
|
||||||
|
|
||||||
exclude = [ "./external/keyring-rs", "./external/netlink", "./external/cursive" ]
|
exclude = [ "./external/keyring-rs", "./external/netlink", "./external/cursive" ]
|
||||||
|
2
external/keyring-manager
vendored
2
external/keyring-manager
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 3713e10599c6078e058aab785ef46594420dc11b
|
Subproject commit 935ca957d7e223ef560a0b20b656730a325e0ba7
|
@ -1,6 +1,6 @@
|
|||||||
|
use crate::core_context::*;
|
||||||
use crate::intf::*;
|
use crate::intf::*;
|
||||||
use crate::veilid_api::*;
|
use crate::veilid_api::*;
|
||||||
use crate::veilid_core::*;
|
|
||||||
use crate::xx::*;
|
use crate::xx::*;
|
||||||
use log::{set_boxed_logger, set_max_level, Level, LevelFilter, Log, Metadata, Record};
|
use log::{set_boxed_logger, set_max_level, Level, LevelFilter, Log, Metadata, Record};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
@ -23,20 +23,12 @@ impl ApiLogger {
|
|||||||
fn new_inner(level: LevelFilter, update_callback: UpdateCallback) -> ApiLoggerInner {
|
fn new_inner(level: LevelFilter, update_callback: UpdateCallback) -> ApiLoggerInner {
|
||||||
let (tx, rx) = async_channel::unbounded::<(VeilidLogLevel, String)>();
|
let (tx, rx) = async_channel::unbounded::<(VeilidLogLevel, String)>();
|
||||||
let _join_handle: JoinHandle<()> = spawn(async move {
|
let _join_handle: JoinHandle<()> = spawn(async move {
|
||||||
loop {
|
while let Ok(v) = rx.recv().await {
|
||||||
match rx.recv().await {
|
(update_callback)(VeilidUpdate::Log {
|
||||||
Ok(v) => {
|
log_level: v.0,
|
||||||
(update_callback)(VeilidUpdate::Log {
|
message: v.1,
|
||||||
log_level: v.0,
|
})
|
||||||
message: v.1,
|
.await;
|
||||||
})
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
// Nothing to be done here...
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ApiLoggerInner {
|
ApiLoggerInner {
|
||||||
|
@ -6,9 +6,10 @@ use crate::xx::*;
|
|||||||
use crate::*;
|
use crate::*;
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
use serde::*;
|
||||||
|
|
||||||
state_machine! {
|
state_machine! {
|
||||||
derive(Debug, PartialEq, Eq, Clone, Copy)
|
derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)
|
||||||
pub Attachment(Detached)
|
pub Attachment(Detached)
|
||||||
//---
|
//---
|
||||||
Detached(AttachRequested) => Attaching [StartAttachment],
|
Detached(AttachRequested) => Attaching [StartAttachment],
|
||||||
@ -102,8 +103,6 @@ impl TryFrom<String> for AttachmentState {
|
|||||||
|
|
||||||
pub struct AttachmentManagerInner {
|
pub struct AttachmentManagerInner {
|
||||||
config: VeilidConfig,
|
config: VeilidConfig,
|
||||||
table_store: TableStore,
|
|
||||||
crypto: Crypto,
|
|
||||||
attachment_machine: CallbackStateMachine<Attachment>,
|
attachment_machine: CallbackStateMachine<Attachment>,
|
||||||
network_manager: NetworkManager,
|
network_manager: NetworkManager,
|
||||||
maintain_peers: bool,
|
maintain_peers: bool,
|
||||||
@ -125,8 +124,6 @@ impl AttachmentManager {
|
|||||||
) -> AttachmentManagerInner {
|
) -> AttachmentManagerInner {
|
||||||
AttachmentManagerInner {
|
AttachmentManagerInner {
|
||||||
config: config.clone(),
|
config: config.clone(),
|
||||||
table_store: table_store.clone(),
|
|
||||||
crypto: crypto.clone(),
|
|
||||||
attachment_machine: CallbackStateMachine::new(),
|
attachment_machine: CallbackStateMachine::new(),
|
||||||
network_manager: NetworkManager::new(config, table_store, crypto),
|
network_manager: NetworkManager::new(config, table_store, crypto),
|
||||||
maintain_peers: false,
|
maintain_peers: false,
|
||||||
@ -145,14 +142,6 @@ impl AttachmentManager {
|
|||||||
self.inner.lock().config.clone()
|
self.inner.lock().config.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn table_store(&self) -> TableStore {
|
|
||||||
self.inner.lock().table_store.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn crypto(&self) -> Crypto {
|
|
||||||
self.inner.lock().crypto.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn network_manager(&self) -> NetworkManager {
|
pub fn network_manager(&self) -> NetworkManager {
|
||||||
self.inner.lock().network_manager.clone()
|
self.inner.lock().network_manager.clone()
|
||||||
}
|
}
|
||||||
@ -274,20 +263,26 @@ impl AttachmentManager {
|
|||||||
&self,
|
&self,
|
||||||
state_change_callback: StateChangeCallback<Attachment>,
|
state_change_callback: StateChangeCallback<Attachment>,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let inner = self.inner.lock();
|
let network_manager = {
|
||||||
inner
|
let inner = self.inner.lock();
|
||||||
.attachment_machine
|
inner
|
||||||
.set_state_change_callback(state_change_callback);
|
.attachment_machine
|
||||||
|
.set_state_change_callback(state_change_callback);
|
||||||
|
inner.network_manager.clone()
|
||||||
|
};
|
||||||
|
|
||||||
inner.network_manager.init().await?;
|
network_manager.init().await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub async fn terminate(&self) {
|
pub async fn terminate(&self) {
|
||||||
// Ensure we detached
|
// Ensure we detached
|
||||||
self.detach().await;
|
self.detach().await;
|
||||||
let inner = self.inner.lock();
|
let network_manager = {
|
||||||
inner.network_manager.terminate().await;
|
let inner = self.inner.lock();
|
||||||
|
inner.network_manager.clone()
|
||||||
|
};
|
||||||
|
network_manager.terminate().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attach(&self) {
|
fn attach(&self) {
|
||||||
|
197
veilid-core/src/core_context.rs
Normal file
197
veilid-core/src/core_context.rs
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
use crate::api_logger::*;
|
||||||
|
use crate::attachment_manager::*;
|
||||||
|
use crate::dht::crypto::Crypto;
|
||||||
|
use crate::intf::*;
|
||||||
|
use crate::veilid_api::*;
|
||||||
|
use crate::veilid_config::*;
|
||||||
|
use crate::xx::*;
|
||||||
|
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(target_arch = "wasm32")] {
|
||||||
|
pub type UpdateCallback = Arc<dyn Fn(VeilidUpdate) -> SystemPinBoxFuture<()>>;
|
||||||
|
} else {
|
||||||
|
pub type UpdateCallback = Arc<dyn Fn(VeilidUpdate) -> SystemPinBoxFuture<()> + Send + Sync>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct VeilidCoreSetup {
|
||||||
|
pub update_callback: UpdateCallback,
|
||||||
|
pub config_callback: ConfigCallback,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct VeilidCoreContext {
|
||||||
|
pub config: VeilidConfig,
|
||||||
|
pub protected_store: ProtectedStore,
|
||||||
|
pub table_store: TableStore,
|
||||||
|
pub block_store: BlockStore,
|
||||||
|
pub crypto: Crypto,
|
||||||
|
pub attachment_manager: AttachmentManager,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VeilidCoreContext {
|
||||||
|
async fn new(setup: VeilidCoreSetup) -> Result<VeilidCoreContext, VeilidAPIError> {
|
||||||
|
// Start up api logging early if it's in the config
|
||||||
|
let api_log_level: VeilidConfigLogLevel =
|
||||||
|
*(setup.config_callback)("api_log_level".to_owned())
|
||||||
|
.map_err(|e| VeilidAPIError::ParseError {
|
||||||
|
message: "Failed to get api_log_level".to_owned(),
|
||||||
|
value: e,
|
||||||
|
})?
|
||||||
|
.downcast()
|
||||||
|
.map_err(|e| VeilidAPIError::ParseError {
|
||||||
|
message: "Incorrect type for key 'api_log_level'".to_owned(),
|
||||||
|
value: format!("Invalid type: {:?}", e.type_id()),
|
||||||
|
})?;
|
||||||
|
if api_log_level != VeilidConfigLogLevel::Off {
|
||||||
|
ApiLogger::init(
|
||||||
|
api_log_level.to_level_filter(),
|
||||||
|
setup.update_callback.clone(),
|
||||||
|
);
|
||||||
|
for ig in crate::DEFAULT_LOG_IGNORE_LIST {
|
||||||
|
ApiLogger::add_filter_ignore_str(ig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trace!("VeilidCoreContext::new starting");
|
||||||
|
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(target_os = "android")] {
|
||||||
|
if utils::android::ANDROID_GLOBALS.lock().is_none() {
|
||||||
|
error!("Android globals are not set up");
|
||||||
|
return Err("Android globals are not set up".to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up config
|
||||||
|
trace!("VeilidCoreContext::new init config");
|
||||||
|
let mut config = VeilidConfig::new();
|
||||||
|
if let Err(e) = config.init(setup.config_callback).await {
|
||||||
|
ApiLogger::terminate();
|
||||||
|
return Err(VeilidAPIError::Internal(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up protected store
|
||||||
|
trace!("VeilidCoreContext::new init protected store");
|
||||||
|
let protected_store = ProtectedStore::new(config.clone());
|
||||||
|
if let Err(e) = protected_store.init().await {
|
||||||
|
config.terminate().await;
|
||||||
|
ApiLogger::terminate();
|
||||||
|
return Err(VeilidAPIError::Internal(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init node id from config now that protected store is set up
|
||||||
|
if let Err(e) = config.init_node_id(protected_store.clone()).await {
|
||||||
|
protected_store.terminate().await;
|
||||||
|
config.terminate().await;
|
||||||
|
ApiLogger::terminate();
|
||||||
|
return Err(VeilidAPIError::Internal(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up tablestore
|
||||||
|
trace!("VeilidCoreContext::new init table store");
|
||||||
|
let table_store = TableStore::new(config.clone());
|
||||||
|
if let Err(e) = table_store.init().await {
|
||||||
|
protected_store.terminate().await;
|
||||||
|
config.terminate().await;
|
||||||
|
ApiLogger::terminate();
|
||||||
|
return Err(VeilidAPIError::Internal(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up crypto
|
||||||
|
trace!("VeilidCoreContext::new init crypto");
|
||||||
|
let crypto = Crypto::new(config.clone(), table_store.clone());
|
||||||
|
if let Err(e) = crypto.init().await {
|
||||||
|
table_store.terminate().await;
|
||||||
|
protected_store.terminate().await;
|
||||||
|
config.terminate().await;
|
||||||
|
ApiLogger::terminate();
|
||||||
|
return Err(VeilidAPIError::Internal(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up block store
|
||||||
|
trace!("VeilidCoreContext::new init block store");
|
||||||
|
let block_store = BlockStore::new(config.clone());
|
||||||
|
if let Err(e) = block_store.init().await {
|
||||||
|
crypto.terminate().await;
|
||||||
|
table_store.terminate().await;
|
||||||
|
protected_store.terminate().await;
|
||||||
|
config.terminate().await;
|
||||||
|
ApiLogger::terminate();
|
||||||
|
return Err(VeilidAPIError::Internal(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up attachment manager
|
||||||
|
trace!("VeilidCoreContext::new init attachment manager");
|
||||||
|
let cb = setup.update_callback;
|
||||||
|
let attachment_manager =
|
||||||
|
AttachmentManager::new(config.clone(), table_store.clone(), crypto.clone());
|
||||||
|
if let Err(e) = attachment_manager
|
||||||
|
.init(Arc::new(
|
||||||
|
move |_old_state: AttachmentState, new_state: AttachmentState| {
|
||||||
|
cb(VeilidUpdate::Attachment(new_state))
|
||||||
|
},
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
block_store.terminate().await;
|
||||||
|
crypto.terminate().await;
|
||||||
|
table_store.terminate().await;
|
||||||
|
protected_store.terminate().await;
|
||||||
|
config.terminate().await;
|
||||||
|
ApiLogger::terminate();
|
||||||
|
return Err(VeilidAPIError::Internal(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(VeilidCoreContext {
|
||||||
|
config,
|
||||||
|
protected_store,
|
||||||
|
table_store,
|
||||||
|
block_store,
|
||||||
|
crypto,
|
||||||
|
attachment_manager,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn shutdown(self) {
|
||||||
|
trace!("VeilidCoreContext::terminate_core_context starting");
|
||||||
|
|
||||||
|
self.attachment_manager.terminate().await;
|
||||||
|
self.block_store.terminate().await;
|
||||||
|
self.crypto.terminate().await;
|
||||||
|
self.table_store.terminate().await;
|
||||||
|
self.protected_store.terminate().await;
|
||||||
|
self.config.terminate().await;
|
||||||
|
|
||||||
|
trace!("VeilidCoreContext::shutdown complete");
|
||||||
|
ApiLogger::terminate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static INITIALIZED: AsyncMutex<bool> = AsyncMutex::new(false);
|
||||||
|
|
||||||
|
pub async fn api_startup(setup: VeilidCoreSetup) -> Result<VeilidAPI, VeilidAPIError> {
|
||||||
|
// See if we have an API started up already
|
||||||
|
let mut initialized_lock = INITIALIZED.lock().await;
|
||||||
|
if *initialized_lock {
|
||||||
|
return Err(VeilidAPIError::AlreadyInitialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create core context
|
||||||
|
let context = VeilidCoreContext::new(setup).await?;
|
||||||
|
|
||||||
|
// Return an API object around our context
|
||||||
|
let veilid_api = VeilidAPI::new(context);
|
||||||
|
|
||||||
|
*initialized_lock = true;
|
||||||
|
|
||||||
|
Ok(veilid_api)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn api_shutdown(context: VeilidCoreContext) {
|
||||||
|
let mut initialized_lock = INITIALIZED.lock().await;
|
||||||
|
context.shutdown().await;
|
||||||
|
*initialized_lock = false;
|
||||||
|
}
|
@ -94,38 +94,43 @@ impl Crypto {
|
|||||||
trace!("Crypto::init");
|
trace!("Crypto::init");
|
||||||
|
|
||||||
// make local copy of node id for easy access
|
// make local copy of node id for easy access
|
||||||
let mut inner = self.inner.lock();
|
let (table_store, node_id) = {
|
||||||
let c = self.config.get();
|
let mut inner = self.inner.lock();
|
||||||
inner.node_id = c.network.node_id;
|
let c = self.config.get();
|
||||||
inner.node_id_secret = c.network.node_id_secret;
|
inner.node_id = c.network.node_id;
|
||||||
|
inner.node_id_secret = c.network.node_id_secret;
|
||||||
|
(inner.table_store.clone(), c.network.node_id)
|
||||||
|
};
|
||||||
|
|
||||||
// load caches if they are valid for this node id
|
// load caches if they are valid for this node id
|
||||||
let mut db = inner.table_store.open("crypto_caches", 1).await?;
|
let mut db = table_store.open("crypto_caches", 1).await?;
|
||||||
let caches_valid = match db.load(0, b"node_id").await? {
|
let caches_valid = match db.load(0, b"node_id").await? {
|
||||||
Some(v) => v.as_slice() == inner.node_id.bytes,
|
Some(v) => v.as_slice() == node_id.bytes,
|
||||||
None => false,
|
None => false,
|
||||||
};
|
};
|
||||||
if caches_valid {
|
if caches_valid {
|
||||||
if let Some(b) = db.load(0, b"dh_cache").await? {
|
if let Some(b) = db.load(0, b"dh_cache").await? {
|
||||||
|
let mut inner = self.inner.lock();
|
||||||
bytes_to_cache(&b, &mut inner.dh_cache);
|
bytes_to_cache(&b, &mut inner.dh_cache);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
drop(db);
|
drop(db);
|
||||||
inner.table_store.delete("crypto_caches").await?;
|
table_store.delete("crypto_caches").await?;
|
||||||
db = inner.table_store.open("crypto_caches", 1).await?;
|
db = table_store.open("crypto_caches", 1).await?;
|
||||||
db.store(0, b"node_id", &inner.node_id.bytes).await?;
|
db.store(0, b"node_id", &node_id.bytes).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schedule flushing
|
// Schedule flushing
|
||||||
let this = self.clone();
|
let this = self.clone();
|
||||||
inner.flush_future = Some(Box::pin(interval(60000, move || {
|
let flush_future = interval(60000, move || {
|
||||||
let this = this.clone();
|
let this = this.clone();
|
||||||
async move {
|
async move {
|
||||||
if let Err(e) = this.flush().await {
|
if let Err(e) = this.flush().await {
|
||||||
warn!("flush failed: {}", e);
|
warn!("flush failed: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})));
|
});
|
||||||
|
self.inner.lock().flush_future = Some(flush_future);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -161,21 +166,23 @@ impl Crypto {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ed25519_to_x25519_pk(key: &ed::PublicKey) -> Result<xd::PublicKey, ()> {
|
fn ed25519_to_x25519_pk(key: &ed::PublicKey) -> Result<xd::PublicKey, String> {
|
||||||
let bytes = key.to_bytes();
|
let bytes = key.to_bytes();
|
||||||
let compressed = cd::edwards::CompressedEdwardsY(bytes);
|
let compressed = cd::edwards::CompressedEdwardsY(bytes);
|
||||||
let point = compressed.decompress().ok_or(())?;
|
let point = compressed
|
||||||
|
.decompress()
|
||||||
|
.ok_or_else(fn_string!("ed25519_to_x25519_pk failed"))?;
|
||||||
let mp = point.to_montgomery();
|
let mp = point.to_montgomery();
|
||||||
Ok(xd::PublicKey::from(mp.to_bytes()))
|
Ok(xd::PublicKey::from(mp.to_bytes()))
|
||||||
}
|
}
|
||||||
fn ed25519_to_x25519_sk(key: &ed::SecretKey) -> Result<xd::StaticSecret, ()> {
|
fn ed25519_to_x25519_sk(key: &ed::SecretKey) -> Result<xd::StaticSecret, String> {
|
||||||
let exp = ed::ExpandedSecretKey::from(key);
|
let exp = ed::ExpandedSecretKey::from(key);
|
||||||
let bytes: [u8; ed::EXPANDED_SECRET_KEY_LENGTH] = exp.to_bytes();
|
let bytes: [u8; ed::EXPANDED_SECRET_KEY_LENGTH] = exp.to_bytes();
|
||||||
let lowbytes: [u8; 32] = bytes[0..32].try_into().map_err(drop)?;
|
let lowbytes: [u8; 32] = bytes[0..32].try_into().map_err(map_to_string)?;
|
||||||
Ok(xd::StaticSecret::from(lowbytes))
|
Ok(xd::StaticSecret::from(lowbytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cached_dh(&self, key: &DHTKey, secret: &DHTKeySecret) -> Result<SharedSecret, ()> {
|
pub fn cached_dh(&self, key: &DHTKey, secret: &DHTKeySecret) -> Result<SharedSecret, String> {
|
||||||
if let Some(c) = self
|
if let Some(c) = self
|
||||||
.inner
|
.inner
|
||||||
.lock()
|
.lock()
|
||||||
@ -197,24 +204,12 @@ impl Crypto {
|
|||||||
///////////
|
///////////
|
||||||
// These are safe to use regardless of initialization status
|
// These are safe to use regardless of initialization status
|
||||||
|
|
||||||
pub fn compute_dh(key: &DHTKey, secret: &DHTKeySecret) -> Result<SharedSecret, ()> {
|
pub fn compute_dh(key: &DHTKey, secret: &DHTKeySecret) -> Result<SharedSecret, String> {
|
||||||
assert!(key.valid);
|
assert!(key.valid);
|
||||||
assert!(secret.valid);
|
assert!(secret.valid);
|
||||||
let pk_ed = match ed::PublicKey::from_bytes(&key.bytes) {
|
let pk_ed = ed::PublicKey::from_bytes(&key.bytes).map_err(map_to_string)?;
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => {
|
|
||||||
trace!("compute_dh error: {:?}", e);
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let pk_xd = Self::ed25519_to_x25519_pk(&pk_ed)?;
|
let pk_xd = Self::ed25519_to_x25519_pk(&pk_ed)?;
|
||||||
let sk_ed = match ed::SecretKey::from_bytes(&secret.bytes) {
|
let sk_ed = ed::SecretKey::from_bytes(&secret.bytes).map_err(map_to_string)?;
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => {
|
|
||||||
trace!("compute_dh error: {:?}", e);
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let sk_xd = Self::ed25519_to_x25519_sk(&sk_ed)?;
|
let sk_xd = Self::ed25519_to_x25519_sk(&sk_ed)?;
|
||||||
Ok(sk_xd.diffie_hellman(&pk_xd).to_bytes())
|
Ok(sk_xd.diffie_hellman(&pk_xd).to_bytes())
|
||||||
}
|
}
|
||||||
@ -236,12 +231,13 @@ impl Crypto {
|
|||||||
nonce: &Nonce,
|
nonce: &Nonce,
|
||||||
shared_secret: &SharedSecret,
|
shared_secret: &SharedSecret,
|
||||||
associated_data: Option<&[u8]>,
|
associated_data: Option<&[u8]>,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), String> {
|
||||||
let key = ch::Key::from(*shared_secret);
|
let key = ch::Key::from(*shared_secret);
|
||||||
let xnonce = ch::XNonce::from(*nonce);
|
let xnonce = ch::XNonce::from(*nonce);
|
||||||
let aead = ch::XChaCha20Poly1305::new(&key);
|
let aead = ch::XChaCha20Poly1305::new(&key);
|
||||||
aead.decrypt_in_place(&xnonce, associated_data.unwrap_or(b""), body)
|
aead.decrypt_in_place(&xnonce, associated_data.unwrap_or(b""), body)
|
||||||
.map_err(|e| trace!("decryption failure: {}", e))
|
.map_err(map_to_string)
|
||||||
|
.map_err(logthru_crypto!())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decrypt(
|
pub fn decrypt(
|
||||||
@ -249,9 +245,11 @@ impl Crypto {
|
|||||||
nonce: &Nonce,
|
nonce: &Nonce,
|
||||||
shared_secret: &SharedSecret,
|
shared_secret: &SharedSecret,
|
||||||
associated_data: Option<&[u8]>,
|
associated_data: Option<&[u8]>,
|
||||||
) -> Result<Vec<u8>, ()> {
|
) -> Result<Vec<u8>, String> {
|
||||||
let mut out = body.to_vec();
|
let mut out = body.to_vec();
|
||||||
Self::decrypt_in_place(&mut out, nonce, shared_secret, associated_data)?;
|
Self::decrypt_in_place(&mut out, nonce, shared_secret, associated_data)
|
||||||
|
.map_err(map_to_string)
|
||||||
|
.map_err(logthru_crypto!())?;
|
||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,13 +258,14 @@ impl Crypto {
|
|||||||
nonce: &Nonce,
|
nonce: &Nonce,
|
||||||
shared_secret: &SharedSecret,
|
shared_secret: &SharedSecret,
|
||||||
associated_data: Option<&[u8]>,
|
associated_data: Option<&[u8]>,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), String> {
|
||||||
let key = ch::Key::from(*shared_secret);
|
let key = ch::Key::from(*shared_secret);
|
||||||
let xnonce = ch::XNonce::from(*nonce);
|
let xnonce = ch::XNonce::from(*nonce);
|
||||||
let aead = ch::XChaCha20Poly1305::new(&key);
|
let aead = ch::XChaCha20Poly1305::new(&key);
|
||||||
|
|
||||||
aead.encrypt_in_place(&xnonce, associated_data.unwrap_or(b""), body)
|
aead.encrypt_in_place(&xnonce, associated_data.unwrap_or(b""), body)
|
||||||
.map_err(|e| trace!("encryption failure: {}", e))
|
.map_err(map_to_string)
|
||||||
|
.map_err(logthru_crypto!())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encrypt(
|
pub fn encrypt(
|
||||||
@ -274,9 +273,11 @@ impl Crypto {
|
|||||||
nonce: &Nonce,
|
nonce: &Nonce,
|
||||||
shared_secret: &SharedSecret,
|
shared_secret: &SharedSecret,
|
||||||
associated_data: Option<&[u8]>,
|
associated_data: Option<&[u8]>,
|
||||||
) -> Result<Vec<u8>, ()> {
|
) -> Result<Vec<u8>, String> {
|
||||||
let mut out = body.to_vec();
|
let mut out = body.to_vec();
|
||||||
Self::encrypt_in_place(&mut out, nonce, shared_secret, associated_data)?;
|
Self::encrypt_in_place(&mut out, nonce, shared_secret, associated_data)
|
||||||
|
.map_err(map_to_string)
|
||||||
|
.map_err(logthru_crypto!())?;
|
||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,7 +172,7 @@ impl Envelope {
|
|||||||
crypto: Crypto,
|
crypto: Crypto,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
node_id_secret: &DHTKeySecret,
|
node_id_secret: &DHTKeySecret,
|
||||||
) -> Result<Vec<u8>, ()> {
|
) -> Result<Vec<u8>, String> {
|
||||||
// Get DH secret
|
// Get DH secret
|
||||||
let dh_secret = crypto.cached_dh(&self.sender_id, node_id_secret)?;
|
let dh_secret = crypto.cached_dh(&self.sender_id, node_id_secret)?;
|
||||||
|
|
||||||
|
@ -1,2 +1,30 @@
|
|||||||
//use crate::intf::*;
|
use crate::intf::*;
|
||||||
//use crate::xx::*;
|
use crate::*;
|
||||||
|
|
||||||
|
struct BlockStoreInner {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct BlockStore {
|
||||||
|
config: VeilidConfig,
|
||||||
|
inner: Arc<Mutex<BlockStoreInner>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlockStore {
|
||||||
|
fn new_inner() -> BlockStoreInner {
|
||||||
|
BlockStoreInner {}
|
||||||
|
}
|
||||||
|
pub fn new(config: VeilidConfig) -> Self {
|
||||||
|
Self {
|
||||||
|
config,
|
||||||
|
inner: Arc::new(Mutex::new(Self::new_inner())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn init(&self) -> Result<(), String> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn terminate(&self) {}
|
||||||
|
}
|
||||||
|
@ -2,7 +2,7 @@ mod block_store;
|
|||||||
mod network;
|
mod network;
|
||||||
mod protected_store;
|
mod protected_store;
|
||||||
mod system;
|
mod system;
|
||||||
pub mod table_store;
|
mod table_store;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
pub use block_store::*;
|
pub use block_store::*;
|
||||||
|
@ -44,8 +44,8 @@ impl ProtectedStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn init(&self) -> Result<(), String> {
|
pub async fn init(&self) -> Result<(), String> {
|
||||||
let c = self.config.get();
|
let delete = {
|
||||||
{
|
let c = self.config.get();
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
if !c.protected_store.always_use_insecure_storage {
|
if !c.protected_store.always_use_insecure_storage {
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
@ -74,9 +74,10 @@ impl ProtectedStore {
|
|||||||
if inner.keyring_manager.is_none() {
|
if inner.keyring_manager.is_none() {
|
||||||
return Err("Could not initialize the protected store.".to_owned());
|
return Err("Could not initialize the protected store.".to_owned());
|
||||||
}
|
}
|
||||||
}
|
c.protected_store.delete
|
||||||
|
};
|
||||||
|
|
||||||
if c.protected_store.delete {
|
if delete {
|
||||||
self.delete_all().await?;
|
self.delete_all().await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,29 +24,6 @@ lazy_static! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn veilid_core_setup_android_no_log<'a>(env: JNIEnv<'a>, ctx: JObject<'a>) {
|
pub fn veilid_core_setup_android_no_log<'a>(env: JNIEnv<'a>, ctx: JObject<'a>) {
|
||||||
panic::set_hook(Box::new(|panic_info| {
|
|
||||||
let bt = Backtrace::new();
|
|
||||||
if let Some(location) = panic_info.location() {
|
|
||||||
error!(
|
|
||||||
"panic occurred in file '{}' at line {}",
|
|
||||||
location.file(),
|
|
||||||
location.line(),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
error!("panic occurred but can't get location information...");
|
|
||||||
}
|
|
||||||
if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
|
|
||||||
error!("panic payload: {:?}", s);
|
|
||||||
} else if let Some(s) = panic_info.payload().downcast_ref::<String>() {
|
|
||||||
error!("panic payload: {:?}", s);
|
|
||||||
} else if let Some(a) = panic_info.payload().downcast_ref::<std::fmt::Arguments>() {
|
|
||||||
error!("panic payload: {:?}", a);
|
|
||||||
} else {
|
|
||||||
error!("no panic payload");
|
|
||||||
}
|
|
||||||
error!("Backtrace:\n{:?}", bt);
|
|
||||||
}));
|
|
||||||
|
|
||||||
*ANDROID_GLOBALS.lock() = Some(AndroidGlobals {
|
*ANDROID_GLOBALS.lock() = Some(AndroidGlobals {
|
||||||
vm: env.get_java_vm().unwrap(),
|
vm: env.get_java_vm().unwrap(),
|
||||||
ctx: env.new_global_ref(ctx).unwrap(),
|
ctx: env.new_global_ref(ctx).unwrap(),
|
||||||
@ -70,6 +47,29 @@ pub fn veilid_core_setup_android<'a>(
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
panic::set_hook(Box::new(|panic_info| {
|
||||||
|
let bt = Backtrace::new();
|
||||||
|
if let Some(location) = panic_info.location() {
|
||||||
|
error!(
|
||||||
|
"panic occurred in file '{}' at line {}",
|
||||||
|
location.file(),
|
||||||
|
location.line(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
error!("panic occurred but can't get location information...");
|
||||||
|
}
|
||||||
|
if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
|
||||||
|
error!("panic payload: {:?}", s);
|
||||||
|
} else if let Some(s) = panic_info.payload().downcast_ref::<String>() {
|
||||||
|
error!("panic payload: {:?}", s);
|
||||||
|
} else if let Some(a) = panic_info.payload().downcast_ref::<std::fmt::Arguments>() {
|
||||||
|
error!("panic payload: {:?}", a);
|
||||||
|
} else {
|
||||||
|
error!("no panic payload");
|
||||||
|
}
|
||||||
|
error!("Backtrace:\n{:?}", bt);
|
||||||
|
}));
|
||||||
|
|
||||||
veilid_core_setup_android_no_log(env, ctx);
|
veilid_core_setup_android_no_log(env, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1 +1,31 @@
|
|||||||
|
|
||||||
|
use crate::intf::*;
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
struct BlockStoreInner {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct BlockStore {
|
||||||
|
config: VeilidConfig,
|
||||||
|
inner: Arc<Mutex<BlockStoreInner>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlockStore {
|
||||||
|
fn new_inner() -> BlockStoreInner {
|
||||||
|
BlockStoreInner {}
|
||||||
|
}
|
||||||
|
pub fn new(config: VeilidConfig) -> Self {
|
||||||
|
Self {
|
||||||
|
config,
|
||||||
|
inner: Arc::new(Mutex::new(Self::new_inner())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn init(&self) -> Result<(), String> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn terminate(&self) {}
|
||||||
|
}
|
||||||
|
@ -78,7 +78,7 @@ impl WebsocketProtocolHandler {
|
|||||||
assert!(local_address.is_none());
|
assert!(local_address.is_none());
|
||||||
|
|
||||||
// Split dial info up
|
// Split dial info up
|
||||||
let (tls, scheme) = match &dial_info {
|
let (_tls, scheme) = match &dial_info {
|
||||||
DialInfo::WS(_) => (false, "ws"),
|
DialInfo::WS(_) => (false, "ws"),
|
||||||
DialInfo::WSS(_) => (true, "wss"),
|
DialInfo::WSS(_) => (true, "wss"),
|
||||||
_ => panic!("invalid dialinfo for WS/WSS protocol"),
|
_ => panic!("invalid dialinfo for WS/WSS protocol"),
|
||||||
|
@ -9,6 +9,7 @@ mod attachment_manager;
|
|||||||
mod callback_state_machine;
|
mod callback_state_machine;
|
||||||
mod connection_manager;
|
mod connection_manager;
|
||||||
mod connection_table;
|
mod connection_table;
|
||||||
|
mod core_context;
|
||||||
mod dht;
|
mod dht;
|
||||||
mod intf;
|
mod intf;
|
||||||
mod lease_manager;
|
mod lease_manager;
|
||||||
@ -19,16 +20,15 @@ mod routing_table;
|
|||||||
mod rpc_processor;
|
mod rpc_processor;
|
||||||
mod veilid_api;
|
mod veilid_api;
|
||||||
mod veilid_config;
|
mod veilid_config;
|
||||||
mod veilid_core;
|
|
||||||
mod veilid_rng;
|
mod veilid_rng;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod xx;
|
pub mod xx;
|
||||||
|
|
||||||
pub use self::attachment_manager::AttachmentState;
|
pub use self::attachment_manager::AttachmentState;
|
||||||
|
pub use self::core_context::{api_startup, VeilidCoreSetup};
|
||||||
pub use self::veilid_api::*;
|
pub use self::veilid_api::*;
|
||||||
pub use self::veilid_config::*;
|
pub use self::veilid_config::*;
|
||||||
pub use self::veilid_core::{VeilidCore, VeilidCoreSetup};
|
|
||||||
|
|
||||||
pub mod veilid_capnp {
|
pub mod veilid_capnp {
|
||||||
include!(concat!(env!("OUT_DIR"), "/proto/veilid_capnp.rs"));
|
include!(concat!(env!("OUT_DIR"), "/proto/veilid_capnp.rs"));
|
||||||
@ -47,7 +47,7 @@ pub fn veilid_version() -> (u32, u32, u32) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub static DEFAULT_LOG_IGNORE_LIST: [&'static str; 8] = [
|
pub static DEFAULT_LOG_IGNORE_LIST: [&str; 8] = [
|
||||||
"async_std",
|
"async_std",
|
||||||
"async_io",
|
"async_io",
|
||||||
"polling",
|
"polling",
|
||||||
|
@ -170,10 +170,12 @@ impl NetworkManager {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub async fn terminate(&self) {
|
pub async fn terminate(&self) {
|
||||||
let mut inner = self.inner.lock();
|
let routing_table = {
|
||||||
if let Some(routing_table) = &inner.routing_table {
|
let mut inner = self.inner.lock();
|
||||||
|
inner.routing_table.take()
|
||||||
|
};
|
||||||
|
if let Some(routing_table) = routing_table {
|
||||||
routing_table.terminate().await;
|
routing_table.terminate().await;
|
||||||
inner.routing_table = None;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,10 +19,9 @@ fn setup_veilid_core() -> VeilidCoreSetup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn startup(core: VeilidCore) -> VeilidAPI {
|
async fn startup() -> VeilidAPI {
|
||||||
trace!("test_table_store: starting");
|
trace!("test_table_store: starting");
|
||||||
let api = core
|
let api = api_startup(setup_veilid_core())
|
||||||
.startup(setup_veilid_core())
|
|
||||||
.await
|
.await
|
||||||
.expect("startup failed");
|
.expect("startup failed");
|
||||||
api
|
api
|
||||||
@ -130,9 +129,8 @@ pub async fn test_dh(crypto: Crypto) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_all() {
|
pub async fn test_all() {
|
||||||
let core = VeilidCore::new();
|
let api = startup().await;
|
||||||
let api = startup(core.clone()).await;
|
let crypto = api.crypto().unwrap();
|
||||||
let crypto = core.crypto();
|
|
||||||
test_enc_dec().await;
|
test_enc_dec().await;
|
||||||
test_dh(crypto).await;
|
test_dh(crypto).await;
|
||||||
shutdown(api.clone()).await;
|
shutdown(api.clone()).await;
|
||||||
|
@ -8,13 +8,12 @@ use crate::*;
|
|||||||
|
|
||||||
pub async fn test_envelope_round_trip() {
|
pub async fn test_envelope_round_trip() {
|
||||||
info!("--- test envelope round trip ---");
|
info!("--- test envelope round trip ---");
|
||||||
let veilid_core = VeilidCore::new();
|
let api = api_startup(setup_veilid_core())
|
||||||
let api = veilid_core
|
|
||||||
.startup(setup_veilid_core())
|
|
||||||
.await
|
.await
|
||||||
.expect("startup failed");
|
.expect("startup failed");
|
||||||
|
|
||||||
// Get crypto
|
// Get crypto
|
||||||
let crypto = veilid_core.crypto();
|
let crypto = api.crypto().unwrap();
|
||||||
|
|
||||||
// Create envelope
|
// Create envelope
|
||||||
let ts = 0x12345678ABCDEF69u64;
|
let ts = 0x12345678ABCDEF69u64;
|
||||||
|
@ -16,9 +16,9 @@ fn setup_veilid_core() -> VeilidCoreSetup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn startup(core: VeilidCore) -> VeilidAPI {
|
async fn startup() -> VeilidAPI {
|
||||||
trace!("test_table_store: starting");
|
trace!("test_table_store: starting");
|
||||||
core.startup(setup_veilid_core())
|
api_startup(setup_veilid_core())
|
||||||
.await
|
.await
|
||||||
.expect("startup failed")
|
.expect("startup failed")
|
||||||
}
|
}
|
||||||
@ -93,10 +93,8 @@ pub async fn test_protected_store(ps: ProtectedStore) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_all() {
|
pub async fn test_all() {
|
||||||
let core = VeilidCore::new();
|
let api = startup().await;
|
||||||
let api = startup(core.clone()).await;
|
let ps = api.protected_store().unwrap();
|
||||||
|
|
||||||
let ps = core.protected_store();
|
|
||||||
test_protected_store(ps.clone()).await;
|
test_protected_store(ps.clone()).await;
|
||||||
|
|
||||||
shutdown(api).await;
|
shutdown(api).await;
|
||||||
|
@ -17,9 +17,9 @@ fn setup_veilid_core() -> VeilidCoreSetup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn startup(core: VeilidCore) -> VeilidAPI {
|
async fn startup() -> VeilidAPI {
|
||||||
trace!("test_table_store: starting");
|
trace!("test_table_store: starting");
|
||||||
core.startup(setup_veilid_core())
|
api_startup(setup_veilid_core())
|
||||||
.await
|
.await
|
||||||
.expect("startup failed")
|
.expect("startup failed")
|
||||||
}
|
}
|
||||||
@ -169,10 +169,8 @@ pub async fn test_cbor(ts: TableStore) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_all() {
|
pub async fn test_all() {
|
||||||
let core = VeilidCore::new();
|
let api = startup().await;
|
||||||
let api = startup(core.clone()).await;
|
let ts = api.table_store().unwrap();
|
||||||
|
|
||||||
let ts = core.table_store();
|
|
||||||
test_delete_open_delete(ts.clone()).await;
|
test_delete_open_delete(ts.clone()).await;
|
||||||
test_store_delete_load(ts.clone()).await;
|
test_store_delete_load(ts.clone()).await;
|
||||||
test_cbor(ts.clone()).await;
|
test_cbor(ts.clone()).await;
|
||||||
|
@ -4,9 +4,7 @@ use crate::*;
|
|||||||
|
|
||||||
pub async fn test_startup_shutdown() {
|
pub async fn test_startup_shutdown() {
|
||||||
trace!("test_startup_shutdown: starting");
|
trace!("test_startup_shutdown: starting");
|
||||||
let veilid_core = VeilidCore::new();
|
let api = api_startup(setup_veilid_core())
|
||||||
let api = veilid_core
|
|
||||||
.startup(setup_veilid_core())
|
|
||||||
.await
|
.await
|
||||||
.expect("startup failed");
|
.expect("startup failed");
|
||||||
trace!("test_startup_shutdown: shutting down");
|
trace!("test_startup_shutdown: shutting down");
|
||||||
@ -15,11 +13,8 @@ pub async fn test_startup_shutdown() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_attach_detach() {
|
pub async fn test_attach_detach() {
|
||||||
let veilid_core = VeilidCore::new();
|
|
||||||
|
|
||||||
info!("--- test normal order ---");
|
info!("--- test normal order ---");
|
||||||
let api = veilid_core
|
let api = api_startup(setup_veilid_core())
|
||||||
.startup(setup_veilid_core())
|
|
||||||
.await
|
.await
|
||||||
.expect("startup failed");
|
.expect("startup failed");
|
||||||
api.attach().await.unwrap();
|
api.attach().await.unwrap();
|
||||||
@ -31,8 +26,7 @@ pub async fn test_attach_detach() {
|
|||||||
api.shutdown().await;
|
api.shutdown().await;
|
||||||
|
|
||||||
info!("--- test auto detach ---");
|
info!("--- test auto detach ---");
|
||||||
let api = veilid_core
|
let api = api_startup(setup_veilid_core())
|
||||||
.startup(setup_veilid_core())
|
|
||||||
.await
|
.await
|
||||||
.expect("startup failed");
|
.expect("startup failed");
|
||||||
api.attach().await.unwrap();
|
api.attach().await.unwrap();
|
||||||
@ -40,8 +34,7 @@ pub async fn test_attach_detach() {
|
|||||||
api.shutdown().await;
|
api.shutdown().await;
|
||||||
|
|
||||||
info!("--- test detach without attach ---");
|
info!("--- test detach without attach ---");
|
||||||
let api = veilid_core
|
let api = api_startup(setup_veilid_core())
|
||||||
.startup(setup_veilid_core())
|
|
||||||
.await
|
.await
|
||||||
.expect("startup failed");
|
.expect("startup failed");
|
||||||
api.detach().await.unwrap();
|
api.detach().await.unwrap();
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// Debugging
|
// Debugging
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use routing_table::*;
|
||||||
|
|
||||||
fn get_bucket_entry_state(text: &str) -> Option<BucketEntryState> {
|
fn get_bucket_entry_state(text: &str) -> Option<BucketEntryState> {
|
||||||
if text == "dead" {
|
if text == "dead" {
|
||||||
|
@ -3,28 +3,38 @@
|
|||||||
mod debug;
|
mod debug;
|
||||||
pub use debug::*;
|
pub use debug::*;
|
||||||
|
|
||||||
pub use crate::rpc_processor::InfoAnswer;
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use api_logger::*;
|
|
||||||
use attachment_manager::*;
|
|
||||||
use core::fmt;
|
|
||||||
use network_manager::NetworkManager;
|
|
||||||
use routing_table::*;
|
|
||||||
use rpc_processor::{RPCError, RPCProcessor};
|
|
||||||
use xx::*;
|
|
||||||
|
|
||||||
pub use crate::dht::key::{generate_secret, DHTKey, DHTKeySecret};
|
|
||||||
pub use crate::xx::{
|
pub use crate::xx::{
|
||||||
IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, SystemPinBoxFuture,
|
IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, SystemPinBoxFuture,
|
||||||
ToSocketAddrs,
|
ToSocketAddrs,
|
||||||
};
|
};
|
||||||
pub use alloc::string::ToString;
|
pub use alloc::string::ToString;
|
||||||
|
pub use attachment_manager::AttachmentManager;
|
||||||
pub use core::str::FromStr;
|
pub use core::str::FromStr;
|
||||||
|
pub use dht::crypto::Crypto;
|
||||||
|
pub use dht::key::{generate_secret, DHTKey, DHTKeySecret};
|
||||||
|
pub use intf::BlockStore;
|
||||||
|
pub use intf::ProtectedStore;
|
||||||
|
pub use intf::TableStore;
|
||||||
|
pub use network_manager::NetworkManager;
|
||||||
|
pub use routing_table::RoutingTable;
|
||||||
|
pub use rpc_processor::InfoAnswer;
|
||||||
|
|
||||||
|
use api_logger::*;
|
||||||
|
use core::fmt;
|
||||||
|
use core_context::{api_shutdown, VeilidCoreContext};
|
||||||
|
use rpc_processor::{RPCError, RPCProcessor};
|
||||||
|
use serde::*;
|
||||||
|
use xx::*;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord)]
|
#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "kind")]
|
||||||
pub enum VeilidAPIError {
|
pub enum VeilidAPIError {
|
||||||
|
NotInitialized,
|
||||||
|
AlreadyInitialized,
|
||||||
Timeout,
|
Timeout,
|
||||||
Shutdown,
|
Shutdown,
|
||||||
NodeNotFound(NodeId),
|
NodeNotFound(NodeId),
|
||||||
@ -49,6 +59,8 @@ pub enum VeilidAPIError {
|
|||||||
impl fmt::Display for VeilidAPIError {
|
impl fmt::Display for VeilidAPIError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||||
match self {
|
match self {
|
||||||
|
VeilidAPIError::NotInitialized => write!(f, "VeilidAPIError::NotInitialized"),
|
||||||
|
VeilidAPIError::AlreadyInitialized => write!(f, "VeilidAPIError::AlreadyInitialized"),
|
||||||
VeilidAPIError::Timeout => write!(f, "VeilidAPIError::Timeout"),
|
VeilidAPIError::Timeout => write!(f, "VeilidAPIError::Timeout"),
|
||||||
VeilidAPIError::Shutdown => write!(f, "VeilidAPIError::Shutdown"),
|
VeilidAPIError::Shutdown => write!(f, "VeilidAPIError::Shutdown"),
|
||||||
VeilidAPIError::NodeNotFound(ni) => write!(f, "VeilidAPIError::NodeNotFound({})", ni),
|
VeilidAPIError::NodeNotFound(ni) => write!(f, "VeilidAPIError::NodeNotFound({})", ni),
|
||||||
@ -107,7 +119,7 @@ macro_rules! parse_error {
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
pub enum VeilidLogLevel {
|
pub enum VeilidLogLevel {
|
||||||
Error = 1,
|
Error = 1,
|
||||||
Warn,
|
Warn,
|
||||||
@ -128,7 +140,8 @@ impl VeilidLogLevel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "kind")]
|
||||||
pub enum VeilidUpdate {
|
pub enum VeilidUpdate {
|
||||||
Log {
|
Log {
|
||||||
log_level: VeilidLogLevel,
|
log_level: VeilidLogLevel,
|
||||||
@ -137,14 +150,14 @@ pub enum VeilidUpdate {
|
|||||||
Attachment(AttachmentState),
|
Attachment(AttachmentState),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidState {
|
pub struct VeilidState {
|
||||||
pub attachment: AttachmentState,
|
pub attachment: AttachmentState,
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
///
|
///
|
||||||
#[derive(Clone, Debug, Default, PartialOrd, PartialEq, Eq, Ord)]
|
#[derive(Clone, Debug, Default, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)]
|
||||||
pub struct NodeId {
|
pub struct NodeId {
|
||||||
pub key: DHTKey,
|
pub key: DHTKey,
|
||||||
}
|
}
|
||||||
@ -160,7 +173,7 @@ impl fmt::Display for NodeId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialOrd, PartialEq, Eq, Ord)]
|
#[derive(Clone, Debug, Default, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)]
|
||||||
pub struct ValueKey {
|
pub struct ValueKey {
|
||||||
pub key: DHTKey,
|
pub key: DHTKey,
|
||||||
pub subkey: Option<String>,
|
pub subkey: Option<String>,
|
||||||
@ -181,7 +194,7 @@ impl ValueKey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialOrd, PartialEq, Eq, Ord)]
|
#[derive(Clone, Debug, Default, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)]
|
||||||
pub struct BlockId {
|
pub struct BlockId {
|
||||||
pub key: DHTKey,
|
pub key: DHTKey,
|
||||||
}
|
}
|
||||||
@ -193,12 +206,12 @@ impl BlockId {
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Default)]
|
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Default, Serialize, Deserialize)]
|
||||||
pub struct SenderInfo {
|
pub struct SenderInfo {
|
||||||
pub socket_address: Option<SocketAddress>,
|
pub socket_address: Option<SocketAddress>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct NodeInfo {
|
pub struct NodeInfo {
|
||||||
pub can_route: bool,
|
pub can_route: bool,
|
||||||
pub will_route: bool,
|
pub will_route: bool,
|
||||||
@ -212,7 +225,7 @@ pub struct NodeInfo {
|
|||||||
pub will_validate_dial_info: bool,
|
pub will_validate_dial_info: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Serialize, Deserialize)]
|
||||||
// The derived ordering here is the order of preference, lower is preferred for connections
|
// The derived ordering here is the order of preference, lower is preferred for connections
|
||||||
// Must match DialInfo order
|
// Must match DialInfo order
|
||||||
pub enum ProtocolType {
|
pub enum ProtocolType {
|
||||||
@ -222,13 +235,13 @@ pub enum ProtocolType {
|
|||||||
WSS,
|
WSS,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Serialize, Deserialize)]
|
||||||
pub enum AddressType {
|
pub enum AddressType {
|
||||||
IPV4,
|
IPV4,
|
||||||
IPV6,
|
IPV6,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Serialize, Deserialize)]
|
||||||
pub enum Address {
|
pub enum Address {
|
||||||
IPV4(Ipv4Addr),
|
IPV4(Ipv4Addr),
|
||||||
IPV6(Ipv6Addr),
|
IPV6(Ipv6Addr),
|
||||||
@ -310,7 +323,9 @@ impl FromStr for Address {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Default, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
|
#[derive(
|
||||||
|
Copy, Default, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Serialize, Deserialize,
|
||||||
|
)]
|
||||||
pub struct SocketAddress {
|
pub struct SocketAddress {
|
||||||
address: Address,
|
address: Address,
|
||||||
port: u16,
|
port: u16,
|
||||||
@ -366,7 +381,7 @@ impl FromStr for SocketAddress {
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct DialInfoFilter {
|
pub struct DialInfoFilter {
|
||||||
pub peer_scope: PeerScope,
|
pub peer_scope: PeerScope,
|
||||||
pub protocol_type: Option<ProtocolType>,
|
pub protocol_type: Option<ProtocolType>,
|
||||||
@ -435,29 +450,30 @@ pub trait MatchesDialInfoFilter {
|
|||||||
fn matches_filter(&self, filter: &DialInfoFilter) -> bool;
|
fn matches_filter(&self, filter: &DialInfoFilter) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Debug, PartialEq, PartialOrd, Ord, Eq)]
|
#[derive(Clone, Default, Debug, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize)]
|
||||||
pub struct DialInfoUDP {
|
pub struct DialInfoUDP {
|
||||||
pub socket_address: SocketAddress,
|
pub socket_address: SocketAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Debug, PartialEq, PartialOrd, Ord, Eq)]
|
#[derive(Clone, Default, Debug, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize)]
|
||||||
pub struct DialInfoTCP {
|
pub struct DialInfoTCP {
|
||||||
pub socket_address: SocketAddress,
|
pub socket_address: SocketAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Debug, PartialEq, PartialOrd, Ord, Eq)]
|
#[derive(Clone, Default, Debug, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize)]
|
||||||
pub struct DialInfoWS {
|
pub struct DialInfoWS {
|
||||||
pub socket_address: SocketAddress,
|
pub socket_address: SocketAddress,
|
||||||
pub request: String,
|
pub request: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Debug, PartialEq, PartialOrd, Ord, Eq)]
|
#[derive(Clone, Default, Debug, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize)]
|
||||||
pub struct DialInfoWSS {
|
pub struct DialInfoWSS {
|
||||||
pub socket_address: SocketAddress,
|
pub socket_address: SocketAddress,
|
||||||
pub request: String,
|
pub request: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
|
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "kind")]
|
||||||
// The derived ordering here is the order of preference, lower is preferred for connections
|
// The derived ordering here is the order of preference, lower is preferred for connections
|
||||||
// Must match ProtocolType order
|
// Must match ProtocolType order
|
||||||
pub enum DialInfo {
|
pub enum DialInfo {
|
||||||
@ -706,7 +722,7 @@ impl MatchesDialInfoFilter for DialInfo {
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
||||||
pub enum PeerScope {
|
pub enum PeerScope {
|
||||||
All,
|
All,
|
||||||
Global,
|
Global,
|
||||||
@ -718,13 +734,13 @@ impl Default for PeerScope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct PeerInfo {
|
pub struct PeerInfo {
|
||||||
pub node_id: NodeId,
|
pub node_id: NodeId,
|
||||||
pub dial_infos: Vec<DialInfo>,
|
pub dial_infos: Vec<DialInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||||
pub struct PeerAddress {
|
pub struct PeerAddress {
|
||||||
pub socket_address: SocketAddress,
|
pub socket_address: SocketAddress,
|
||||||
pub protocol_type: ProtocolType,
|
pub protocol_type: ProtocolType,
|
||||||
@ -747,7 +763,7 @@ impl PeerAddress {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||||
pub struct ConnectionDescriptor {
|
pub struct ConnectionDescriptor {
|
||||||
pub remote: PeerAddress,
|
pub remote: PeerAddress,
|
||||||
pub local: Option<SocketAddress>,
|
pub local: Option<SocketAddress>,
|
||||||
@ -802,7 +818,7 @@ impl MatchesDialInfoFilter for ConnectionDescriptor {
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct NodeDialInfo {
|
pub struct NodeDialInfo {
|
||||||
pub node_id: NodeId,
|
pub node_id: NodeId,
|
||||||
pub dial_info: DialInfo,
|
pub dial_info: DialInfo,
|
||||||
@ -837,20 +853,20 @@ impl FromStr for NodeDialInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct LatencyStats {
|
pub struct LatencyStats {
|
||||||
pub fastest: u64, // fastest latency in the ROLLING_LATENCIES_SIZE last latencies
|
pub fastest: u64, // fastest latency in the ROLLING_LATENCIES_SIZE last latencies
|
||||||
pub average: u64, // average latency over the ROLLING_LATENCIES_SIZE last latencies
|
pub average: u64, // average latency over the ROLLING_LATENCIES_SIZE last latencies
|
||||||
pub slowest: u64, // slowest latency in the ROLLING_LATENCIES_SIZE last latencies
|
pub slowest: u64, // slowest latency in the ROLLING_LATENCIES_SIZE last latencies
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct TransferStatsDownUp {
|
pub struct TransferStatsDownUp {
|
||||||
pub down: TransferStats,
|
pub down: TransferStats,
|
||||||
pub up: TransferStats,
|
pub up: TransferStats,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct TransferStats {
|
pub struct TransferStats {
|
||||||
pub total: u64, // total amount transferred ever
|
pub total: u64, // total amount transferred ever
|
||||||
pub maximum: u64, // maximum rate over the ROLLING_TRANSFERS_SIZE last amounts
|
pub maximum: u64, // maximum rate over the ROLLING_TRANSFERS_SIZE last amounts
|
||||||
@ -858,7 +874,7 @@ pub struct TransferStats {
|
|||||||
pub minimum: u64, // minimum rate over the ROLLING_TRANSFERS_SIZE last amounts
|
pub minimum: u64, // minimum rate over the ROLLING_TRANSFERS_SIZE last amounts
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct PingStats {
|
pub struct PingStats {
|
||||||
pub in_flight: u32, // number of pings issued that have yet to be answered
|
pub in_flight: u32, // number of pings issued that have yet to be answered
|
||||||
pub total_sent: u32, // number of pings that have been sent in the total_time range
|
pub total_sent: u32, // number of pings that have been sent in the total_time range
|
||||||
@ -869,7 +885,7 @@ pub struct PingStats {
|
|||||||
pub recent_lost_pings: u32, // number of pings that have been lost since we lost reliability
|
pub recent_lost_pings: u32, // number of pings that have been lost since we lost reliability
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct PeerStats {
|
pub struct PeerStats {
|
||||||
pub time_added: u64, // when the peer was added to the routing table
|
pub time_added: u64, // when the peer was added to the routing table
|
||||||
pub last_seen: Option<u64>, // when the peer was last seen for any reason, including when we first attempted to reach out to it
|
pub last_seen: Option<u64>, // when the peer was last seen for any reason, including when we first attempted to reach out to it
|
||||||
@ -889,7 +905,7 @@ cfg_if! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord)]
|
#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)]
|
||||||
pub enum TunnelMode {
|
pub enum TunnelMode {
|
||||||
Raw,
|
Raw,
|
||||||
Turn,
|
Turn,
|
||||||
@ -897,7 +913,7 @@ pub enum TunnelMode {
|
|||||||
|
|
||||||
type TunnelId = u64;
|
type TunnelId = u64;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct TunnelEndpoint {
|
pub struct TunnelEndpoint {
|
||||||
pub node_id: NodeId, // the node id of the tunnel endpoint
|
pub node_id: NodeId, // the node id of the tunnel endpoint
|
||||||
pub dial_info: Vec<DialInfo>, // multiple ways of how to get to the node
|
pub dial_info: Vec<DialInfo>, // multiple ways of how to get to the node
|
||||||
@ -914,7 +930,7 @@ impl Default for TunnelEndpoint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct FullTunnel {
|
pub struct FullTunnel {
|
||||||
pub id: TunnelId,
|
pub id: TunnelId,
|
||||||
pub timeout: u64,
|
pub timeout: u64,
|
||||||
@ -922,7 +938,7 @@ pub struct FullTunnel {
|
|||||||
pub remote: TunnelEndpoint,
|
pub remote: TunnelEndpoint,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct PartialTunnel {
|
pub struct PartialTunnel {
|
||||||
pub id: TunnelId,
|
pub id: TunnelId,
|
||||||
pub timeout: u64,
|
pub timeout: u64,
|
||||||
@ -931,12 +947,12 @@ pub struct PartialTunnel {
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct RouteHopSpec {
|
pub struct RouteHopSpec {
|
||||||
pub dial_info: NodeDialInfo,
|
pub dial_info: NodeDialInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct PrivateRouteSpec {
|
pub struct PrivateRouteSpec {
|
||||||
//
|
//
|
||||||
pub public_key: DHTKey,
|
pub public_key: DHTKey,
|
||||||
@ -944,7 +960,7 @@ pub struct PrivateRouteSpec {
|
|||||||
pub hops: Vec<RouteHopSpec>,
|
pub hops: Vec<RouteHopSpec>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct SafetyRouteSpec {
|
pub struct SafetyRouteSpec {
|
||||||
pub public_key: DHTKey,
|
pub public_key: DHTKey,
|
||||||
pub secret_key: DHTKeySecret,
|
pub secret_key: DHTKeySecret,
|
||||||
@ -962,7 +978,7 @@ impl SafetyRouteSpec {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct RoutingContextOptions {
|
pub struct RoutingContextOptions {
|
||||||
pub safety_route_spec: Option<SafetyRouteSpec>,
|
pub safety_route_spec: Option<SafetyRouteSpec>,
|
||||||
pub private_route_spec: Option<PrivateRouteSpec>,
|
pub private_route_spec: Option<PrivateRouteSpec>,
|
||||||
@ -970,7 +986,7 @@ pub struct RoutingContextOptions {
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct SearchDHTAnswer {
|
pub struct SearchDHTAnswer {
|
||||||
pub node_id: NodeId,
|
pub node_id: NodeId,
|
||||||
pub dial_info: Vec<DialInfo>,
|
pub dial_info: Vec<DialInfo>,
|
||||||
@ -1051,26 +1067,19 @@ impl RoutingContext {
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct VeilidAPIInner {
|
struct VeilidAPIInner {
|
||||||
core: Option<VeilidCore>,
|
context: Option<VeilidCoreContext>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for VeilidAPIInner {
|
impl fmt::Debug for VeilidAPIInner {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(
|
write!(f, "VeilidAPIInner")
|
||||||
f,
|
|
||||||
"VeilidAPIInner: {}",
|
|
||||||
match self.core {
|
|
||||||
Some(_) => "active",
|
|
||||||
None => "shutdown",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for VeilidAPIInner {
|
impl Drop for VeilidAPIInner {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Some(core) = self.core.take() {
|
if let Some(context) = self.context.take() {
|
||||||
intf::spawn_local(core.shutdown()).detach();
|
intf::spawn_local(api_shutdown(context)).detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1080,59 +1089,83 @@ pub struct VeilidAPI {
|
|||||||
inner: Arc<Mutex<VeilidAPIInner>>,
|
inner: Arc<Mutex<VeilidAPIInner>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
|
||||||
pub struct VeilidAPIWeak {
|
|
||||||
inner: Weak<Mutex<VeilidAPIInner>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VeilidAPIWeak {
|
|
||||||
pub fn upgrade(&self) -> Option<VeilidAPI> {
|
|
||||||
self.inner.upgrade().map(|v| VeilidAPI { inner: v })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VeilidAPI {
|
impl VeilidAPI {
|
||||||
pub(crate) fn new(core: VeilidCore) -> Self {
|
pub(crate) fn new(context: VeilidCoreContext) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: Arc::new(Mutex::new(VeilidAPIInner { core: Some(core) })),
|
inner: Arc::new(Mutex::new(VeilidAPIInner {
|
||||||
|
context: Some(context),
|
||||||
|
})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn weak(&self) -> VeilidAPIWeak {
|
|
||||||
VeilidAPIWeak {
|
|
||||||
inner: Arc::downgrade(&self.inner),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn core(&self) -> Result<VeilidCore, VeilidAPIError> {
|
|
||||||
Ok(self
|
|
||||||
.inner
|
|
||||||
.lock()
|
|
||||||
.core
|
|
||||||
.as_ref()
|
|
||||||
.ok_or(VeilidAPIError::Shutdown)?
|
|
||||||
.clone())
|
|
||||||
}
|
|
||||||
fn config(&self) -> Result<VeilidConfig, VeilidAPIError> {
|
|
||||||
Ok(self.core()?.config())
|
|
||||||
}
|
|
||||||
fn attachment_manager(&self) -> Result<AttachmentManager, VeilidAPIError> {
|
|
||||||
Ok(self.core()?.attachment_manager())
|
|
||||||
}
|
|
||||||
fn network_manager(&self) -> Result<NetworkManager, VeilidAPIError> {
|
|
||||||
Ok(self.attachment_manager()?.network_manager())
|
|
||||||
}
|
|
||||||
fn rpc_processor(&self) -> Result<RPCProcessor, VeilidAPIError> {
|
|
||||||
Ok(self.network_manager()?.rpc_processor())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn shutdown(self) {
|
pub async fn shutdown(self) {
|
||||||
let core = { self.inner.lock().core.take() };
|
let context = { self.inner.lock().context.take() };
|
||||||
if let Some(core) = core {
|
if let Some(context) = context {
|
||||||
core.shutdown().await;
|
api_shutdown(context).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_shutdown(&self) -> bool {
|
pub fn is_shutdown(&self) -> bool {
|
||||||
self.inner.lock().core.is_none()
|
self.inner.lock().context.is_none()
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
// Accessors
|
||||||
|
pub fn config(&self) -> Result<VeilidConfig, VeilidAPIError> {
|
||||||
|
let inner = self.inner.lock();
|
||||||
|
if let Some(context) = &inner.context {
|
||||||
|
return Ok(context.config.clone());
|
||||||
|
}
|
||||||
|
Err(VeilidAPIError::NotInitialized)
|
||||||
|
}
|
||||||
|
pub fn crypto(&self) -> Result<Crypto, VeilidAPIError> {
|
||||||
|
let inner = self.inner.lock();
|
||||||
|
if let Some(context) = &inner.context {
|
||||||
|
return Ok(context.crypto.clone());
|
||||||
|
}
|
||||||
|
Err(VeilidAPIError::NotInitialized)
|
||||||
|
}
|
||||||
|
pub fn table_store(&self) -> Result<TableStore, VeilidAPIError> {
|
||||||
|
let inner = self.inner.lock();
|
||||||
|
if let Some(context) = &inner.context {
|
||||||
|
return Ok(context.table_store.clone());
|
||||||
|
}
|
||||||
|
Err(VeilidAPIError::NotInitialized)
|
||||||
|
}
|
||||||
|
pub fn block_store(&self) -> Result<BlockStore, VeilidAPIError> {
|
||||||
|
let inner = self.inner.lock();
|
||||||
|
if let Some(context) = &inner.context {
|
||||||
|
return Ok(context.block_store.clone());
|
||||||
|
}
|
||||||
|
Err(VeilidAPIError::NotInitialized)
|
||||||
|
}
|
||||||
|
pub fn protected_store(&self) -> Result<ProtectedStore, VeilidAPIError> {
|
||||||
|
let inner = self.inner.lock();
|
||||||
|
if let Some(context) = &inner.context {
|
||||||
|
return Ok(context.protected_store.clone());
|
||||||
|
}
|
||||||
|
Err(VeilidAPIError::NotInitialized)
|
||||||
|
}
|
||||||
|
pub fn attachment_manager(&self) -> Result<AttachmentManager, VeilidAPIError> {
|
||||||
|
let inner = self.inner.lock();
|
||||||
|
if let Some(context) = &inner.context {
|
||||||
|
return Ok(context.attachment_manager.clone());
|
||||||
|
}
|
||||||
|
Err(VeilidAPIError::NotInitialized)
|
||||||
|
}
|
||||||
|
pub fn network_manager(&self) -> Result<NetworkManager, VeilidAPIError> {
|
||||||
|
let inner = self.inner.lock();
|
||||||
|
if let Some(context) = &inner.context {
|
||||||
|
return Ok(context.attachment_manager.network_manager());
|
||||||
|
}
|
||||||
|
Err(VeilidAPIError::NotInitialized)
|
||||||
|
}
|
||||||
|
pub fn rpc_processor(&self) -> Result<RPCProcessor, VeilidAPIError> {
|
||||||
|
let inner = self.inner.lock();
|
||||||
|
if let Some(context) = &inner.context {
|
||||||
|
return Ok(context.attachment_manager.network_manager().rpc_processor());
|
||||||
|
}
|
||||||
|
Err(VeilidAPIError::NotInitialized)
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
@ -2,6 +2,8 @@ use crate::dht::key;
|
|||||||
use crate::intf;
|
use crate::intf;
|
||||||
use crate::xx::*;
|
use crate::xx::*;
|
||||||
|
|
||||||
|
use serde::*;
|
||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(target_arch = "wasm32")] {
|
if #[cfg(target_arch = "wasm32")] {
|
||||||
pub type ConfigCallbackReturn = Result<Box<dyn core::any::Any>, String>;
|
pub type ConfigCallbackReturn = Result<Box<dyn core::any::Any>, String>;
|
||||||
@ -9,7 +11,7 @@ cfg_if! {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
pub type ConfigCallbackReturn = Result<Box<dyn core::any::Any + Send>, String>;
|
pub type ConfigCallbackReturn = Result<Box<dyn core::any::Any + Send>, String>;
|
||||||
pub type ConfigCallback = Arc<dyn Fn(String) -> ConfigCallbackReturn + Send>;
|
pub type ConfigCallback = Arc<dyn Fn(String) -> ConfigCallbackReturn + Send + Sync>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +174,7 @@ pub struct VeilidConfigCapabilities {
|
|||||||
pub protocol_accept_wss: bool,
|
pub protocol_accept_wss: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||||
pub enum VeilidConfigLogLevel {
|
pub enum VeilidConfigLogLevel {
|
||||||
Off,
|
Off,
|
||||||
Error,
|
Error,
|
||||||
|
@ -1,241 +0,0 @@
|
|||||||
use crate::api_logger::*;
|
|
||||||
use crate::attachment_manager::*;
|
|
||||||
use crate::dht::crypto::Crypto;
|
|
||||||
use crate::intf::*;
|
|
||||||
use crate::veilid_api::*;
|
|
||||||
use crate::veilid_config::*;
|
|
||||||
use crate::xx::*;
|
|
||||||
|
|
||||||
cfg_if! {
|
|
||||||
if #[cfg(target_arch = "wasm32")] {
|
|
||||||
pub type UpdateCallback = Arc<dyn Fn(VeilidUpdate) -> SystemPinBoxFuture<()>>;
|
|
||||||
} else {
|
|
||||||
pub type UpdateCallback = Arc<dyn Fn(VeilidUpdate) -> SystemPinBoxFuture<()> + Send + Sync>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct VeilidCoreSetup {
|
|
||||||
pub update_callback: UpdateCallback,
|
|
||||||
pub config_callback: ConfigCallback,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct VeilidCoreInner {
|
|
||||||
config: Option<VeilidConfig>,
|
|
||||||
protected_store: Option<ProtectedStore>,
|
|
||||||
table_store: Option<TableStore>,
|
|
||||||
crypto: Option<Crypto>,
|
|
||||||
attachment_manager: Option<AttachmentManager>,
|
|
||||||
api: VeilidAPIWeak,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct VeilidCore {
|
|
||||||
inner: Arc<Mutex<VeilidCoreInner>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for VeilidCore {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VeilidCore {
|
|
||||||
fn new_inner() -> VeilidCoreInner {
|
|
||||||
VeilidCoreInner {
|
|
||||||
config: None,
|
|
||||||
table_store: None,
|
|
||||||
protected_store: None,
|
|
||||||
crypto: None,
|
|
||||||
attachment_manager: None,
|
|
||||||
api: VeilidAPIWeak::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
inner: Arc::new(Mutex::new(Self::new_inner())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn config(&self) -> VeilidConfig {
|
|
||||||
self.inner.lock().config.as_ref().unwrap().clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn table_store(&self) -> TableStore {
|
|
||||||
self.inner.lock().table_store.as_ref().unwrap().clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn protected_store(&self) -> ProtectedStore {
|
|
||||||
self.inner.lock().protected_store.as_ref().unwrap().clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn crypto(&self) -> Crypto {
|
|
||||||
self.inner.lock().crypto.as_ref().unwrap().clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn attachment_manager(&self) -> AttachmentManager {
|
|
||||||
self.inner
|
|
||||||
.lock()
|
|
||||||
.attachment_manager
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
// internal startup
|
|
||||||
async fn internal_startup(
|
|
||||||
&self,
|
|
||||||
inner: &mut VeilidCoreInner,
|
|
||||||
setup: VeilidCoreSetup,
|
|
||||||
) -> Result<VeilidAPI, String> {
|
|
||||||
// Start up api logging early if it's in the config
|
|
||||||
let api_log_level: VeilidConfigLogLevel =
|
|
||||||
*(setup.config_callback)("api_log_level".to_owned())?
|
|
||||||
.downcast()
|
|
||||||
.map_err(|_| "incorrect type for key 'api_log_level'".to_owned())?;
|
|
||||||
if api_log_level != VeilidConfigLogLevel::Off {
|
|
||||||
ApiLogger::init(
|
|
||||||
api_log_level.to_level_filter(),
|
|
||||||
setup.update_callback.clone(),
|
|
||||||
);
|
|
||||||
for ig in crate::DEFAULT_LOG_IGNORE_LIST {
|
|
||||||
ApiLogger::add_filter_ignore_str(ig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trace!("VeilidCore::internal_startup starting");
|
|
||||||
|
|
||||||
cfg_if! {
|
|
||||||
if #[cfg(target_os = "android")] {
|
|
||||||
if utils::android::ANDROID_GLOBALS.lock().is_none() {
|
|
||||||
error!("Android globals are not set up");
|
|
||||||
return Err("Android globals are not set up".to_owned());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up config
|
|
||||||
trace!("VeilidCore::internal_startup init config");
|
|
||||||
let mut config = VeilidConfig::new();
|
|
||||||
config.init(setup.config_callback).await?;
|
|
||||||
inner.config = Some(config.clone());
|
|
||||||
|
|
||||||
// Set up protected store
|
|
||||||
trace!("VeilidCore::internal_startup init protected store");
|
|
||||||
let protected_store = ProtectedStore::new(config.clone());
|
|
||||||
protected_store.init().await?;
|
|
||||||
inner.protected_store = Some(protected_store.clone());
|
|
||||||
|
|
||||||
// Init node id from config now that protected store is set up
|
|
||||||
config.init_node_id(protected_store).await?;
|
|
||||||
|
|
||||||
// Set up tablestore
|
|
||||||
trace!("VeilidCore::internal_startup init table store");
|
|
||||||
let table_store = TableStore::new(config.clone());
|
|
||||||
table_store.init().await?;
|
|
||||||
inner.table_store = Some(table_store.clone());
|
|
||||||
|
|
||||||
// Set up crypto
|
|
||||||
trace!("VeilidCore::internal_startup init crypto");
|
|
||||||
let crypto = Crypto::new(config.clone(), table_store.clone());
|
|
||||||
crypto.init().await?;
|
|
||||||
inner.crypto = Some(crypto.clone());
|
|
||||||
|
|
||||||
// Set up block store
|
|
||||||
// trace!("VeilidCore::internal_startup init block store");
|
|
||||||
// let block_store = BlockStore::new(config.clone());
|
|
||||||
// block_store.init().await?;
|
|
||||||
// inner.block_store = Some(block_store.clone();)
|
|
||||||
|
|
||||||
// Set up attachment manager
|
|
||||||
trace!("VeilidCore::internal_startup init attachment manager");
|
|
||||||
let cb = setup.update_callback;
|
|
||||||
let attachment_manager =
|
|
||||||
AttachmentManager::new(config.clone(), table_store.clone(), crypto.clone());
|
|
||||||
attachment_manager
|
|
||||||
.init(Arc::new(
|
|
||||||
move |_old_state: AttachmentState, new_state: AttachmentState| {
|
|
||||||
cb(VeilidUpdate::Attachment(new_state))
|
|
||||||
},
|
|
||||||
))
|
|
||||||
.await?;
|
|
||||||
inner.attachment_manager = Some(attachment_manager.clone());
|
|
||||||
|
|
||||||
// Set up the API
|
|
||||||
trace!("VeilidCore::internal_startup init API");
|
|
||||||
let this = self.clone();
|
|
||||||
let veilid_api = VeilidAPI::new(this);
|
|
||||||
inner.api = veilid_api.weak();
|
|
||||||
|
|
||||||
trace!("VeilidCore::internal_startup complete");
|
|
||||||
|
|
||||||
Ok(veilid_api)
|
|
||||||
}
|
|
||||||
|
|
||||||
// called once at the beginning to start the node
|
|
||||||
pub async fn startup(&self, setup: VeilidCoreSetup) -> Result<VeilidAPI, String> {
|
|
||||||
// See if we have an API started up already
|
|
||||||
let mut inner = self.inner.lock();
|
|
||||||
if inner.api.upgrade().is_some() {
|
|
||||||
// If so, return an error because we shouldn't try to do this more than once
|
|
||||||
return Err("Veilid API is started".to_owned());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure we never end up partially initialized
|
|
||||||
match self.internal_startup(&mut *inner, setup).await {
|
|
||||||
Ok(v) => Ok(v),
|
|
||||||
Err(e) => {
|
|
||||||
Self::internal_shutdown(&mut *inner).await;
|
|
||||||
Err(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn internal_shutdown(inner: &mut VeilidCoreInner) {
|
|
||||||
trace!("VeilidCore::internal_shutdown starting");
|
|
||||||
|
|
||||||
// Detach the API object
|
|
||||||
inner.api = VeilidAPIWeak::default();
|
|
||||||
|
|
||||||
// Shut down up attachment manager
|
|
||||||
if let Some(attachment_manager) = &inner.attachment_manager {
|
|
||||||
attachment_manager.terminate().await;
|
|
||||||
inner.attachment_manager = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shut down crypto
|
|
||||||
if let Some(crypto) = &inner.crypto {
|
|
||||||
crypto.terminate().await;
|
|
||||||
inner.crypto = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shut down table store
|
|
||||||
if let Some(table_store) = &inner.table_store {
|
|
||||||
table_store.terminate().await;
|
|
||||||
inner.table_store = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shut down protected store
|
|
||||||
if let Some(protected_store) = &inner.protected_store {
|
|
||||||
protected_store.terminate().await;
|
|
||||||
inner.protected_store = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shut down config
|
|
||||||
if let Some(config) = &inner.config {
|
|
||||||
config.terminate().await;
|
|
||||||
inner.config = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
trace!("VeilidCore::shutdown complete");
|
|
||||||
|
|
||||||
ApiLogger::terminate();
|
|
||||||
}
|
|
||||||
|
|
||||||
// stop the node gracefully because the veilid api was dropped
|
|
||||||
pub(crate) async fn shutdown(self) {
|
|
||||||
let mut inner = self.inner.lock();
|
|
||||||
Self::internal_shutdown(&mut *inner).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
}
|
|
@ -158,6 +158,18 @@ macro_rules! logthru_pstore {
|
|||||||
logthru!($($level)? "pstore", $fmt, $($arg),+)
|
logthru!($($level)? "pstore", $fmt, $($arg),+)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! logthru_crypto {
|
||||||
|
($($level:ident)?) => {
|
||||||
|
logthru!($($level)? "crypto")
|
||||||
|
};
|
||||||
|
($($level:ident)? $text:literal) => {
|
||||||
|
logthru!($($level)? "crypto", $text)
|
||||||
|
};
|
||||||
|
($($level:ident)? $fmt:literal, $($arg:expr),+) => {
|
||||||
|
logthru!($($level)? "crypto", $fmt, $($arg),+)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! logthru {
|
macro_rules! logthru {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.veilid.veilid
|
package com.veilid.veilid
|
||||||
|
|
||||||
import androidx.annotation.NonNull
|
import androidx.annotation.NonNull
|
||||||
|
import android.content.Context
|
||||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||||
import io.flutter.plugin.common.MethodCall
|
import io.flutter.plugin.common.MethodCall
|
||||||
import io.flutter.plugin.common.MethodChannel
|
import io.flutter.plugin.common.MethodChannel
|
||||||
@ -10,32 +10,23 @@ import io.flutter.plugin.common.MethodChannel.Result
|
|||||||
|
|
||||||
/** VeilidPlugin */
|
/** VeilidPlugin */
|
||||||
class VeilidPlugin: FlutterPlugin, MethodCallHandler {
|
class VeilidPlugin: FlutterPlugin, MethodCallHandler {
|
||||||
/// The MethodChannel that will the communication between Flutter and native Android
|
|
||||||
///
|
|
||||||
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
|
|
||||||
/// when the Flutter Engine is detached from the Activity
|
|
||||||
// private lateinit var channel : MethodChannel
|
|
||||||
|
|
||||||
// static {
|
class object {
|
||||||
// System.loadLibrary("veilid_flutter");
|
{
|
||||||
// }
|
System.loadLibrary("veilid_flutter");
|
||||||
// xxx get main activity
|
}
|
||||||
// private static native void init_android(Context context);
|
}
|
||||||
|
|
||||||
|
native fun init_android(ctx: Context)
|
||||||
|
|
||||||
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
||||||
// channel = MethodChannel(flutterPluginBinding.binaryMessenger, "veilid")
|
init_android(flutterPluginBinding.getApplicationContext())
|
||||||
// channel.setMethodCallHandler(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
|
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
|
||||||
// if (call.method == "getPlatformVersion") {
|
|
||||||
// result.success("Android ${android.os.Build.VERSION.RELEASE}")
|
|
||||||
// } else {
|
|
||||||
result.notImplemented()
|
result.notImplemented()
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
|
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
|
||||||
// channel.setMethodCallHandler(null)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4"
|
version: "1.0.4"
|
||||||
|
equatable:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: equatable
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.3"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -121,6 +128,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.11"
|
version: "0.12.11"
|
||||||
|
material_color_utilities:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: material_color_utilities
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.3"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -128,6 +142,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.7.0"
|
version: "1.7.0"
|
||||||
|
oxidized:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: oxidized
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "5.1.0"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -181,7 +202,7 @@ packages:
|
|||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.3"
|
version: "0.4.8"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -1,367 +0,0 @@
|
|||||||
// coverage:ignore-file
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
// ignore_for_file: type=lint
|
|
||||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
|
|
||||||
|
|
||||||
part of 'bridge_generated.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// FreezedGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
T _$identity<T>(T value) => value;
|
|
||||||
|
|
||||||
final _privateConstructorUsedError = UnsupportedError(
|
|
||||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
class _$VeilidUpdateTearOff {
|
|
||||||
const _$VeilidUpdateTearOff();
|
|
||||||
|
|
||||||
Log log({required VeilidLogLevel logLevel, required String message}) {
|
|
||||||
return Log(
|
|
||||||
logLevel: logLevel,
|
|
||||||
message: message,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Attachment attachment(AttachmentState field0) {
|
|
||||||
return Attachment(
|
|
||||||
field0,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
const $VeilidUpdate = _$VeilidUpdateTearOff();
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
mixin _$VeilidUpdate {
|
|
||||||
@optionalTypeArgs
|
|
||||||
TResult when<TResult extends Object?>({
|
|
||||||
required TResult Function(VeilidLogLevel logLevel, String message) log,
|
|
||||||
required TResult Function(AttachmentState field0) attachment,
|
|
||||||
}) =>
|
|
||||||
throw _privateConstructorUsedError;
|
|
||||||
@optionalTypeArgs
|
|
||||||
TResult? whenOrNull<TResult extends Object?>({
|
|
||||||
TResult Function(VeilidLogLevel logLevel, String message)? log,
|
|
||||||
TResult Function(AttachmentState field0)? attachment,
|
|
||||||
}) =>
|
|
||||||
throw _privateConstructorUsedError;
|
|
||||||
@optionalTypeArgs
|
|
||||||
TResult maybeWhen<TResult extends Object?>({
|
|
||||||
TResult Function(VeilidLogLevel logLevel, String message)? log,
|
|
||||||
TResult Function(AttachmentState field0)? attachment,
|
|
||||||
required TResult orElse(),
|
|
||||||
}) =>
|
|
||||||
throw _privateConstructorUsedError;
|
|
||||||
@optionalTypeArgs
|
|
||||||
TResult map<TResult extends Object?>({
|
|
||||||
required TResult Function(Log value) log,
|
|
||||||
required TResult Function(Attachment value) attachment,
|
|
||||||
}) =>
|
|
||||||
throw _privateConstructorUsedError;
|
|
||||||
@optionalTypeArgs
|
|
||||||
TResult? mapOrNull<TResult extends Object?>({
|
|
||||||
TResult Function(Log value)? log,
|
|
||||||
TResult Function(Attachment value)? attachment,
|
|
||||||
}) =>
|
|
||||||
throw _privateConstructorUsedError;
|
|
||||||
@optionalTypeArgs
|
|
||||||
TResult maybeMap<TResult extends Object?>({
|
|
||||||
TResult Function(Log value)? log,
|
|
||||||
TResult Function(Attachment value)? attachment,
|
|
||||||
required TResult orElse(),
|
|
||||||
}) =>
|
|
||||||
throw _privateConstructorUsedError;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
abstract class $VeilidUpdateCopyWith<$Res> {
|
|
||||||
factory $VeilidUpdateCopyWith(
|
|
||||||
VeilidUpdate value, $Res Function(VeilidUpdate) then) =
|
|
||||||
_$VeilidUpdateCopyWithImpl<$Res>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
class _$VeilidUpdateCopyWithImpl<$Res> implements $VeilidUpdateCopyWith<$Res> {
|
|
||||||
_$VeilidUpdateCopyWithImpl(this._value, this._then);
|
|
||||||
|
|
||||||
final VeilidUpdate _value;
|
|
||||||
// ignore: unused_field
|
|
||||||
final $Res Function(VeilidUpdate) _then;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
abstract class $LogCopyWith<$Res> {
|
|
||||||
factory $LogCopyWith(Log value, $Res Function(Log) then) =
|
|
||||||
_$LogCopyWithImpl<$Res>;
|
|
||||||
$Res call({VeilidLogLevel logLevel, String message});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
class _$LogCopyWithImpl<$Res> extends _$VeilidUpdateCopyWithImpl<$Res>
|
|
||||||
implements $LogCopyWith<$Res> {
|
|
||||||
_$LogCopyWithImpl(Log _value, $Res Function(Log) _then)
|
|
||||||
: super(_value, (v) => _then(v as Log));
|
|
||||||
|
|
||||||
@override
|
|
||||||
Log get _value => super._value as Log;
|
|
||||||
|
|
||||||
@override
|
|
||||||
$Res call({
|
|
||||||
Object? logLevel = freezed,
|
|
||||||
Object? message = freezed,
|
|
||||||
}) {
|
|
||||||
return _then(Log(
|
|
||||||
logLevel: logLevel == freezed
|
|
||||||
? _value.logLevel
|
|
||||||
: logLevel // ignore: cast_nullable_to_non_nullable
|
|
||||||
as VeilidLogLevel,
|
|
||||||
message: message == freezed
|
|
||||||
? _value.message
|
|
||||||
: message // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
|
|
||||||
class _$Log implements Log {
|
|
||||||
const _$Log({required this.logLevel, required this.message});
|
|
||||||
|
|
||||||
@override
|
|
||||||
final VeilidLogLevel logLevel;
|
|
||||||
@override
|
|
||||||
final String message;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return 'VeilidUpdate.log(logLevel: $logLevel, message: $message)';
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(dynamic other) {
|
|
||||||
return identical(this, other) ||
|
|
||||||
(other.runtimeType == runtimeType &&
|
|
||||||
other is Log &&
|
|
||||||
const DeepCollectionEquality().equals(other.logLevel, logLevel) &&
|
|
||||||
const DeepCollectionEquality().equals(other.message, message));
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(
|
|
||||||
runtimeType,
|
|
||||||
const DeepCollectionEquality().hash(logLevel),
|
|
||||||
const DeepCollectionEquality().hash(message));
|
|
||||||
|
|
||||||
@JsonKey(ignore: true)
|
|
||||||
@override
|
|
||||||
$LogCopyWith<Log> get copyWith => _$LogCopyWithImpl<Log>(this, _$identity);
|
|
||||||
|
|
||||||
@override
|
|
||||||
@optionalTypeArgs
|
|
||||||
TResult when<TResult extends Object?>({
|
|
||||||
required TResult Function(VeilidLogLevel logLevel, String message) log,
|
|
||||||
required TResult Function(AttachmentState field0) attachment,
|
|
||||||
}) {
|
|
||||||
return log(logLevel, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
@optionalTypeArgs
|
|
||||||
TResult? whenOrNull<TResult extends Object?>({
|
|
||||||
TResult Function(VeilidLogLevel logLevel, String message)? log,
|
|
||||||
TResult Function(AttachmentState field0)? attachment,
|
|
||||||
}) {
|
|
||||||
return log?.call(logLevel, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
@optionalTypeArgs
|
|
||||||
TResult maybeWhen<TResult extends Object?>({
|
|
||||||
TResult Function(VeilidLogLevel logLevel, String message)? log,
|
|
||||||
TResult Function(AttachmentState field0)? attachment,
|
|
||||||
required TResult orElse(),
|
|
||||||
}) {
|
|
||||||
if (log != null) {
|
|
||||||
return log(logLevel, message);
|
|
||||||
}
|
|
||||||
return orElse();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
@optionalTypeArgs
|
|
||||||
TResult map<TResult extends Object?>({
|
|
||||||
required TResult Function(Log value) log,
|
|
||||||
required TResult Function(Attachment value) attachment,
|
|
||||||
}) {
|
|
||||||
return log(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
@optionalTypeArgs
|
|
||||||
TResult? mapOrNull<TResult extends Object?>({
|
|
||||||
TResult Function(Log value)? log,
|
|
||||||
TResult Function(Attachment value)? attachment,
|
|
||||||
}) {
|
|
||||||
return log?.call(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
@optionalTypeArgs
|
|
||||||
TResult maybeMap<TResult extends Object?>({
|
|
||||||
TResult Function(Log value)? log,
|
|
||||||
TResult Function(Attachment value)? attachment,
|
|
||||||
required TResult orElse(),
|
|
||||||
}) {
|
|
||||||
if (log != null) {
|
|
||||||
return log(this);
|
|
||||||
}
|
|
||||||
return orElse();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class Log implements VeilidUpdate {
|
|
||||||
const factory Log(
|
|
||||||
{required VeilidLogLevel logLevel, required String message}) = _$Log;
|
|
||||||
|
|
||||||
VeilidLogLevel get logLevel;
|
|
||||||
String get message;
|
|
||||||
@JsonKey(ignore: true)
|
|
||||||
$LogCopyWith<Log> get copyWith => throw _privateConstructorUsedError;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
abstract class $AttachmentCopyWith<$Res> {
|
|
||||||
factory $AttachmentCopyWith(
|
|
||||||
Attachment value, $Res Function(Attachment) then) =
|
|
||||||
_$AttachmentCopyWithImpl<$Res>;
|
|
||||||
$Res call({AttachmentState field0});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
class _$AttachmentCopyWithImpl<$Res> extends _$VeilidUpdateCopyWithImpl<$Res>
|
|
||||||
implements $AttachmentCopyWith<$Res> {
|
|
||||||
_$AttachmentCopyWithImpl(Attachment _value, $Res Function(Attachment) _then)
|
|
||||||
: super(_value, (v) => _then(v as Attachment));
|
|
||||||
|
|
||||||
@override
|
|
||||||
Attachment get _value => super._value as Attachment;
|
|
||||||
|
|
||||||
@override
|
|
||||||
$Res call({
|
|
||||||
Object? field0 = freezed,
|
|
||||||
}) {
|
|
||||||
return _then(Attachment(
|
|
||||||
field0 == freezed
|
|
||||||
? _value.field0
|
|
||||||
: field0 // ignore: cast_nullable_to_non_nullable
|
|
||||||
as AttachmentState,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
|
|
||||||
class _$Attachment implements Attachment {
|
|
||||||
const _$Attachment(this.field0);
|
|
||||||
|
|
||||||
@override
|
|
||||||
final AttachmentState field0;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return 'VeilidUpdate.attachment(field0: $field0)';
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(dynamic other) {
|
|
||||||
return identical(this, other) ||
|
|
||||||
(other.runtimeType == runtimeType &&
|
|
||||||
other is Attachment &&
|
|
||||||
const DeepCollectionEquality().equals(other.field0, field0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode =>
|
|
||||||
Object.hash(runtimeType, const DeepCollectionEquality().hash(field0));
|
|
||||||
|
|
||||||
@JsonKey(ignore: true)
|
|
||||||
@override
|
|
||||||
$AttachmentCopyWith<Attachment> get copyWith =>
|
|
||||||
_$AttachmentCopyWithImpl<Attachment>(this, _$identity);
|
|
||||||
|
|
||||||
@override
|
|
||||||
@optionalTypeArgs
|
|
||||||
TResult when<TResult extends Object?>({
|
|
||||||
required TResult Function(VeilidLogLevel logLevel, String message) log,
|
|
||||||
required TResult Function(AttachmentState field0) attachment,
|
|
||||||
}) {
|
|
||||||
return attachment(field0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
@optionalTypeArgs
|
|
||||||
TResult? whenOrNull<TResult extends Object?>({
|
|
||||||
TResult Function(VeilidLogLevel logLevel, String message)? log,
|
|
||||||
TResult Function(AttachmentState field0)? attachment,
|
|
||||||
}) {
|
|
||||||
return attachment?.call(field0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
@optionalTypeArgs
|
|
||||||
TResult maybeWhen<TResult extends Object?>({
|
|
||||||
TResult Function(VeilidLogLevel logLevel, String message)? log,
|
|
||||||
TResult Function(AttachmentState field0)? attachment,
|
|
||||||
required TResult orElse(),
|
|
||||||
}) {
|
|
||||||
if (attachment != null) {
|
|
||||||
return attachment(field0);
|
|
||||||
}
|
|
||||||
return orElse();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
@optionalTypeArgs
|
|
||||||
TResult map<TResult extends Object?>({
|
|
||||||
required TResult Function(Log value) log,
|
|
||||||
required TResult Function(Attachment value) attachment,
|
|
||||||
}) {
|
|
||||||
return attachment(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
@optionalTypeArgs
|
|
||||||
TResult? mapOrNull<TResult extends Object?>({
|
|
||||||
TResult Function(Log value)? log,
|
|
||||||
TResult Function(Attachment value)? attachment,
|
|
||||||
}) {
|
|
||||||
return attachment?.call(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
@optionalTypeArgs
|
|
||||||
TResult maybeMap<TResult extends Object?>({
|
|
||||||
TResult Function(Log value)? log,
|
|
||||||
TResult Function(Attachment value)? attachment,
|
|
||||||
required TResult orElse(),
|
|
||||||
}) {
|
|
||||||
if (attachment != null) {
|
|
||||||
return attachment(this);
|
|
||||||
}
|
|
||||||
return orElse();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class Attachment implements VeilidUpdate {
|
|
||||||
const factory Attachment(AttachmentState field0) = _$Attachment;
|
|
||||||
|
|
||||||
AttachmentState get field0;
|
|
||||||
@JsonKey(ignore: true)
|
|
||||||
$AttachmentCopyWith<Attachment> get copyWith =>
|
|
||||||
throw _privateConstructorUsedError;
|
|
||||||
}
|
|
@ -1,31 +1,92 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:ffi';
|
|
||||||
import 'dart:io';
|
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:veilid/bridge_generated.dart';
|
import 'package:oxidized/oxidized.dart';
|
||||||
|
|
||||||
const base = 'veilid_flutter';
|
import 'veilid_stub.dart'
|
||||||
final path = Platform.isWindows
|
if (dart.library.io) 'veilid_ffi.dart'
|
||||||
? '$base.dll'
|
if (dart.library.js) 'veilid_js.dart';
|
||||||
: Platform.isMacOS
|
|
||||||
? 'lib$base.dylib'
|
|
||||||
: 'lib$base.so';
|
|
||||||
late final dylib = Platform.isIOS ? DynamicLibrary.process() : DynamicLibrary.open(path);
|
|
||||||
late final veilidApi = VeilidFlutterImpl(dylib);
|
|
||||||
|
|
||||||
class Veilid {
|
//////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static VeilidFlutterImpl get api {
|
enum AttachmentState {
|
||||||
if (veilidApi == null) {
|
Detached,
|
||||||
throw PlatformException(
|
Attaching,
|
||||||
code: 'Library missing',
|
AttachedWeak,
|
||||||
details: 'veilid_flutter library could not be loaded dynamically',
|
AttachedGood,
|
||||||
);
|
AttachedStrong,
|
||||||
}
|
FullyAttached,
|
||||||
return veilidApi;
|
OverAttached,
|
||||||
|
Detaching,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum VeilidLogLevel {
|
||||||
|
Error,
|
||||||
|
Warn,
|
||||||
|
Info,
|
||||||
|
Debug,
|
||||||
|
Trace,
|
||||||
|
}
|
||||||
|
|
||||||
|
// VeilidVersion
|
||||||
|
|
||||||
|
class VeilidVersion {
|
||||||
|
final int major;
|
||||||
|
final int minor;
|
||||||
|
final int patch;
|
||||||
|
|
||||||
|
VeilidVersion({
|
||||||
|
required this.major,
|
||||||
|
required this.minor,
|
||||||
|
required this.patch,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// VeilidUpdate
|
||||||
|
|
||||||
|
abstract class VeilidUpdate {
|
||||||
|
VeilidUpdateKind get kind;
|
||||||
|
}
|
||||||
|
|
||||||
|
class VeilidUpdateLog implements VeilidUpdate {
|
||||||
|
final VeilidLogLevel logLevel;
|
||||||
|
final String message;
|
||||||
|
|
||||||
|
VeilidUpdateLog(this.logLevel, this.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
class VeilidUpdateAttachment implements VeilidUpdate {
|
||||||
|
final AttachmentState state;
|
||||||
|
|
||||||
|
VeilidUpdateAttachment(this.state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// VeilidState
|
||||||
|
|
||||||
|
class VeilidState {
|
||||||
|
final AttachmentState attachment;
|
||||||
|
|
||||||
|
VeilidState(this.attachment);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Veilid singleton factory
|
||||||
|
|
||||||
|
abstract class Veilid {
|
||||||
|
static Veilid _instance;
|
||||||
|
|
||||||
|
static Veilid get instance {
|
||||||
|
_instance ??= getVeilid();
|
||||||
|
return _instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Stream<VeilidUpdate> startupVeilidCore(String config);
|
||||||
|
Future<Result<VeilidState, VeilidAPIError>> getVeilidState();
|
||||||
|
Future<Result<Unit, VeilidAPIError>> changeApiLogLevel(VeilidLogLevel logLevel);
|
||||||
|
Future<Result<Unit, VeilidAPIError>> shutdownVeilidCore();
|
||||||
|
String veilidVersionString();
|
||||||
|
VeilidVersion veilidVersion();
|
||||||
}
|
}
|
||||||
|
106
veilid-flutter/lib/veilid_ffi.dart
Normal file
106
veilid-flutter/lib/veilid_ffi.dart
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:ffi' as ffi;
|
||||||
|
import 'dart:io';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:ffi/ffi.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:oxidized/oxidized.dart';
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Load the veilid_flutter library once
|
||||||
|
const _base = 'veilid_flutter';
|
||||||
|
final _path = Platform.isWindows
|
||||||
|
? '$_base.dll'
|
||||||
|
: Platform.isMacOS
|
||||||
|
? 'lib$_base.dylib'
|
||||||
|
: 'lib$_base.so';
|
||||||
|
late final _dylib = Platform.isIOS ? DynamicLibrary.process() : DynamicLibrary.open(_path);
|
||||||
|
|
||||||
|
// Linkage for initialization
|
||||||
|
typedef _dart_postCObject = NativeFunction<Int8 Function(Int64, Pointer<Dart_CObject>)>;
|
||||||
|
// fn free_string(s: *mut std::os::raw::c_char)
|
||||||
|
typedef _free_string_C = Void Function(Pointer<Utf8>);
|
||||||
|
typedef _free_string_Dart = void Function(Pointer<Utf8>);
|
||||||
|
// fn initialize_veilid_flutter(dart_post_c_object_ptr: ffi::DartPostCObjectFnType)
|
||||||
|
typedef _initializeVeilidFlutter_C = Void Function(Pointer<_dart_postCObject>);
|
||||||
|
typedef _initializeVeilidFlutter_Dart = void Function(Pointer<_dart_postCObject>);
|
||||||
|
// fn startup_veilid_core(port: i64, config: FfiStr)
|
||||||
|
typedef _startup_veilid_core_C = Void Function(Int64, Pointer<Utf8>);
|
||||||
|
typedef _startup_veilid_core_Dart = void Function(int, Pointer<Utf8>);
|
||||||
|
// fn get_veilid_state(port: i64)
|
||||||
|
typedef _get_veilid_state_C = Void Function(Int64);
|
||||||
|
typedef _get_veilid_state_Dart = void Function(int);
|
||||||
|
// fn change_api_log_level(port: i64, log_level: FfiStr)
|
||||||
|
typedef _change_api_log_level_C = Void Function(Int64, Pointer<Utf8>);
|
||||||
|
typedef _change_api_log_level_Dart = void Function(int, Pointer<Utf8>);
|
||||||
|
// fn shutdown_veilid_core(port: i64)
|
||||||
|
typedef _shutdown_veilid_core_C = Void Function(Int64);
|
||||||
|
typedef _shutdown_veilid_core_Dart = void Function(int);
|
||||||
|
// fn veilid_version_string() -> *mut c_char
|
||||||
|
typedef _veilid_version_string_C = Pointer<Utf8> Function();
|
||||||
|
typedef _veilid_version_string_Dart = Pointer<Utf8> Function();
|
||||||
|
// fn veilid_version() -> VeilidVersion
|
||||||
|
class VeilidVersion extends Struct {
|
||||||
|
@Uint32()
|
||||||
|
external int major;
|
||||||
|
@Uint32()
|
||||||
|
external int minor;
|
||||||
|
@Uint32()
|
||||||
|
external int patch;
|
||||||
|
}
|
||||||
|
typedef _veilid_version_C = VeilidVersion Function();
|
||||||
|
typedef _veilid_version_Dart = VeilidVersion Function();
|
||||||
|
|
||||||
|
// Interface factory for high level Veilid API
|
||||||
|
Veilid getVeilid() => VeilidFFI(_dylib);
|
||||||
|
|
||||||
|
// FFI implementation of high level Veilid API
|
||||||
|
class VeilidFFI {
|
||||||
|
// veilid_core shared library
|
||||||
|
final DynamicLibrary _dylib;
|
||||||
|
|
||||||
|
// Shared library functions
|
||||||
|
final _free_string_Dart _freeString;
|
||||||
|
final _startup_veilid_core_Dart _startupVeilidCore;
|
||||||
|
final _get_veilid_state_Dart _getVeilidState;
|
||||||
|
final _change_api_log_level_Dart _changeApiLogLevel;
|
||||||
|
final _shutdown_veilid_core_Dart _shutdownVeilidCore;
|
||||||
|
final _veilid_version_string_Dart _veilidVersionString;
|
||||||
|
final _veilid_version_Dat _veilidVersion;
|
||||||
|
|
||||||
|
VeilidFFI(DynamicLibrary dylib): _dylib = dylib {
|
||||||
|
var initializeVeilidFlutter = _dylib.lookupFunction<_initializeVeilidFlutter_C, _initializeVeilidFlutter_Dart>('initialize_veilid_flutter');
|
||||||
|
initializeVeilidFlutter(NativeApi.postCObject);
|
||||||
|
|
||||||
|
// Look up shared library functions
|
||||||
|
_freeString = dylib.lookupFunction<_free_string_C, _free_string_Dart>('free_string');
|
||||||
|
_startupVeilidCore = dylib.lookupFunction<_startup_veilid_core_C, _startup_veilid_core_Dart>('startup_veilid_core');
|
||||||
|
_getveilidState = dylib.lookupFunction<_get_veilid_state_C, _get_veilid_state_Dart>('get_veilid_state');
|
||||||
|
_changeApiLogLevel = dylib.lookupFunction<_change_api_log_level_C, _change_api_log_level_Dart>('change_api_log_level');
|
||||||
|
_shutdownVeilidCore = dylib.lookupFunction<_shutdown_veilid_core_C, _shutdown_veilid_core_Dart>('shutdown_veilid_core');
|
||||||
|
_veilidVersionString = dylib.lookupFunction<_veilid_version_string_C, _veilid_version_string_Dart>('veilid_version_string');
|
||||||
|
_veilidVersion = dylib.lookupFunction<_veilid_version_C, _veilid_version_Dart>('veilid_version');
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<VeilidUpdate> startupVeilidCore(String config);
|
||||||
|
Future<Result<VeilidState, VeilidAPIError>> getVeilidState();
|
||||||
|
Future<Result<Unit, VeilidAPIError>> changeApiLogLevel(VeilidLogLevel logLevel);
|
||||||
|
Future<Result<Unit, VeilidAPIError>> shutdownVeilidCore() async {
|
||||||
|
// xxx continue here
|
||||||
|
}
|
||||||
|
|
||||||
|
String veilidVersionString() {
|
||||||
|
final version_string = _veilidVersionString();
|
||||||
|
String ret = version_string.toDartString();
|
||||||
|
_freeString(version_string);
|
||||||
|
return version_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
VeilidVersion veilidVersion() {
|
||||||
|
return _veilidVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
41
veilid-flutter/lib/veilid_js.dart
Normal file
41
veilid-flutter/lib/veilid_js.dart
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import 'veilid.dart';
|
||||||
|
|
||||||
|
import 'dart:js';
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:oxidized/oxidized.dart';
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
Veilid getVeilid() => VeilidJS();
|
||||||
|
|
||||||
|
class VeilidJS {
|
||||||
|
|
||||||
|
Stream<VeilidUpdate> startupVeilidCore(Object? configCallback(String key)) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<VeilidState> getVeilidState() {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> changeApiLogLevel(VeilidLogLevel logLevel) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> shutdownVeilidCore() {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> veilidVersionString() {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<VeilidVersion> veilidVersion() {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -11,7 +11,7 @@ import 'package:flutter_web_plugins/flutter_web_plugins.dart';
|
|||||||
// xxx link in WASM version of veilid-flutter
|
// xxx link in WASM version of veilid-flutter
|
||||||
|
|
||||||
/// A web implementation of the Veilid plugin.
|
/// A web implementation of the Veilid plugin.
|
||||||
class VeilidWeb {
|
class VeilidPluginStubWeb {
|
||||||
static void registerWith(Registrar registrar) {
|
static void registerWith(Registrar registrar) {
|
||||||
// final MethodChannel channel = MethodChannel(
|
// final MethodChannel channel = MethodChannel(
|
||||||
// 'veilid',
|
// 'veilid',
|
3
veilid-flutter/lib/veilid_stub.dart
Normal file
3
veilid-flutter/lib/veilid_stub.dart
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import 'veilid.dart'
|
||||||
|
|
||||||
|
Veilid getVeilid() => throw UnsupportedError('Cannot create Veilid object');
|
@ -15,6 +15,8 @@ dependencies:
|
|||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_rust_bridge: ^1.14.0
|
flutter_rust_bridge: ^1.14.0
|
||||||
freezed_annotation: ^1.1.0
|
freezed_annotation: ^1.1.0
|
||||||
|
oxidized: ^5.1.0
|
||||||
|
ffi: ^1.1.2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@ -46,8 +48,8 @@ flutter:
|
|||||||
windows:
|
windows:
|
||||||
pluginClass: VeilidPlugin
|
pluginClass: VeilidPlugin
|
||||||
web:
|
web:
|
||||||
pluginClass: VeilidWeb
|
pluginClass: VeilidPluginStubWeb
|
||||||
fileName: veilid_web.dart
|
fileName: veilid_plugin_stub_web.dart
|
||||||
|
|
||||||
# To add assets to your plugin package, add an assets section, like this:
|
# To add assets to your plugin package, add an assets section, like this:
|
||||||
# assets:
|
# assets:
|
||||||
|
@ -4,16 +4,39 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["cdylib", "staticlib"]
|
crate-type = ["cdylib", "staticlib", "rlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
async-std = { version = "^1", features = ["unstable"] }
|
|
||||||
veilid-core = { path="../../veilid-core" }
|
veilid-core = { path="../../veilid-core" }
|
||||||
flutter_rust_bridge = "^1"
|
|
||||||
parking_lot = "^0"
|
parking_lot = "^0"
|
||||||
log = "^0"
|
log = "^0"
|
||||||
anyhow = { version = "^1", features = ["backtrace"] }
|
|
||||||
cfg-if = "^1"
|
cfg-if = "^1"
|
||||||
|
backtrace = "^0"
|
||||||
|
serde_json = "^1"
|
||||||
|
serde = "^1"
|
||||||
|
futures = "^0"
|
||||||
|
|
||||||
|
# Dependencies for native builds only
|
||||||
|
# Linux, Windows, Mac, iOS, Android
|
||||||
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
|
async-std = { version = "^1", features = ["unstable"] }
|
||||||
|
anyhow = { version = "^1", features = ["backtrace"] }
|
||||||
|
allo-isolate = "^0"
|
||||||
|
ffi-support = "^0"
|
||||||
|
lazy_static = "^1"
|
||||||
|
|
||||||
|
# Dependencies for WASM builds only
|
||||||
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
|
wasm-bindgen = "^0"
|
||||||
|
console_error_panic_hook = "^0"
|
||||||
|
wee_alloc = "^0"
|
||||||
|
wasm-logger = "^0"
|
||||||
|
wasm-bindgen-futures = "^0"
|
||||||
|
js-sys = "^0"
|
||||||
|
|
||||||
|
# Dev Dependencies for WASM builds only
|
||||||
|
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
|
||||||
|
wasm-bindgen-test = "^0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cfg-if = "^1"
|
cfg-if = "^1"
|
||||||
|
@ -1,155 +0,0 @@
|
|||||||
use cfg_if::*;
|
|
||||||
use std::env;
|
|
||||||
use std::ffi::OsStr;
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
use std::process::Command;
|
|
||||||
|
|
||||||
fn resolve_llvm_path() -> Option<PathBuf> {
|
|
||||||
cfg_if! {
|
|
||||||
if #[cfg(target_os="linux")] {
|
|
||||||
// build host is linux
|
|
||||||
let paths: Vec<PathBuf> =
|
|
||||||
env::var_os("PATH").map(|paths| env::split_paths(&paths).collect())?;
|
|
||||||
|
|
||||||
// find clang
|
|
||||||
let d = paths.iter().find_map(|p| {
|
|
||||||
if p.join("clang").exists() {
|
|
||||||
if let Ok(real_clang_path) = std::fs::canonicalize(p.join("clang")) {
|
|
||||||
if let Some(llvmbindir) = real_clang_path.parent() {
|
|
||||||
if let Some(llvmdir) = llvmbindir.parent() {
|
|
||||||
return Some(llvmdir.to_owned());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
});
|
|
||||||
|
|
||||||
d.or_else(|| {
|
|
||||||
["/usr/lib/llvm-13", "/usr/lib/llvm-12", "/usr/lib/llvm-11", "/usr/lib/llvm-10"].iter().map(Path::new).find_map(|p| if p.exists() { Some(p.to_owned()) } else { None } )
|
|
||||||
})
|
|
||||||
|
|
||||||
} else if #[cfg(target_os="macos")] {
|
|
||||||
// build host is mac
|
|
||||||
["/usr/local/opt/llvm", "/opt/homebrew/opt/llvm", ].iter().map(Path::new).find_map(|p| if p.exists() { Some(p.to_owned()) } else { None } )
|
|
||||||
} else {
|
|
||||||
// anywhere else, just use the default paths
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
//let out_dir = env::var_os("OUT_DIR").unwrap();
|
|
||||||
let manifest_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap();
|
|
||||||
|
|
||||||
let input_path = Path::new(&manifest_dir).join("src").join("api.rs");
|
|
||||||
let output_path = Path::new(&manifest_dir)
|
|
||||||
.parent()
|
|
||||||
.unwrap()
|
|
||||||
.join("lib")
|
|
||||||
.join("bridge_generated.dart");
|
|
||||||
let c_path = Path::new(&manifest_dir)
|
|
||||||
.parent()
|
|
||||||
.unwrap()
|
|
||||||
.join("ios")
|
|
||||||
.join("Classes")
|
|
||||||
.join("bridge_generated.h");
|
|
||||||
let llvm_path = resolve_llvm_path();
|
|
||||||
|
|
||||||
//eprintln!("input_path: {:?}", input_path);
|
|
||||||
//eprintln!("output_path: {:?}", output_path);
|
|
||||||
//eprintln!("c_path: {:?}", c_path);
|
|
||||||
//eprintln!("llvm_path: {:?}", llvm_path);
|
|
||||||
|
|
||||||
let mut command = Command::new("flutter_rust_bridge_codegen");
|
|
||||||
if let Some(llvm_path) = llvm_path {
|
|
||||||
command.args([
|
|
||||||
OsStr::new("--rust-input"),
|
|
||||||
input_path.as_os_str(),
|
|
||||||
OsStr::new("--dart-output"),
|
|
||||||
output_path.as_os_str(),
|
|
||||||
OsStr::new("--c-output"),
|
|
||||||
c_path.as_os_str(),
|
|
||||||
OsStr::new("--llvm-path"),
|
|
||||||
llvm_path.as_os_str(),
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
command.args([
|
|
||||||
OsStr::new("--rust-input"),
|
|
||||||
input_path.as_os_str(),
|
|
||||||
OsStr::new("--dart-output"),
|
|
||||||
output_path.as_os_str(),
|
|
||||||
OsStr::new("--c-output"),
|
|
||||||
c_path.as_os_str(),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut child = command
|
|
||||||
.spawn()
|
|
||||||
.expect("flutter_rust_bridge_codegen did not execute correctly");
|
|
||||||
child
|
|
||||||
.wait()
|
|
||||||
.expect("flutter_rust_bridge_codegen was not running");
|
|
||||||
|
|
||||||
// Flutter pub get
|
|
||||||
// Run: flutter pub get
|
|
||||||
|
|
||||||
let mut command;
|
|
||||||
cfg_if! {
|
|
||||||
if #[cfg(target_os="windows")] {
|
|
||||||
command = Command::new("cmd");
|
|
||||||
command.args([
|
|
||||||
OsStr::new("/c"),
|
|
||||||
OsStr::new("flutter"),
|
|
||||||
OsStr::new("pub"),
|
|
||||||
OsStr::new("get"),
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
command = Command::new("flutter");
|
|
||||||
command.args([
|
|
||||||
OsStr::new("pub"),
|
|
||||||
OsStr::new("get"),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut child = command
|
|
||||||
.spawn()
|
|
||||||
.expect("'flutter pub get' did not execute correctly");
|
|
||||||
child.wait().expect("'flutter pub get' was not running");
|
|
||||||
|
|
||||||
// Build freezed
|
|
||||||
// Run: flutter pub run build_runner build
|
|
||||||
|
|
||||||
let mut command;
|
|
||||||
cfg_if! {
|
|
||||||
if #[cfg(target_os="windows")] {
|
|
||||||
command = Command::new("cmd");
|
|
||||||
command.args([
|
|
||||||
OsStr::new("/c"),
|
|
||||||
OsStr::new("flutter"),
|
|
||||||
OsStr::new("pub"),
|
|
||||||
OsStr::new("run"),
|
|
||||||
OsStr::new("build_runner"),
|
|
||||||
OsStr::new("build"),
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
command = Command::new("flutter");
|
|
||||||
command.args([
|
|
||||||
OsStr::new("pub"),
|
|
||||||
OsStr::new("run"),
|
|
||||||
OsStr::new("build_runner"),
|
|
||||||
OsStr::new("build"),
|
|
||||||
OsStr::new("--delete-conflicting-outputs"),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut child = command
|
|
||||||
.spawn()
|
|
||||||
.expect("'flutter pub run build_runner build' did not execute correctly");
|
|
||||||
child
|
|
||||||
.wait()
|
|
||||||
.expect("'flutter pub run build_runner build' was not running");
|
|
||||||
}
|
|
@ -1,608 +0,0 @@
|
|||||||
use anyhow::*;
|
|
||||||
use async_std::sync::Mutex as AsyncMutex;
|
|
||||||
use cfg_if::*;
|
|
||||||
use flutter_rust_bridge::*;
|
|
||||||
use log::*;
|
|
||||||
use std::fmt;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
// Globals
|
|
||||||
|
|
||||||
static VEILID_API: AsyncMutex<Option<veilid_core::VeilidAPI>> = AsyncMutex::new(None);
|
|
||||||
async fn get_veilid_api() -> Result<veilid_core::VeilidAPI> {
|
|
||||||
let api_lock = VEILID_API.lock().await;
|
|
||||||
let veilid_api = match &*api_lock {
|
|
||||||
None => {
|
|
||||||
return Err(anyhow!(VeilidAPIError::NotInitialized));
|
|
||||||
}
|
|
||||||
Some(api) => api.clone(),
|
|
||||||
};
|
|
||||||
Ok(veilid_api)
|
|
||||||
}
|
|
||||||
async fn take_veilid_api() -> Result<veilid_core::VeilidAPI> {
|
|
||||||
let mut api_lock = VEILID_API.lock().await;
|
|
||||||
let veilid_api = match api_lock.take() {
|
|
||||||
None => {
|
|
||||||
return Err(anyhow!(VeilidAPIError::NotInitialized));
|
|
||||||
}
|
|
||||||
Some(api) => api,
|
|
||||||
};
|
|
||||||
Ok(veilid_api)
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////
|
|
||||||
// Config Settings
|
|
||||||
// Not all settings available through Veilid API are available to Flutter applications
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub struct VeilidConfig {
|
|
||||||
pub program_name: String,
|
|
||||||
pub veilid_namespace: String,
|
|
||||||
pub api_log_level: VeilidLogLevel,
|
|
||||||
// Capabilities
|
|
||||||
pub capabilities__protocol_udp: bool,
|
|
||||||
pub capabilities__protocol_connect_tcp: bool,
|
|
||||||
pub capabilities__protocol_accept_tcp: bool,
|
|
||||||
pub capabilities__protocol_connect_ws: bool,
|
|
||||||
pub capabilities__protocol_accept_ws: bool,
|
|
||||||
pub capabilities__protocol_connect_wss: bool,
|
|
||||||
pub capabilities__protocol_accept_wss: bool,
|
|
||||||
// Protected Store
|
|
||||||
pub protected_store__allow_insecure_fallback: bool,
|
|
||||||
pub protected_store__always_use_insecure_storage: bool,
|
|
||||||
pub protected_store__insecure_fallback_directory: String,
|
|
||||||
pub protected_store__delete: bool,
|
|
||||||
// Table Store
|
|
||||||
pub table_store__directory: String,
|
|
||||||
pub table_store__delete: bool,
|
|
||||||
// Block Store
|
|
||||||
pub block_store__directory: String,
|
|
||||||
pub block_store__delete: bool,
|
|
||||||
// Network
|
|
||||||
pub network__max_connections: u32,
|
|
||||||
pub network__connection_initial_timeout_ms: u32,
|
|
||||||
pub network__node_id: String,
|
|
||||||
pub network__node_id_secret: String,
|
|
||||||
pub network__bootstrap: Vec<String>,
|
|
||||||
pub network__upnp: bool,
|
|
||||||
pub network__natpmp: bool,
|
|
||||||
pub network__enable_local_peer_scope: bool,
|
|
||||||
pub network__restricted_nat_retries: u32,
|
|
||||||
// Network / RPC
|
|
||||||
pub network__rpc__concurrency: u32,
|
|
||||||
pub network__rpc__queue_size: u32,
|
|
||||||
pub network__rpc__max_timestamp_behind_ms: Option<u32>,
|
|
||||||
pub network__rpc__max_timestamp_ahead_ms: Option<u32>,
|
|
||||||
pub network__rpc__timeout_ms: u32,
|
|
||||||
pub network__rpc__max_route_hop_count: u8,
|
|
||||||
// Network / DHT
|
|
||||||
pub network__dht__resolve_node_timeout_ms: Option<u32>,
|
|
||||||
pub network__dht__resolve_node_count: u32,
|
|
||||||
pub network__dht__resolve_node_fanout: u32,
|
|
||||||
pub network__dht__max_find_node_count: u32,
|
|
||||||
pub network__dht__get_value_timeout_ms: Option<u32>,
|
|
||||||
pub network__dht__get_value_count: u32,
|
|
||||||
pub network__dht__get_value_fanout: u32,
|
|
||||||
pub network__dht__set_value_timeout_ms: Option<u32>,
|
|
||||||
pub network__dht__set_value_count: u32,
|
|
||||||
pub network__dht__set_value_fanout: u32,
|
|
||||||
pub network__dht__min_peer_count: u32,
|
|
||||||
pub network__dht__min_peer_refresh_time_ms: u32,
|
|
||||||
pub network__dht__validate_dial_info_receipt_time_ms: u32,
|
|
||||||
// Network / Protocol
|
|
||||||
// Network / Protocol / UDP
|
|
||||||
pub network__protocol__udp__enabled: bool,
|
|
||||||
pub network__protocol__udp__socket_pool_size: u32,
|
|
||||||
pub network__protocol__udp__listen_address: String,
|
|
||||||
pub network__protocol__udp__public_address: Option<String>,
|
|
||||||
// Network / Protocol / TCP
|
|
||||||
pub network__protocol__tcp__connect: bool,
|
|
||||||
pub network__protocol__tcp__listen: bool,
|
|
||||||
pub network__protocol__tcp__max_connections: u32,
|
|
||||||
pub network__protocol__tcp__listen_address: String,
|
|
||||||
pub network__protocol__tcp__public_address: Option<String>,
|
|
||||||
// Network / Protocol / WS
|
|
||||||
pub network__protocol__ws__connect: bool,
|
|
||||||
pub network__protocol__ws__listen: bool,
|
|
||||||
pub network__protocol__ws__max_connections: u32,
|
|
||||||
pub network__protocol__ws__listen_address: String,
|
|
||||||
pub network__protocol__ws__path: String,
|
|
||||||
pub network__protocol__ws__url: Option<String>,
|
|
||||||
// Network / Protocol / WSS
|
|
||||||
pub network__protocol__wss__connect: bool,
|
|
||||||
pub network__protocol__wss__max_connections: u32,
|
|
||||||
// Network / Leases
|
|
||||||
pub network__leases__max_server_signal_leases: u32,
|
|
||||||
pub network__leases__max_server_relay_leases: u32,
|
|
||||||
pub network__leases__max_client_signal_leases: u32,
|
|
||||||
pub network__leases__max_client_relay_leases: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg_if! {
|
|
||||||
if #[cfg(target_arch="wasm32")] {
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg_if! {
|
|
||||||
if #[cfg(target_arch="wasm32")] {
|
|
||||||
type ConfigReturn = Box<dyn std::any::Any + 'static>;
|
|
||||||
} else {
|
|
||||||
type ConfigReturn = Box<dyn std::any::Any + Send + 'static>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VeilidConfig {
|
|
||||||
pub fn get_by_str(&self, key: &str) -> std::result::Result<ConfigReturn, String> {
|
|
||||||
let out: ConfigReturn = match key {
|
|
||||||
"program_name" => Box::new(self.program_name.clone()),
|
|
||||||
"namespace" => Box::new(self.veilid_namespace.clone()),
|
|
||||||
"api_log_level" => Box::new(self.api_log_level.to_config_log_level()),
|
|
||||||
"capabilities.protocol_udp" => Box::new(self.capabilities__protocol_udp.clone()),
|
|
||||||
"capabilities.protocol_connect_tcp" => {
|
|
||||||
Box::new(self.capabilities__protocol_connect_tcp.clone())
|
|
||||||
}
|
|
||||||
"capabilities.protocol_accept_tcp" => {
|
|
||||||
Box::new(self.capabilities__protocol_accept_tcp.clone())
|
|
||||||
}
|
|
||||||
"capabilities.protocol_connect_ws" => {
|
|
||||||
Box::new(self.capabilities__protocol_connect_ws.clone())
|
|
||||||
}
|
|
||||||
"capabilities.protocol_accept_ws" => {
|
|
||||||
Box::new(self.capabilities__protocol_accept_ws.clone())
|
|
||||||
}
|
|
||||||
"capabilities.protocol_connect_wss" => {
|
|
||||||
Box::new(self.capabilities__protocol_connect_wss.clone())
|
|
||||||
}
|
|
||||||
"capabilities.protocol_accept_wss" => {
|
|
||||||
Box::new(self.capabilities__protocol_accept_wss.clone())
|
|
||||||
}
|
|
||||||
"table_store.directory" => Box::new(self.table_store__directory.clone()),
|
|
||||||
"table_store.delete" => Box::new(self.table_store__delete.clone()),
|
|
||||||
"block_store.directory" => Box::new(self.block_store__directory.clone()),
|
|
||||||
"block_store.delete" => Box::new(self.block_store__delete.clone()),
|
|
||||||
"protected_store.allow_insecure_fallback" => {
|
|
||||||
Box::new(self.protected_store__allow_insecure_fallback.clone())
|
|
||||||
}
|
|
||||||
"protected_store.always_use_insecure_storage" => {
|
|
||||||
Box::new(self.protected_store__always_use_insecure_storage.clone())
|
|
||||||
}
|
|
||||||
"protected_store.insecure_fallback_directory" => {
|
|
||||||
Box::new(self.protected_store__insecure_fallback_directory.clone())
|
|
||||||
}
|
|
||||||
"protected_store.delete" => Box::new(self.protected_store__delete.clone()),
|
|
||||||
"network.node_id" => Box::new(self.network__node_id.clone()),
|
|
||||||
"network.node_id_secret" => Box::new(self.network__node_id_secret.clone()),
|
|
||||||
"network.max_connections" => Box::new(self.network__max_connections.clone()),
|
|
||||||
"network.connection_initial_timeout_ms" => {
|
|
||||||
Box::new(self.network__connection_initial_timeout_ms.clone())
|
|
||||||
}
|
|
||||||
"network.bootstrap" => Box::new(self.network__bootstrap.clone()),
|
|
||||||
"network.dht.resolve_node_timeout_ms" => {
|
|
||||||
Box::new(self.network__dht__resolve_node_timeout_ms.clone())
|
|
||||||
}
|
|
||||||
"network.dht.resolve_node_count" => {
|
|
||||||
Box::new(self.network__dht__resolve_node_count.clone())
|
|
||||||
}
|
|
||||||
"network.dht.resolve_node_fanout" => {
|
|
||||||
Box::new(self.network__dht__resolve_node_fanout.clone())
|
|
||||||
}
|
|
||||||
"network.dht.max_find_node_count" => {
|
|
||||||
Box::new(self.network__dht__max_find_node_count.clone())
|
|
||||||
}
|
|
||||||
"network.dht.get_value_timeout_ms" => {
|
|
||||||
Box::new(self.network__dht__get_value_timeout_ms.clone())
|
|
||||||
}
|
|
||||||
"network.dht.get_value_count" => Box::new(self.network__dht__get_value_count.clone()),
|
|
||||||
"network.dht.get_value_fanout" => Box::new(self.network__dht__get_value_fanout.clone()),
|
|
||||||
"network.dht.set_value_timeout_ms" => {
|
|
||||||
Box::new(self.network__dht__set_value_timeout_ms.clone())
|
|
||||||
}
|
|
||||||
"network.dht.set_value_count" => Box::new(self.network__dht__set_value_count.clone()),
|
|
||||||
"network.dht.set_value_fanout" => Box::new(self.network__dht__set_value_fanout.clone()),
|
|
||||||
"network.dht.min_peer_count" => Box::new(self.network__dht__min_peer_count.clone()),
|
|
||||||
"network.dht.min_peer_refresh_time_ms" => {
|
|
||||||
Box::new(self.network__dht__min_peer_refresh_time_ms.clone())
|
|
||||||
}
|
|
||||||
"network.dht.validate_dial_info_receipt_time_ms" => Box::new(
|
|
||||||
self.network__dht__validate_dial_info_receipt_time_ms
|
|
||||||
.clone(),
|
|
||||||
),
|
|
||||||
"network.rpc.concurrency" => Box::new(self.network__rpc__concurrency.clone()),
|
|
||||||
"network.rpc.queue_size" => Box::new(self.network__rpc__queue_size.clone()),
|
|
||||||
"network.rpc.max_timestamp_behind_ms" => {
|
|
||||||
Box::new(self.network__rpc__max_timestamp_behind_ms.clone())
|
|
||||||
}
|
|
||||||
"network.rpc.max_timestamp_ahead_ms" => {
|
|
||||||
Box::new(self.network__rpc__max_timestamp_ahead_ms.clone())
|
|
||||||
}
|
|
||||||
"network.rpc.timeout_ms" => Box::new(self.network__rpc__timeout_ms.clone()),
|
|
||||||
"network.rpc.max_route_hop_count" => {
|
|
||||||
Box::new(self.network__rpc__max_route_hop_count.clone())
|
|
||||||
}
|
|
||||||
"network.upnp" => Box::new(self.network__upnp.clone()),
|
|
||||||
"network.natpmp" => Box::new(self.network__natpmp.clone()),
|
|
||||||
"network.enable_local_peer_scope" => {
|
|
||||||
Box::new(self.network__enable_local_peer_scope.clone())
|
|
||||||
}
|
|
||||||
"network.restricted_nat_retries" => {
|
|
||||||
Box::new(self.network__restricted_nat_retries.clone())
|
|
||||||
}
|
|
||||||
"network.tls.certificate_path" => Box::new("".to_owned()),
|
|
||||||
"network.tls.private_key_path" => Box::new("".to_owned()),
|
|
||||||
"network.tls.connection_initial_timeout" => Box::new(0u32),
|
|
||||||
"network.application.https.enabled" => Box::new(false),
|
|
||||||
"network.application.https.listen_address" => Box::new("".to_owned()),
|
|
||||||
"network.application.https.path" => Box::new("".to_owned()),
|
|
||||||
"network.application.https.url" => Box::new(Option::<String>::None),
|
|
||||||
"network.application.http.enabled" => Box::new(false),
|
|
||||||
"network.application.http.listen_address" => Box::new("".to_owned()),
|
|
||||||
"network.application.http.path" => Box::new("".to_owned()),
|
|
||||||
"network.application.http.url" => Box::new(Option::<String>::None),
|
|
||||||
"network.protocol.udp.enabled" => {
|
|
||||||
Box::new(self.network__protocol__udp__enabled.clone())
|
|
||||||
}
|
|
||||||
"network.protocol.udp.socket_pool_size" => {
|
|
||||||
Box::new(self.network__protocol__udp__socket_pool_size.clone())
|
|
||||||
}
|
|
||||||
"network.protocol.udp.listen_address" => {
|
|
||||||
Box::new(self.network__protocol__udp__listen_address.clone())
|
|
||||||
}
|
|
||||||
"network.protocol.udp.public_address" => {
|
|
||||||
Box::new(self.network__protocol__udp__public_address.clone())
|
|
||||||
}
|
|
||||||
"network.protocol.tcp.connect" => {
|
|
||||||
Box::new(self.network__protocol__tcp__connect.clone())
|
|
||||||
}
|
|
||||||
"network.protocol.tcp.listen" => Box::new(self.network__protocol__tcp__listen.clone()),
|
|
||||||
"network.protocol.tcp.max_connections" => {
|
|
||||||
Box::new(self.network__protocol__tcp__max_connections.clone())
|
|
||||||
}
|
|
||||||
"network.protocol.tcp.listen_address" => {
|
|
||||||
Box::new(self.network__protocol__tcp__listen_address.clone())
|
|
||||||
}
|
|
||||||
"network.protocol.tcp.public_address" => {
|
|
||||||
Box::new(self.network__protocol__tcp__public_address.clone())
|
|
||||||
}
|
|
||||||
"network.protocol.ws.connect" => Box::new(self.network__protocol__ws__connect.clone()),
|
|
||||||
"network.protocol.ws.listen" => Box::new(self.network__protocol__ws__listen.clone()),
|
|
||||||
"network.protocol.ws.max_connections" => {
|
|
||||||
Box::new(self.network__protocol__ws__max_connections.clone())
|
|
||||||
}
|
|
||||||
"network.protocol.ws.listen_address" => {
|
|
||||||
Box::new(self.network__protocol__ws__listen_address.clone())
|
|
||||||
}
|
|
||||||
"network.protocol.ws.path" => Box::new(self.network__protocol__ws__path.clone()),
|
|
||||||
"network.protocol.ws.url" => Box::new(self.network__protocol__ws__url.clone()),
|
|
||||||
"network.protocol.wss.connect" => {
|
|
||||||
Box::new(self.network__protocol__wss__connect.clone())
|
|
||||||
}
|
|
||||||
"network.protocol.wss.listen" => Box::new(false),
|
|
||||||
"network.protocol.wss.max_connections" => {
|
|
||||||
Box::new(self.network__protocol__wss__max_connections.clone())
|
|
||||||
}
|
|
||||||
"network.protocol.wss.listen_address" => Box::new("".to_owned()),
|
|
||||||
"network.protocol.wss.path" => Box::new("".to_owned()),
|
|
||||||
"network.protocol.wss.url" => Box::new(Option::<String>::None),
|
|
||||||
"network.leases.max_server_signal_leases" => {
|
|
||||||
Box::new(self.network__leases__max_server_signal_leases.clone())
|
|
||||||
}
|
|
||||||
"network.leases.max_server_relay_leases" => {
|
|
||||||
Box::new(self.network__leases__max_server_relay_leases.clone())
|
|
||||||
}
|
|
||||||
"network.leases.max_client_signal_leases" => {
|
|
||||||
Box::new(self.network__leases__max_client_signal_leases.clone())
|
|
||||||
}
|
|
||||||
"network.leases.max_client_relay_leases" => {
|
|
||||||
Box::new(self.network__leases__max_client_relay_leases.clone())
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let err = format!("config key '{}' doesn't exist", key);
|
|
||||||
error!("{}", err);
|
|
||||||
return Err(err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
std::result::Result::Ok(out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum VeilidAPIError {
|
|
||||||
AlreadyInitialized,
|
|
||||||
NotInitialized,
|
|
||||||
InvalidConfig(String),
|
|
||||||
Timeout,
|
|
||||||
Shutdown,
|
|
||||||
NodeNotFound(String),
|
|
||||||
NoDialInfo(String),
|
|
||||||
Internal(String),
|
|
||||||
Unimplemented(String),
|
|
||||||
ParseError {
|
|
||||||
message: String,
|
|
||||||
value: String,
|
|
||||||
},
|
|
||||||
InvalidArgument {
|
|
||||||
context: String,
|
|
||||||
argument: String,
|
|
||||||
value: String,
|
|
||||||
},
|
|
||||||
MissingArgument {
|
|
||||||
context: String,
|
|
||||||
argument: String,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for VeilidAPIError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
VeilidAPIError::AlreadyInitialized => write!(f, "VeilidAPIError::AlreadyInitialized"),
|
|
||||||
VeilidAPIError::NotInitialized => write!(f, "VeilidAPIError::NotInitialized"),
|
|
||||||
VeilidAPIError::InvalidConfig(e) => write!(f, "VeilidAPIError::InvalidConfig({})", e),
|
|
||||||
VeilidAPIError::Timeout => write!(f, "VeilidAPIError::Timeout"),
|
|
||||||
VeilidAPIError::Shutdown => write!(f, "VeilidAPIError::Shutdown"),
|
|
||||||
VeilidAPIError::NodeNotFound(ni) => write!(f, "VeilidAPIError::NodeNotFound({})", ni),
|
|
||||||
VeilidAPIError::NoDialInfo(ni) => write!(f, "VeilidAPIError::NoDialInfo({})", ni),
|
|
||||||
VeilidAPIError::Internal(e) => write!(f, "VeilidAPIError::Internal({})", e),
|
|
||||||
VeilidAPIError::Unimplemented(e) => write!(f, "VeilidAPIError::Unimplemented({})", e),
|
|
||||||
VeilidAPIError::ParseError { message, value } => {
|
|
||||||
write!(f, "VeilidAPIError::ParseError({}: {})", message, value)
|
|
||||||
}
|
|
||||||
VeilidAPIError::InvalidArgument {
|
|
||||||
context,
|
|
||||||
argument,
|
|
||||||
value,
|
|
||||||
} => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"VeilidAPIError::InvalidArgument({}: {} = {})",
|
|
||||||
context, argument, value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
VeilidAPIError::MissingArgument { context, argument } => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"VeilidAPIError::MissingArgument({}: {})",
|
|
||||||
context, argument
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::error::Error for VeilidAPIError {}
|
|
||||||
|
|
||||||
impl VeilidAPIError {
|
|
||||||
fn from_core(api_error: veilid_core::VeilidAPIError) -> Self {
|
|
||||||
match api_error {
|
|
||||||
veilid_core::VeilidAPIError::Timeout => VeilidAPIError::Timeout,
|
|
||||||
veilid_core::VeilidAPIError::Shutdown => VeilidAPIError::Shutdown,
|
|
||||||
veilid_core::VeilidAPIError::NodeNotFound(node_id) => {
|
|
||||||
VeilidAPIError::NodeNotFound(format!("{}", node_id))
|
|
||||||
}
|
|
||||||
veilid_core::VeilidAPIError::NoDialInfo(node_id) => {
|
|
||||||
VeilidAPIError::NodeNotFound(format!("{}", node_id))
|
|
||||||
}
|
|
||||||
veilid_core::VeilidAPIError::Internal(msg) => VeilidAPIError::Internal(msg.clone()),
|
|
||||||
veilid_core::VeilidAPIError::Unimplemented(msg) => {
|
|
||||||
VeilidAPIError::Unimplemented(msg.clone())
|
|
||||||
}
|
|
||||||
veilid_core::VeilidAPIError::ParseError { message, value } => {
|
|
||||||
VeilidAPIError::ParseError {
|
|
||||||
message: message.clone(),
|
|
||||||
value: value.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
veilid_core::VeilidAPIError::InvalidArgument {
|
|
||||||
context,
|
|
||||||
argument,
|
|
||||||
value,
|
|
||||||
} => VeilidAPIError::InvalidArgument {
|
|
||||||
context: context.clone(),
|
|
||||||
argument: argument.clone(),
|
|
||||||
value: value.clone(),
|
|
||||||
},
|
|
||||||
veilid_core::VeilidAPIError::MissingArgument { context, argument } => {
|
|
||||||
VeilidAPIError::MissingArgument {
|
|
||||||
context: context.clone(),
|
|
||||||
argument: argument.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub enum AttachmentState {
|
|
||||||
Detached,
|
|
||||||
Attaching,
|
|
||||||
AttachedWeak,
|
|
||||||
AttachedGood,
|
|
||||||
AttachedStrong,
|
|
||||||
FullyAttached,
|
|
||||||
OverAttached,
|
|
||||||
Detaching,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AttachmentState {
|
|
||||||
fn from_core(attachment_state: veilid_core::AttachmentState) -> Self {
|
|
||||||
match attachment_state {
|
|
||||||
veilid_core::AttachmentState::Detached => AttachmentState::Detached,
|
|
||||||
veilid_core::AttachmentState::Attaching => AttachmentState::Attaching,
|
|
||||||
veilid_core::AttachmentState::AttachedWeak => AttachmentState::AttachedWeak,
|
|
||||||
veilid_core::AttachmentState::AttachedGood => AttachmentState::AttachedGood,
|
|
||||||
veilid_core::AttachmentState::AttachedStrong => AttachmentState::AttachedStrong,
|
|
||||||
veilid_core::AttachmentState::FullyAttached => AttachmentState::FullyAttached,
|
|
||||||
veilid_core::AttachmentState::OverAttached => AttachmentState::OverAttached,
|
|
||||||
veilid_core::AttachmentState::Detaching => AttachmentState::Detaching,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub enum VeilidLogLevel {
|
|
||||||
Error,
|
|
||||||
Warn,
|
|
||||||
Info,
|
|
||||||
Debug,
|
|
||||||
Trace,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for VeilidLogLevel {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::Info
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VeilidLogLevel {
|
|
||||||
fn from_core(level: veilid_core::VeilidLogLevel) -> Self {
|
|
||||||
match level {
|
|
||||||
veilid_core::VeilidLogLevel::Error => VeilidLogLevel::Error,
|
|
||||||
veilid_core::VeilidLogLevel::Warn => VeilidLogLevel::Warn,
|
|
||||||
veilid_core::VeilidLogLevel::Info => VeilidLogLevel::Info,
|
|
||||||
veilid_core::VeilidLogLevel::Debug => VeilidLogLevel::Debug,
|
|
||||||
veilid_core::VeilidLogLevel::Trace => VeilidLogLevel::Trace,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_config_log_level(&self) -> veilid_core::VeilidConfigLogLevel {
|
|
||||||
match self {
|
|
||||||
Self::Error => veilid_core::VeilidConfigLogLevel::Error,
|
|
||||||
Self::Warn => veilid_core::VeilidConfigLogLevel::Warn,
|
|
||||||
Self::Info => veilid_core::VeilidConfigLogLevel::Info,
|
|
||||||
Self::Debug => veilid_core::VeilidConfigLogLevel::Debug,
|
|
||||||
Self::Trace => veilid_core::VeilidConfigLogLevel::Trace,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum VeilidUpdate {
|
|
||||||
Log {
|
|
||||||
log_level: VeilidLogLevel,
|
|
||||||
message: String,
|
|
||||||
},
|
|
||||||
Attachment(AttachmentState),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VeilidUpdate {
|
|
||||||
fn from_core(veilid_update: veilid_core::VeilidUpdate) -> Self {
|
|
||||||
match veilid_update {
|
|
||||||
veilid_core::VeilidUpdate::Log { log_level, message } => Self::Log {
|
|
||||||
log_level: VeilidLogLevel::from_core(log_level),
|
|
||||||
message,
|
|
||||||
},
|
|
||||||
veilid_core::VeilidUpdate::Attachment(attachment) => {
|
|
||||||
Self::Attachment(AttachmentState::from_core(attachment))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct VeilidState {
|
|
||||||
pub attachment: AttachmentState,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VeilidState {
|
|
||||||
fn from_core(veilid_state: veilid_core::VeilidState) -> Self {
|
|
||||||
Self {
|
|
||||||
attachment: AttachmentState::from_core(veilid_state.attachment),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////
|
|
||||||
pub fn startup_veilid_core(
|
|
||||||
sink: StreamSink<VeilidUpdate>,
|
|
||||||
config: VeilidConfig,
|
|
||||||
) -> Result<VeilidState> {
|
|
||||||
async_std::task::block_on(async {
|
|
||||||
let mut api_lock = VEILID_API.lock().await;
|
|
||||||
if api_lock.is_some() {
|
|
||||||
return Err(anyhow!(VeilidAPIError::AlreadyInitialized));
|
|
||||||
}
|
|
||||||
|
|
||||||
let core = veilid_core::VeilidCore::new();
|
|
||||||
|
|
||||||
let setup = veilid_core::VeilidCoreSetup {
|
|
||||||
update_callback: Arc::new(
|
|
||||||
move |update: veilid_core::VeilidUpdate| -> veilid_core::SystemPinBoxFuture<()> {
|
|
||||||
let sink = sink.clone();
|
|
||||||
Box::pin(async move {
|
|
||||||
if !sink.add(VeilidUpdate::from_core(update)) {
|
|
||||||
error!("error sending veilid update callback");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
),
|
|
||||||
config_callback: Arc::new(move |key| config.get_by_str(&key)),
|
|
||||||
};
|
|
||||||
|
|
||||||
let veilid_api = core
|
|
||||||
.startup(setup)
|
|
||||||
.await
|
|
||||||
.map_err(|e| VeilidAPIError::InvalidConfig(e.clone()))?;
|
|
||||||
*api_lock = Some(veilid_api.clone());
|
|
||||||
|
|
||||||
let core_state = veilid_api
|
|
||||||
.get_state()
|
|
||||||
.await
|
|
||||||
.map_err(VeilidAPIError::from_core)?;
|
|
||||||
Ok(VeilidState::from_core(core_state))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_veilid_state() -> Result<VeilidState> {
|
|
||||||
async_std::task::block_on(async {
|
|
||||||
let veilid_api = get_veilid_api().await?;
|
|
||||||
let core_state = veilid_api
|
|
||||||
.get_state()
|
|
||||||
.await
|
|
||||||
.map_err(VeilidAPIError::from_core)?;
|
|
||||||
Ok(VeilidState::from_core(core_state))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// xxx api functions
|
|
||||||
|
|
||||||
pub fn change_api_log_level(log_level: VeilidLogLevel) -> Result<()> {
|
|
||||||
async_std::task::block_on(async {
|
|
||||||
let veilid_api = get_veilid_api().await?;
|
|
||||||
veilid_api
|
|
||||||
.change_api_log_level(log_level.to_config_log_level())
|
|
||||||
.await;
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn shutdown_veilid_core() -> Result<()> {
|
|
||||||
async_std::task::block_on(async {
|
|
||||||
let veilid_api = get_veilid_api().await?;
|
|
||||||
veilid_api.shutdown().await;
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn veilid_version_string() -> Result<String> {
|
|
||||||
Ok(veilid_core::veilid_version_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct VeilidVersion {
|
|
||||||
pub major: u32,
|
|
||||||
pub minor: u32,
|
|
||||||
pub patch: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn veilid_version() -> Result<VeilidVersion> {
|
|
||||||
let (major, minor, patch) = veilid_core::veilid_version();
|
|
||||||
Ok(VeilidVersion {
|
|
||||||
major,
|
|
||||||
minor,
|
|
||||||
patch,
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,581 +0,0 @@
|
|||||||
#![allow(
|
|
||||||
non_camel_case_types,
|
|
||||||
unused,
|
|
||||||
clippy::redundant_closure,
|
|
||||||
clippy::useless_conversion,
|
|
||||||
non_snake_case
|
|
||||||
)]
|
|
||||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
|
||||||
// Generated by `flutter_rust_bridge`.
|
|
||||||
|
|
||||||
use crate::api::*;
|
|
||||||
use flutter_rust_bridge::*;
|
|
||||||
|
|
||||||
// Section: wire functions
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn wire_startup_veilid_core(port_: i64, config: *mut wire_VeilidConfig) {
|
|
||||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap(
|
|
||||||
WrapInfo {
|
|
||||||
debug_name: "startup_veilid_core",
|
|
||||||
port: Some(port_),
|
|
||||||
mode: FfiCallMode::Stream,
|
|
||||||
},
|
|
||||||
move || {
|
|
||||||
let api_config = config.wire2api();
|
|
||||||
move |task_callback| startup_veilid_core(task_callback.stream_sink(), api_config)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn wire_get_veilid_state(port_: i64) {
|
|
||||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap(
|
|
||||||
WrapInfo {
|
|
||||||
debug_name: "get_veilid_state",
|
|
||||||
port: Some(port_),
|
|
||||||
mode: FfiCallMode::Normal,
|
|
||||||
},
|
|
||||||
move || move |task_callback| get_veilid_state(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn wire_change_api_log_level(port_: i64, log_level: i32) {
|
|
||||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap(
|
|
||||||
WrapInfo {
|
|
||||||
debug_name: "change_api_log_level",
|
|
||||||
port: Some(port_),
|
|
||||||
mode: FfiCallMode::Normal,
|
|
||||||
},
|
|
||||||
move || {
|
|
||||||
let api_log_level = log_level.wire2api();
|
|
||||||
move |task_callback| change_api_log_level(api_log_level)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn wire_shutdown_veilid_core(port_: i64) {
|
|
||||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap(
|
|
||||||
WrapInfo {
|
|
||||||
debug_name: "shutdown_veilid_core",
|
|
||||||
port: Some(port_),
|
|
||||||
mode: FfiCallMode::Normal,
|
|
||||||
},
|
|
||||||
move || move |task_callback| shutdown_veilid_core(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn wire_veilid_version_string(port_: i64) {
|
|
||||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap(
|
|
||||||
WrapInfo {
|
|
||||||
debug_name: "veilid_version_string",
|
|
||||||
port: Some(port_),
|
|
||||||
mode: FfiCallMode::Normal,
|
|
||||||
},
|
|
||||||
move || move |task_callback| veilid_version_string(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn wire_veilid_version(port_: i64) {
|
|
||||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap(
|
|
||||||
WrapInfo {
|
|
||||||
debug_name: "veilid_version",
|
|
||||||
port: Some(port_),
|
|
||||||
mode: FfiCallMode::Normal,
|
|
||||||
},
|
|
||||||
move || move |task_callback| veilid_version(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Section: wire structs
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct wire_StringList {
|
|
||||||
ptr: *mut *mut wire_uint_8_list,
|
|
||||||
len: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct wire_uint_8_list {
|
|
||||||
ptr: *mut u8,
|
|
||||||
len: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct wire_VeilidConfig {
|
|
||||||
program_name: *mut wire_uint_8_list,
|
|
||||||
veilid_namespace: *mut wire_uint_8_list,
|
|
||||||
api_log_level: i32,
|
|
||||||
capabilities__protocol_udp: bool,
|
|
||||||
capabilities__protocol_connect_tcp: bool,
|
|
||||||
capabilities__protocol_accept_tcp: bool,
|
|
||||||
capabilities__protocol_connect_ws: bool,
|
|
||||||
capabilities__protocol_accept_ws: bool,
|
|
||||||
capabilities__protocol_connect_wss: bool,
|
|
||||||
capabilities__protocol_accept_wss: bool,
|
|
||||||
protected_store__allow_insecure_fallback: bool,
|
|
||||||
protected_store__always_use_insecure_storage: bool,
|
|
||||||
protected_store__insecure_fallback_directory: *mut wire_uint_8_list,
|
|
||||||
protected_store__delete: bool,
|
|
||||||
table_store__directory: *mut wire_uint_8_list,
|
|
||||||
table_store__delete: bool,
|
|
||||||
block_store__directory: *mut wire_uint_8_list,
|
|
||||||
block_store__delete: bool,
|
|
||||||
network__max_connections: u32,
|
|
||||||
network__connection_initial_timeout_ms: u32,
|
|
||||||
network__node_id: *mut wire_uint_8_list,
|
|
||||||
network__node_id_secret: *mut wire_uint_8_list,
|
|
||||||
network__bootstrap: *mut wire_StringList,
|
|
||||||
network__upnp: bool,
|
|
||||||
network__natpmp: bool,
|
|
||||||
network__enable_local_peer_scope: bool,
|
|
||||||
network__restricted_nat_retries: u32,
|
|
||||||
network__rpc__concurrency: u32,
|
|
||||||
network__rpc__queue_size: u32,
|
|
||||||
network__rpc__max_timestamp_behind_ms: *mut u32,
|
|
||||||
network__rpc__max_timestamp_ahead_ms: *mut u32,
|
|
||||||
network__rpc__timeout_ms: u32,
|
|
||||||
network__rpc__max_route_hop_count: u8,
|
|
||||||
network__dht__resolve_node_timeout_ms: *mut u32,
|
|
||||||
network__dht__resolve_node_count: u32,
|
|
||||||
network__dht__resolve_node_fanout: u32,
|
|
||||||
network__dht__max_find_node_count: u32,
|
|
||||||
network__dht__get_value_timeout_ms: *mut u32,
|
|
||||||
network__dht__get_value_count: u32,
|
|
||||||
network__dht__get_value_fanout: u32,
|
|
||||||
network__dht__set_value_timeout_ms: *mut u32,
|
|
||||||
network__dht__set_value_count: u32,
|
|
||||||
network__dht__set_value_fanout: u32,
|
|
||||||
network__dht__min_peer_count: u32,
|
|
||||||
network__dht__min_peer_refresh_time_ms: u32,
|
|
||||||
network__dht__validate_dial_info_receipt_time_ms: u32,
|
|
||||||
network__protocol__udp__enabled: bool,
|
|
||||||
network__protocol__udp__socket_pool_size: u32,
|
|
||||||
network__protocol__udp__listen_address: *mut wire_uint_8_list,
|
|
||||||
network__protocol__udp__public_address: *mut wire_uint_8_list,
|
|
||||||
network__protocol__tcp__connect: bool,
|
|
||||||
network__protocol__tcp__listen: bool,
|
|
||||||
network__protocol__tcp__max_connections: u32,
|
|
||||||
network__protocol__tcp__listen_address: *mut wire_uint_8_list,
|
|
||||||
network__protocol__tcp__public_address: *mut wire_uint_8_list,
|
|
||||||
network__protocol__ws__connect: bool,
|
|
||||||
network__protocol__ws__listen: bool,
|
|
||||||
network__protocol__ws__max_connections: u32,
|
|
||||||
network__protocol__ws__listen_address: *mut wire_uint_8_list,
|
|
||||||
network__protocol__ws__path: *mut wire_uint_8_list,
|
|
||||||
network__protocol__ws__url: *mut wire_uint_8_list,
|
|
||||||
network__protocol__wss__connect: bool,
|
|
||||||
network__protocol__wss__max_connections: u32,
|
|
||||||
network__leases__max_server_signal_leases: u32,
|
|
||||||
network__leases__max_server_relay_leases: u32,
|
|
||||||
network__leases__max_client_signal_leases: u32,
|
|
||||||
network__leases__max_client_relay_leases: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Section: wire enums
|
|
||||||
|
|
||||||
// Section: allocate functions
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn new_StringList(len: i32) -> *mut wire_StringList {
|
|
||||||
let wrap = wire_StringList {
|
|
||||||
ptr: support::new_leak_vec_ptr(<*mut wire_uint_8_list>::new_with_null_ptr(), len),
|
|
||||||
len,
|
|
||||||
};
|
|
||||||
support::new_leak_box_ptr(wrap)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn new_box_autoadd_u32(value: u32) -> *mut u32 {
|
|
||||||
support::new_leak_box_ptr(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn new_box_autoadd_veilid_config() -> *mut wire_VeilidConfig {
|
|
||||||
support::new_leak_box_ptr(wire_VeilidConfig::new_with_null_ptr())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn new_uint_8_list(len: i32) -> *mut wire_uint_8_list {
|
|
||||||
let ans = wire_uint_8_list {
|
|
||||||
ptr: support::new_leak_vec_ptr(Default::default(), len),
|
|
||||||
len,
|
|
||||||
};
|
|
||||||
support::new_leak_box_ptr(ans)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Section: impl Wire2Api
|
|
||||||
|
|
||||||
pub trait Wire2Api<T> {
|
|
||||||
fn wire2api(self) -> T;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, S> Wire2Api<Option<T>> for *mut S
|
|
||||||
where
|
|
||||||
*mut S: Wire2Api<T>,
|
|
||||||
{
|
|
||||||
fn wire2api(self) -> Option<T> {
|
|
||||||
if self.is_null() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(self.wire2api())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Wire2Api<String> for *mut wire_uint_8_list {
|
|
||||||
fn wire2api(self) -> String {
|
|
||||||
let vec: Vec<u8> = self.wire2api();
|
|
||||||
String::from_utf8_lossy(&vec).into_owned()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Wire2Api<Vec<String>> for *mut wire_StringList {
|
|
||||||
fn wire2api(self) -> Vec<String> {
|
|
||||||
let vec = unsafe {
|
|
||||||
let wrap = support::box_from_leak_ptr(self);
|
|
||||||
support::vec_from_leak_ptr(wrap.ptr, wrap.len)
|
|
||||||
};
|
|
||||||
vec.into_iter().map(Wire2Api::wire2api).collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Wire2Api<bool> for bool {
|
|
||||||
fn wire2api(self) -> bool {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Wire2Api<u32> for *mut u32 {
|
|
||||||
fn wire2api(self) -> u32 {
|
|
||||||
unsafe { *support::box_from_leak_ptr(self) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Wire2Api<VeilidConfig> for *mut wire_VeilidConfig {
|
|
||||||
fn wire2api(self) -> VeilidConfig {
|
|
||||||
let wrap = unsafe { support::box_from_leak_ptr(self) };
|
|
||||||
(*wrap).wire2api().into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Wire2Api<u32> for u32 {
|
|
||||||
fn wire2api(self) -> u32 {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Wire2Api<u8> for u8 {
|
|
||||||
fn wire2api(self) -> u8 {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Wire2Api<Vec<u8>> for *mut wire_uint_8_list {
|
|
||||||
fn wire2api(self) -> Vec<u8> {
|
|
||||||
unsafe {
|
|
||||||
let wrap = support::box_from_leak_ptr(self);
|
|
||||||
support::vec_from_leak_ptr(wrap.ptr, wrap.len)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Wire2Api<VeilidConfig> for wire_VeilidConfig {
|
|
||||||
fn wire2api(self) -> VeilidConfig {
|
|
||||||
VeilidConfig {
|
|
||||||
program_name: self.program_name.wire2api(),
|
|
||||||
veilid_namespace: self.veilid_namespace.wire2api(),
|
|
||||||
api_log_level: self.api_log_level.wire2api(),
|
|
||||||
capabilities__protocol_udp: self.capabilities__protocol_udp.wire2api(),
|
|
||||||
capabilities__protocol_connect_tcp: self.capabilities__protocol_connect_tcp.wire2api(),
|
|
||||||
capabilities__protocol_accept_tcp: self.capabilities__protocol_accept_tcp.wire2api(),
|
|
||||||
capabilities__protocol_connect_ws: self.capabilities__protocol_connect_ws.wire2api(),
|
|
||||||
capabilities__protocol_accept_ws: self.capabilities__protocol_accept_ws.wire2api(),
|
|
||||||
capabilities__protocol_connect_wss: self.capabilities__protocol_connect_wss.wire2api(),
|
|
||||||
capabilities__protocol_accept_wss: self.capabilities__protocol_accept_wss.wire2api(),
|
|
||||||
protected_store__allow_insecure_fallback: self
|
|
||||||
.protected_store__allow_insecure_fallback
|
|
||||||
.wire2api(),
|
|
||||||
protected_store__always_use_insecure_storage: self
|
|
||||||
.protected_store__always_use_insecure_storage
|
|
||||||
.wire2api(),
|
|
||||||
protected_store__insecure_fallback_directory: self
|
|
||||||
.protected_store__insecure_fallback_directory
|
|
||||||
.wire2api(),
|
|
||||||
protected_store__delete: self.protected_store__delete.wire2api(),
|
|
||||||
table_store__directory: self.table_store__directory.wire2api(),
|
|
||||||
table_store__delete: self.table_store__delete.wire2api(),
|
|
||||||
block_store__directory: self.block_store__directory.wire2api(),
|
|
||||||
block_store__delete: self.block_store__delete.wire2api(),
|
|
||||||
network__max_connections: self.network__max_connections.wire2api(),
|
|
||||||
network__connection_initial_timeout_ms: self
|
|
||||||
.network__connection_initial_timeout_ms
|
|
||||||
.wire2api(),
|
|
||||||
network__node_id: self.network__node_id.wire2api(),
|
|
||||||
network__node_id_secret: self.network__node_id_secret.wire2api(),
|
|
||||||
network__bootstrap: self.network__bootstrap.wire2api(),
|
|
||||||
network__upnp: self.network__upnp.wire2api(),
|
|
||||||
network__natpmp: self.network__natpmp.wire2api(),
|
|
||||||
network__enable_local_peer_scope: self.network__enable_local_peer_scope.wire2api(),
|
|
||||||
network__restricted_nat_retries: self.network__restricted_nat_retries.wire2api(),
|
|
||||||
network__rpc__concurrency: self.network__rpc__concurrency.wire2api(),
|
|
||||||
network__rpc__queue_size: self.network__rpc__queue_size.wire2api(),
|
|
||||||
network__rpc__max_timestamp_behind_ms: self
|
|
||||||
.network__rpc__max_timestamp_behind_ms
|
|
||||||
.wire2api(),
|
|
||||||
network__rpc__max_timestamp_ahead_ms: self
|
|
||||||
.network__rpc__max_timestamp_ahead_ms
|
|
||||||
.wire2api(),
|
|
||||||
network__rpc__timeout_ms: self.network__rpc__timeout_ms.wire2api(),
|
|
||||||
network__rpc__max_route_hop_count: self.network__rpc__max_route_hop_count.wire2api(),
|
|
||||||
network__dht__resolve_node_timeout_ms: self
|
|
||||||
.network__dht__resolve_node_timeout_ms
|
|
||||||
.wire2api(),
|
|
||||||
network__dht__resolve_node_count: self.network__dht__resolve_node_count.wire2api(),
|
|
||||||
network__dht__resolve_node_fanout: self.network__dht__resolve_node_fanout.wire2api(),
|
|
||||||
network__dht__max_find_node_count: self.network__dht__max_find_node_count.wire2api(),
|
|
||||||
network__dht__get_value_timeout_ms: self.network__dht__get_value_timeout_ms.wire2api(),
|
|
||||||
network__dht__get_value_count: self.network__dht__get_value_count.wire2api(),
|
|
||||||
network__dht__get_value_fanout: self.network__dht__get_value_fanout.wire2api(),
|
|
||||||
network__dht__set_value_timeout_ms: self.network__dht__set_value_timeout_ms.wire2api(),
|
|
||||||
network__dht__set_value_count: self.network__dht__set_value_count.wire2api(),
|
|
||||||
network__dht__set_value_fanout: self.network__dht__set_value_fanout.wire2api(),
|
|
||||||
network__dht__min_peer_count: self.network__dht__min_peer_count.wire2api(),
|
|
||||||
network__dht__min_peer_refresh_time_ms: self
|
|
||||||
.network__dht__min_peer_refresh_time_ms
|
|
||||||
.wire2api(),
|
|
||||||
network__dht__validate_dial_info_receipt_time_ms: self
|
|
||||||
.network__dht__validate_dial_info_receipt_time_ms
|
|
||||||
.wire2api(),
|
|
||||||
network__protocol__udp__enabled: self.network__protocol__udp__enabled.wire2api(),
|
|
||||||
network__protocol__udp__socket_pool_size: self
|
|
||||||
.network__protocol__udp__socket_pool_size
|
|
||||||
.wire2api(),
|
|
||||||
network__protocol__udp__listen_address: self
|
|
||||||
.network__protocol__udp__listen_address
|
|
||||||
.wire2api(),
|
|
||||||
network__protocol__udp__public_address: self
|
|
||||||
.network__protocol__udp__public_address
|
|
||||||
.wire2api(),
|
|
||||||
network__protocol__tcp__connect: self.network__protocol__tcp__connect.wire2api(),
|
|
||||||
network__protocol__tcp__listen: self.network__protocol__tcp__listen.wire2api(),
|
|
||||||
network__protocol__tcp__max_connections: self
|
|
||||||
.network__protocol__tcp__max_connections
|
|
||||||
.wire2api(),
|
|
||||||
network__protocol__tcp__listen_address: self
|
|
||||||
.network__protocol__tcp__listen_address
|
|
||||||
.wire2api(),
|
|
||||||
network__protocol__tcp__public_address: self
|
|
||||||
.network__protocol__tcp__public_address
|
|
||||||
.wire2api(),
|
|
||||||
network__protocol__ws__connect: self.network__protocol__ws__connect.wire2api(),
|
|
||||||
network__protocol__ws__listen: self.network__protocol__ws__listen.wire2api(),
|
|
||||||
network__protocol__ws__max_connections: self
|
|
||||||
.network__protocol__ws__max_connections
|
|
||||||
.wire2api(),
|
|
||||||
network__protocol__ws__listen_address: self
|
|
||||||
.network__protocol__ws__listen_address
|
|
||||||
.wire2api(),
|
|
||||||
network__protocol__ws__path: self.network__protocol__ws__path.wire2api(),
|
|
||||||
network__protocol__ws__url: self.network__protocol__ws__url.wire2api(),
|
|
||||||
network__protocol__wss__connect: self.network__protocol__wss__connect.wire2api(),
|
|
||||||
network__protocol__wss__max_connections: self
|
|
||||||
.network__protocol__wss__max_connections
|
|
||||||
.wire2api(),
|
|
||||||
network__leases__max_server_signal_leases: self
|
|
||||||
.network__leases__max_server_signal_leases
|
|
||||||
.wire2api(),
|
|
||||||
network__leases__max_server_relay_leases: self
|
|
||||||
.network__leases__max_server_relay_leases
|
|
||||||
.wire2api(),
|
|
||||||
network__leases__max_client_signal_leases: self
|
|
||||||
.network__leases__max_client_signal_leases
|
|
||||||
.wire2api(),
|
|
||||||
network__leases__max_client_relay_leases: self
|
|
||||||
.network__leases__max_client_relay_leases
|
|
||||||
.wire2api(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Wire2Api<VeilidLogLevel> for i32 {
|
|
||||||
fn wire2api(self) -> VeilidLogLevel {
|
|
||||||
match self {
|
|
||||||
0 => VeilidLogLevel::Error,
|
|
||||||
1 => VeilidLogLevel::Warn,
|
|
||||||
2 => VeilidLogLevel::Info,
|
|
||||||
3 => VeilidLogLevel::Debug,
|
|
||||||
4 => VeilidLogLevel::Trace,
|
|
||||||
_ => unreachable!("Invalid variant for VeilidLogLevel: {}", self),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Section: impl NewWithNullPtr
|
|
||||||
|
|
||||||
pub trait NewWithNullPtr {
|
|
||||||
fn new_with_null_ptr() -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> NewWithNullPtr for *mut T {
|
|
||||||
fn new_with_null_ptr() -> Self {
|
|
||||||
std::ptr::null_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NewWithNullPtr for wire_VeilidConfig {
|
|
||||||
fn new_with_null_ptr() -> Self {
|
|
||||||
Self {
|
|
||||||
program_name: core::ptr::null_mut(),
|
|
||||||
veilid_namespace: core::ptr::null_mut(),
|
|
||||||
api_log_level: Default::default(),
|
|
||||||
capabilities__protocol_udp: Default::default(),
|
|
||||||
capabilities__protocol_connect_tcp: Default::default(),
|
|
||||||
capabilities__protocol_accept_tcp: Default::default(),
|
|
||||||
capabilities__protocol_connect_ws: Default::default(),
|
|
||||||
capabilities__protocol_accept_ws: Default::default(),
|
|
||||||
capabilities__protocol_connect_wss: Default::default(),
|
|
||||||
capabilities__protocol_accept_wss: Default::default(),
|
|
||||||
protected_store__allow_insecure_fallback: Default::default(),
|
|
||||||
protected_store__always_use_insecure_storage: Default::default(),
|
|
||||||
protected_store__insecure_fallback_directory: core::ptr::null_mut(),
|
|
||||||
protected_store__delete: Default::default(),
|
|
||||||
table_store__directory: core::ptr::null_mut(),
|
|
||||||
table_store__delete: Default::default(),
|
|
||||||
block_store__directory: core::ptr::null_mut(),
|
|
||||||
block_store__delete: Default::default(),
|
|
||||||
network__max_connections: Default::default(),
|
|
||||||
network__connection_initial_timeout_ms: Default::default(),
|
|
||||||
network__node_id: core::ptr::null_mut(),
|
|
||||||
network__node_id_secret: core::ptr::null_mut(),
|
|
||||||
network__bootstrap: core::ptr::null_mut(),
|
|
||||||
network__upnp: Default::default(),
|
|
||||||
network__natpmp: Default::default(),
|
|
||||||
network__enable_local_peer_scope: Default::default(),
|
|
||||||
network__restricted_nat_retries: Default::default(),
|
|
||||||
network__rpc__concurrency: Default::default(),
|
|
||||||
network__rpc__queue_size: Default::default(),
|
|
||||||
network__rpc__max_timestamp_behind_ms: core::ptr::null_mut(),
|
|
||||||
network__rpc__max_timestamp_ahead_ms: core::ptr::null_mut(),
|
|
||||||
network__rpc__timeout_ms: Default::default(),
|
|
||||||
network__rpc__max_route_hop_count: Default::default(),
|
|
||||||
network__dht__resolve_node_timeout_ms: core::ptr::null_mut(),
|
|
||||||
network__dht__resolve_node_count: Default::default(),
|
|
||||||
network__dht__resolve_node_fanout: Default::default(),
|
|
||||||
network__dht__max_find_node_count: Default::default(),
|
|
||||||
network__dht__get_value_timeout_ms: core::ptr::null_mut(),
|
|
||||||
network__dht__get_value_count: Default::default(),
|
|
||||||
network__dht__get_value_fanout: Default::default(),
|
|
||||||
network__dht__set_value_timeout_ms: core::ptr::null_mut(),
|
|
||||||
network__dht__set_value_count: Default::default(),
|
|
||||||
network__dht__set_value_fanout: Default::default(),
|
|
||||||
network__dht__min_peer_count: Default::default(),
|
|
||||||
network__dht__min_peer_refresh_time_ms: Default::default(),
|
|
||||||
network__dht__validate_dial_info_receipt_time_ms: Default::default(),
|
|
||||||
network__protocol__udp__enabled: Default::default(),
|
|
||||||
network__protocol__udp__socket_pool_size: Default::default(),
|
|
||||||
network__protocol__udp__listen_address: core::ptr::null_mut(),
|
|
||||||
network__protocol__udp__public_address: core::ptr::null_mut(),
|
|
||||||
network__protocol__tcp__connect: Default::default(),
|
|
||||||
network__protocol__tcp__listen: Default::default(),
|
|
||||||
network__protocol__tcp__max_connections: Default::default(),
|
|
||||||
network__protocol__tcp__listen_address: core::ptr::null_mut(),
|
|
||||||
network__protocol__tcp__public_address: core::ptr::null_mut(),
|
|
||||||
network__protocol__ws__connect: Default::default(),
|
|
||||||
network__protocol__ws__listen: Default::default(),
|
|
||||||
network__protocol__ws__max_connections: Default::default(),
|
|
||||||
network__protocol__ws__listen_address: core::ptr::null_mut(),
|
|
||||||
network__protocol__ws__path: core::ptr::null_mut(),
|
|
||||||
network__protocol__ws__url: core::ptr::null_mut(),
|
|
||||||
network__protocol__wss__connect: Default::default(),
|
|
||||||
network__protocol__wss__max_connections: Default::default(),
|
|
||||||
network__leases__max_server_signal_leases: Default::default(),
|
|
||||||
network__leases__max_server_relay_leases: Default::default(),
|
|
||||||
network__leases__max_client_signal_leases: Default::default(),
|
|
||||||
network__leases__max_client_relay_leases: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Section: impl IntoDart
|
|
||||||
|
|
||||||
impl support::IntoDart for AttachmentState {
|
|
||||||
fn into_dart(self) -> support::DartCObject {
|
|
||||||
match self {
|
|
||||||
Self::Detached => 0,
|
|
||||||
Self::Attaching => 1,
|
|
||||||
Self::AttachedWeak => 2,
|
|
||||||
Self::AttachedGood => 3,
|
|
||||||
Self::AttachedStrong => 4,
|
|
||||||
Self::FullyAttached => 5,
|
|
||||||
Self::OverAttached => 6,
|
|
||||||
Self::Detaching => 7,
|
|
||||||
}
|
|
||||||
.into_dart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl support::IntoDart for VeilidLogLevel {
|
|
||||||
fn into_dart(self) -> support::DartCObject {
|
|
||||||
match self {
|
|
||||||
Self::Error => 0,
|
|
||||||
Self::Warn => 1,
|
|
||||||
Self::Info => 2,
|
|
||||||
Self::Debug => 3,
|
|
||||||
Self::Trace => 4,
|
|
||||||
}
|
|
||||||
.into_dart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl support::IntoDart for VeilidState {
|
|
||||||
fn into_dart(self) -> support::DartCObject {
|
|
||||||
vec![self.attachment.into_dart()].into_dart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl support::IntoDartExceptPrimitive for VeilidState {}
|
|
||||||
|
|
||||||
impl support::IntoDart for VeilidUpdate {
|
|
||||||
fn into_dart(self) -> support::DartCObject {
|
|
||||||
match self {
|
|
||||||
Self::Log { log_level, message } => {
|
|
||||||
vec![0.into_dart(), log_level.into_dart(), message.into_dart()]
|
|
||||||
}
|
|
||||||
Self::Attachment(field0) => vec![1.into_dart(), field0.into_dart()],
|
|
||||||
}
|
|
||||||
.into_dart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl support::IntoDart for VeilidVersion {
|
|
||||||
fn into_dart(self) -> support::DartCObject {
|
|
||||||
vec![
|
|
||||||
self.major.into_dart(),
|
|
||||||
self.minor.into_dart(),
|
|
||||||
self.patch.into_dart(),
|
|
||||||
]
|
|
||||||
.into_dart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl support::IntoDartExceptPrimitive for VeilidVersion {}
|
|
||||||
|
|
||||||
// Section: executor
|
|
||||||
support::lazy_static! {
|
|
||||||
pub static ref FLUTTER_RUST_BRIDGE_HANDLER: support::DefaultHandler = Default::default();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Section: sync execution mode utility
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn free_WireSyncReturnStruct(val: support::WireSyncReturnStruct) {
|
|
||||||
unsafe {
|
|
||||||
let _ = support::vec_from_leak_ptr(val.ptr, val.len);
|
|
||||||
}
|
|
||||||
}
|
|
243
veilid-flutter/rust/src/config.rs
Normal file
243
veilid-flutter/rust/src/config.rs
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
use cfg_if::*;
|
||||||
|
use log::*;
|
||||||
|
use serde::*;
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
// Config Settings
|
||||||
|
// Not all settings available through Veilid API are available to Flutter applications
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct VeilidConfig {
|
||||||
|
pub program_name: String,
|
||||||
|
pub veilid_namespace: String,
|
||||||
|
pub api_log_level: veilid_core::VeilidConfigLogLevel,
|
||||||
|
// Capabilities
|
||||||
|
pub capabilities__protocol_udp: bool,
|
||||||
|
pub capabilities__protocol_connect_tcp: bool,
|
||||||
|
pub capabilities__protocol_accept_tcp: bool,
|
||||||
|
pub capabilities__protocol_connect_ws: bool,
|
||||||
|
pub capabilities__protocol_accept_ws: bool,
|
||||||
|
pub capabilities__protocol_connect_wss: bool,
|
||||||
|
pub capabilities__protocol_accept_wss: bool,
|
||||||
|
// Protected Store
|
||||||
|
pub protected_store__allow_insecure_fallback: bool,
|
||||||
|
pub protected_store__always_use_insecure_storage: bool,
|
||||||
|
pub protected_store__insecure_fallback_directory: String,
|
||||||
|
pub protected_store__delete: bool,
|
||||||
|
// Table Store
|
||||||
|
pub table_store__directory: String,
|
||||||
|
pub table_store__delete: bool,
|
||||||
|
// Block Store
|
||||||
|
pub block_store__directory: String,
|
||||||
|
pub block_store__delete: bool,
|
||||||
|
// Network
|
||||||
|
pub network__max_connections: u32,
|
||||||
|
pub network__connection_initial_timeout_ms: u32,
|
||||||
|
pub network__node_id: String,
|
||||||
|
pub network__node_id_secret: String,
|
||||||
|
pub network__bootstrap: Vec<String>,
|
||||||
|
pub network__upnp: bool,
|
||||||
|
pub network__natpmp: bool,
|
||||||
|
pub network__enable_local_peer_scope: bool,
|
||||||
|
pub network__restricted_nat_retries: u32,
|
||||||
|
// Network / RPC
|
||||||
|
pub network__rpc__concurrency: u32,
|
||||||
|
pub network__rpc__queue_size: u32,
|
||||||
|
pub network__rpc__max_timestamp_behind_ms: Option<u32>,
|
||||||
|
pub network__rpc__max_timestamp_ahead_ms: Option<u32>,
|
||||||
|
pub network__rpc__timeout_ms: u32,
|
||||||
|
pub network__rpc__max_route_hop_count: u8,
|
||||||
|
// Network / DHT
|
||||||
|
pub network__dht__resolve_node_timeout_ms: Option<u32>,
|
||||||
|
pub network__dht__resolve_node_count: u32,
|
||||||
|
pub network__dht__resolve_node_fanout: u32,
|
||||||
|
pub network__dht__max_find_node_count: u32,
|
||||||
|
pub network__dht__get_value_timeout_ms: Option<u32>,
|
||||||
|
pub network__dht__get_value_count: u32,
|
||||||
|
pub network__dht__get_value_fanout: u32,
|
||||||
|
pub network__dht__set_value_timeout_ms: Option<u32>,
|
||||||
|
pub network__dht__set_value_count: u32,
|
||||||
|
pub network__dht__set_value_fanout: u32,
|
||||||
|
pub network__dht__min_peer_count: u32,
|
||||||
|
pub network__dht__min_peer_refresh_time_ms: u32,
|
||||||
|
pub network__dht__validate_dial_info_receipt_time_ms: u32,
|
||||||
|
// Network / Protocol
|
||||||
|
// Network / Protocol / UDP
|
||||||
|
pub network__protocol__udp__enabled: bool,
|
||||||
|
pub network__protocol__udp__socket_pool_size: u32,
|
||||||
|
pub network__protocol__udp__listen_address: String,
|
||||||
|
pub network__protocol__udp__public_address: Option<String>,
|
||||||
|
// Network / Protocol / TCP
|
||||||
|
pub network__protocol__tcp__connect: bool,
|
||||||
|
pub network__protocol__tcp__listen: bool,
|
||||||
|
pub network__protocol__tcp__max_connections: u32,
|
||||||
|
pub network__protocol__tcp__listen_address: String,
|
||||||
|
pub network__protocol__tcp__public_address: Option<String>,
|
||||||
|
// Network / Protocol / WS
|
||||||
|
pub network__protocol__ws__connect: bool,
|
||||||
|
pub network__protocol__ws__listen: bool,
|
||||||
|
pub network__protocol__ws__max_connections: u32,
|
||||||
|
pub network__protocol__ws__listen_address: String,
|
||||||
|
pub network__protocol__ws__path: String,
|
||||||
|
pub network__protocol__ws__url: Option<String>,
|
||||||
|
// Network / Protocol / WSS
|
||||||
|
pub network__protocol__wss__connect: bool,
|
||||||
|
pub network__protocol__wss__max_connections: u32,
|
||||||
|
// Network / Leases
|
||||||
|
pub network__leases__max_server_signal_leases: u32,
|
||||||
|
pub network__leases__max_server_relay_leases: u32,
|
||||||
|
pub network__leases__max_client_signal_leases: u32,
|
||||||
|
pub network__leases__max_client_relay_leases: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(target_arch="wasm32")] {
|
||||||
|
type ConfigReturn = Box<dyn std::any::Any + 'static>;
|
||||||
|
} else {
|
||||||
|
type ConfigReturn = Box<dyn std::any::Any + Send + 'static>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VeilidConfig {
|
||||||
|
pub fn get_by_str(&self, key: &str) -> std::result::Result<ConfigReturn, String> {
|
||||||
|
let out: ConfigReturn = match key {
|
||||||
|
"program_name" => Box::new(self.program_name.clone()),
|
||||||
|
"namespace" => Box::new(self.veilid_namespace.clone()),
|
||||||
|
"api_log_level" => Box::new(self.api_log_level),
|
||||||
|
"capabilities.protocol_udp" => Box::new(self.capabilities__protocol_udp),
|
||||||
|
"capabilities.protocol_connect_tcp" => {
|
||||||
|
Box::new(self.capabilities__protocol_connect_tcp)
|
||||||
|
}
|
||||||
|
"capabilities.protocol_accept_tcp" => Box::new(self.capabilities__protocol_accept_tcp),
|
||||||
|
"capabilities.protocol_connect_ws" => Box::new(self.capabilities__protocol_connect_ws),
|
||||||
|
"capabilities.protocol_accept_ws" => Box::new(self.capabilities__protocol_accept_ws),
|
||||||
|
"capabilities.protocol_connect_wss" => {
|
||||||
|
Box::new(self.capabilities__protocol_connect_wss)
|
||||||
|
}
|
||||||
|
"capabilities.protocol_accept_wss" => Box::new(self.capabilities__protocol_accept_wss),
|
||||||
|
"table_store.directory" => Box::new(self.table_store__directory.clone()),
|
||||||
|
"table_store.delete" => Box::new(self.table_store__delete),
|
||||||
|
"block_store.directory" => Box::new(self.block_store__directory.clone()),
|
||||||
|
"block_store.delete" => Box::new(self.block_store__delete),
|
||||||
|
"protected_store.allow_insecure_fallback" => {
|
||||||
|
Box::new(self.protected_store__allow_insecure_fallback)
|
||||||
|
}
|
||||||
|
"protected_store.always_use_insecure_storage" => {
|
||||||
|
Box::new(self.protected_store__always_use_insecure_storage)
|
||||||
|
}
|
||||||
|
"protected_store.insecure_fallback_directory" => {
|
||||||
|
Box::new(self.protected_store__insecure_fallback_directory.clone())
|
||||||
|
}
|
||||||
|
"protected_store.delete" => Box::new(self.protected_store__delete),
|
||||||
|
"network.node_id" => Box::new(self.network__node_id.clone()),
|
||||||
|
"network.node_id_secret" => Box::new(self.network__node_id_secret.clone()),
|
||||||
|
"network.max_connections" => Box::new(self.network__max_connections),
|
||||||
|
"network.connection_initial_timeout_ms" => {
|
||||||
|
Box::new(self.network__connection_initial_timeout_ms)
|
||||||
|
}
|
||||||
|
"network.bootstrap" => Box::new(self.network__bootstrap.clone()),
|
||||||
|
"network.dht.resolve_node_timeout_ms" => {
|
||||||
|
Box::new(self.network__dht__resolve_node_timeout_ms)
|
||||||
|
}
|
||||||
|
"network.dht.resolve_node_count" => Box::new(self.network__dht__resolve_node_count),
|
||||||
|
"network.dht.resolve_node_fanout" => Box::new(self.network__dht__resolve_node_fanout),
|
||||||
|
"network.dht.max_find_node_count" => Box::new(self.network__dht__max_find_node_count),
|
||||||
|
"network.dht.get_value_timeout_ms" => Box::new(self.network__dht__get_value_timeout_ms),
|
||||||
|
"network.dht.get_value_count" => Box::new(self.network__dht__get_value_count),
|
||||||
|
"network.dht.get_value_fanout" => Box::new(self.network__dht__get_value_fanout),
|
||||||
|
"network.dht.set_value_timeout_ms" => Box::new(self.network__dht__set_value_timeout_ms),
|
||||||
|
"network.dht.set_value_count" => Box::new(self.network__dht__set_value_count),
|
||||||
|
"network.dht.set_value_fanout" => Box::new(self.network__dht__set_value_fanout),
|
||||||
|
"network.dht.min_peer_count" => Box::new(self.network__dht__min_peer_count),
|
||||||
|
"network.dht.min_peer_refresh_time_ms" => {
|
||||||
|
Box::new(self.network__dht__min_peer_refresh_time_ms)
|
||||||
|
}
|
||||||
|
"network.dht.validate_dial_info_receipt_time_ms" => {
|
||||||
|
Box::new(self.network__dht__validate_dial_info_receipt_time_ms)
|
||||||
|
}
|
||||||
|
"network.rpc.concurrency" => Box::new(self.network__rpc__concurrency),
|
||||||
|
"network.rpc.queue_size" => Box::new(self.network__rpc__queue_size),
|
||||||
|
"network.rpc.max_timestamp_behind_ms" => {
|
||||||
|
Box::new(self.network__rpc__max_timestamp_behind_ms)
|
||||||
|
}
|
||||||
|
"network.rpc.max_timestamp_ahead_ms" => {
|
||||||
|
Box::new(self.network__rpc__max_timestamp_ahead_ms)
|
||||||
|
}
|
||||||
|
"network.rpc.timeout_ms" => Box::new(self.network__rpc__timeout_ms),
|
||||||
|
"network.rpc.max_route_hop_count" => Box::new(self.network__rpc__max_route_hop_count),
|
||||||
|
"network.upnp" => Box::new(self.network__upnp),
|
||||||
|
"network.natpmp" => Box::new(self.network__natpmp),
|
||||||
|
"network.enable_local_peer_scope" => Box::new(self.network__enable_local_peer_scope),
|
||||||
|
"network.restricted_nat_retries" => Box::new(self.network__restricted_nat_retries),
|
||||||
|
"network.tls.certificate_path" => Box::new("".to_owned()),
|
||||||
|
"network.tls.private_key_path" => Box::new("".to_owned()),
|
||||||
|
"network.tls.connection_initial_timeout" => Box::new(0u32),
|
||||||
|
"network.application.https.enabled" => Box::new(false),
|
||||||
|
"network.application.https.listen_address" => Box::new("".to_owned()),
|
||||||
|
"network.application.https.path" => Box::new("".to_owned()),
|
||||||
|
"network.application.https.url" => Box::new(Option::<String>::None),
|
||||||
|
"network.application.http.enabled" => Box::new(false),
|
||||||
|
"network.application.http.listen_address" => Box::new("".to_owned()),
|
||||||
|
"network.application.http.path" => Box::new("".to_owned()),
|
||||||
|
"network.application.http.url" => Box::new(Option::<String>::None),
|
||||||
|
"network.protocol.udp.enabled" => Box::new(self.network__protocol__udp__enabled),
|
||||||
|
"network.protocol.udp.socket_pool_size" => {
|
||||||
|
Box::new(self.network__protocol__udp__socket_pool_size)
|
||||||
|
}
|
||||||
|
"network.protocol.udp.listen_address" => {
|
||||||
|
Box::new(self.network__protocol__udp__listen_address.clone())
|
||||||
|
}
|
||||||
|
"network.protocol.udp.public_address" => {
|
||||||
|
Box::new(self.network__protocol__udp__public_address.clone())
|
||||||
|
}
|
||||||
|
"network.protocol.tcp.connect" => Box::new(self.network__protocol__tcp__connect),
|
||||||
|
"network.protocol.tcp.listen" => Box::new(self.network__protocol__tcp__listen),
|
||||||
|
"network.protocol.tcp.max_connections" => {
|
||||||
|
Box::new(self.network__protocol__tcp__max_connections)
|
||||||
|
}
|
||||||
|
"network.protocol.tcp.listen_address" => {
|
||||||
|
Box::new(self.network__protocol__tcp__listen_address.clone())
|
||||||
|
}
|
||||||
|
"network.protocol.tcp.public_address" => {
|
||||||
|
Box::new(self.network__protocol__tcp__public_address.clone())
|
||||||
|
}
|
||||||
|
"network.protocol.ws.connect" => Box::new(self.network__protocol__ws__connect),
|
||||||
|
"network.protocol.ws.listen" => Box::new(self.network__protocol__ws__listen),
|
||||||
|
"network.protocol.ws.max_connections" => {
|
||||||
|
Box::new(self.network__protocol__ws__max_connections)
|
||||||
|
}
|
||||||
|
"network.protocol.ws.listen_address" => {
|
||||||
|
Box::new(self.network__protocol__ws__listen_address.clone())
|
||||||
|
}
|
||||||
|
"network.protocol.ws.path" => Box::new(self.network__protocol__ws__path.clone()),
|
||||||
|
"network.protocol.ws.url" => Box::new(self.network__protocol__ws__url.clone()),
|
||||||
|
"network.protocol.wss.connect" => Box::new(self.network__protocol__wss__connect),
|
||||||
|
"network.protocol.wss.listen" => Box::new(false),
|
||||||
|
"network.protocol.wss.max_connections" => {
|
||||||
|
Box::new(self.network__protocol__wss__max_connections)
|
||||||
|
}
|
||||||
|
"network.protocol.wss.listen_address" => Box::new("".to_owned()),
|
||||||
|
"network.protocol.wss.path" => Box::new("".to_owned()),
|
||||||
|
"network.protocol.wss.url" => Box::new(Option::<String>::None),
|
||||||
|
"network.leases.max_server_signal_leases" => {
|
||||||
|
Box::new(self.network__leases__max_server_signal_leases)
|
||||||
|
}
|
||||||
|
"network.leases.max_server_relay_leases" => {
|
||||||
|
Box::new(self.network__leases__max_server_relay_leases)
|
||||||
|
}
|
||||||
|
"network.leases.max_client_signal_leases" => {
|
||||||
|
Box::new(self.network__leases__max_client_signal_leases)
|
||||||
|
}
|
||||||
|
"network.leases.max_client_relay_leases" => {
|
||||||
|
Box::new(self.network__leases__max_client_relay_leases)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let err = format!("config key '{}' doesn't exist", key);
|
||||||
|
error!("{}", err);
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::result::Result::Ok(out)
|
||||||
|
}
|
||||||
|
}
|
177
veilid-flutter/rust/src/dart_ffi.rs
Normal file
177
veilid-flutter/rust/src/dart_ffi.rs
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
use crate::config::*;
|
||||||
|
use crate::dart_isolate_wrapper::*;
|
||||||
|
use crate::dart_serialize::*;
|
||||||
|
|
||||||
|
use allo_isolate::*;
|
||||||
|
use async_std::sync::Mutex as AsyncMutex;
|
||||||
|
use ffi_support::*;
|
||||||
|
use lazy_static::*;
|
||||||
|
use log::*;
|
||||||
|
use std::os::raw::c_char;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
// Globals
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref VEILID_API: AsyncMutex<Option<veilid_core::VeilidAPI>> = AsyncMutex::new(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_veilid_api() -> Result<veilid_core::VeilidAPI, veilid_core::VeilidAPIError> {
|
||||||
|
let api_lock = VEILID_API.lock().await;
|
||||||
|
api_lock
|
||||||
|
.as_ref()
|
||||||
|
.cloned()
|
||||||
|
.ok_or(veilid_core::VeilidAPIError::NotInitialized)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn take_veilid_api() -> Result<veilid_core::VeilidAPI, veilid_core::VeilidAPIError> {
|
||||||
|
let mut api_lock = VEILID_API.lock().await;
|
||||||
|
api_lock
|
||||||
|
.take()
|
||||||
|
.ok_or(veilid_core::VeilidAPIError::NotInitialized)
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
// FFI Helpers
|
||||||
|
|
||||||
|
// Declare external routine to release ffi strings
|
||||||
|
define_string_destructor!(free_string);
|
||||||
|
|
||||||
|
// Utility types for async API results
|
||||||
|
type APIResult<T> = Result<T, veilid_core::VeilidAPIError>;
|
||||||
|
const APIRESULT_VOID: APIResult<()> = APIResult::Ok(());
|
||||||
|
|
||||||
|
// Stream abort macro for simplified error handling
|
||||||
|
macro_rules! check_err_json {
|
||||||
|
($stream:expr, $ex:expr) => {
|
||||||
|
match $ex {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
$stream.abort_json(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
// Initializer
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn initialize_veilid_flutter(dart_post_c_object_ptr: ffi::DartPostCObjectFnType) {
|
||||||
|
unsafe {
|
||||||
|
store_dart_post_cobject(dart_post_c_object_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
use std::sync::Once;
|
||||||
|
static INIT_BACKTRACE: Once = Once::new();
|
||||||
|
INIT_BACKTRACE.call_once(move || {
|
||||||
|
std::env::set_var("RUST_BACKTRACE", "1");
|
||||||
|
std::panic::set_hook(Box::new(move |panic_info| {
|
||||||
|
let (file, line) = if let Some(loc) = panic_info.location() {
|
||||||
|
(loc.file(), loc.line())
|
||||||
|
} else {
|
||||||
|
("<unknown>", 0)
|
||||||
|
};
|
||||||
|
log::error!("### Rust `panic!` hit at file '{}', line {}", file, line);
|
||||||
|
if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
|
||||||
|
error!("panic payload: {:?}", s);
|
||||||
|
} else if let Some(s) = panic_info.payload().downcast_ref::<String>() {
|
||||||
|
error!("panic payload: {:?}", s);
|
||||||
|
} else if let Some(a) = panic_info.payload().downcast_ref::<std::fmt::Arguments>() {
|
||||||
|
error!("panic payload: {:?}", a);
|
||||||
|
} else {
|
||||||
|
error!("no panic payload");
|
||||||
|
}
|
||||||
|
log::error!(" Complete stack trace:\n{:?}", backtrace::Backtrace::new());
|
||||||
|
|
||||||
|
// And stop the process, no recovery is going to be possible here
|
||||||
|
std::process::abort();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// C-compatible FFI Functions
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn startup_veilid_core(port: i64, config: FfiStr) {
|
||||||
|
let config = config.into_opt_string();
|
||||||
|
let stream = DartIsolateStream::new(port);
|
||||||
|
async_std::task::spawn(async move {
|
||||||
|
let config: VeilidConfig = check_err_json!(stream, deserialize_opt_json(config));
|
||||||
|
|
||||||
|
let mut api_lock = VEILID_API.lock().await;
|
||||||
|
if api_lock.is_some() {
|
||||||
|
stream.abort_json(veilid_core::VeilidAPIError::AlreadyInitialized);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sink = stream.clone();
|
||||||
|
let setup = veilid_core::VeilidCoreSetup {
|
||||||
|
update_callback: Arc::new(
|
||||||
|
move |update: veilid_core::VeilidUpdate| -> veilid_core::SystemPinBoxFuture<()> {
|
||||||
|
let sink = sink.clone();
|
||||||
|
Box::pin(async move {
|
||||||
|
sink.item_json(update);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
),
|
||||||
|
config_callback: Arc::new(move |key| config.get_by_str(&key)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let res = veilid_core::api_startup(setup).await;
|
||||||
|
let veilid_api = check_err_json!(stream, res);
|
||||||
|
*api_lock = Some(veilid_api);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn get_veilid_state(port: i64) {
|
||||||
|
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||||
|
let veilid_api = get_veilid_api().await?;
|
||||||
|
let core_state = veilid_api.get_state().await?;
|
||||||
|
APIResult::Ok(core_state)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn change_api_log_level(port: i64, log_level: FfiStr) {
|
||||||
|
let log_level = log_level.into_opt_string();
|
||||||
|
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||||
|
let log_level: veilid_core::VeilidConfigLogLevel = deserialize_opt_json(log_level)?;
|
||||||
|
let veilid_api = get_veilid_api().await?;
|
||||||
|
veilid_api.change_api_log_level(log_level).await;
|
||||||
|
APIRESULT_VOID
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn shutdown_veilid_core(port: i64) {
|
||||||
|
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||||
|
let veilid_api = take_veilid_api().await?;
|
||||||
|
veilid_api.shutdown().await;
|
||||||
|
APIRESULT_VOID
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn veilid_version_string() -> *mut c_char {
|
||||||
|
veilid_core::veilid_version_string().into_ffi_value()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct VeilidVersion {
|
||||||
|
pub major: u32,
|
||||||
|
pub minor: u32,
|
||||||
|
pub patch: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn veilid_version() -> VeilidVersion {
|
||||||
|
let (major, minor, patch) = veilid_core::veilid_version();
|
||||||
|
VeilidVersion {
|
||||||
|
major,
|
||||||
|
minor,
|
||||||
|
patch,
|
||||||
|
}
|
||||||
|
}
|
151
veilid-flutter/rust/src/dart_isolate_wrapper.rs
Normal file
151
veilid-flutter/rust/src/dart_isolate_wrapper.rs
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
use crate::dart_serialize::*;
|
||||||
|
pub use allo_isolate::ffi::DartCObject;
|
||||||
|
pub use allo_isolate::IntoDart;
|
||||||
|
use allo_isolate::Isolate;
|
||||||
|
use core::future::Future;
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
use serde::*;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct DartIsolateWrapper {
|
||||||
|
isolate: Isolate,
|
||||||
|
}
|
||||||
|
|
||||||
|
const MESSAGE_OK: i32 = 0;
|
||||||
|
const MESSAGE_ERR: i32 = 1;
|
||||||
|
const MESSAGE_OK_JSON: i32 = 2;
|
||||||
|
const MESSAGE_ERR_JSON: i32 = 3;
|
||||||
|
const MESSAGE_STREAM_ITEM: i32 = 4;
|
||||||
|
const MESSAGE_STREAM_ITEM_JSON: i32 = 5;
|
||||||
|
const MESSAGE_STREAM_ABORT: i32 = 6;
|
||||||
|
const MESSAGE_STREAM_ABORT_JSON: i32 = 7;
|
||||||
|
const MESSAGE_STREAM_CLOSE: i32 = 8;
|
||||||
|
|
||||||
|
impl DartIsolateWrapper {
|
||||||
|
pub fn new(port: i64) -> Self {
|
||||||
|
DartIsolateWrapper {
|
||||||
|
isolate: Isolate::new(port),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn_result_json<F, T, E>(self, future: F)
|
||||||
|
where
|
||||||
|
F: Future<Output = Result<T, E>> + Send + 'static,
|
||||||
|
T: Serialize,
|
||||||
|
E: Serialize,
|
||||||
|
{
|
||||||
|
async_std::task::spawn(async move {
|
||||||
|
self.result_json(future.await);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn result<T: IntoDart, E: IntoDart>(&self, result: Result<T, E>) -> bool {
|
||||||
|
match result {
|
||||||
|
Ok(v) => self.ok(v),
|
||||||
|
Err(e) => self.err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn result_json<T: Serialize, E: Serialize>(&self, result: Result<T, E>) -> bool {
|
||||||
|
match result {
|
||||||
|
Ok(v) => self.ok_json(v),
|
||||||
|
Err(e) => self.err_json(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn ok<T: IntoDart>(&self, value: T) -> bool {
|
||||||
|
self.isolate
|
||||||
|
.post(vec![MESSAGE_OK.into_dart(), value.into_dart()])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ok_json<T: Serialize>(&self, value: T) -> bool {
|
||||||
|
self.isolate.post(vec![
|
||||||
|
MESSAGE_OK_JSON.into_dart(),
|
||||||
|
serialize_json(value).into_dart(),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn err<E: IntoDart>(&self, error: E) -> bool {
|
||||||
|
self.isolate
|
||||||
|
.post(vec![MESSAGE_ERR.into_dart(), error.into_dart()])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn err_json<E: Serialize>(&self, error: E) -> bool {
|
||||||
|
self.isolate.post(vec![
|
||||||
|
MESSAGE_ERR_JSON.into_dart(),
|
||||||
|
serialize_json(error).into_dart(),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct DartIsolateStream {
|
||||||
|
isolate: Arc<Mutex<Option<Isolate>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DartIsolateStream {
|
||||||
|
pub fn new(port: i64) -> Self {
|
||||||
|
DartIsolateStream {
|
||||||
|
isolate: Arc::new(Mutex::new(Some(Isolate::new(port)))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn item<T: IntoDart>(&self, value: T) -> bool {
|
||||||
|
let isolate = self.isolate.lock();
|
||||||
|
if let Some(isolate) = &*isolate {
|
||||||
|
isolate.post(vec![MESSAGE_STREAM_ITEM.into_dart(), value.into_dart()])
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn item_json<T: Serialize>(&self, value: T) -> bool {
|
||||||
|
let isolate = self.isolate.lock();
|
||||||
|
if let Some(isolate) = &*isolate {
|
||||||
|
isolate.post(vec![
|
||||||
|
MESSAGE_STREAM_ITEM_JSON.into_dart(),
|
||||||
|
serialize_json(value).into_dart(),
|
||||||
|
])
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn abort<E: IntoDart>(self, error: E) -> bool {
|
||||||
|
let mut isolate = self.isolate.lock();
|
||||||
|
if let Some(isolate) = isolate.take() {
|
||||||
|
isolate.post(vec![MESSAGE_STREAM_ABORT.into_dart(), error.into_dart()])
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn abort_json<E: Serialize>(self, error: E) -> bool {
|
||||||
|
let mut isolate = self.isolate.lock();
|
||||||
|
if let Some(isolate) = isolate.take() {
|
||||||
|
isolate.post(vec![
|
||||||
|
MESSAGE_STREAM_ABORT_JSON.into_dart(),
|
||||||
|
serialize_json(error).into_dart(),
|
||||||
|
])
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn close(self) -> bool {
|
||||||
|
let mut isolate = self.isolate.lock();
|
||||||
|
if let Some(isolate) = isolate.take() {
|
||||||
|
isolate.post(vec![MESSAGE_STREAM_CLOSE.into_dart()])
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for DartIsolateStream {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let mut isolate = self.isolate.lock();
|
||||||
|
if let Some(isolate) = isolate.take() {
|
||||||
|
isolate.post(vec![MESSAGE_STREAM_CLOSE.into_dart()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
veilid-flutter/rust/src/dart_serialize.rs
Normal file
24
veilid-flutter/rust/src/dart_serialize.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use serde::*;
|
||||||
|
|
||||||
|
pub fn deserialize_json<'a, T: de::Deserialize<'a>>(
|
||||||
|
arg: &'a str,
|
||||||
|
) -> Result<T, veilid_core::VeilidAPIError> {
|
||||||
|
serde_json::from_str(arg).map_err(|e| veilid_core::VeilidAPIError::ParseError {
|
||||||
|
message: e.to_string(),
|
||||||
|
value: String::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize_opt_json<T: de::DeserializeOwned>(
|
||||||
|
arg: Option<String>,
|
||||||
|
) -> Result<T, veilid_core::VeilidAPIError> {
|
||||||
|
let arg = arg.ok_or_else(|| veilid_core::VeilidAPIError::ParseError {
|
||||||
|
message: "invalid null string passed to rust".to_owned(),
|
||||||
|
value: String::new(),
|
||||||
|
})?;
|
||||||
|
deserialize_json(&arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn serialize_json<T: Serialize>(val: T) -> String {
|
||||||
|
serde_json::to_string(&val).expect("failed to serialize json value")
|
||||||
|
}
|
@ -1,5 +1,15 @@
|
|||||||
mod api;
|
use cfg_if::*;
|
||||||
mod bridge_generated;
|
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(not(target_arch = "wasm32"))] {
|
||||||
|
mod dart_ffi;
|
||||||
|
mod dart_isolate_wrapper;
|
||||||
|
mod dart_serialize;
|
||||||
|
} else {
|
||||||
|
mod wasm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mod config;
|
||||||
|
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
use jni::{objects::JClass, objects::JObject, JNIEnv};
|
use jni::{objects::JClass, objects::JObject, JNIEnv};
|
||||||
|
25
veilid-flutter/rust/src/wasm/mod.rs
Normal file
25
veilid-flutter/rust/src/wasm/mod.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#![cfg(target_arch = "wasm32")]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
pub use log::*;
|
||||||
|
pub use wasm_bindgen::prelude::*;
|
||||||
|
pub use wasm_bindgen::JsCast;
|
||||||
|
|
||||||
|
pub use alloc::boxed::Box;
|
||||||
|
pub use alloc::string::String;
|
||||||
|
pub use alloc::sync::Arc;
|
||||||
|
pub use alloc::vec::Vec;
|
||||||
|
pub use core::convert::TryFrom;
|
||||||
|
pub use js_sys::*;
|
||||||
|
pub use js_veilid_core::*;
|
||||||
|
pub use utils::*;
|
||||||
|
pub use veilid_core::dht::key::*;
|
||||||
|
pub use veilid_core::xx::*;
|
||||||
|
pub use veilid_core::*;
|
||||||
|
pub use wasm_logger::*;
|
||||||
|
|
||||||
|
mod js_veilid_core;
|
||||||
|
mod utils;
|
@ -36,7 +36,10 @@ fn convert_update(
|
|||||||
rpc_update: crate::veilid_client_capnp::veilid_update::Builder,
|
rpc_update: crate::veilid_client_capnp::veilid_update::Builder,
|
||||||
) {
|
) {
|
||||||
match update {
|
match update {
|
||||||
veilid_core::VeilidUpdate::Log(_ll, _s) => {
|
veilid_core::VeilidUpdate::Log {
|
||||||
|
log_level: _,
|
||||||
|
message: _,
|
||||||
|
} => {
|
||||||
panic!("Should not be logging to api in server!");
|
panic!("Should not be logging to api in server!");
|
||||||
}
|
}
|
||||||
veilid_core::VeilidUpdate::Attachment(state) => {
|
veilid_core::VeilidUpdate::Attachment(state) => {
|
||||||
|
@ -24,9 +24,6 @@ pub fn shutdown() {
|
|||||||
pub async fn run_veilid_server(settings: Settings, logs: VeilidLogs) -> Result<(), String> {
|
pub async fn run_veilid_server(settings: Settings, logs: VeilidLogs) -> Result<(), String> {
|
||||||
let settingsr = settings.read();
|
let settingsr = settings.read();
|
||||||
|
|
||||||
// Create Veilid Core
|
|
||||||
let veilid_core = veilid_core::VeilidCore::new();
|
|
||||||
|
|
||||||
// Create client api state change pipe
|
// Create client api state change pipe
|
||||||
let (sender, receiver): (
|
let (sender, receiver): (
|
||||||
Sender<veilid_core::VeilidUpdate>,
|
Sender<veilid_core::VeilidUpdate>,
|
||||||
@ -49,8 +46,7 @@ pub async fn run_veilid_server(settings: Settings, logs: VeilidLogs) -> Result<(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Start Veilid Core and get API
|
// Start Veilid Core and get API
|
||||||
let veilid_api = veilid_core
|
let veilid_api = veilid_core::api_startup(vcs)
|
||||||
.startup(vcs)
|
|
||||||
.await
|
.await
|
||||||
.map_err(|e| format!("VeilidCore startup failed: {}", e))?;
|
.map_err(|e| format!("VeilidCore startup failed: {}", e))?;
|
||||||
|
|
||||||
|
5
veilid-wasm/.gitignore
vendored
Normal file
5
veilid-wasm/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/target
|
||||||
|
**/*.rs.bk
|
||||||
|
bin/
|
||||||
|
pkg/
|
||||||
|
wasm-pack.log
|
23
veilid-wasm/Cargo.toml
Normal file
23
veilid-wasm/Cargo.toml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
[package]
|
||||||
|
name = "veilid-wasm"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["John Smith <jsmith@example.com>"]
|
||||||
|
edition = "2021"
|
||||||
|
license = "LGPL-2.0-or-later OR MPL-2.0 OR (MIT AND BSD-3-Clause)"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
wasm-bindgen = "^0"
|
||||||
|
console_error_panic_hook = "^0"
|
||||||
|
wee_alloc = "^0"
|
||||||
|
wasm-logger = "^0"
|
||||||
|
log = "^0"
|
||||||
|
veilid-core = { path = "../veilid-core" }
|
||||||
|
cfg-if = "^1"
|
||||||
|
wasm-bindgen-futures = "^0"
|
||||||
|
js-sys = "^0"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
wasm-bindgen-test = "^0"
|
286
veilid-wasm/src/js_veilid_core.rs
Normal file
286
veilid-wasm/src/js_veilid_core.rs
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
use crate::*;
|
||||||
|
pub use wasm_bindgen_futures::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = VeilidStateChange)]
|
||||||
|
pub struct JsVeilidStateChange {
|
||||||
|
kind: String, // "attachment" => AttachmentState(String)
|
||||||
|
from: JsValue,
|
||||||
|
to: JsValue,
|
||||||
|
}
|
||||||
|
#[wasm_bindgen(js_name = VeilidState)]
|
||||||
|
pub struct JsVeilidState {
|
||||||
|
kind: String, // "attachment" => AttachmentState(String)
|
||||||
|
state: JsValue,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = VeilidCore)]
|
||||||
|
pub struct JsVeilidCore {
|
||||||
|
core: VeilidCore,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen(js_class = VeilidCore)]
|
||||||
|
impl JsVeilidCore {
|
||||||
|
#[wasm_bindgen(constructor)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
set_panic_hook();
|
||||||
|
JsVeilidCore {
|
||||||
|
core: VeilidCore::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn value_to_string(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
||||||
|
Ok(Box::new(val.as_string().ok_or(())?))
|
||||||
|
}
|
||||||
|
fn value_to_option_string(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
||||||
|
if val.is_null() || val.is_undefined() {
|
||||||
|
return Ok(Box::new(Option::<String>::None));
|
||||||
|
}
|
||||||
|
Ok(Box::new(Some(val.as_string().ok_or(())?)))
|
||||||
|
}
|
||||||
|
fn value_to_bool(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
||||||
|
Ok(Box::new(val.is_truthy()))
|
||||||
|
}
|
||||||
|
fn value_to_u8(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
||||||
|
Ok(Box::new(f64_try_to_unsigned::<u8>(
|
||||||
|
val.as_f64().ok_or(())?,
|
||||||
|
)?))
|
||||||
|
}
|
||||||
|
fn value_to_u32(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
||||||
|
Ok(Box::new(f64_try_to_unsigned::<u32>(
|
||||||
|
val.as_f64().ok_or(())?,
|
||||||
|
)?))
|
||||||
|
}
|
||||||
|
fn value_to_u64(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
||||||
|
Ok(Box::new(f64_try_to_unsigned::<u64>(
|
||||||
|
val.as_f64().ok_or(())?,
|
||||||
|
)?))
|
||||||
|
}
|
||||||
|
fn value_to_option_u64(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
||||||
|
if val.is_null() || val.is_undefined() {
|
||||||
|
return Ok(Box::new(Option::<u64>::None));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Box::new(Some(f64_try_to_unsigned::<u64>(
|
||||||
|
val.as_f64().ok_or(())?,
|
||||||
|
)?)))
|
||||||
|
}
|
||||||
|
fn value_to_dht_key(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
||||||
|
Ok(Box::new(
|
||||||
|
DHTKey::try_decode(val.as_string().ok_or(())?.as_str()).map_err(drop)?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
fn value_to_dht_key_secret(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
||||||
|
Ok(Box::new(
|
||||||
|
DHTKeySecret::try_decode(val.as_string().ok_or(())?.as_str()).map_err(drop)?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
fn value_to_vec_string(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
||||||
|
let arrval = val.dyn_into::<Array>().map_err(drop)?.to_vec();
|
||||||
|
let mut out = Vec::<String>::with_capacity(arrval.len());
|
||||||
|
for v in arrval {
|
||||||
|
out.push(v.as_string().ok_or(())?);
|
||||||
|
}
|
||||||
|
Ok(Box::new(out))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn translate_config_callback(key: &str, val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
||||||
|
match key {
|
||||||
|
// xxx: lots of missing keys here
|
||||||
|
"namespace" => Self::value_to_string(val),
|
||||||
|
"capabilities.protocol_udp" => Self::value_to_bool(val),
|
||||||
|
"capabilities.protocol_connect_tcp" => Self::value_to_bool(val),
|
||||||
|
"capabilities.protocol_accept_tcp" => Self::value_to_bool(val),
|
||||||
|
"capabilities.protocol_connect_ws" => Self::value_to_bool(val),
|
||||||
|
"capabilities.protocol_accept_ws" => Self::value_to_bool(val),
|
||||||
|
"capabilities.protocol_connect_wss" => Self::value_to_bool(val),
|
||||||
|
"capabilities.protocol_accept_wss" => Self::value_to_bool(val),
|
||||||
|
"tablestore.directory" => Self::value_to_string(val),
|
||||||
|
"network.max_connections" => Self::value_to_u32(val),
|
||||||
|
"network.node_id" => Self::value_to_dht_key(val),
|
||||||
|
"network.node_id_secret" => Self::value_to_dht_key_secret(val),
|
||||||
|
"network.bootstrap" => Self::value_to_vec_string(val),
|
||||||
|
"network.rpc.concurrency" => Self::value_to_u32(val),
|
||||||
|
"network.rpc.queue_size" => Self::value_to_u32(val),
|
||||||
|
"network.rpc.max_timestamp_behind" => Self::value_to_option_u64(val),
|
||||||
|
"network.rpc.max_timestamp_ahead" => Self::value_to_option_u64(val),
|
||||||
|
"network.rpc.timeout" => Self::value_to_u64(val),
|
||||||
|
"network.rpc.max_route_hop_count" => Self::value_to_u8(val),
|
||||||
|
"network.dht.resolve_node_timeout" => Self::value_to_option_u64(val),
|
||||||
|
"network.dht.resolve_node_count" => Self::value_to_u32(val),
|
||||||
|
"network.dht.resolve_node_fanout" => Self::value_to_u32(val),
|
||||||
|
"network.dht.max_find_node_count" => Self::value_to_u32(val),
|
||||||
|
"network.dht.get_value_timeout" => Self::value_to_option_u64(val),
|
||||||
|
"network.dht.get_value_count" => Self::value_to_u32(val),
|
||||||
|
"network.dht.get_value_fanout" => Self::value_to_u32(val),
|
||||||
|
"network.dht.set_value_timeout" => Self::value_to_option_u64(val),
|
||||||
|
"network.dht.set_value_count" => Self::value_to_u32(val),
|
||||||
|
"network.dht.set_value_fanout" => Self::value_to_u32(val),
|
||||||
|
"network.dht.min_peer_count" => Self::value_to_u32(val),
|
||||||
|
"network.dht.min_peer_refresh_time" => Self::value_to_u64(val),
|
||||||
|
"network.dht.validate_dial_info_receipt_time" => Self::value_to_u64(val),
|
||||||
|
"network.upnp" => Self::value_to_bool(val),
|
||||||
|
"network.natpmp" => Self::value_to_bool(val),
|
||||||
|
"network.address_filter" => Self::value_to_bool(val),
|
||||||
|
"network.restricted_nat_retries" => Self::value_to_u32(val),
|
||||||
|
"network.tls.certificate_path" => Self::value_to_string(val),
|
||||||
|
"network.tls.private_key_path" => Self::value_to_string(val),
|
||||||
|
"network.application.path" => Self::value_to_string(val),
|
||||||
|
"network.application.https.enabled" => Self::value_to_bool(val),
|
||||||
|
"network.application.https.listen_address" => Self::value_to_string(val),
|
||||||
|
"network.application.http.enabled" => Self::value_to_bool(val),
|
||||||
|
"network.application.http.listen_address" => Self::value_to_string(val),
|
||||||
|
"network.protocol.udp.enabled" => Self::value_to_bool(val),
|
||||||
|
"network.protocol.udp.socket_pool_size" => Self::value_to_u32(val),
|
||||||
|
"network.protocol.udp.listen_address" => Self::value_to_string(val),
|
||||||
|
"network.protocol.udp.public_address" => Self::value_to_option_string(val),
|
||||||
|
"network.protocol.tcp.connect" => Self::value_to_bool(val),
|
||||||
|
"network.protocol.tcp.listen" => Self::value_to_bool(val),
|
||||||
|
"network.protocol.tcp.max_connections" => Self::value_to_u32(val),
|
||||||
|
"network.protocol.tcp.listen_address" => Self::value_to_string(val),
|
||||||
|
"network.protocol.tcp.public_address" => Self::value_to_option_string(val),
|
||||||
|
"network.protocol.ws.connect" => Self::value_to_bool(val),
|
||||||
|
"network.protocol.ws.listen" => Self::value_to_bool(val),
|
||||||
|
"network.protocol.ws.max_connections" => Self::value_to_u32(val),
|
||||||
|
"network.protocol.ws.listen_address" => Self::value_to_string(val),
|
||||||
|
"network.protocol.ws.path" => Self::value_to_string(val),
|
||||||
|
"network.protocol.ws.public_address" => Self::value_to_option_string(val),
|
||||||
|
"network.protocol.wss.connect" => Self::value_to_bool(val),
|
||||||
|
"network.protocol.wss.listen" => Self::value_to_bool(val),
|
||||||
|
"network.protocol.wss.max_connections" => Self::value_to_u32(val),
|
||||||
|
"network.protocol.wss.listen_address" => Self::value_to_string(val),
|
||||||
|
"network.protocol.wss.path" => Self::value_to_string(val),
|
||||||
|
"network.protocol.wss.public_address" => Self::value_to_option_string(val),
|
||||||
|
_ => return Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn translate_veilid_state(state: JsVeilidState) -> Result<VeilidState, JsValue> {
|
||||||
|
Ok(match state.kind.as_str() {
|
||||||
|
"attachment" => {
|
||||||
|
let state_string = state
|
||||||
|
.state
|
||||||
|
.as_string()
|
||||||
|
.ok_or(JsValue::from_str("state should be a string"))?;
|
||||||
|
let astate = AttachmentState::try_from(state_string)
|
||||||
|
.map_err(|e| JsValue::from_str(format!("invalid state: {:?}", e).as_str()))?;
|
||||||
|
VeilidState::Attachment(astate)
|
||||||
|
}
|
||||||
|
_ => return Err(JsValue::from_str("unknown state kind")),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// xxx rework this for new veilid_api mechanism which should be its own js object now
|
||||||
|
pub fn startup(
|
||||||
|
&self,
|
||||||
|
js_state_change_callback: Function,
|
||||||
|
js_config_callback: Function,
|
||||||
|
) -> Promise {
|
||||||
|
let core = self.core.clone();
|
||||||
|
future_to_promise(async move {
|
||||||
|
let vcs = VeilidCoreSetup {
|
||||||
|
state_change_callback: Arc::new(
|
||||||
|
move |change: VeilidStateChange| -> SystemPinBoxFuture<()> {
|
||||||
|
let js_state_change_callback = js_state_change_callback.clone();
|
||||||
|
Box::pin(async move {
|
||||||
|
let js_change = match change {
|
||||||
|
VeilidStateChange::Attachment {
|
||||||
|
old_state,
|
||||||
|
new_state,
|
||||||
|
} => JsVeilidStateChange {
|
||||||
|
kind: "attachment".to_owned(),
|
||||||
|
from: JsValue::from_str(old_state.to_string().as_str()),
|
||||||
|
to: JsValue::from_str(new_state.to_string().as_str()),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let ret = match Function::call1(
|
||||||
|
&js_state_change_callback,
|
||||||
|
&JsValue::UNDEFINED,
|
||||||
|
&JsValue::from(js_change),
|
||||||
|
) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
error!("calling state change callback failed: {:?}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let retp: Promise = match ret.dyn_into() {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
error!(
|
||||||
|
"state change callback did not return a promise: {:?}",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
match JsFuture::from(retp).await {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(e) => {
|
||||||
|
error!("state change callback returned an error: {:?}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})
|
||||||
|
},
|
||||||
|
),
|
||||||
|
config_callback: Arc::new(
|
||||||
|
move |key: String| -> Result<Box<dyn core::any::Any>, String> {
|
||||||
|
let val = Function::call1(
|
||||||
|
&js_config_callback,
|
||||||
|
&JsValue::UNDEFINED,
|
||||||
|
&JsValue::from_str(key.as_str()),
|
||||||
|
)
|
||||||
|
.map_err(|_| {
|
||||||
|
format!("Failed to get config from callback for key '{}'", key)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Self::translate_config_callback(key.as_str(), val)
|
||||||
|
.map_err(|_| format!("invalid value type for config key '{}'", key))
|
||||||
|
},
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
match core.startup(vcs).await {
|
||||||
|
Ok(_) => Ok(JsValue::UNDEFINED),
|
||||||
|
Err(e) => Err(JsValue::from_str(
|
||||||
|
format!("VeilidCore startup() failed: {}", e.to_string()).as_str(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_state_update(&self) {
|
||||||
|
self.core.send_state_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shutdown(&self) -> Promise {
|
||||||
|
let core = self.core.clone();
|
||||||
|
future_to_promise(async move {
|
||||||
|
core.shutdown().await;
|
||||||
|
Ok(JsValue::UNDEFINED)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn attach(&self) -> Promise {
|
||||||
|
let core = self.core.clone();
|
||||||
|
future_to_promise(async move {
|
||||||
|
core.attach();
|
||||||
|
Ok(JsValue::UNDEFINED)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn detach(&self) -> Promise {
|
||||||
|
let core = self.core.clone();
|
||||||
|
future_to_promise(async move {
|
||||||
|
core.detach();
|
||||||
|
Ok(JsValue::UNDEFINED)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wait_for_state(&self, state: JsVeilidState) -> Promise {
|
||||||
|
let core = self.core.clone();
|
||||||
|
future_to_promise(async move {
|
||||||
|
let state = Self::translate_veilid_state(state)?;
|
||||||
|
core.wait_for_state(state).await;
|
||||||
|
Ok(JsValue::UNDEFINED)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
25
veilid-wasm/src/lib.rs
Normal file
25
veilid-wasm/src/lib.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#![cfg(target_arch = "wasm32")]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
pub use log::*;
|
||||||
|
pub use wasm_bindgen::prelude::*;
|
||||||
|
pub use wasm_bindgen::JsCast;
|
||||||
|
|
||||||
|
pub use alloc::boxed::Box;
|
||||||
|
pub use alloc::string::String;
|
||||||
|
pub use alloc::sync::Arc;
|
||||||
|
pub use alloc::vec::Vec;
|
||||||
|
pub use core::convert::TryFrom;
|
||||||
|
pub use js_sys::*;
|
||||||
|
pub use js_veilid_core::*;
|
||||||
|
pub use utils::*;
|
||||||
|
pub use veilid_core::dht::key::*;
|
||||||
|
pub use veilid_core::xx::*;
|
||||||
|
pub use veilid_core::*;
|
||||||
|
pub use wasm_logger::*;
|
||||||
|
|
||||||
|
mod js_veilid_core;
|
||||||
|
mod utils;
|
38
veilid-wasm/src/utils.rs
Normal file
38
veilid-wasm/src/utils.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
use cfg_if::*;
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
//use wasm_bindgen_futures::*;
|
||||||
|
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(feature = "wee_alloc")] {
|
||||||
|
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
|
||||||
|
// allocator.
|
||||||
|
extern crate wee_alloc;
|
||||||
|
#[global_allocator]
|
||||||
|
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern "C" {
|
||||||
|
#[wasm_bindgen(js_namespace = console, js_name = log)]
|
||||||
|
pub fn console_log(s: &str);
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn alert(s: &str);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_panic_hook() {
|
||||||
|
#[cfg(feature = "console_error_panic_hook")]
|
||||||
|
console_error_panic_hook::set_once();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn f64_try_to_unsigned<T>(f: f64) -> Result<T, ()>
|
||||||
|
where
|
||||||
|
T: core::convert::TryFrom<u64>,
|
||||||
|
{
|
||||||
|
let rf = f.floor();
|
||||||
|
if rf < 0.0 {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
T::try_from(rf as u64).map_err(drop)
|
||||||
|
}
|
179
veilid-wasm/tests/web.rs
Normal file
179
veilid-wasm/tests/web.rs
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
//! Test suite for the Web and headless browsers.
|
||||||
|
#![cfg(target_arch = "wasm32")]
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
extern crate wasm_bindgen_test;
|
||||||
|
use core::sync::atomic::AtomicBool;
|
||||||
|
use veilid_wasm::*;
|
||||||
|
use wasm_bindgen_test::*;
|
||||||
|
|
||||||
|
wasm_bindgen_test_configure!(run_in_browser);
|
||||||
|
|
||||||
|
static SETUP_ONCE: AtomicBool = AtomicBool::new(false);
|
||||||
|
pub fn setup() -> () {
|
||||||
|
if SETUP_ONCE
|
||||||
|
.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
console_log("setup()");
|
||||||
|
console_error_panic_hook::set_once();
|
||||||
|
wasm_logger::init(wasm_logger::Config::new(Level::Trace));
|
||||||
|
init_callbacks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// xxx needs updating to new keys and veilid_api object
|
||||||
|
fn init_callbacks() {
|
||||||
|
assert_eq!(js_sys::eval(r#"
|
||||||
|
window.sleep = (milliseconds) => { return new Promise(resolve => setTimeout(resolve, milliseconds)) };
|
||||||
|
window.stateChangeCallback = async (stateChange) => { console.log("State change: " + stateChange); };
|
||||||
|
window.configCallback = (configKey) => {
|
||||||
|
switch(configKey) {
|
||||||
|
case "namespace": return "";
|
||||||
|
case "capabilities.protocol_udp": return false;
|
||||||
|
case "capabilities.protocol_connect_tcp": return false;
|
||||||
|
case "capabilities.protocol_accept_tcp": return false;
|
||||||
|
case "capabilities.protocol_connect_ws": return true;
|
||||||
|
case "capabilities.protocol_accept_ws": return false;
|
||||||
|
case "capabilities.protocol_connect_wss": return true;
|
||||||
|
case "capabilities.protocol_accept_wss": return false;
|
||||||
|
case "tablestore.directory": return "";
|
||||||
|
case "network.max_connections": return 16;
|
||||||
|
case "network.node_id": return "ZLd4uMYdP4qYLtxF6GqrzBb32Z6T3rE2FWMkWup1pdY";
|
||||||
|
case "network.node_id_secret": return "s2Gvq6HJOxgQh-3xIgfWSL3I-DWZ2c1RjZLJl2Xmg2E";
|
||||||
|
case "network.bootstrap": return [];
|
||||||
|
case "network.rpc.concurrency": return 2;
|
||||||
|
case "network.rpc.queue_size": return 128;
|
||||||
|
case "network.rpc.max_timestamp_behind": return 10000000;
|
||||||
|
case "network.rpc.max_timestamp_ahead": return 10000000;
|
||||||
|
case "network.rpc.timeout": return 10000000;
|
||||||
|
case "network.rpc.max_route_hop_count": return 7;
|
||||||
|
case "network.dht.resolve_node_timeout": return null;
|
||||||
|
case "network.dht.resolve_node_count": return 20;
|
||||||
|
case "network.dht.resolve_node_fanout": return 3;
|
||||||
|
case "network.dht.max_find_node_count": return 20;
|
||||||
|
case "network.dht.get_value_timeout": return null;
|
||||||
|
case "network.dht.get_value_count": return 20;
|
||||||
|
case "network.dht.get_value_fanout": return 3;
|
||||||
|
case "network.dht.set_value_timeout": return null;
|
||||||
|
case "network.dht.set_value_count": return 20;
|
||||||
|
case "network.dht.set_value_fanout": return 5;
|
||||||
|
case "network.dht.min_peer_count": return 20;
|
||||||
|
case "network.dht.min_peer_refresh_time": return 2000000;
|
||||||
|
case "network.dht.validate_dial_info_receipt_time": return 5000000;
|
||||||
|
case "network.upnp": return false;
|
||||||
|
case "network.natpmp": return false;
|
||||||
|
case "network.address_filter": return true;
|
||||||
|
case "network.restricted_nat_retries": return 3;
|
||||||
|
case "network.tls.certificate_path": return "";
|
||||||
|
case "network.tls.private_key_path": return "";
|
||||||
|
case "network.application.path": return "/app";
|
||||||
|
case "network.application.https.enabled": return false;
|
||||||
|
case "network.application.https.listen_address": return "";
|
||||||
|
case "network.application.http.enabled": return false;
|
||||||
|
case "network.application.http.listen_address": return "";
|
||||||
|
case "network.protocol.udp.enabled": return false;
|
||||||
|
case "network.protocol.udp.socket_pool_size": return 0;
|
||||||
|
case "network.protocol.udp.listen_address": return "";
|
||||||
|
case "network.protocol.udp.public_address": return "";
|
||||||
|
case "network.protocol.tcp.connect": return false;
|
||||||
|
case "network.protocol.tcp.listen": return false;
|
||||||
|
case "network.protocol.tcp.max_connections": return 32;
|
||||||
|
case "network.protocol.tcp.listen_address": return "";
|
||||||
|
case "network.protocol.tcp.public_address": return "";
|
||||||
|
case "network.protocol.ws.connect": return true;
|
||||||
|
case "network.protocol.ws.listen": return false;
|
||||||
|
case "network.protocol.ws.max_connections": return 16;
|
||||||
|
case "network.protocol.ws.listen_address": return "";
|
||||||
|
case "network.protocol.ws.path": return "/ws";
|
||||||
|
case "network.protocol.ws.public_address": return "";
|
||||||
|
case "network.protocol.wss.connect": return true;
|
||||||
|
case "network.protocol.wss.listen": return false;
|
||||||
|
case "network.protocol.wss.max_connections": return 16;
|
||||||
|
case "network.protocol.wss.listen_address": return "";
|
||||||
|
case "network.protocol.wss.path": return "/ws";
|
||||||
|
case "network.protocol.wss.public_address": return "";
|
||||||
|
default:
|
||||||
|
console.log("config key '" + key +"' doesn't exist"); break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
true
|
||||||
|
"#).expect("failed to eval"), JsValue::TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn test_construct() {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
js_sys::eval(
|
||||||
|
r#"
|
||||||
|
let vc = new VeilidCore();
|
||||||
|
true
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
.expect("failed to eval"),
|
||||||
|
JsValue::TRUE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test(async)]
|
||||||
|
async fn test_startup_shutdown() {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
JsFuture::from(
|
||||||
|
js_sys::eval(
|
||||||
|
r#"
|
||||||
|
(async function() {
|
||||||
|
let vc = new VeilidCore();
|
||||||
|
await vc.startup(window.stateChangeCallback, window.configCallback);
|
||||||
|
await vc.shutdown();
|
||||||
|
return true;
|
||||||
|
})().then(v => {
|
||||||
|
console.log("finished: " + v);
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
.expect("failed to eval")
|
||||||
|
.dyn_into::<Promise>()
|
||||||
|
.unwrap()
|
||||||
|
)
|
||||||
|
.await,
|
||||||
|
Ok(JsValue::TRUE)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test(async)]
|
||||||
|
async fn test_attach_detach() {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
JsFuture::from(
|
||||||
|
js_sys::eval(
|
||||||
|
r#"
|
||||||
|
(async function() {
|
||||||
|
let vc = new VeilidCore();
|
||||||
|
await vc.startup(window.stateChangeCallback, window.configCallback);
|
||||||
|
await vc.attach();
|
||||||
|
await window.sleep(1000);
|
||||||
|
await vc.detach();
|
||||||
|
await vc.shutdown();
|
||||||
|
return true;
|
||||||
|
})().then(v => {
|
||||||
|
console.log("finished: " + v);
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
.expect("failed to eval")
|
||||||
|
.dyn_into::<Promise>()
|
||||||
|
.unwrap()
|
||||||
|
)
|
||||||
|
.await,
|
||||||
|
Ok(JsValue::TRUE)
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user