This commit is contained in:
John Smith
2022-02-06 21:18:42 -05:00
parent d660d86884
commit 70960fa592
53 changed files with 2062 additions and 2316 deletions

View File

@@ -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,
})
}

View File

@@ -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);
}
}

View 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)
}
}

View 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,
}
}

View 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()]);
}
}
}

View 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")
}

View File

@@ -1,5 +1,15 @@
mod api;
mod bridge_generated;
use cfg_if::*;
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")]
use jni::{objects::JClass, objects::JObject, JNIEnv};

View 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;