ffi work
This commit is contained in:
@@ -1,608 +0,0 @@
|
||||
use anyhow::*;
|
||||
use async_std::sync::Mutex as AsyncMutex;
|
||||
use cfg_if::*;
|
||||
use flutter_rust_bridge::*;
|
||||
use log::*;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
// Globals
|
||||
|
||||
static VEILID_API: AsyncMutex<Option<veilid_core::VeilidAPI>> = AsyncMutex::new(None);
|
||||
async fn get_veilid_api() -> Result<veilid_core::VeilidAPI> {
|
||||
let api_lock = VEILID_API.lock().await;
|
||||
let veilid_api = match &*api_lock {
|
||||
None => {
|
||||
return Err(anyhow!(VeilidAPIError::NotInitialized));
|
||||
}
|
||||
Some(api) => api.clone(),
|
||||
};
|
||||
Ok(veilid_api)
|
||||
}
|
||||
async fn take_veilid_api() -> Result<veilid_core::VeilidAPI> {
|
||||
let mut api_lock = VEILID_API.lock().await;
|
||||
let veilid_api = match api_lock.take() {
|
||||
None => {
|
||||
return Err(anyhow!(VeilidAPIError::NotInitialized));
|
||||
}
|
||||
Some(api) => api,
|
||||
};
|
||||
Ok(veilid_api)
|
||||
}
|
||||
|
||||
/////////////////////////////////////////
|
||||
// Config Settings
|
||||
// Not all settings available through Veilid API are available to Flutter applications
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
#[allow(non_snake_case)]
|
||||
pub struct VeilidConfig {
|
||||
pub program_name: String,
|
||||
pub veilid_namespace: String,
|
||||
pub api_log_level: VeilidLogLevel,
|
||||
// Capabilities
|
||||
pub capabilities__protocol_udp: bool,
|
||||
pub capabilities__protocol_connect_tcp: bool,
|
||||
pub capabilities__protocol_accept_tcp: bool,
|
||||
pub capabilities__protocol_connect_ws: bool,
|
||||
pub capabilities__protocol_accept_ws: bool,
|
||||
pub capabilities__protocol_connect_wss: bool,
|
||||
pub capabilities__protocol_accept_wss: bool,
|
||||
// Protected Store
|
||||
pub protected_store__allow_insecure_fallback: bool,
|
||||
pub protected_store__always_use_insecure_storage: bool,
|
||||
pub protected_store__insecure_fallback_directory: String,
|
||||
pub protected_store__delete: bool,
|
||||
// Table Store
|
||||
pub table_store__directory: String,
|
||||
pub table_store__delete: bool,
|
||||
// Block Store
|
||||
pub block_store__directory: String,
|
||||
pub block_store__delete: bool,
|
||||
// Network
|
||||
pub network__max_connections: u32,
|
||||
pub network__connection_initial_timeout_ms: u32,
|
||||
pub network__node_id: String,
|
||||
pub network__node_id_secret: String,
|
||||
pub network__bootstrap: Vec<String>,
|
||||
pub network__upnp: bool,
|
||||
pub network__natpmp: bool,
|
||||
pub network__enable_local_peer_scope: bool,
|
||||
pub network__restricted_nat_retries: u32,
|
||||
// Network / RPC
|
||||
pub network__rpc__concurrency: u32,
|
||||
pub network__rpc__queue_size: u32,
|
||||
pub network__rpc__max_timestamp_behind_ms: Option<u32>,
|
||||
pub network__rpc__max_timestamp_ahead_ms: Option<u32>,
|
||||
pub network__rpc__timeout_ms: u32,
|
||||
pub network__rpc__max_route_hop_count: u8,
|
||||
// Network / DHT
|
||||
pub network__dht__resolve_node_timeout_ms: Option<u32>,
|
||||
pub network__dht__resolve_node_count: u32,
|
||||
pub network__dht__resolve_node_fanout: u32,
|
||||
pub network__dht__max_find_node_count: u32,
|
||||
pub network__dht__get_value_timeout_ms: Option<u32>,
|
||||
pub network__dht__get_value_count: u32,
|
||||
pub network__dht__get_value_fanout: u32,
|
||||
pub network__dht__set_value_timeout_ms: Option<u32>,
|
||||
pub network__dht__set_value_count: u32,
|
||||
pub network__dht__set_value_fanout: u32,
|
||||
pub network__dht__min_peer_count: u32,
|
||||
pub network__dht__min_peer_refresh_time_ms: u32,
|
||||
pub network__dht__validate_dial_info_receipt_time_ms: u32,
|
||||
// Network / Protocol
|
||||
// Network / Protocol / UDP
|
||||
pub network__protocol__udp__enabled: bool,
|
||||
pub network__protocol__udp__socket_pool_size: u32,
|
||||
pub network__protocol__udp__listen_address: String,
|
||||
pub network__protocol__udp__public_address: Option<String>,
|
||||
// Network / Protocol / TCP
|
||||
pub network__protocol__tcp__connect: bool,
|
||||
pub network__protocol__tcp__listen: bool,
|
||||
pub network__protocol__tcp__max_connections: u32,
|
||||
pub network__protocol__tcp__listen_address: String,
|
||||
pub network__protocol__tcp__public_address: Option<String>,
|
||||
// Network / Protocol / WS
|
||||
pub network__protocol__ws__connect: bool,
|
||||
pub network__protocol__ws__listen: bool,
|
||||
pub network__protocol__ws__max_connections: u32,
|
||||
pub network__protocol__ws__listen_address: String,
|
||||
pub network__protocol__ws__path: String,
|
||||
pub network__protocol__ws__url: Option<String>,
|
||||
// Network / Protocol / WSS
|
||||
pub network__protocol__wss__connect: bool,
|
||||
pub network__protocol__wss__max_connections: u32,
|
||||
// Network / Leases
|
||||
pub network__leases__max_server_signal_leases: u32,
|
||||
pub network__leases__max_server_relay_leases: u32,
|
||||
pub network__leases__max_client_signal_leases: u32,
|
||||
pub network__leases__max_client_relay_leases: u32,
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(target_arch="wasm32")] {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(target_arch="wasm32")] {
|
||||
type ConfigReturn = Box<dyn std::any::Any + 'static>;
|
||||
} else {
|
||||
type ConfigReturn = Box<dyn std::any::Any + Send + 'static>;
|
||||
}
|
||||
}
|
||||
|
||||
impl VeilidConfig {
|
||||
pub fn get_by_str(&self, key: &str) -> std::result::Result<ConfigReturn, String> {
|
||||
let out: ConfigReturn = match key {
|
||||
"program_name" => Box::new(self.program_name.clone()),
|
||||
"namespace" => Box::new(self.veilid_namespace.clone()),
|
||||
"api_log_level" => Box::new(self.api_log_level.to_config_log_level()),
|
||||
"capabilities.protocol_udp" => Box::new(self.capabilities__protocol_udp.clone()),
|
||||
"capabilities.protocol_connect_tcp" => {
|
||||
Box::new(self.capabilities__protocol_connect_tcp.clone())
|
||||
}
|
||||
"capabilities.protocol_accept_tcp" => {
|
||||
Box::new(self.capabilities__protocol_accept_tcp.clone())
|
||||
}
|
||||
"capabilities.protocol_connect_ws" => {
|
||||
Box::new(self.capabilities__protocol_connect_ws.clone())
|
||||
}
|
||||
"capabilities.protocol_accept_ws" => {
|
||||
Box::new(self.capabilities__protocol_accept_ws.clone())
|
||||
}
|
||||
"capabilities.protocol_connect_wss" => {
|
||||
Box::new(self.capabilities__protocol_connect_wss.clone())
|
||||
}
|
||||
"capabilities.protocol_accept_wss" => {
|
||||
Box::new(self.capabilities__protocol_accept_wss.clone())
|
||||
}
|
||||
"table_store.directory" => Box::new(self.table_store__directory.clone()),
|
||||
"table_store.delete" => Box::new(self.table_store__delete.clone()),
|
||||
"block_store.directory" => Box::new(self.block_store__directory.clone()),
|
||||
"block_store.delete" => Box::new(self.block_store__delete.clone()),
|
||||
"protected_store.allow_insecure_fallback" => {
|
||||
Box::new(self.protected_store__allow_insecure_fallback.clone())
|
||||
}
|
||||
"protected_store.always_use_insecure_storage" => {
|
||||
Box::new(self.protected_store__always_use_insecure_storage.clone())
|
||||
}
|
||||
"protected_store.insecure_fallback_directory" => {
|
||||
Box::new(self.protected_store__insecure_fallback_directory.clone())
|
||||
}
|
||||
"protected_store.delete" => Box::new(self.protected_store__delete.clone()),
|
||||
"network.node_id" => Box::new(self.network__node_id.clone()),
|
||||
"network.node_id_secret" => Box::new(self.network__node_id_secret.clone()),
|
||||
"network.max_connections" => Box::new(self.network__max_connections.clone()),
|
||||
"network.connection_initial_timeout_ms" => {
|
||||
Box::new(self.network__connection_initial_timeout_ms.clone())
|
||||
}
|
||||
"network.bootstrap" => Box::new(self.network__bootstrap.clone()),
|
||||
"network.dht.resolve_node_timeout_ms" => {
|
||||
Box::new(self.network__dht__resolve_node_timeout_ms.clone())
|
||||
}
|
||||
"network.dht.resolve_node_count" => {
|
||||
Box::new(self.network__dht__resolve_node_count.clone())
|
||||
}
|
||||
"network.dht.resolve_node_fanout" => {
|
||||
Box::new(self.network__dht__resolve_node_fanout.clone())
|
||||
}
|
||||
"network.dht.max_find_node_count" => {
|
||||
Box::new(self.network__dht__max_find_node_count.clone())
|
||||
}
|
||||
"network.dht.get_value_timeout_ms" => {
|
||||
Box::new(self.network__dht__get_value_timeout_ms.clone())
|
||||
}
|
||||
"network.dht.get_value_count" => Box::new(self.network__dht__get_value_count.clone()),
|
||||
"network.dht.get_value_fanout" => Box::new(self.network__dht__get_value_fanout.clone()),
|
||||
"network.dht.set_value_timeout_ms" => {
|
||||
Box::new(self.network__dht__set_value_timeout_ms.clone())
|
||||
}
|
||||
"network.dht.set_value_count" => Box::new(self.network__dht__set_value_count.clone()),
|
||||
"network.dht.set_value_fanout" => Box::new(self.network__dht__set_value_fanout.clone()),
|
||||
"network.dht.min_peer_count" => Box::new(self.network__dht__min_peer_count.clone()),
|
||||
"network.dht.min_peer_refresh_time_ms" => {
|
||||
Box::new(self.network__dht__min_peer_refresh_time_ms.clone())
|
||||
}
|
||||
"network.dht.validate_dial_info_receipt_time_ms" => Box::new(
|
||||
self.network__dht__validate_dial_info_receipt_time_ms
|
||||
.clone(),
|
||||
),
|
||||
"network.rpc.concurrency" => Box::new(self.network__rpc__concurrency.clone()),
|
||||
"network.rpc.queue_size" => Box::new(self.network__rpc__queue_size.clone()),
|
||||
"network.rpc.max_timestamp_behind_ms" => {
|
||||
Box::new(self.network__rpc__max_timestamp_behind_ms.clone())
|
||||
}
|
||||
"network.rpc.max_timestamp_ahead_ms" => {
|
||||
Box::new(self.network__rpc__max_timestamp_ahead_ms.clone())
|
||||
}
|
||||
"network.rpc.timeout_ms" => Box::new(self.network__rpc__timeout_ms.clone()),
|
||||
"network.rpc.max_route_hop_count" => {
|
||||
Box::new(self.network__rpc__max_route_hop_count.clone())
|
||||
}
|
||||
"network.upnp" => Box::new(self.network__upnp.clone()),
|
||||
"network.natpmp" => Box::new(self.network__natpmp.clone()),
|
||||
"network.enable_local_peer_scope" => {
|
||||
Box::new(self.network__enable_local_peer_scope.clone())
|
||||
}
|
||||
"network.restricted_nat_retries" => {
|
||||
Box::new(self.network__restricted_nat_retries.clone())
|
||||
}
|
||||
"network.tls.certificate_path" => Box::new("".to_owned()),
|
||||
"network.tls.private_key_path" => Box::new("".to_owned()),
|
||||
"network.tls.connection_initial_timeout" => Box::new(0u32),
|
||||
"network.application.https.enabled" => Box::new(false),
|
||||
"network.application.https.listen_address" => Box::new("".to_owned()),
|
||||
"network.application.https.path" => Box::new("".to_owned()),
|
||||
"network.application.https.url" => Box::new(Option::<String>::None),
|
||||
"network.application.http.enabled" => Box::new(false),
|
||||
"network.application.http.listen_address" => Box::new("".to_owned()),
|
||||
"network.application.http.path" => Box::new("".to_owned()),
|
||||
"network.application.http.url" => Box::new(Option::<String>::None),
|
||||
"network.protocol.udp.enabled" => {
|
||||
Box::new(self.network__protocol__udp__enabled.clone())
|
||||
}
|
||||
"network.protocol.udp.socket_pool_size" => {
|
||||
Box::new(self.network__protocol__udp__socket_pool_size.clone())
|
||||
}
|
||||
"network.protocol.udp.listen_address" => {
|
||||
Box::new(self.network__protocol__udp__listen_address.clone())
|
||||
}
|
||||
"network.protocol.udp.public_address" => {
|
||||
Box::new(self.network__protocol__udp__public_address.clone())
|
||||
}
|
||||
"network.protocol.tcp.connect" => {
|
||||
Box::new(self.network__protocol__tcp__connect.clone())
|
||||
}
|
||||
"network.protocol.tcp.listen" => Box::new(self.network__protocol__tcp__listen.clone()),
|
||||
"network.protocol.tcp.max_connections" => {
|
||||
Box::new(self.network__protocol__tcp__max_connections.clone())
|
||||
}
|
||||
"network.protocol.tcp.listen_address" => {
|
||||
Box::new(self.network__protocol__tcp__listen_address.clone())
|
||||
}
|
||||
"network.protocol.tcp.public_address" => {
|
||||
Box::new(self.network__protocol__tcp__public_address.clone())
|
||||
}
|
||||
"network.protocol.ws.connect" => Box::new(self.network__protocol__ws__connect.clone()),
|
||||
"network.protocol.ws.listen" => Box::new(self.network__protocol__ws__listen.clone()),
|
||||
"network.protocol.ws.max_connections" => {
|
||||
Box::new(self.network__protocol__ws__max_connections.clone())
|
||||
}
|
||||
"network.protocol.ws.listen_address" => {
|
||||
Box::new(self.network__protocol__ws__listen_address.clone())
|
||||
}
|
||||
"network.protocol.ws.path" => Box::new(self.network__protocol__ws__path.clone()),
|
||||
"network.protocol.ws.url" => Box::new(self.network__protocol__ws__url.clone()),
|
||||
"network.protocol.wss.connect" => {
|
||||
Box::new(self.network__protocol__wss__connect.clone())
|
||||
}
|
||||
"network.protocol.wss.listen" => Box::new(false),
|
||||
"network.protocol.wss.max_connections" => {
|
||||
Box::new(self.network__protocol__wss__max_connections.clone())
|
||||
}
|
||||
"network.protocol.wss.listen_address" => Box::new("".to_owned()),
|
||||
"network.protocol.wss.path" => Box::new("".to_owned()),
|
||||
"network.protocol.wss.url" => Box::new(Option::<String>::None),
|
||||
"network.leases.max_server_signal_leases" => {
|
||||
Box::new(self.network__leases__max_server_signal_leases.clone())
|
||||
}
|
||||
"network.leases.max_server_relay_leases" => {
|
||||
Box::new(self.network__leases__max_server_relay_leases.clone())
|
||||
}
|
||||
"network.leases.max_client_signal_leases" => {
|
||||
Box::new(self.network__leases__max_client_signal_leases.clone())
|
||||
}
|
||||
"network.leases.max_client_relay_leases" => {
|
||||
Box::new(self.network__leases__max_client_relay_leases.clone())
|
||||
}
|
||||
_ => {
|
||||
let err = format!("config key '{}' doesn't exist", key);
|
||||
error!("{}", err);
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
std::result::Result::Ok(out)
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum VeilidAPIError {
|
||||
AlreadyInitialized,
|
||||
NotInitialized,
|
||||
InvalidConfig(String),
|
||||
Timeout,
|
||||
Shutdown,
|
||||
NodeNotFound(String),
|
||||
NoDialInfo(String),
|
||||
Internal(String),
|
||||
Unimplemented(String),
|
||||
ParseError {
|
||||
message: String,
|
||||
value: String,
|
||||
},
|
||||
InvalidArgument {
|
||||
context: String,
|
||||
argument: String,
|
||||
value: String,
|
||||
},
|
||||
MissingArgument {
|
||||
context: String,
|
||||
argument: String,
|
||||
},
|
||||
}
|
||||
|
||||
impl fmt::Display for VeilidAPIError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
VeilidAPIError::AlreadyInitialized => write!(f, "VeilidAPIError::AlreadyInitialized"),
|
||||
VeilidAPIError::NotInitialized => write!(f, "VeilidAPIError::NotInitialized"),
|
||||
VeilidAPIError::InvalidConfig(e) => write!(f, "VeilidAPIError::InvalidConfig({})", e),
|
||||
VeilidAPIError::Timeout => write!(f, "VeilidAPIError::Timeout"),
|
||||
VeilidAPIError::Shutdown => write!(f, "VeilidAPIError::Shutdown"),
|
||||
VeilidAPIError::NodeNotFound(ni) => write!(f, "VeilidAPIError::NodeNotFound({})", ni),
|
||||
VeilidAPIError::NoDialInfo(ni) => write!(f, "VeilidAPIError::NoDialInfo({})", ni),
|
||||
VeilidAPIError::Internal(e) => write!(f, "VeilidAPIError::Internal({})", e),
|
||||
VeilidAPIError::Unimplemented(e) => write!(f, "VeilidAPIError::Unimplemented({})", e),
|
||||
VeilidAPIError::ParseError { message, value } => {
|
||||
write!(f, "VeilidAPIError::ParseError({}: {})", message, value)
|
||||
}
|
||||
VeilidAPIError::InvalidArgument {
|
||||
context,
|
||||
argument,
|
||||
value,
|
||||
} => {
|
||||
write!(
|
||||
f,
|
||||
"VeilidAPIError::InvalidArgument({}: {} = {})",
|
||||
context, argument, value
|
||||
)
|
||||
}
|
||||
VeilidAPIError::MissingArgument { context, argument } => {
|
||||
write!(
|
||||
f,
|
||||
"VeilidAPIError::MissingArgument({}: {})",
|
||||
context, argument
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for VeilidAPIError {}
|
||||
|
||||
impl VeilidAPIError {
|
||||
fn from_core(api_error: veilid_core::VeilidAPIError) -> Self {
|
||||
match api_error {
|
||||
veilid_core::VeilidAPIError::Timeout => VeilidAPIError::Timeout,
|
||||
veilid_core::VeilidAPIError::Shutdown => VeilidAPIError::Shutdown,
|
||||
veilid_core::VeilidAPIError::NodeNotFound(node_id) => {
|
||||
VeilidAPIError::NodeNotFound(format!("{}", node_id))
|
||||
}
|
||||
veilid_core::VeilidAPIError::NoDialInfo(node_id) => {
|
||||
VeilidAPIError::NodeNotFound(format!("{}", node_id))
|
||||
}
|
||||
veilid_core::VeilidAPIError::Internal(msg) => VeilidAPIError::Internal(msg.clone()),
|
||||
veilid_core::VeilidAPIError::Unimplemented(msg) => {
|
||||
VeilidAPIError::Unimplemented(msg.clone())
|
||||
}
|
||||
veilid_core::VeilidAPIError::ParseError { message, value } => {
|
||||
VeilidAPIError::ParseError {
|
||||
message: message.clone(),
|
||||
value: value.clone(),
|
||||
}
|
||||
}
|
||||
veilid_core::VeilidAPIError::InvalidArgument {
|
||||
context,
|
||||
argument,
|
||||
value,
|
||||
} => VeilidAPIError::InvalidArgument {
|
||||
context: context.clone(),
|
||||
argument: argument.clone(),
|
||||
value: value.clone(),
|
||||
},
|
||||
veilid_core::VeilidAPIError::MissingArgument { context, argument } => {
|
||||
VeilidAPIError::MissingArgument {
|
||||
context: context.clone(),
|
||||
argument: argument.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum AttachmentState {
|
||||
Detached,
|
||||
Attaching,
|
||||
AttachedWeak,
|
||||
AttachedGood,
|
||||
AttachedStrong,
|
||||
FullyAttached,
|
||||
OverAttached,
|
||||
Detaching,
|
||||
}
|
||||
|
||||
impl AttachmentState {
|
||||
fn from_core(attachment_state: veilid_core::AttachmentState) -> Self {
|
||||
match attachment_state {
|
||||
veilid_core::AttachmentState::Detached => AttachmentState::Detached,
|
||||
veilid_core::AttachmentState::Attaching => AttachmentState::Attaching,
|
||||
veilid_core::AttachmentState::AttachedWeak => AttachmentState::AttachedWeak,
|
||||
veilid_core::AttachmentState::AttachedGood => AttachmentState::AttachedGood,
|
||||
veilid_core::AttachmentState::AttachedStrong => AttachmentState::AttachedStrong,
|
||||
veilid_core::AttachmentState::FullyAttached => AttachmentState::FullyAttached,
|
||||
veilid_core::AttachmentState::OverAttached => AttachmentState::OverAttached,
|
||||
veilid_core::AttachmentState::Detaching => AttachmentState::Detaching,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum VeilidLogLevel {
|
||||
Error,
|
||||
Warn,
|
||||
Info,
|
||||
Debug,
|
||||
Trace,
|
||||
}
|
||||
|
||||
impl Default for VeilidLogLevel {
|
||||
fn default() -> Self {
|
||||
Self::Info
|
||||
}
|
||||
}
|
||||
|
||||
impl VeilidLogLevel {
|
||||
fn from_core(level: veilid_core::VeilidLogLevel) -> Self {
|
||||
match level {
|
||||
veilid_core::VeilidLogLevel::Error => VeilidLogLevel::Error,
|
||||
veilid_core::VeilidLogLevel::Warn => VeilidLogLevel::Warn,
|
||||
veilid_core::VeilidLogLevel::Info => VeilidLogLevel::Info,
|
||||
veilid_core::VeilidLogLevel::Debug => VeilidLogLevel::Debug,
|
||||
veilid_core::VeilidLogLevel::Trace => VeilidLogLevel::Trace,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_config_log_level(&self) -> veilid_core::VeilidConfigLogLevel {
|
||||
match self {
|
||||
Self::Error => veilid_core::VeilidConfigLogLevel::Error,
|
||||
Self::Warn => veilid_core::VeilidConfigLogLevel::Warn,
|
||||
Self::Info => veilid_core::VeilidConfigLogLevel::Info,
|
||||
Self::Debug => veilid_core::VeilidConfigLogLevel::Debug,
|
||||
Self::Trace => veilid_core::VeilidConfigLogLevel::Trace,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum VeilidUpdate {
|
||||
Log {
|
||||
log_level: VeilidLogLevel,
|
||||
message: String,
|
||||
},
|
||||
Attachment(AttachmentState),
|
||||
}
|
||||
|
||||
impl VeilidUpdate {
|
||||
fn from_core(veilid_update: veilid_core::VeilidUpdate) -> Self {
|
||||
match veilid_update {
|
||||
veilid_core::VeilidUpdate::Log { log_level, message } => Self::Log {
|
||||
log_level: VeilidLogLevel::from_core(log_level),
|
||||
message,
|
||||
},
|
||||
veilid_core::VeilidUpdate::Attachment(attachment) => {
|
||||
Self::Attachment(AttachmentState::from_core(attachment))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VeilidState {
|
||||
pub attachment: AttachmentState,
|
||||
}
|
||||
|
||||
impl VeilidState {
|
||||
fn from_core(veilid_state: veilid_core::VeilidState) -> Self {
|
||||
Self {
|
||||
attachment: AttachmentState::from_core(veilid_state.attachment),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////
|
||||
pub fn startup_veilid_core(
|
||||
sink: StreamSink<VeilidUpdate>,
|
||||
config: VeilidConfig,
|
||||
) -> Result<VeilidState> {
|
||||
async_std::task::block_on(async {
|
||||
let mut api_lock = VEILID_API.lock().await;
|
||||
if api_lock.is_some() {
|
||||
return Err(anyhow!(VeilidAPIError::AlreadyInitialized));
|
||||
}
|
||||
|
||||
let core = veilid_core::VeilidCore::new();
|
||||
|
||||
let setup = veilid_core::VeilidCoreSetup {
|
||||
update_callback: Arc::new(
|
||||
move |update: veilid_core::VeilidUpdate| -> veilid_core::SystemPinBoxFuture<()> {
|
||||
let sink = sink.clone();
|
||||
Box::pin(async move {
|
||||
if !sink.add(VeilidUpdate::from_core(update)) {
|
||||
error!("error sending veilid update callback");
|
||||
}
|
||||
})
|
||||
},
|
||||
),
|
||||
config_callback: Arc::new(move |key| config.get_by_str(&key)),
|
||||
};
|
||||
|
||||
let veilid_api = core
|
||||
.startup(setup)
|
||||
.await
|
||||
.map_err(|e| VeilidAPIError::InvalidConfig(e.clone()))?;
|
||||
*api_lock = Some(veilid_api.clone());
|
||||
|
||||
let core_state = veilid_api
|
||||
.get_state()
|
||||
.await
|
||||
.map_err(VeilidAPIError::from_core)?;
|
||||
Ok(VeilidState::from_core(core_state))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_veilid_state() -> Result<VeilidState> {
|
||||
async_std::task::block_on(async {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let core_state = veilid_api
|
||||
.get_state()
|
||||
.await
|
||||
.map_err(VeilidAPIError::from_core)?;
|
||||
Ok(VeilidState::from_core(core_state))
|
||||
})
|
||||
}
|
||||
|
||||
// xxx api functions
|
||||
|
||||
pub fn change_api_log_level(log_level: VeilidLogLevel) -> Result<()> {
|
||||
async_std::task::block_on(async {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
veilid_api
|
||||
.change_api_log_level(log_level.to_config_log_level())
|
||||
.await;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn shutdown_veilid_core() -> Result<()> {
|
||||
async_std::task::block_on(async {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
veilid_api.shutdown().await;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn veilid_version_string() -> Result<String> {
|
||||
Ok(veilid_core::veilid_version_string())
|
||||
}
|
||||
|
||||
pub struct VeilidVersion {
|
||||
pub major: u32,
|
||||
pub minor: u32,
|
||||
pub patch: u32,
|
||||
}
|
||||
|
||||
pub fn veilid_version() -> Result<VeilidVersion> {
|
||||
let (major, minor, patch) = veilid_core::veilid_version();
|
||||
Ok(VeilidVersion {
|
||||
major,
|
||||
minor,
|
||||
patch,
|
||||
})
|
||||
}
|
@@ -1,581 +0,0 @@
|
||||
#![allow(
|
||||
non_camel_case_types,
|
||||
unused,
|
||||
clippy::redundant_closure,
|
||||
clippy::useless_conversion,
|
||||
non_snake_case
|
||||
)]
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
// Generated by `flutter_rust_bridge`.
|
||||
|
||||
use crate::api::*;
|
||||
use flutter_rust_bridge::*;
|
||||
|
||||
// Section: wire functions
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wire_startup_veilid_core(port_: i64, config: *mut wire_VeilidConfig) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap(
|
||||
WrapInfo {
|
||||
debug_name: "startup_veilid_core",
|
||||
port: Some(port_),
|
||||
mode: FfiCallMode::Stream,
|
||||
},
|
||||
move || {
|
||||
let api_config = config.wire2api();
|
||||
move |task_callback| startup_veilid_core(task_callback.stream_sink(), api_config)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wire_get_veilid_state(port_: i64) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap(
|
||||
WrapInfo {
|
||||
debug_name: "get_veilid_state",
|
||||
port: Some(port_),
|
||||
mode: FfiCallMode::Normal,
|
||||
},
|
||||
move || move |task_callback| get_veilid_state(),
|
||||
)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wire_change_api_log_level(port_: i64, log_level: i32) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap(
|
||||
WrapInfo {
|
||||
debug_name: "change_api_log_level",
|
||||
port: Some(port_),
|
||||
mode: FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
let api_log_level = log_level.wire2api();
|
||||
move |task_callback| change_api_log_level(api_log_level)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wire_shutdown_veilid_core(port_: i64) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap(
|
||||
WrapInfo {
|
||||
debug_name: "shutdown_veilid_core",
|
||||
port: Some(port_),
|
||||
mode: FfiCallMode::Normal,
|
||||
},
|
||||
move || move |task_callback| shutdown_veilid_core(),
|
||||
)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wire_veilid_version_string(port_: i64) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap(
|
||||
WrapInfo {
|
||||
debug_name: "veilid_version_string",
|
||||
port: Some(port_),
|
||||
mode: FfiCallMode::Normal,
|
||||
},
|
||||
move || move |task_callback| veilid_version_string(),
|
||||
)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wire_veilid_version(port_: i64) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap(
|
||||
WrapInfo {
|
||||
debug_name: "veilid_version",
|
||||
port: Some(port_),
|
||||
mode: FfiCallMode::Normal,
|
||||
},
|
||||
move || move |task_callback| veilid_version(),
|
||||
)
|
||||
}
|
||||
|
||||
// Section: wire structs
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wire_StringList {
|
||||
ptr: *mut *mut wire_uint_8_list,
|
||||
len: i32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wire_uint_8_list {
|
||||
ptr: *mut u8,
|
||||
len: i32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wire_VeilidConfig {
|
||||
program_name: *mut wire_uint_8_list,
|
||||
veilid_namespace: *mut wire_uint_8_list,
|
||||
api_log_level: i32,
|
||||
capabilities__protocol_udp: bool,
|
||||
capabilities__protocol_connect_tcp: bool,
|
||||
capabilities__protocol_accept_tcp: bool,
|
||||
capabilities__protocol_connect_ws: bool,
|
||||
capabilities__protocol_accept_ws: bool,
|
||||
capabilities__protocol_connect_wss: bool,
|
||||
capabilities__protocol_accept_wss: bool,
|
||||
protected_store__allow_insecure_fallback: bool,
|
||||
protected_store__always_use_insecure_storage: bool,
|
||||
protected_store__insecure_fallback_directory: *mut wire_uint_8_list,
|
||||
protected_store__delete: bool,
|
||||
table_store__directory: *mut wire_uint_8_list,
|
||||
table_store__delete: bool,
|
||||
block_store__directory: *mut wire_uint_8_list,
|
||||
block_store__delete: bool,
|
||||
network__max_connections: u32,
|
||||
network__connection_initial_timeout_ms: u32,
|
||||
network__node_id: *mut wire_uint_8_list,
|
||||
network__node_id_secret: *mut wire_uint_8_list,
|
||||
network__bootstrap: *mut wire_StringList,
|
||||
network__upnp: bool,
|
||||
network__natpmp: bool,
|
||||
network__enable_local_peer_scope: bool,
|
||||
network__restricted_nat_retries: u32,
|
||||
network__rpc__concurrency: u32,
|
||||
network__rpc__queue_size: u32,
|
||||
network__rpc__max_timestamp_behind_ms: *mut u32,
|
||||
network__rpc__max_timestamp_ahead_ms: *mut u32,
|
||||
network__rpc__timeout_ms: u32,
|
||||
network__rpc__max_route_hop_count: u8,
|
||||
network__dht__resolve_node_timeout_ms: *mut u32,
|
||||
network__dht__resolve_node_count: u32,
|
||||
network__dht__resolve_node_fanout: u32,
|
||||
network__dht__max_find_node_count: u32,
|
||||
network__dht__get_value_timeout_ms: *mut u32,
|
||||
network__dht__get_value_count: u32,
|
||||
network__dht__get_value_fanout: u32,
|
||||
network__dht__set_value_timeout_ms: *mut u32,
|
||||
network__dht__set_value_count: u32,
|
||||
network__dht__set_value_fanout: u32,
|
||||
network__dht__min_peer_count: u32,
|
||||
network__dht__min_peer_refresh_time_ms: u32,
|
||||
network__dht__validate_dial_info_receipt_time_ms: u32,
|
||||
network__protocol__udp__enabled: bool,
|
||||
network__protocol__udp__socket_pool_size: u32,
|
||||
network__protocol__udp__listen_address: *mut wire_uint_8_list,
|
||||
network__protocol__udp__public_address: *mut wire_uint_8_list,
|
||||
network__protocol__tcp__connect: bool,
|
||||
network__protocol__tcp__listen: bool,
|
||||
network__protocol__tcp__max_connections: u32,
|
||||
network__protocol__tcp__listen_address: *mut wire_uint_8_list,
|
||||
network__protocol__tcp__public_address: *mut wire_uint_8_list,
|
||||
network__protocol__ws__connect: bool,
|
||||
network__protocol__ws__listen: bool,
|
||||
network__protocol__ws__max_connections: u32,
|
||||
network__protocol__ws__listen_address: *mut wire_uint_8_list,
|
||||
network__protocol__ws__path: *mut wire_uint_8_list,
|
||||
network__protocol__ws__url: *mut wire_uint_8_list,
|
||||
network__protocol__wss__connect: bool,
|
||||
network__protocol__wss__max_connections: u32,
|
||||
network__leases__max_server_signal_leases: u32,
|
||||
network__leases__max_server_relay_leases: u32,
|
||||
network__leases__max_client_signal_leases: u32,
|
||||
network__leases__max_client_relay_leases: u32,
|
||||
}
|
||||
|
||||
// Section: wire enums
|
||||
|
||||
// Section: allocate functions
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn new_StringList(len: i32) -> *mut wire_StringList {
|
||||
let wrap = wire_StringList {
|
||||
ptr: support::new_leak_vec_ptr(<*mut wire_uint_8_list>::new_with_null_ptr(), len),
|
||||
len,
|
||||
};
|
||||
support::new_leak_box_ptr(wrap)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn new_box_autoadd_u32(value: u32) -> *mut u32 {
|
||||
support::new_leak_box_ptr(value)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn new_box_autoadd_veilid_config() -> *mut wire_VeilidConfig {
|
||||
support::new_leak_box_ptr(wire_VeilidConfig::new_with_null_ptr())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn new_uint_8_list(len: i32) -> *mut wire_uint_8_list {
|
||||
let ans = wire_uint_8_list {
|
||||
ptr: support::new_leak_vec_ptr(Default::default(), len),
|
||||
len,
|
||||
};
|
||||
support::new_leak_box_ptr(ans)
|
||||
}
|
||||
|
||||
// Section: impl Wire2Api
|
||||
|
||||
pub trait Wire2Api<T> {
|
||||
fn wire2api(self) -> T;
|
||||
}
|
||||
|
||||
impl<T, S> Wire2Api<Option<T>> for *mut S
|
||||
where
|
||||
*mut S: Wire2Api<T>,
|
||||
{
|
||||
fn wire2api(self) -> Option<T> {
|
||||
if self.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(self.wire2api())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Wire2Api<String> for *mut wire_uint_8_list {
|
||||
fn wire2api(self) -> String {
|
||||
let vec: Vec<u8> = self.wire2api();
|
||||
String::from_utf8_lossy(&vec).into_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl Wire2Api<Vec<String>> for *mut wire_StringList {
|
||||
fn wire2api(self) -> Vec<String> {
|
||||
let vec = unsafe {
|
||||
let wrap = support::box_from_leak_ptr(self);
|
||||
support::vec_from_leak_ptr(wrap.ptr, wrap.len)
|
||||
};
|
||||
vec.into_iter().map(Wire2Api::wire2api).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl Wire2Api<bool> for bool {
|
||||
fn wire2api(self) -> bool {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Wire2Api<u32> for *mut u32 {
|
||||
fn wire2api(self) -> u32 {
|
||||
unsafe { *support::box_from_leak_ptr(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Wire2Api<VeilidConfig> for *mut wire_VeilidConfig {
|
||||
fn wire2api(self) -> VeilidConfig {
|
||||
let wrap = unsafe { support::box_from_leak_ptr(self) };
|
||||
(*wrap).wire2api().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl Wire2Api<u32> for u32 {
|
||||
fn wire2api(self) -> u32 {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Wire2Api<u8> for u8 {
|
||||
fn wire2api(self) -> u8 {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Wire2Api<Vec<u8>> for *mut wire_uint_8_list {
|
||||
fn wire2api(self) -> Vec<u8> {
|
||||
unsafe {
|
||||
let wrap = support::box_from_leak_ptr(self);
|
||||
support::vec_from_leak_ptr(wrap.ptr, wrap.len)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Wire2Api<VeilidConfig> for wire_VeilidConfig {
|
||||
fn wire2api(self) -> VeilidConfig {
|
||||
VeilidConfig {
|
||||
program_name: self.program_name.wire2api(),
|
||||
veilid_namespace: self.veilid_namespace.wire2api(),
|
||||
api_log_level: self.api_log_level.wire2api(),
|
||||
capabilities__protocol_udp: self.capabilities__protocol_udp.wire2api(),
|
||||
capabilities__protocol_connect_tcp: self.capabilities__protocol_connect_tcp.wire2api(),
|
||||
capabilities__protocol_accept_tcp: self.capabilities__protocol_accept_tcp.wire2api(),
|
||||
capabilities__protocol_connect_ws: self.capabilities__protocol_connect_ws.wire2api(),
|
||||
capabilities__protocol_accept_ws: self.capabilities__protocol_accept_ws.wire2api(),
|
||||
capabilities__protocol_connect_wss: self.capabilities__protocol_connect_wss.wire2api(),
|
||||
capabilities__protocol_accept_wss: self.capabilities__protocol_accept_wss.wire2api(),
|
||||
protected_store__allow_insecure_fallback: self
|
||||
.protected_store__allow_insecure_fallback
|
||||
.wire2api(),
|
||||
protected_store__always_use_insecure_storage: self
|
||||
.protected_store__always_use_insecure_storage
|
||||
.wire2api(),
|
||||
protected_store__insecure_fallback_directory: self
|
||||
.protected_store__insecure_fallback_directory
|
||||
.wire2api(),
|
||||
protected_store__delete: self.protected_store__delete.wire2api(),
|
||||
table_store__directory: self.table_store__directory.wire2api(),
|
||||
table_store__delete: self.table_store__delete.wire2api(),
|
||||
block_store__directory: self.block_store__directory.wire2api(),
|
||||
block_store__delete: self.block_store__delete.wire2api(),
|
||||
network__max_connections: self.network__max_connections.wire2api(),
|
||||
network__connection_initial_timeout_ms: self
|
||||
.network__connection_initial_timeout_ms
|
||||
.wire2api(),
|
||||
network__node_id: self.network__node_id.wire2api(),
|
||||
network__node_id_secret: self.network__node_id_secret.wire2api(),
|
||||
network__bootstrap: self.network__bootstrap.wire2api(),
|
||||
network__upnp: self.network__upnp.wire2api(),
|
||||
network__natpmp: self.network__natpmp.wire2api(),
|
||||
network__enable_local_peer_scope: self.network__enable_local_peer_scope.wire2api(),
|
||||
network__restricted_nat_retries: self.network__restricted_nat_retries.wire2api(),
|
||||
network__rpc__concurrency: self.network__rpc__concurrency.wire2api(),
|
||||
network__rpc__queue_size: self.network__rpc__queue_size.wire2api(),
|
||||
network__rpc__max_timestamp_behind_ms: self
|
||||
.network__rpc__max_timestamp_behind_ms
|
||||
.wire2api(),
|
||||
network__rpc__max_timestamp_ahead_ms: self
|
||||
.network__rpc__max_timestamp_ahead_ms
|
||||
.wire2api(),
|
||||
network__rpc__timeout_ms: self.network__rpc__timeout_ms.wire2api(),
|
||||
network__rpc__max_route_hop_count: self.network__rpc__max_route_hop_count.wire2api(),
|
||||
network__dht__resolve_node_timeout_ms: self
|
||||
.network__dht__resolve_node_timeout_ms
|
||||
.wire2api(),
|
||||
network__dht__resolve_node_count: self.network__dht__resolve_node_count.wire2api(),
|
||||
network__dht__resolve_node_fanout: self.network__dht__resolve_node_fanout.wire2api(),
|
||||
network__dht__max_find_node_count: self.network__dht__max_find_node_count.wire2api(),
|
||||
network__dht__get_value_timeout_ms: self.network__dht__get_value_timeout_ms.wire2api(),
|
||||
network__dht__get_value_count: self.network__dht__get_value_count.wire2api(),
|
||||
network__dht__get_value_fanout: self.network__dht__get_value_fanout.wire2api(),
|
||||
network__dht__set_value_timeout_ms: self.network__dht__set_value_timeout_ms.wire2api(),
|
||||
network__dht__set_value_count: self.network__dht__set_value_count.wire2api(),
|
||||
network__dht__set_value_fanout: self.network__dht__set_value_fanout.wire2api(),
|
||||
network__dht__min_peer_count: self.network__dht__min_peer_count.wire2api(),
|
||||
network__dht__min_peer_refresh_time_ms: self
|
||||
.network__dht__min_peer_refresh_time_ms
|
||||
.wire2api(),
|
||||
network__dht__validate_dial_info_receipt_time_ms: self
|
||||
.network__dht__validate_dial_info_receipt_time_ms
|
||||
.wire2api(),
|
||||
network__protocol__udp__enabled: self.network__protocol__udp__enabled.wire2api(),
|
||||
network__protocol__udp__socket_pool_size: self
|
||||
.network__protocol__udp__socket_pool_size
|
||||
.wire2api(),
|
||||
network__protocol__udp__listen_address: self
|
||||
.network__protocol__udp__listen_address
|
||||
.wire2api(),
|
||||
network__protocol__udp__public_address: self
|
||||
.network__protocol__udp__public_address
|
||||
.wire2api(),
|
||||
network__protocol__tcp__connect: self.network__protocol__tcp__connect.wire2api(),
|
||||
network__protocol__tcp__listen: self.network__protocol__tcp__listen.wire2api(),
|
||||
network__protocol__tcp__max_connections: self
|
||||
.network__protocol__tcp__max_connections
|
||||
.wire2api(),
|
||||
network__protocol__tcp__listen_address: self
|
||||
.network__protocol__tcp__listen_address
|
||||
.wire2api(),
|
||||
network__protocol__tcp__public_address: self
|
||||
.network__protocol__tcp__public_address
|
||||
.wire2api(),
|
||||
network__protocol__ws__connect: self.network__protocol__ws__connect.wire2api(),
|
||||
network__protocol__ws__listen: self.network__protocol__ws__listen.wire2api(),
|
||||
network__protocol__ws__max_connections: self
|
||||
.network__protocol__ws__max_connections
|
||||
.wire2api(),
|
||||
network__protocol__ws__listen_address: self
|
||||
.network__protocol__ws__listen_address
|
||||
.wire2api(),
|
||||
network__protocol__ws__path: self.network__protocol__ws__path.wire2api(),
|
||||
network__protocol__ws__url: self.network__protocol__ws__url.wire2api(),
|
||||
network__protocol__wss__connect: self.network__protocol__wss__connect.wire2api(),
|
||||
network__protocol__wss__max_connections: self
|
||||
.network__protocol__wss__max_connections
|
||||
.wire2api(),
|
||||
network__leases__max_server_signal_leases: self
|
||||
.network__leases__max_server_signal_leases
|
||||
.wire2api(),
|
||||
network__leases__max_server_relay_leases: self
|
||||
.network__leases__max_server_relay_leases
|
||||
.wire2api(),
|
||||
network__leases__max_client_signal_leases: self
|
||||
.network__leases__max_client_signal_leases
|
||||
.wire2api(),
|
||||
network__leases__max_client_relay_leases: self
|
||||
.network__leases__max_client_relay_leases
|
||||
.wire2api(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Wire2Api<VeilidLogLevel> for i32 {
|
||||
fn wire2api(self) -> VeilidLogLevel {
|
||||
match self {
|
||||
0 => VeilidLogLevel::Error,
|
||||
1 => VeilidLogLevel::Warn,
|
||||
2 => VeilidLogLevel::Info,
|
||||
3 => VeilidLogLevel::Debug,
|
||||
4 => VeilidLogLevel::Trace,
|
||||
_ => unreachable!("Invalid variant for VeilidLogLevel: {}", self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Section: impl NewWithNullPtr
|
||||
|
||||
pub trait NewWithNullPtr {
|
||||
fn new_with_null_ptr() -> Self;
|
||||
}
|
||||
|
||||
impl<T> NewWithNullPtr for *mut T {
|
||||
fn new_with_null_ptr() -> Self {
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl NewWithNullPtr for wire_VeilidConfig {
|
||||
fn new_with_null_ptr() -> Self {
|
||||
Self {
|
||||
program_name: core::ptr::null_mut(),
|
||||
veilid_namespace: core::ptr::null_mut(),
|
||||
api_log_level: Default::default(),
|
||||
capabilities__protocol_udp: Default::default(),
|
||||
capabilities__protocol_connect_tcp: Default::default(),
|
||||
capabilities__protocol_accept_tcp: Default::default(),
|
||||
capabilities__protocol_connect_ws: Default::default(),
|
||||
capabilities__protocol_accept_ws: Default::default(),
|
||||
capabilities__protocol_connect_wss: Default::default(),
|
||||
capabilities__protocol_accept_wss: Default::default(),
|
||||
protected_store__allow_insecure_fallback: Default::default(),
|
||||
protected_store__always_use_insecure_storage: Default::default(),
|
||||
protected_store__insecure_fallback_directory: core::ptr::null_mut(),
|
||||
protected_store__delete: Default::default(),
|
||||
table_store__directory: core::ptr::null_mut(),
|
||||
table_store__delete: Default::default(),
|
||||
block_store__directory: core::ptr::null_mut(),
|
||||
block_store__delete: Default::default(),
|
||||
network__max_connections: Default::default(),
|
||||
network__connection_initial_timeout_ms: Default::default(),
|
||||
network__node_id: core::ptr::null_mut(),
|
||||
network__node_id_secret: core::ptr::null_mut(),
|
||||
network__bootstrap: core::ptr::null_mut(),
|
||||
network__upnp: Default::default(),
|
||||
network__natpmp: Default::default(),
|
||||
network__enable_local_peer_scope: Default::default(),
|
||||
network__restricted_nat_retries: Default::default(),
|
||||
network__rpc__concurrency: Default::default(),
|
||||
network__rpc__queue_size: Default::default(),
|
||||
network__rpc__max_timestamp_behind_ms: core::ptr::null_mut(),
|
||||
network__rpc__max_timestamp_ahead_ms: core::ptr::null_mut(),
|
||||
network__rpc__timeout_ms: Default::default(),
|
||||
network__rpc__max_route_hop_count: Default::default(),
|
||||
network__dht__resolve_node_timeout_ms: core::ptr::null_mut(),
|
||||
network__dht__resolve_node_count: Default::default(),
|
||||
network__dht__resolve_node_fanout: Default::default(),
|
||||
network__dht__max_find_node_count: Default::default(),
|
||||
network__dht__get_value_timeout_ms: core::ptr::null_mut(),
|
||||
network__dht__get_value_count: Default::default(),
|
||||
network__dht__get_value_fanout: Default::default(),
|
||||
network__dht__set_value_timeout_ms: core::ptr::null_mut(),
|
||||
network__dht__set_value_count: Default::default(),
|
||||
network__dht__set_value_fanout: Default::default(),
|
||||
network__dht__min_peer_count: Default::default(),
|
||||
network__dht__min_peer_refresh_time_ms: Default::default(),
|
||||
network__dht__validate_dial_info_receipt_time_ms: Default::default(),
|
||||
network__protocol__udp__enabled: Default::default(),
|
||||
network__protocol__udp__socket_pool_size: Default::default(),
|
||||
network__protocol__udp__listen_address: core::ptr::null_mut(),
|
||||
network__protocol__udp__public_address: core::ptr::null_mut(),
|
||||
network__protocol__tcp__connect: Default::default(),
|
||||
network__protocol__tcp__listen: Default::default(),
|
||||
network__protocol__tcp__max_connections: Default::default(),
|
||||
network__protocol__tcp__listen_address: core::ptr::null_mut(),
|
||||
network__protocol__tcp__public_address: core::ptr::null_mut(),
|
||||
network__protocol__ws__connect: Default::default(),
|
||||
network__protocol__ws__listen: Default::default(),
|
||||
network__protocol__ws__max_connections: Default::default(),
|
||||
network__protocol__ws__listen_address: core::ptr::null_mut(),
|
||||
network__protocol__ws__path: core::ptr::null_mut(),
|
||||
network__protocol__ws__url: core::ptr::null_mut(),
|
||||
network__protocol__wss__connect: Default::default(),
|
||||
network__protocol__wss__max_connections: Default::default(),
|
||||
network__leases__max_server_signal_leases: Default::default(),
|
||||
network__leases__max_server_relay_leases: Default::default(),
|
||||
network__leases__max_client_signal_leases: Default::default(),
|
||||
network__leases__max_client_relay_leases: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Section: impl IntoDart
|
||||
|
||||
impl support::IntoDart for AttachmentState {
|
||||
fn into_dart(self) -> support::DartCObject {
|
||||
match self {
|
||||
Self::Detached => 0,
|
||||
Self::Attaching => 1,
|
||||
Self::AttachedWeak => 2,
|
||||
Self::AttachedGood => 3,
|
||||
Self::AttachedStrong => 4,
|
||||
Self::FullyAttached => 5,
|
||||
Self::OverAttached => 6,
|
||||
Self::Detaching => 7,
|
||||
}
|
||||
.into_dart()
|
||||
}
|
||||
}
|
||||
|
||||
impl support::IntoDart for VeilidLogLevel {
|
||||
fn into_dart(self) -> support::DartCObject {
|
||||
match self {
|
||||
Self::Error => 0,
|
||||
Self::Warn => 1,
|
||||
Self::Info => 2,
|
||||
Self::Debug => 3,
|
||||
Self::Trace => 4,
|
||||
}
|
||||
.into_dart()
|
||||
}
|
||||
}
|
||||
|
||||
impl support::IntoDart for VeilidState {
|
||||
fn into_dart(self) -> support::DartCObject {
|
||||
vec![self.attachment.into_dart()].into_dart()
|
||||
}
|
||||
}
|
||||
impl support::IntoDartExceptPrimitive for VeilidState {}
|
||||
|
||||
impl support::IntoDart for VeilidUpdate {
|
||||
fn into_dart(self) -> support::DartCObject {
|
||||
match self {
|
||||
Self::Log { log_level, message } => {
|
||||
vec![0.into_dart(), log_level.into_dart(), message.into_dart()]
|
||||
}
|
||||
Self::Attachment(field0) => vec![1.into_dart(), field0.into_dart()],
|
||||
}
|
||||
.into_dart()
|
||||
}
|
||||
}
|
||||
|
||||
impl support::IntoDart for VeilidVersion {
|
||||
fn into_dart(self) -> support::DartCObject {
|
||||
vec![
|
||||
self.major.into_dart(),
|
||||
self.minor.into_dart(),
|
||||
self.patch.into_dart(),
|
||||
]
|
||||
.into_dart()
|
||||
}
|
||||
}
|
||||
impl support::IntoDartExceptPrimitive for VeilidVersion {}
|
||||
|
||||
// Section: executor
|
||||
support::lazy_static! {
|
||||
pub static ref FLUTTER_RUST_BRIDGE_HANDLER: support::DefaultHandler = Default::default();
|
||||
}
|
||||
|
||||
// Section: sync execution mode utility
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn free_WireSyncReturnStruct(val: support::WireSyncReturnStruct) {
|
||||
unsafe {
|
||||
let _ = support::vec_from_leak_ptr(val.ptr, val.len);
|
||||
}
|
||||
}
|
243
veilid-flutter/rust/src/config.rs
Normal file
243
veilid-flutter/rust/src/config.rs
Normal file
@@ -0,0 +1,243 @@
|
||||
use cfg_if::*;
|
||||
use log::*;
|
||||
use serde::*;
|
||||
|
||||
/////////////////////////////////////////
|
||||
// Config Settings
|
||||
// Not all settings available through Veilid API are available to Flutter applications
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[allow(non_snake_case)]
|
||||
pub struct VeilidConfig {
|
||||
pub program_name: String,
|
||||
pub veilid_namespace: String,
|
||||
pub api_log_level: veilid_core::VeilidConfigLogLevel,
|
||||
// Capabilities
|
||||
pub capabilities__protocol_udp: bool,
|
||||
pub capabilities__protocol_connect_tcp: bool,
|
||||
pub capabilities__protocol_accept_tcp: bool,
|
||||
pub capabilities__protocol_connect_ws: bool,
|
||||
pub capabilities__protocol_accept_ws: bool,
|
||||
pub capabilities__protocol_connect_wss: bool,
|
||||
pub capabilities__protocol_accept_wss: bool,
|
||||
// Protected Store
|
||||
pub protected_store__allow_insecure_fallback: bool,
|
||||
pub protected_store__always_use_insecure_storage: bool,
|
||||
pub protected_store__insecure_fallback_directory: String,
|
||||
pub protected_store__delete: bool,
|
||||
// Table Store
|
||||
pub table_store__directory: String,
|
||||
pub table_store__delete: bool,
|
||||
// Block Store
|
||||
pub block_store__directory: String,
|
||||
pub block_store__delete: bool,
|
||||
// Network
|
||||
pub network__max_connections: u32,
|
||||
pub network__connection_initial_timeout_ms: u32,
|
||||
pub network__node_id: String,
|
||||
pub network__node_id_secret: String,
|
||||
pub network__bootstrap: Vec<String>,
|
||||
pub network__upnp: bool,
|
||||
pub network__natpmp: bool,
|
||||
pub network__enable_local_peer_scope: bool,
|
||||
pub network__restricted_nat_retries: u32,
|
||||
// Network / RPC
|
||||
pub network__rpc__concurrency: u32,
|
||||
pub network__rpc__queue_size: u32,
|
||||
pub network__rpc__max_timestamp_behind_ms: Option<u32>,
|
||||
pub network__rpc__max_timestamp_ahead_ms: Option<u32>,
|
||||
pub network__rpc__timeout_ms: u32,
|
||||
pub network__rpc__max_route_hop_count: u8,
|
||||
// Network / DHT
|
||||
pub network__dht__resolve_node_timeout_ms: Option<u32>,
|
||||
pub network__dht__resolve_node_count: u32,
|
||||
pub network__dht__resolve_node_fanout: u32,
|
||||
pub network__dht__max_find_node_count: u32,
|
||||
pub network__dht__get_value_timeout_ms: Option<u32>,
|
||||
pub network__dht__get_value_count: u32,
|
||||
pub network__dht__get_value_fanout: u32,
|
||||
pub network__dht__set_value_timeout_ms: Option<u32>,
|
||||
pub network__dht__set_value_count: u32,
|
||||
pub network__dht__set_value_fanout: u32,
|
||||
pub network__dht__min_peer_count: u32,
|
||||
pub network__dht__min_peer_refresh_time_ms: u32,
|
||||
pub network__dht__validate_dial_info_receipt_time_ms: u32,
|
||||
// Network / Protocol
|
||||
// Network / Protocol / UDP
|
||||
pub network__protocol__udp__enabled: bool,
|
||||
pub network__protocol__udp__socket_pool_size: u32,
|
||||
pub network__protocol__udp__listen_address: String,
|
||||
pub network__protocol__udp__public_address: Option<String>,
|
||||
// Network / Protocol / TCP
|
||||
pub network__protocol__tcp__connect: bool,
|
||||
pub network__protocol__tcp__listen: bool,
|
||||
pub network__protocol__tcp__max_connections: u32,
|
||||
pub network__protocol__tcp__listen_address: String,
|
||||
pub network__protocol__tcp__public_address: Option<String>,
|
||||
// Network / Protocol / WS
|
||||
pub network__protocol__ws__connect: bool,
|
||||
pub network__protocol__ws__listen: bool,
|
||||
pub network__protocol__ws__max_connections: u32,
|
||||
pub network__protocol__ws__listen_address: String,
|
||||
pub network__protocol__ws__path: String,
|
||||
pub network__protocol__ws__url: Option<String>,
|
||||
// Network / Protocol / WSS
|
||||
pub network__protocol__wss__connect: bool,
|
||||
pub network__protocol__wss__max_connections: u32,
|
||||
// Network / Leases
|
||||
pub network__leases__max_server_signal_leases: u32,
|
||||
pub network__leases__max_server_relay_leases: u32,
|
||||
pub network__leases__max_client_signal_leases: u32,
|
||||
pub network__leases__max_client_relay_leases: u32,
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(target_arch="wasm32")] {
|
||||
type ConfigReturn = Box<dyn std::any::Any + 'static>;
|
||||
} else {
|
||||
type ConfigReturn = Box<dyn std::any::Any + Send + 'static>;
|
||||
}
|
||||
}
|
||||
|
||||
impl VeilidConfig {
|
||||
pub fn get_by_str(&self, key: &str) -> std::result::Result<ConfigReturn, String> {
|
||||
let out: ConfigReturn = match key {
|
||||
"program_name" => Box::new(self.program_name.clone()),
|
||||
"namespace" => Box::new(self.veilid_namespace.clone()),
|
||||
"api_log_level" => Box::new(self.api_log_level),
|
||||
"capabilities.protocol_udp" => Box::new(self.capabilities__protocol_udp),
|
||||
"capabilities.protocol_connect_tcp" => {
|
||||
Box::new(self.capabilities__protocol_connect_tcp)
|
||||
}
|
||||
"capabilities.protocol_accept_tcp" => Box::new(self.capabilities__protocol_accept_tcp),
|
||||
"capabilities.protocol_connect_ws" => Box::new(self.capabilities__protocol_connect_ws),
|
||||
"capabilities.protocol_accept_ws" => Box::new(self.capabilities__protocol_accept_ws),
|
||||
"capabilities.protocol_connect_wss" => {
|
||||
Box::new(self.capabilities__protocol_connect_wss)
|
||||
}
|
||||
"capabilities.protocol_accept_wss" => Box::new(self.capabilities__protocol_accept_wss),
|
||||
"table_store.directory" => Box::new(self.table_store__directory.clone()),
|
||||
"table_store.delete" => Box::new(self.table_store__delete),
|
||||
"block_store.directory" => Box::new(self.block_store__directory.clone()),
|
||||
"block_store.delete" => Box::new(self.block_store__delete),
|
||||
"protected_store.allow_insecure_fallback" => {
|
||||
Box::new(self.protected_store__allow_insecure_fallback)
|
||||
}
|
||||
"protected_store.always_use_insecure_storage" => {
|
||||
Box::new(self.protected_store__always_use_insecure_storage)
|
||||
}
|
||||
"protected_store.insecure_fallback_directory" => {
|
||||
Box::new(self.protected_store__insecure_fallback_directory.clone())
|
||||
}
|
||||
"protected_store.delete" => Box::new(self.protected_store__delete),
|
||||
"network.node_id" => Box::new(self.network__node_id.clone()),
|
||||
"network.node_id_secret" => Box::new(self.network__node_id_secret.clone()),
|
||||
"network.max_connections" => Box::new(self.network__max_connections),
|
||||
"network.connection_initial_timeout_ms" => {
|
||||
Box::new(self.network__connection_initial_timeout_ms)
|
||||
}
|
||||
"network.bootstrap" => Box::new(self.network__bootstrap.clone()),
|
||||
"network.dht.resolve_node_timeout_ms" => {
|
||||
Box::new(self.network__dht__resolve_node_timeout_ms)
|
||||
}
|
||||
"network.dht.resolve_node_count" => Box::new(self.network__dht__resolve_node_count),
|
||||
"network.dht.resolve_node_fanout" => Box::new(self.network__dht__resolve_node_fanout),
|
||||
"network.dht.max_find_node_count" => Box::new(self.network__dht__max_find_node_count),
|
||||
"network.dht.get_value_timeout_ms" => Box::new(self.network__dht__get_value_timeout_ms),
|
||||
"network.dht.get_value_count" => Box::new(self.network__dht__get_value_count),
|
||||
"network.dht.get_value_fanout" => Box::new(self.network__dht__get_value_fanout),
|
||||
"network.dht.set_value_timeout_ms" => Box::new(self.network__dht__set_value_timeout_ms),
|
||||
"network.dht.set_value_count" => Box::new(self.network__dht__set_value_count),
|
||||
"network.dht.set_value_fanout" => Box::new(self.network__dht__set_value_fanout),
|
||||
"network.dht.min_peer_count" => Box::new(self.network__dht__min_peer_count),
|
||||
"network.dht.min_peer_refresh_time_ms" => {
|
||||
Box::new(self.network__dht__min_peer_refresh_time_ms)
|
||||
}
|
||||
"network.dht.validate_dial_info_receipt_time_ms" => {
|
||||
Box::new(self.network__dht__validate_dial_info_receipt_time_ms)
|
||||
}
|
||||
"network.rpc.concurrency" => Box::new(self.network__rpc__concurrency),
|
||||
"network.rpc.queue_size" => Box::new(self.network__rpc__queue_size),
|
||||
"network.rpc.max_timestamp_behind_ms" => {
|
||||
Box::new(self.network__rpc__max_timestamp_behind_ms)
|
||||
}
|
||||
"network.rpc.max_timestamp_ahead_ms" => {
|
||||
Box::new(self.network__rpc__max_timestamp_ahead_ms)
|
||||
}
|
||||
"network.rpc.timeout_ms" => Box::new(self.network__rpc__timeout_ms),
|
||||
"network.rpc.max_route_hop_count" => Box::new(self.network__rpc__max_route_hop_count),
|
||||
"network.upnp" => Box::new(self.network__upnp),
|
||||
"network.natpmp" => Box::new(self.network__natpmp),
|
||||
"network.enable_local_peer_scope" => Box::new(self.network__enable_local_peer_scope),
|
||||
"network.restricted_nat_retries" => Box::new(self.network__restricted_nat_retries),
|
||||
"network.tls.certificate_path" => Box::new("".to_owned()),
|
||||
"network.tls.private_key_path" => Box::new("".to_owned()),
|
||||
"network.tls.connection_initial_timeout" => Box::new(0u32),
|
||||
"network.application.https.enabled" => Box::new(false),
|
||||
"network.application.https.listen_address" => Box::new("".to_owned()),
|
||||
"network.application.https.path" => Box::new("".to_owned()),
|
||||
"network.application.https.url" => Box::new(Option::<String>::None),
|
||||
"network.application.http.enabled" => Box::new(false),
|
||||
"network.application.http.listen_address" => Box::new("".to_owned()),
|
||||
"network.application.http.path" => Box::new("".to_owned()),
|
||||
"network.application.http.url" => Box::new(Option::<String>::None),
|
||||
"network.protocol.udp.enabled" => Box::new(self.network__protocol__udp__enabled),
|
||||
"network.protocol.udp.socket_pool_size" => {
|
||||
Box::new(self.network__protocol__udp__socket_pool_size)
|
||||
}
|
||||
"network.protocol.udp.listen_address" => {
|
||||
Box::new(self.network__protocol__udp__listen_address.clone())
|
||||
}
|
||||
"network.protocol.udp.public_address" => {
|
||||
Box::new(self.network__protocol__udp__public_address.clone())
|
||||
}
|
||||
"network.protocol.tcp.connect" => Box::new(self.network__protocol__tcp__connect),
|
||||
"network.protocol.tcp.listen" => Box::new(self.network__protocol__tcp__listen),
|
||||
"network.protocol.tcp.max_connections" => {
|
||||
Box::new(self.network__protocol__tcp__max_connections)
|
||||
}
|
||||
"network.protocol.tcp.listen_address" => {
|
||||
Box::new(self.network__protocol__tcp__listen_address.clone())
|
||||
}
|
||||
"network.protocol.tcp.public_address" => {
|
||||
Box::new(self.network__protocol__tcp__public_address.clone())
|
||||
}
|
||||
"network.protocol.ws.connect" => Box::new(self.network__protocol__ws__connect),
|
||||
"network.protocol.ws.listen" => Box::new(self.network__protocol__ws__listen),
|
||||
"network.protocol.ws.max_connections" => {
|
||||
Box::new(self.network__protocol__ws__max_connections)
|
||||
}
|
||||
"network.protocol.ws.listen_address" => {
|
||||
Box::new(self.network__protocol__ws__listen_address.clone())
|
||||
}
|
||||
"network.protocol.ws.path" => Box::new(self.network__protocol__ws__path.clone()),
|
||||
"network.protocol.ws.url" => Box::new(self.network__protocol__ws__url.clone()),
|
||||
"network.protocol.wss.connect" => Box::new(self.network__protocol__wss__connect),
|
||||
"network.protocol.wss.listen" => Box::new(false),
|
||||
"network.protocol.wss.max_connections" => {
|
||||
Box::new(self.network__protocol__wss__max_connections)
|
||||
}
|
||||
"network.protocol.wss.listen_address" => Box::new("".to_owned()),
|
||||
"network.protocol.wss.path" => Box::new("".to_owned()),
|
||||
"network.protocol.wss.url" => Box::new(Option::<String>::None),
|
||||
"network.leases.max_server_signal_leases" => {
|
||||
Box::new(self.network__leases__max_server_signal_leases)
|
||||
}
|
||||
"network.leases.max_server_relay_leases" => {
|
||||
Box::new(self.network__leases__max_server_relay_leases)
|
||||
}
|
||||
"network.leases.max_client_signal_leases" => {
|
||||
Box::new(self.network__leases__max_client_signal_leases)
|
||||
}
|
||||
"network.leases.max_client_relay_leases" => {
|
||||
Box::new(self.network__leases__max_client_relay_leases)
|
||||
}
|
||||
_ => {
|
||||
let err = format!("config key '{}' doesn't exist", key);
|
||||
error!("{}", err);
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
std::result::Result::Ok(out)
|
||||
}
|
||||
}
|
177
veilid-flutter/rust/src/dart_ffi.rs
Normal file
177
veilid-flutter/rust/src/dart_ffi.rs
Normal file
@@ -0,0 +1,177 @@
|
||||
use crate::config::*;
|
||||
use crate::dart_isolate_wrapper::*;
|
||||
use crate::dart_serialize::*;
|
||||
|
||||
use allo_isolate::*;
|
||||
use async_std::sync::Mutex as AsyncMutex;
|
||||
use ffi_support::*;
|
||||
use lazy_static::*;
|
||||
use log::*;
|
||||
use std::os::raw::c_char;
|
||||
use std::sync::Arc;
|
||||
|
||||
// Globals
|
||||
|
||||
lazy_static! {
|
||||
static ref VEILID_API: AsyncMutex<Option<veilid_core::VeilidAPI>> = AsyncMutex::new(None);
|
||||
}
|
||||
|
||||
async fn get_veilid_api() -> Result<veilid_core::VeilidAPI, veilid_core::VeilidAPIError> {
|
||||
let api_lock = VEILID_API.lock().await;
|
||||
api_lock
|
||||
.as_ref()
|
||||
.cloned()
|
||||
.ok_or(veilid_core::VeilidAPIError::NotInitialized)
|
||||
}
|
||||
|
||||
async fn take_veilid_api() -> Result<veilid_core::VeilidAPI, veilid_core::VeilidAPIError> {
|
||||
let mut api_lock = VEILID_API.lock().await;
|
||||
api_lock
|
||||
.take()
|
||||
.ok_or(veilid_core::VeilidAPIError::NotInitialized)
|
||||
}
|
||||
|
||||
/////////////////////////////////////////
|
||||
// FFI Helpers
|
||||
|
||||
// Declare external routine to release ffi strings
|
||||
define_string_destructor!(free_string);
|
||||
|
||||
// Utility types for async API results
|
||||
type APIResult<T> = Result<T, veilid_core::VeilidAPIError>;
|
||||
const APIRESULT_VOID: APIResult<()> = APIResult::Ok(());
|
||||
|
||||
// Stream abort macro for simplified error handling
|
||||
macro_rules! check_err_json {
|
||||
($stream:expr, $ex:expr) => {
|
||||
match $ex {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
$stream.abort_json(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/////////////////////////////////////////
|
||||
// Initializer
|
||||
#[no_mangle]
|
||||
pub extern "C" fn initialize_veilid_flutter(dart_post_c_object_ptr: ffi::DartPostCObjectFnType) {
|
||||
unsafe {
|
||||
store_dart_post_cobject(dart_post_c_object_ptr);
|
||||
}
|
||||
|
||||
use std::sync::Once;
|
||||
static INIT_BACKTRACE: Once = Once::new();
|
||||
INIT_BACKTRACE.call_once(move || {
|
||||
std::env::set_var("RUST_BACKTRACE", "1");
|
||||
std::panic::set_hook(Box::new(move |panic_info| {
|
||||
let (file, line) = if let Some(loc) = panic_info.location() {
|
||||
(loc.file(), loc.line())
|
||||
} else {
|
||||
("<unknown>", 0)
|
||||
};
|
||||
log::error!("### Rust `panic!` hit at file '{}', line {}", file, line);
|
||||
if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
|
||||
error!("panic payload: {:?}", s);
|
||||
} else if let Some(s) = panic_info.payload().downcast_ref::<String>() {
|
||||
error!("panic payload: {:?}", s);
|
||||
} else if let Some(a) = panic_info.payload().downcast_ref::<std::fmt::Arguments>() {
|
||||
error!("panic payload: {:?}", a);
|
||||
} else {
|
||||
error!("no panic payload");
|
||||
}
|
||||
log::error!(" Complete stack trace:\n{:?}", backtrace::Backtrace::new());
|
||||
|
||||
// And stop the process, no recovery is going to be possible here
|
||||
std::process::abort();
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
/// C-compatible FFI Functions
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn startup_veilid_core(port: i64, config: FfiStr) {
|
||||
let config = config.into_opt_string();
|
||||
let stream = DartIsolateStream::new(port);
|
||||
async_std::task::spawn(async move {
|
||||
let config: VeilidConfig = check_err_json!(stream, deserialize_opt_json(config));
|
||||
|
||||
let mut api_lock = VEILID_API.lock().await;
|
||||
if api_lock.is_some() {
|
||||
stream.abort_json(veilid_core::VeilidAPIError::AlreadyInitialized);
|
||||
return;
|
||||
}
|
||||
|
||||
let sink = stream.clone();
|
||||
let setup = veilid_core::VeilidCoreSetup {
|
||||
update_callback: Arc::new(
|
||||
move |update: veilid_core::VeilidUpdate| -> veilid_core::SystemPinBoxFuture<()> {
|
||||
let sink = sink.clone();
|
||||
Box::pin(async move {
|
||||
sink.item_json(update);
|
||||
})
|
||||
},
|
||||
),
|
||||
config_callback: Arc::new(move |key| config.get_by_str(&key)),
|
||||
};
|
||||
|
||||
let res = veilid_core::api_startup(setup).await;
|
||||
let veilid_api = check_err_json!(stream, res);
|
||||
*api_lock = Some(veilid_api);
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn get_veilid_state(port: i64) {
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let core_state = veilid_api.get_state().await?;
|
||||
APIResult::Ok(core_state)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn change_api_log_level(port: i64, log_level: FfiStr) {
|
||||
let log_level = log_level.into_opt_string();
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let log_level: veilid_core::VeilidConfigLogLevel = deserialize_opt_json(log_level)?;
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
veilid_api.change_api_log_level(log_level).await;
|
||||
APIRESULT_VOID
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn shutdown_veilid_core(port: i64) {
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let veilid_api = take_veilid_api().await?;
|
||||
veilid_api.shutdown().await;
|
||||
APIRESULT_VOID
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn veilid_version_string() -> *mut c_char {
|
||||
veilid_core::veilid_version_string().into_ffi_value()
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct VeilidVersion {
|
||||
pub major: u32,
|
||||
pub minor: u32,
|
||||
pub patch: u32,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn veilid_version() -> VeilidVersion {
|
||||
let (major, minor, patch) = veilid_core::veilid_version();
|
||||
VeilidVersion {
|
||||
major,
|
||||
minor,
|
||||
patch,
|
||||
}
|
||||
}
|
151
veilid-flutter/rust/src/dart_isolate_wrapper.rs
Normal file
151
veilid-flutter/rust/src/dart_isolate_wrapper.rs
Normal file
@@ -0,0 +1,151 @@
|
||||
use crate::dart_serialize::*;
|
||||
pub use allo_isolate::ffi::DartCObject;
|
||||
pub use allo_isolate::IntoDart;
|
||||
use allo_isolate::Isolate;
|
||||
use core::future::Future;
|
||||
use parking_lot::Mutex;
|
||||
use serde::*;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DartIsolateWrapper {
|
||||
isolate: Isolate,
|
||||
}
|
||||
|
||||
const MESSAGE_OK: i32 = 0;
|
||||
const MESSAGE_ERR: i32 = 1;
|
||||
const MESSAGE_OK_JSON: i32 = 2;
|
||||
const MESSAGE_ERR_JSON: i32 = 3;
|
||||
const MESSAGE_STREAM_ITEM: i32 = 4;
|
||||
const MESSAGE_STREAM_ITEM_JSON: i32 = 5;
|
||||
const MESSAGE_STREAM_ABORT: i32 = 6;
|
||||
const MESSAGE_STREAM_ABORT_JSON: i32 = 7;
|
||||
const MESSAGE_STREAM_CLOSE: i32 = 8;
|
||||
|
||||
impl DartIsolateWrapper {
|
||||
pub fn new(port: i64) -> Self {
|
||||
DartIsolateWrapper {
|
||||
isolate: Isolate::new(port),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spawn_result_json<F, T, E>(self, future: F)
|
||||
where
|
||||
F: Future<Output = Result<T, E>> + Send + 'static,
|
||||
T: Serialize,
|
||||
E: Serialize,
|
||||
{
|
||||
async_std::task::spawn(async move {
|
||||
self.result_json(future.await);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn result<T: IntoDart, E: IntoDart>(&self, result: Result<T, E>) -> bool {
|
||||
match result {
|
||||
Ok(v) => self.ok(v),
|
||||
Err(e) => self.err(e),
|
||||
}
|
||||
}
|
||||
pub fn result_json<T: Serialize, E: Serialize>(&self, result: Result<T, E>) -> bool {
|
||||
match result {
|
||||
Ok(v) => self.ok_json(v),
|
||||
Err(e) => self.err_json(e),
|
||||
}
|
||||
}
|
||||
pub fn ok<T: IntoDart>(&self, value: T) -> bool {
|
||||
self.isolate
|
||||
.post(vec![MESSAGE_OK.into_dart(), value.into_dart()])
|
||||
}
|
||||
|
||||
pub fn ok_json<T: Serialize>(&self, value: T) -> bool {
|
||||
self.isolate.post(vec![
|
||||
MESSAGE_OK_JSON.into_dart(),
|
||||
serialize_json(value).into_dart(),
|
||||
])
|
||||
}
|
||||
|
||||
pub fn err<E: IntoDart>(&self, error: E) -> bool {
|
||||
self.isolate
|
||||
.post(vec![MESSAGE_ERR.into_dart(), error.into_dart()])
|
||||
}
|
||||
|
||||
pub fn err_json<E: Serialize>(&self, error: E) -> bool {
|
||||
self.isolate.post(vec![
|
||||
MESSAGE_ERR_JSON.into_dart(),
|
||||
serialize_json(error).into_dart(),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DartIsolateStream {
|
||||
isolate: Arc<Mutex<Option<Isolate>>>,
|
||||
}
|
||||
|
||||
impl DartIsolateStream {
|
||||
pub fn new(port: i64) -> Self {
|
||||
DartIsolateStream {
|
||||
isolate: Arc::new(Mutex::new(Some(Isolate::new(port)))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn item<T: IntoDart>(&self, value: T) -> bool {
|
||||
let isolate = self.isolate.lock();
|
||||
if let Some(isolate) = &*isolate {
|
||||
isolate.post(vec![MESSAGE_STREAM_ITEM.into_dart(), value.into_dart()])
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn item_json<T: Serialize>(&self, value: T) -> bool {
|
||||
let isolate = self.isolate.lock();
|
||||
if let Some(isolate) = &*isolate {
|
||||
isolate.post(vec![
|
||||
MESSAGE_STREAM_ITEM_JSON.into_dart(),
|
||||
serialize_json(value).into_dart(),
|
||||
])
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn abort<E: IntoDart>(self, error: E) -> bool {
|
||||
let mut isolate = self.isolate.lock();
|
||||
if let Some(isolate) = isolate.take() {
|
||||
isolate.post(vec![MESSAGE_STREAM_ABORT.into_dart(), error.into_dart()])
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn abort_json<E: Serialize>(self, error: E) -> bool {
|
||||
let mut isolate = self.isolate.lock();
|
||||
if let Some(isolate) = isolate.take() {
|
||||
isolate.post(vec![
|
||||
MESSAGE_STREAM_ABORT_JSON.into_dart(),
|
||||
serialize_json(error).into_dart(),
|
||||
])
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn close(self) -> bool {
|
||||
let mut isolate = self.isolate.lock();
|
||||
if let Some(isolate) = isolate.take() {
|
||||
isolate.post(vec![MESSAGE_STREAM_CLOSE.into_dart()])
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for DartIsolateStream {
|
||||
fn drop(&mut self) {
|
||||
let mut isolate = self.isolate.lock();
|
||||
if let Some(isolate) = isolate.take() {
|
||||
isolate.post(vec![MESSAGE_STREAM_CLOSE.into_dart()]);
|
||||
}
|
||||
}
|
||||
}
|
24
veilid-flutter/rust/src/dart_serialize.rs
Normal file
24
veilid-flutter/rust/src/dart_serialize.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use serde::*;
|
||||
|
||||
pub fn deserialize_json<'a, T: de::Deserialize<'a>>(
|
||||
arg: &'a str,
|
||||
) -> Result<T, veilid_core::VeilidAPIError> {
|
||||
serde_json::from_str(arg).map_err(|e| veilid_core::VeilidAPIError::ParseError {
|
||||
message: e.to_string(),
|
||||
value: String::new(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn deserialize_opt_json<T: de::DeserializeOwned>(
|
||||
arg: Option<String>,
|
||||
) -> Result<T, veilid_core::VeilidAPIError> {
|
||||
let arg = arg.ok_or_else(|| veilid_core::VeilidAPIError::ParseError {
|
||||
message: "invalid null string passed to rust".to_owned(),
|
||||
value: String::new(),
|
||||
})?;
|
||||
deserialize_json(&arg)
|
||||
}
|
||||
|
||||
pub fn serialize_json<T: Serialize>(val: T) -> String {
|
||||
serde_json::to_string(&val).expect("failed to serialize json value")
|
||||
}
|
@@ -1,5 +1,15 @@
|
||||
mod api;
|
||||
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};
|
||||
|
25
veilid-flutter/rust/src/wasm/mod.rs
Normal file
25
veilid-flutter/rust/src/wasm/mod.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
#![cfg(target_arch = "wasm32")]
|
||||
#![no_std]
|
||||
|
||||
#[macro_use]
|
||||
extern crate alloc;
|
||||
|
||||
pub use log::*;
|
||||
pub use wasm_bindgen::prelude::*;
|
||||
pub use wasm_bindgen::JsCast;
|
||||
|
||||
pub use alloc::boxed::Box;
|
||||
pub use alloc::string::String;
|
||||
pub use alloc::sync::Arc;
|
||||
pub use alloc::vec::Vec;
|
||||
pub use core::convert::TryFrom;
|
||||
pub use js_sys::*;
|
||||
pub use js_veilid_core::*;
|
||||
pub use utils::*;
|
||||
pub use veilid_core::dht::key::*;
|
||||
pub use veilid_core::xx::*;
|
||||
pub use veilid_core::*;
|
||||
pub use wasm_logger::*;
|
||||
|
||||
mod js_veilid_core;
|
||||
mod utils;
|
Reference in New Issue
Block a user