This commit is contained in:
John Smith 2022-01-23 11:12:54 -05:00
parent 2eeb8e52f2
commit 1decd333c8
4 changed files with 221 additions and 154 deletions

View File

@ -109,6 +109,9 @@ name = "anyhow"
version = "1.0.52" version = "1.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3" checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3"
dependencies = [
"backtrace",
]
[[package]] [[package]]
name = "arrayref" name = "arrayref"
@ -1357,9 +1360,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.112" version = "0.2.113"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" checksum = "eef78b64d87775463c549fbd80e19249ef436ea3bf1de2a1eb7e717ec7fab1e9"
[[package]] [[package]]
name = "libsqlite3-sys" name = "libsqlite3-sys"
@ -2392,9 +2395,9 @@ dependencies = [
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.4.2" version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" checksum = "0f82496b90c36d70af5fcd482edaa2e0bd16fade569de1330405fecbbdac736b"
dependencies = [ dependencies = [
"libc", "libc",
"winapi", "winapi",
@ -2432,9 +2435,9 @@ checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.85" version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7" checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2718,10 +2721,12 @@ dependencies = [
name = "veilid-flutter" name = "veilid-flutter"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow",
"async-std", "async-std",
"cfg-if 1.0.0", "cfg-if 1.0.0",
"flutter_rust_bridge", "flutter_rust_bridge",
"log", "log",
"parking_lot",
"veilid-core", "veilid-core",
] ]

View File

@ -10,7 +10,9 @@ crate-type = ["cdylib", "staticlib"]
async-std = { version = "^1", features = ["unstable"] } async-std = { version = "^1", features = ["unstable"] }
veilid-core = { path="../../veilid-core" } veilid-core = { path="../../veilid-core" }
flutter_rust_bridge = "^1" flutter_rust_bridge = "^1"
parking_lot = "^0"
log = "^0" log = "^0"
anyhow = { version = "^1", features = ["backtrace"] }
[build-dependencies] [build-dependencies]
cfg-if = "^1" cfg-if = "^1"

View File

@ -83,5 +83,5 @@ fn main() {
.wait() .wait()
.expect("flutter_rust_bridge_codegen was not running"); .expect("flutter_rust_bridge_codegen was not running");
println!("cargo:rerun-if-changed=src/api.c"); println!("cargo:rerun-if-changed={}", input_path.to_str().unwrap());
} }

View File

@ -2,6 +2,13 @@ use std::sync::Arc;
use flutter_rust_bridge::*; use flutter_rust_bridge::*;
use log::*; use log::*;
use std::collections::HashMap; use std::collections::HashMap;
use async_std::sync::Mutex as AsyncMutex;
use anyhow::*;
use std::fmt;
// Globals
static API: AsyncMutex<Option<veilid_core::VeilidAPI>> = AsyncMutex::new(None);
///////////////////////////////////////// /////////////////////////////////////////
// Config Settings // Config Settings
@ -100,45 +107,45 @@ pub struct VeilidConfigNetwork {
pub leases: VeilidConfigLeases, pub leases: VeilidConfigLeases,
} }
#[derive(Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct VeilidConfigTableStore { pub struct VeilidConfigTableStore {
pub directory: String, pub directory: String,
pub delete: bool, pub delete: bool,
} }
#[derive(Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct VeilidConfigBlockStore { pub struct VeilidConfigBlockStore {
pub directory: String, pub directory: String,
pub delete: bool, pub delete: bool,
} }
#[derive(Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct VeilidConfigProtectedStore { pub struct VeilidConfigProtectedStore {
pub allow_insecure_fallback: bool,
pub always_use_insecure_storage: bool,
pub insecure_fallback_directory: String,
pub delete: bool,
} }
#[derive(Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct VeilidConfigCapabilities {
pub protocol_udp: bool,
pub protocol_connect_tcp: bool,
pub protocol_accept_tcp: bool,
pub protocol_connect_ws: bool,
pub protocol_accept_ws: bool,
pub protocol_connect_wss: bool,
pub protocol_accept_wss: bool,
}
#[derive(Default, Clone)]
pub struct VeilidConfig { pub struct VeilidConfig {
pub program_name: String, pub program_name: String,
pub namespace: String, pub namespace: String,
pub capabilities: VeilidConfigCapabilities, // Capabilities
pub protected_store: VeilidConfigProtectedStore, 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: VeilidConfigTableStore, pub table_store: VeilidConfigTableStore,
// Block Store
pub block_store: VeilidConfigBlockStore, pub block_store: VeilidConfigBlockStore,
// Network
pub network: VeilidConfigNetwork, pub network: VeilidConfigNetwork,
} }
@ -173,6 +180,45 @@ pub enum VeilidAPIError {
}, },
} }
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 { impl VeilidAPIError {
fn from_core(api_error: veilid_core::VeilidAPIError) -> Self { fn from_core(api_error: veilid_core::VeilidAPIError) -> Self {
match api_error { match api_error {
@ -233,7 +279,7 @@ impl VeilidUpdate {
#[derive(Debug)] #[derive(Debug)]
pub struct VeilidState { pub struct VeilidState {
attachment: AttachmentState, pub attachment: AttachmentState,
} }
impl VeilidState { impl VeilidState {
@ -244,142 +290,156 @@ impl VeilidState {
} }
} }
type Result<T> = std::result::Result<T, VeilidAPIError>;
///////////////////////////////////////// /////////////////////////////////////////
pub fn startup_veilid_core(sink: StreamSink<VeilidUpdate>, config: VeilidConfig) -> Result<VeilidState> { pub fn startup_veilid_core(sink: StreamSink<VeilidUpdate>, config: VeilidConfig) -> Result<VeilidState> {
let core = veilid_core::VeilidCore::new();
// convert config to hashmap
let config_map = HashMap::<String, Box<dyn core::any::Any + 'static>>::new();
macro_rules! get_config {
($key:expr) => {
config_map.insert(stringify!($key)[7..].to_owned(), Box::new($key.clone()));
}
}
macro_rules! default_config {
($key:expr, $default_value:expr) => {
config_map.insert(stringify!($key)[7..].to_owned(), Box::new($default_value));
}
}
get_config!(config.program_name);
get_config!(config.namespace);
get_config!(config.capabilities.protocol_udp);
get_config!(config.capabilities.protocol_connect_tcp);
get_config!(config.capabilities.protocol_accept_tcp);
get_config!(config.capabilities.protocol_connect_ws);
get_config!(config.capabilities.protocol_accept_ws);
get_config!(config.capabilities.protocol_connect_wss);
get_config!(config.capabilities.protocol_accept_wss);
get_config!(config.table_store.directory);
get_config!(config.table_store.delete);
get_config!(config.block_store.directory);
get_config!(config.block_store.delete);
get_config!(config.protected_store.allow_insecure_fallback);
get_config!(config.protected_store.always_use_insecure_storage);
get_config!(config.protected_store.insecure_fallback_directory);
get_config!(config.protected_store.delete);
get_config!(config.network.node_id);
get_config!(config.network.node_id_secret);
get_config!(config.network.max_connections);
get_config!(config.network.connection_initial_timeout);
get_config!(config.network.bootstrap);
get_config!(config.network.dht.resolve_node_timeout);
get_config!(config.network.dht.resolve_node_count);
get_config!(config.network.dht.resolve_node_fanout);
get_config!(config.network.dht.max_find_node_count);
get_config!(config.network.dht.get_value_timeout);
get_config!(config.network.dht.get_value_count);
get_config!(config.network.dht.get_value_fanout);
get_config!(config.network.dht.set_value_timeout);
get_config!(config.network.dht.set_value_count);
get_config!(config.network.dht.set_value_fanout);
get_config!(config.network.dht.min_peer_count);
get_config!(config.network.dht.min_peer_refresh_time);
get_config!(config.network.dht.validate_dial_info_receipt_time);
get_config!(config.network.rpc.concurrency);
get_config!(config.network.rpc.queue_size);
get_config!(config.network.rpc.max_timestamp_behind);
get_config!(config.network.rpc.max_timestamp_ahead);
get_config!(config.network.rpc.timeout);
get_config!(config.network.rpc.max_route_hop_count);
get_config!(config.network.upnp);
get_config!(config.network.natpmp);
get_config!(config.network.enable_local_peer_scope);
get_config!(config.network.restricted_nat_retries);
default_config!(config.network.tls.certificate_path, "");
default_config!(config.network.tls.private_key_path, "");
default_config!(config.network.tls.connection_initial_timeout, 0u64);
default_config!(config.network.application.https.enabled, false);
default_config!(config.network.application.https.listen_address, "");
default_config!(config.network.application.https.path, "");
default_config!(config.network.application.https.url, Option::<String>::None);
default_config!(config.network.application.http.enabled, false);
default_config!(config.network.application.http.listen_address, "");
default_config!(config.network.application.http.path, "");
default_config!(config.network.application.http.url, Option::<String>::None);
get_config!(config.network.protocol.udp.enabled);
get_config!(config.network.protocol.udp.socket_pool_size);
get_config!(config.network.protocol.udp.listen_address);
get_config!(config.network.protocol.udp.public_address);
get_config!(config.network.protocol.tcp.connect);
get_config!(config.network.protocol.tcp.listen);
get_config!(config.network.protocol.tcp.max_connections);
get_config!(config.network.protocol.tcp.listen_address);
get_config!(config.network.protocol.tcp.public_address);
get_config!(config.network.protocol.ws.connect);
get_config!(config.network.protocol.ws.listen);
get_config!(config.network.protocol.ws.max_connections);
get_config!(config.network.protocol.ws.listen_address);
get_config!(config.network.protocol.ws.path);
get_config!(config.network.protocol.ws.url);
get_config!(config.network.protocol.wss.connect);
default_config!(config.network.protocol.wss.listen, false);
get_config!(config.network.protocol.wss.max_connections);
default_config!(config.network.protocol.wss.listen_address, "");
default_config!(config.network.protocol.wss.path, "");
default_config!(config.network.protocol.wss.url, Option::<String>::None);
get_config!(config.network.leases.max_server_signal_leases);
get_config!(config.network.leases.max_server_relay_leases);
get_config!(config.network.leases.max_client_signal_leases);
get_config!(config.network.leases.max_client_relay_leases);
let setup = veilid_core::VeilidCoreSetup {
update_callback: Arc::new(
move |update: veilid_core::VeilidUpdate| -> veilid_core::SystemPinBoxFuture<()> {
Box::pin(async move {
if !sink.add(VeilidUpdate::from_core(update)) {
error!("error sending veilid update callback");
}
})
},
),
config_callback: Arc::new(
move |key| {
config_map.get(&key).ok_or_else(|| {
let err = format!("config key '{}' doesn't exist", key);
error!("{}",err);
err
}).map(|v| {
*v.clone()
})
}
),
};
async_std::task::block_on( async { async_std::task::block_on( async {
let api = core.startup(setup).await.map_err(|e| VeilidAPIError::InvalidConfig(e.clone()))?;
let core_state = api.get_state().await.map_err(VeilidAPIError::from_core)?; let api = API.lock().await;
if api.is_some() {
return Err(anyhow!(VeilidAPIError::AlreadyInitialized));
}
let core = veilid_core::VeilidCore::new();
// convert config to hashmap
let config_map = HashMap::<String, Box<dyn core::any::Any + Send + 'static>>::new();
macro_rules! get_config {
($key:expr) => {
config_map.insert(stringify!($key)[7..].to_owned(), Box::new($key.clone()));
}
}
macro_rules! default_config {
($key:expr, $default_value:expr) => {
config_map.insert(stringify!($key)[7..].to_owned(), Box::new($default_value));
}
}
get_config!(config.program_name);
get_config!(config.namespace);
get_config!(config.capabilities.protocol_udp);
get_config!(config.capabilities.protocol_connect_tcp);
get_config!(config.capabilities.protocol_accept_tcp);
get_config!(config.capabilities.protocol_connect_ws);
get_config!(config.capabilities.protocol_accept_ws);
get_config!(config.capabilities.protocol_connect_wss);
get_config!(config.capabilities.protocol_accept_wss);
get_config!(config.table_store.directory);
get_config!(config.table_store.delete);
get_config!(config.block_store.directory);
get_config!(config.block_store.delete);
get_config!(config.protected_store.allow_insecure_fallback);
get_config!(config.protected_store.always_use_insecure_storage);
get_config!(config.protected_store.insecure_fallback_directory);
get_config!(config.protected_store.delete);
get_config!(config.network.node_id);
get_config!(config.network.node_id_secret);
get_config!(config.network.max_connections);
get_config!(config.network.connection_initial_timeout);
get_config!(config.network.bootstrap);
get_config!(config.network.dht.resolve_node_timeout);
get_config!(config.network.dht.resolve_node_count);
get_config!(config.network.dht.resolve_node_fanout);
get_config!(config.network.dht.max_find_node_count);
get_config!(config.network.dht.get_value_timeout);
get_config!(config.network.dht.get_value_count);
get_config!(config.network.dht.get_value_fanout);
get_config!(config.network.dht.set_value_timeout);
get_config!(config.network.dht.set_value_count);
get_config!(config.network.dht.set_value_fanout);
get_config!(config.network.dht.min_peer_count);
get_config!(config.network.dht.min_peer_refresh_time);
get_config!(config.network.dht.validate_dial_info_receipt_time);
get_config!(config.network.rpc.concurrency);
get_config!(config.network.rpc.queue_size);
get_config!(config.network.rpc.max_timestamp_behind);
get_config!(config.network.rpc.max_timestamp_ahead);
get_config!(config.network.rpc.timeout);
get_config!(config.network.rpc.max_route_hop_count);
get_config!(config.network.upnp);
get_config!(config.network.natpmp);
get_config!(config.network.enable_local_peer_scope);
get_config!(config.network.restricted_nat_retries);
default_config!(config.network.tls.certificate_path, "");
default_config!(config.network.tls.private_key_path, "");
default_config!(config.network.tls.connection_initial_timeout, 0u64);
default_config!(config.network.application.https.enabled, false);
default_config!(config.network.application.https.listen_address, "");
default_config!(config.network.application.https.path, "");
default_config!(config.network.application.https.url, Option::<String>::None);
default_config!(config.network.application.http.enabled, false);
default_config!(config.network.application.http.listen_address, "");
default_config!(config.network.application.http.path, "");
default_config!(config.network.application.http.url, Option::<String>::None);
get_config!(config.network.protocol.udp.enabled);
get_config!(config.network.protocol.udp.socket_pool_size);
get_config!(config.network.protocol.udp.listen_address);
get_config!(config.network.protocol.udp.public_address);
get_config!(config.network.protocol.tcp.connect);
get_config!(config.network.protocol.tcp.listen);
get_config!(config.network.protocol.tcp.max_connections);
get_config!(config.network.protocol.tcp.listen_address);
get_config!(config.network.protocol.tcp.public_address);
get_config!(config.network.protocol.ws.connect);
get_config!(config.network.protocol.ws.listen);
get_config!(config.network.protocol.ws.max_connections);
get_config!(config.network.protocol.ws.listen_address);
get_config!(config.network.protocol.ws.path);
get_config!(config.network.protocol.ws.url);
get_config!(config.network.protocol.wss.connect);
default_config!(config.network.protocol.wss.listen, false);
get_config!(config.network.protocol.wss.max_connections);
default_config!(config.network.protocol.wss.listen_address, "");
default_config!(config.network.protocol.wss.path, "");
default_config!(config.network.protocol.wss.url, Option::<String>::None);
get_config!(config.network.leases.max_server_signal_leases);
get_config!(config.network.leases.max_server_relay_leases);
get_config!(config.network.leases.max_client_signal_leases);
get_config!(config.network.leases.max_client_relay_leases);
let setup = veilid_core::VeilidCoreSetup {
update_callback: Arc::new(
move |update: veilid_core::VeilidUpdate| -> veilid_core::SystemPinBoxFuture<()> {
Box::pin(async move {
if !sink.add(VeilidUpdate::from_core(update)) {
error!("error sending veilid update callback");
}
})
},
),
config_callback: Arc::new(
move |key| {
config_map.get(&key).ok_or_else(|| {
let err = format!("config key '{}' doesn't exist", key);
error!("{}",err);
err
}).map(|v| {
*v.clone()
})
}
),
};
let veilid_api = core.startup(setup).await.map_err(|e| VeilidAPIError::InvalidConfig(e.clone()))?;
*api = Some(veilid_api.clone());
let core_state = veilid_api.get_state().await.map_err(VeilidAPIError::from_core)?;
Ok(VeilidState::from_core(core_state)) Ok(VeilidState::from_core(core_state))
}) })
} }
pub fn get_veilid_state() -> Result<VeilidState> { pub fn get_veilid_state() -> Result<VeilidState> {
async_std::task::block_on( async {
let veilid_api = API.lock().await.ok_or(anyhow!(VeilidAPIError::NotInitialized))?;
let core_state = veilid_api.get_state().await.map_err(VeilidAPIError::from_core)?;
Ok(VeilidState::from_core(core_state))
})
} }
// xxx api functions // xxx api functions
pub fn shutdown_veilid_core() -> Result<()> { pub fn shutdown_veilid_core() -> Result<()> {
async_std::task::block_on( async {
let veilid_api = API.lock().await.take().ok_or(anyhow!(VeilidAPIError::NotInitialized))?;
veilid_api.shutdown().await;
Ok(())
})
} }