This commit is contained in:
John Smith
2022-01-27 09:53:01 -05:00
parent 1decd333c8
commit 7ef6d407a5
13 changed files with 702 additions and 907 deletions

View File

@@ -1,130 +1,45 @@
use std::sync::Arc;
use flutter_rust_bridge::*;
use log::*;
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);
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)]
pub struct VeilidConfigUDP {
pub enabled: bool,
pub socket_pool_size: u32,
pub listen_address: String,
pub public_address: Option<String>,
}
#[derive(Debug, Default, Clone)]
pub struct VeilidConfigTCP {
pub connect: bool,
pub listen: bool,
pub max_connections: u32,
pub listen_address: String,
pub public_address: Option<String>,
}
#[derive(Debug, Default, Clone)]
pub struct VeilidConfigWS {
pub connect: bool,
pub listen: bool,
pub max_connections: u32,
pub listen_address: String,
pub path: String,
pub url: Option<String>,
}
#[derive(Debug, Default, Clone)]
pub struct VeilidConfigWSS {
pub connect: bool,
pub max_connections: u32,
}
#[derive(Debug, Default, Clone)]
pub struct VeilidConfigProtocol {
pub udp: VeilidConfigUDP,
pub tcp: VeilidConfigTCP,
pub ws: VeilidConfigWS,
pub wss: VeilidConfigWSS,
}
#[derive(Debug, Default, Clone)]
pub struct VeilidConfigDHT {
pub resolve_node_timeout: Option<u64>,
pub resolve_node_count: u32,
pub resolve_node_fanout: u32,
pub max_find_node_count: u32,
pub get_value_timeout: Option<u64>,
pub get_value_count: u32,
pub get_value_fanout: u32,
pub set_value_timeout: Option<u64>,
pub set_value_count: u32,
pub set_value_fanout: u32,
pub min_peer_count: u32,
pub min_peer_refresh_time: u64,
pub validate_dial_info_receipt_time: u64,
}
#[derive(Debug, Default, Clone)]
pub struct VeilidConfigRPC {
pub concurrency: u32,
pub queue_size: u32,
pub max_timestamp_behind: Option<u64>,
pub max_timestamp_ahead: Option<u64>,
pub timeout: u64,
pub max_route_hop_count: u8,
}
#[derive(Debug, Default, Clone)]
pub struct VeilidConfigLeases {
pub max_server_signal_leases: u32,
pub max_server_relay_leases: u32,
pub max_client_signal_leases: u32,
pub max_client_relay_leases: u32,
}
#[derive(Debug, Default, Clone)]
pub struct VeilidConfigNetwork {
pub max_connections: u32,
pub connection_initial_timeout: u64,
pub node_id: String,
pub node_id_secret: String,
pub bootstrap: Vec<String>,
pub rpc: VeilidConfigRPC,
pub dht: VeilidConfigDHT,
pub upnp: bool,
pub natpmp: bool,
pub enable_local_peer_scope: bool,
pub restricted_nat_retries: u32,
pub protocol: VeilidConfigProtocol,
pub leases: VeilidConfigLeases,
}
#[derive(Debug, Default, Clone)]
pub struct VeilidConfigTableStore {
pub directory: String,
pub delete: bool,
}
#[derive(Debug, Default, Clone)]
pub struct VeilidConfigBlockStore {
pub directory: String,
pub delete: bool,
}
#[derive(Debug, Default, Clone)]
pub struct VeilidConfigProtectedStore {
}
#[derive(Debug, Default, Clone)]
#[allow(non_snake_case)]
pub struct VeilidConfig {
pub program_name: String,
pub namespace: String,
@@ -142,15 +57,164 @@ pub struct VeilidConfig {
pub protected_store__insecure_fallback_directory: String,
pub protected_store__delete: bool,
// Table Store
pub table_store: VeilidConfigTableStore,
pub table_store__directory: String,
pub table_store__delete: bool,
// Block Store
pub block_store: VeilidConfigBlockStore,
pub block_store__directory: String,
pub block_store__delete: bool,
// Network
pub network: VeilidConfigNetwork,
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,
}
/////////////////////////////////////////
impl VeilidConfig {
pub fn get_by_str(&self, key: &str) -> std::result::Result<Box<dyn std::any::Any + Send + 'static>, String> {
let out: Box<dyn core::any::Any + Send> = match key {
"program_name" => Box::new(self.program_name.clone()),
"namespace" => Box::new(self.namespace.clone()),
"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)
}
}
/////////////////////////////////////////
@@ -235,7 +299,7 @@ impl VeilidAPIError {
}
}
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]
pub enum AttachmentState {
Detached,
Attaching,
@@ -251,19 +315,19 @@ 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,
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)]
#[derive(Debug, Clone)]
pub enum VeilidUpdate {
Attachment (AttachmentState),
}
@@ -277,7 +341,7 @@ impl VeilidUpdate {
}
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct VeilidState {
pub attachment: AttachmentState,
}
@@ -294,110 +358,17 @@ impl VeilidState {
pub fn startup_veilid_core(sink: StreamSink<VeilidUpdate>, config: VeilidConfig) -> Result<VeilidState> {
async_std::task::block_on( async {
let api = API.lock().await;
if api.is_some() {
let mut api_lock = VEILID_API.lock().await;
if api_lock.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<()> {
let sink = sink.clone();
Box::pin(async move {
if !sink.add(VeilidUpdate::from_core(update)) {
error!("error sending veilid update callback");
@@ -407,19 +378,13 @@ pub fn startup_veilid_core(sink: StreamSink<VeilidUpdate>, config: VeilidConfig)
),
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()
})
config.get_by_str(&key)
}
),
};
let veilid_api = core.startup(setup).await.map_err(|e| VeilidAPIError::InvalidConfig(e.clone()))?;
*api = Some(veilid_api.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))
@@ -428,7 +393,7 @@ pub fn startup_veilid_core(sink: StreamSink<VeilidUpdate>, config: VeilidConfig)
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 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))
})
@@ -438,7 +403,7 @@ pub fn get_veilid_state() -> Result<VeilidState> {
pub fn shutdown_veilid_core() -> Result<()> {
async_std::task::block_on( async {
let veilid_api = API.lock().await.take().ok_or(anyhow!(VeilidAPIError::NotInitialized))?;
let veilid_api = get_veilid_api().await?;
veilid_api.shutdown().await;
Ok(())
})