mirror of
https://gitlab.com/veilid/veilid.git
synced 2025-02-08 18:58:32 -05:00
remove veilid-wasm project, too out of date
refactor state updates and formalize a VeilidState object work on veilid-flutter api
This commit is contained in:
parent
e39835d51f
commit
1b6864bf22
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -3774,7 +3774,6 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
|||||||
name = "veilid-cli"
|
name = "veilid-cli"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
|
||||||
"async-std",
|
"async-std",
|
||||||
"async-tungstenite 0.8.0",
|
"async-tungstenite 0.8.0",
|
||||||
"bugsalot",
|
"bugsalot",
|
||||||
|
@ -6,7 +6,7 @@ members = [
|
|||||||
"veilid-cli"
|
"veilid-cli"
|
||||||
]
|
]
|
||||||
|
|
||||||
exclude = [ "./external/cursive" ]
|
exclude = [ "./external/cursive", "./veilid-flutter" ]
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
cursive = { path = "./external/cursive/cursive" }
|
cursive = { path = "./external/cursive/cursive" }
|
||||||
|
@ -31,7 +31,6 @@ cfg-if = "^1"
|
|||||||
capnp = "^0.14"
|
capnp = "^0.14"
|
||||||
capnp-rpc = "^0.14"
|
capnp-rpc = "^0.14"
|
||||||
config = { version = "0.10.1", features = ["yaml"] }
|
config = { version = "0.10.1", features = ["yaml"] }
|
||||||
anyhow = "^1"
|
|
||||||
bugsalot = "^0.2"
|
bugsalot = "^0.2"
|
||||||
flexi_logger = "0.17"
|
flexi_logger = "0.17"
|
||||||
thiserror = "^1.0"
|
thiserror = "^1.0"
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use crate::command_processor::*;
|
use crate::command_processor::*;
|
||||||
use crate::veilid_client_capnp::*;
|
use crate::veilid_client_capnp::*;
|
||||||
use anyhow::*;
|
use veilid_core::xx::*;
|
||||||
|
|
||||||
use async_std::prelude::*;
|
use async_std::prelude::*;
|
||||||
use capnp::capability::Promise;
|
use capnp::capability::Promise;
|
||||||
use capnp_rpc::{pry, rpc_twoparty_capnp, twoparty, Disconnector, RpcSystem};
|
use capnp_rpc::{pry, rpc_twoparty_capnp, twoparty, Disconnector, RpcSystem};
|
||||||
use futures::AsyncReadExt;
|
use futures::AsyncReadExt;
|
||||||
use log::*;
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@ -21,24 +21,29 @@ impl VeilidClientImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl veilid_client::Server for VeilidClientImpl {
|
impl veilid_client::Server for VeilidClientImpl {
|
||||||
fn state_changed(
|
fn update(
|
||||||
&mut self,
|
&mut self,
|
||||||
params: veilid_client::StateChangedParams,
|
params: veilid_client::UpdateParams,
|
||||||
_results: veilid_client::StateChangedResults,
|
_results: veilid_client::UpdateResults,
|
||||||
) -> Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
let changed = pry!(pry!(params.get()).get_changed());
|
let veilid_update = pry!(pry!(params.get()).get_veilid_update());
|
||||||
|
|
||||||
if changed.has_attachment() {
|
let which = match veilid_update.which() {
|
||||||
let attachment = pry!(changed.get_attachment());
|
Ok(v) => v,
|
||||||
let old_state = pry!(attachment.get_old_state());
|
Err(e) => {
|
||||||
let new_state = pry!(attachment.get_new_state());
|
panic!("(missing update kind in schema: {:?})", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
match which {
|
||||||
|
veilid_update::Attachment(Ok(attachment)) => {
|
||||||
|
let state = pry!(attachment.get_state());
|
||||||
|
|
||||||
trace!(
|
trace!("Attachment: {}", state as u16);
|
||||||
"AttachmentStateChange: old_state={} new_state={}",
|
self.comproc.update_attachment(state);
|
||||||
old_state as u16,
|
}
|
||||||
new_state as u16
|
_ => {
|
||||||
);
|
panic!("shouldn't get this")
|
||||||
self.comproc.set_attachment_state(new_state);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise::ok(())
|
Promise::ok(())
|
||||||
@ -83,13 +88,15 @@ impl ClientApiConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_connection(&mut self) -> Result<()> {
|
async fn handle_connection(&mut self) -> Result<(), String> {
|
||||||
trace!("ClientApiConnection::handle_connection");
|
trace!("ClientApiConnection::handle_connection");
|
||||||
let connect_addr = self.inner.borrow().connect_addr.unwrap();
|
let connect_addr = self.inner.borrow().connect_addr.unwrap();
|
||||||
// Connect the TCP socket
|
// Connect the TCP socket
|
||||||
let stream = async_std::net::TcpStream::connect(connect_addr).await?;
|
let stream = async_std::net::TcpStream::connect(connect_addr)
|
||||||
|
.await
|
||||||
|
.map_err(map_to_string)?;
|
||||||
// If it succeed, disable nagle algorithm
|
// If it succeed, disable nagle algorithm
|
||||||
stream.set_nodelay(true)?;
|
stream.set_nodelay(true).map_err(map_to_string)?;
|
||||||
|
|
||||||
// Create the VAT network
|
// Create the VAT network
|
||||||
let (reader, writer) = stream.split();
|
let (reader, writer) = stream.split();
|
||||||
@ -134,7 +141,10 @@ impl ClientApiConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Don't drop the registration
|
// Don't drop the registration
|
||||||
rpc_system.try_join(request.send().promise).await?;
|
rpc_system
|
||||||
|
.try_join(request.send().promise)
|
||||||
|
.await
|
||||||
|
.map_err(map_to_string)?;
|
||||||
|
|
||||||
// Drop the server and disconnector too (if we still have it)
|
// Drop the server and disconnector too (if we still have it)
|
||||||
let mut inner = self.inner.borrow_mut();
|
let mut inner = self.inner.borrow_mut();
|
||||||
@ -145,80 +155,81 @@ impl ClientApiConnection {
|
|||||||
|
|
||||||
if !disconnect_requested {
|
if !disconnect_requested {
|
||||||
// Connection lost
|
// Connection lost
|
||||||
Err(anyhow!("Connection lost"))
|
Err("Connection lost".to_owned())
|
||||||
} else {
|
} else {
|
||||||
// Connection finished
|
// Connection finished
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn server_attach(&mut self) -> Result<()> {
|
pub async fn server_attach(&mut self) -> Result<(), String> {
|
||||||
trace!("ClientApiConnection::server_attach");
|
trace!("ClientApiConnection::server_attach");
|
||||||
let server = {
|
let server = {
|
||||||
let inner = self.inner.borrow();
|
let inner = self.inner.borrow();
|
||||||
inner
|
inner
|
||||||
.server
|
.server
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or(anyhow!("Not connected, ignoring attach request"))?
|
.ok_or("Not connected, ignoring attach request".to_owned())?
|
||||||
.clone()
|
.clone()
|
||||||
};
|
};
|
||||||
let request = server.borrow().attach_request();
|
let request = server.borrow().attach_request();
|
||||||
let response = request.send().promise.await?;
|
let response = request.send().promise.await.map_err(map_to_string)?;
|
||||||
response.get().map(drop).map_err(|e| anyhow!(e))
|
response.get().map(drop).map_err(map_to_string)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn server_detach(&mut self) -> Result<()> {
|
pub async fn server_detach(&mut self) -> Result<(), String> {
|
||||||
trace!("ClientApiConnection::server_detach");
|
trace!("ClientApiConnection::server_detach");
|
||||||
let server = {
|
let server = {
|
||||||
let inner = self.inner.borrow();
|
let inner = self.inner.borrow();
|
||||||
inner
|
inner
|
||||||
.server
|
.server
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or(anyhow!("Not connected, ignoring detach request"))?
|
.ok_or("Not connected, ignoring detach request".to_owned())?
|
||||||
.clone()
|
.clone()
|
||||||
};
|
};
|
||||||
let request = server.borrow().detach_request();
|
let request = server.borrow().detach_request();
|
||||||
let response = request.send().promise.await?;
|
let response = request.send().promise.await.map_err(map_to_string)?;
|
||||||
response.get().map(drop).map_err(|e| anyhow!(e))
|
response.get().map(drop).map_err(map_to_string)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn server_shutdown(&mut self) -> Result<()> {
|
pub async fn server_shutdown(&mut self) -> Result<(), String> {
|
||||||
trace!("ClientApiConnection::server_shutdown");
|
trace!("ClientApiConnection::server_shutdown");
|
||||||
let server = {
|
let server = {
|
||||||
let inner = self.inner.borrow();
|
let inner = self.inner.borrow();
|
||||||
inner
|
inner
|
||||||
.server
|
.server
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or(anyhow!("Not connected, ignoring attach request"))?
|
.ok_or("Not connected, ignoring attach request".to_owned())?
|
||||||
.clone()
|
.clone()
|
||||||
};
|
};
|
||||||
let request = server.borrow().shutdown_request();
|
let request = server.borrow().shutdown_request();
|
||||||
let response = request.send().promise.await?;
|
let response = request.send().promise.await.map_err(map_to_string)?;
|
||||||
response.get().map(drop).map_err(|e| anyhow!(e))
|
response.get().map(drop).map_err(map_to_string)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn server_debug(&mut self, what: String) -> Result<String> {
|
pub async fn server_debug(&mut self, what: String) -> Result<String, String> {
|
||||||
trace!("ClientApiConnection::server_debug");
|
trace!("ClientApiConnection::server_debug");
|
||||||
let server = {
|
let server = {
|
||||||
let inner = self.inner.borrow();
|
let inner = self.inner.borrow();
|
||||||
inner
|
inner
|
||||||
.server
|
.server
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or(anyhow!("Not connected, ignoring attach request"))?
|
.ok_or("Not connected, ignoring attach request".to_owned())?
|
||||||
.clone()
|
.clone()
|
||||||
};
|
};
|
||||||
let mut request = server.borrow().debug_request();
|
let mut request = server.borrow().debug_request();
|
||||||
request.get().set_what(&what);
|
request.get().set_what(&what);
|
||||||
let response = request.send().promise.await?;
|
let response = request.send().promise.await.map_err(map_to_string)?;
|
||||||
response
|
response
|
||||||
.get()?
|
.get()
|
||||||
|
.map_err(map_to_string)?
|
||||||
.get_output()
|
.get_output()
|
||||||
.map(|o| o.to_owned())
|
.map(|o| o.to_owned())
|
||||||
.map_err(|e| anyhow!(e))
|
.map_err(map_to_string)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start Client API connection
|
// Start Client API connection
|
||||||
pub async fn connect(&mut self, connect_addr: SocketAddr) -> Result<()> {
|
pub async fn connect(&mut self, connect_addr: SocketAddr) -> Result<(), String> {
|
||||||
trace!("ClientApiConnection::connect");
|
trace!("ClientApiConnection::connect");
|
||||||
// Save the address to connect to
|
// Save the address to connect to
|
||||||
self.inner.borrow_mut().connect_addr = Some(connect_addr);
|
self.inner.borrow_mut().connect_addr = Some(connect_addr);
|
||||||
|
@ -273,7 +273,7 @@ debug - send a debugging command to the Veilid server
|
|||||||
// called by client_api_connection
|
// called by client_api_connection
|
||||||
// calls into ui
|
// calls into ui
|
||||||
////////////////////////////////////////////
|
////////////////////////////////////////////
|
||||||
pub fn set_attachment_state(&mut self, state: AttachmentState) {
|
pub fn update_attachment(&mut self, state: AttachmentState) {
|
||||||
self.inner_mut().ui.set_attachment_state(state);
|
self.inner_mut().ui.set_attachment_state(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
#![deny(clippy::all)]
|
#![deny(clippy::all)]
|
||||||
#![deny(unused_must_use)]
|
#![deny(unused_must_use)]
|
||||||
|
|
||||||
use anyhow::*;
|
use veilid_core::xx::*;
|
||||||
|
|
||||||
use async_std::prelude::*;
|
use async_std::prelude::*;
|
||||||
use clap::{App, Arg, ColorChoice};
|
use clap::{App, Arg, ColorChoice};
|
||||||
use flexi_logger::*;
|
use flexi_logger::*;
|
||||||
use log::*;
|
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::net::ToSocketAddrs;
|
use std::net::ToSocketAddrs;
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ pub mod veilid_client_capnp {
|
|||||||
include!(concat!(env!("OUT_DIR"), "/proto/veilid_client_capnp.rs"));
|
include!(concat!(env!("OUT_DIR"), "/proto/veilid_client_capnp.rs"));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_command_line(default_config_path: &OsStr) -> Result<clap::ArgMatches, anyhow::Error> {
|
fn parse_command_line(default_config_path: &OsStr) -> Result<clap::ArgMatches, String> {
|
||||||
let matches = App::new("veilid-cli")
|
let matches = App::new("veilid-cli")
|
||||||
.version("0.1")
|
.version("0.1")
|
||||||
.color(ColorChoice::Auto)
|
.color(ColorChoice::Auto)
|
||||||
@ -59,7 +59,7 @@ fn parse_command_line(default_config_path: &OsStr) -> Result<clap::ArgMatches, a
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_std::main]
|
#[async_std::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<(), String> {
|
||||||
// Get command line options
|
// Get command line options
|
||||||
let default_config_path = settings::Settings::get_default_config_path();
|
let default_config_path = settings::Settings::get_default_config_path();
|
||||||
let matches = parse_command_line(default_config_path.as_os_str())?;
|
let matches = parse_command_line(default_config_path.as_os_str())?;
|
||||||
@ -73,7 +73,7 @@ async fn main() -> Result<()> {
|
|||||||
matches.occurrences_of("config-file") == 0,
|
matches.occurrences_of("config-file") == 0,
|
||||||
matches.value_of_os("config-file").unwrap(),
|
matches.value_of_os("config-file").unwrap(),
|
||||||
)
|
)
|
||||||
.map_err(Box::new)?;
|
.map_err(map_to_string)?;
|
||||||
|
|
||||||
// Set config from command line
|
// Set config from command line
|
||||||
if matches.occurrences_of("debug") != 0 {
|
if matches.occurrences_of("debug") != 0 {
|
||||||
@ -104,7 +104,8 @@ async fn main() -> Result<()> {
|
|||||||
if settings.logging.terminal.enabled {
|
if settings.logging.terminal.enabled {
|
||||||
let flv = sivui.cursive_flexi_logger();
|
let flv = sivui.cursive_flexi_logger();
|
||||||
if settings.logging.file.enabled {
|
if settings.logging.file.enabled {
|
||||||
std::fs::create_dir_all(settings.logging.file.directory.clone())?;
|
std::fs::create_dir_all(settings.logging.file.directory.clone())
|
||||||
|
.map_err(map_to_string)?;
|
||||||
logger
|
logger
|
||||||
.log_target(LogTarget::FileAndWriter(flv))
|
.log_target(LogTarget::FileAndWriter(flv))
|
||||||
.suppress_timestamp()
|
.suppress_timestamp()
|
||||||
@ -121,7 +122,8 @@ async fn main() -> Result<()> {
|
|||||||
.expect("failed to initialize logger!");
|
.expect("failed to initialize logger!");
|
||||||
}
|
}
|
||||||
} else if settings.logging.file.enabled {
|
} else if settings.logging.file.enabled {
|
||||||
std::fs::create_dir_all(settings.logging.file.directory.clone())?;
|
std::fs::create_dir_all(settings.logging.file.directory.clone())
|
||||||
|
.map_err(map_to_string)?;
|
||||||
logger
|
logger
|
||||||
.log_target(LogTarget::File)
|
.log_target(LogTarget::File)
|
||||||
.suppress_timestamp()
|
.suppress_timestamp()
|
||||||
@ -135,7 +137,7 @@ async fn main() -> Result<()> {
|
|||||||
if let Some(address_arg) = matches.value_of("address") {
|
if let Some(address_arg) = matches.value_of("address") {
|
||||||
server_addrs = address_arg
|
server_addrs = address_arg
|
||||||
.to_socket_addrs()
|
.to_socket_addrs()
|
||||||
.context(format!("Invalid server address '{}'", address_arg))?
|
.map_err(|e| format!("Invalid server address '{}'", e))?
|
||||||
.collect()
|
.collect()
|
||||||
} else {
|
} else {
|
||||||
server_addrs = settings.address.addrs.clone();
|
server_addrs = settings.address.addrs.clone();
|
||||||
|
@ -367,7 +367,9 @@ impl AttachmentManager {
|
|||||||
attachment_machine.state()
|
attachment_machine.state()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn wait_for_state(&self, state: AttachmentState) {
|
pub async fn wait_for_state(&self, state: AttachmentState, timeout_ms: Option<u32>) -> bool {
|
||||||
|
let start_time = intf::get_timestamp();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (current_state, eventual) = self
|
let (current_state, eventual) = self
|
||||||
.inner
|
.inner
|
||||||
@ -377,9 +379,28 @@ impl AttachmentManager {
|
|||||||
if current_state == state {
|
if current_state == state {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if let Some(timeout_ms) = timeout_ms {
|
||||||
|
let timeout_time = start_time + (timeout_ms as u64 * 1000);
|
||||||
|
let cur_time = intf::get_timestamp();
|
||||||
|
if timeout_time > cur_time {
|
||||||
|
let timeout_dur_ms = ((timeout_time - cur_time) / 1000) as u32;
|
||||||
|
|
||||||
|
if match intf::timeout(timeout_dur_ms, eventual).await {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(_) => return false,
|
||||||
|
} == state
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if eventual.await == state {
|
if eventual.await == state {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ pub mod xx;
|
|||||||
pub use self::attachment_manager::AttachmentState;
|
pub use self::attachment_manager::AttachmentState;
|
||||||
pub use self::veilid_api::*;
|
pub use self::veilid_api::*;
|
||||||
pub use self::veilid_config::*;
|
pub use self::veilid_config::*;
|
||||||
pub use self::veilid_core::{VeilidCore, VeilidCoreSetup, VeilidState, VeilidStateChange};
|
pub use self::veilid_core::{VeilidCore, VeilidCoreSetup};
|
||||||
|
|
||||||
pub mod veilid_capnp {
|
pub mod veilid_capnp {
|
||||||
include!(concat!(env!("OUT_DIR"), "/proto/veilid_capnp.rs"));
|
include!(concat!(env!("OUT_DIR"), "/proto/veilid_capnp.rs"));
|
||||||
|
@ -8,10 +8,10 @@ static LOREM_IPSUM:&[u8] = b"Lorem ipsum dolor sit amet, consectetur adipiscing
|
|||||||
|
|
||||||
fn setup_veilid_core() -> VeilidCoreSetup {
|
fn setup_veilid_core() -> VeilidCoreSetup {
|
||||||
VeilidCoreSetup {
|
VeilidCoreSetup {
|
||||||
state_change_callback: Arc::new(
|
update_callback: Arc::new(
|
||||||
move |change: VeilidStateChange| -> SystemPinBoxFuture<()> {
|
move |veilid_update: VeilidUpdate| -> SystemPinBoxFuture<()> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
trace!("state_change_callback: {:?}", change);
|
trace!("update_callback: {:?}", veilid_update);
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -5,10 +5,10 @@ use crate::*;
|
|||||||
|
|
||||||
fn setup_veilid_core() -> VeilidCoreSetup {
|
fn setup_veilid_core() -> VeilidCoreSetup {
|
||||||
VeilidCoreSetup {
|
VeilidCoreSetup {
|
||||||
state_change_callback: Arc::new(
|
update_callback: Arc::new(
|
||||||
move |change: VeilidStateChange| -> SystemPinBoxFuture<()> {
|
move |veilid_update: VeilidUpdate| -> SystemPinBoxFuture<()> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
trace!("state_change_callback: {:?}", change);
|
trace!("update_callback: {:?}", veilid_update);
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -6,10 +6,10 @@ use crate::*;
|
|||||||
|
|
||||||
fn setup_veilid_core() -> VeilidCoreSetup {
|
fn setup_veilid_core() -> VeilidCoreSetup {
|
||||||
VeilidCoreSetup {
|
VeilidCoreSetup {
|
||||||
state_change_callback: Arc::new(
|
update_callback: Arc::new(
|
||||||
move |change: VeilidStateChange| -> SystemPinBoxFuture<()> {
|
move |veilid_update: VeilidUpdate| -> SystemPinBoxFuture<()> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
trace!("state_change_callback: {:?}", change);
|
trace!("update_callback: {:?}", veilid_update);
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -145,10 +145,10 @@ cfg_if! {
|
|||||||
|
|
||||||
pub fn setup_veilid_core() -> VeilidCoreSetup {
|
pub fn setup_veilid_core() -> VeilidCoreSetup {
|
||||||
VeilidCoreSetup {
|
VeilidCoreSetup {
|
||||||
state_change_callback: Arc::new(
|
update_callback: Arc::new(
|
||||||
move |change: VeilidStateChange| -> SystemPinBoxFuture<()> {
|
move |veilid_update: VeilidUpdate| -> SystemPinBoxFuture<()> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
trace!("state_change_callback: {:?}", change);
|
trace!("update_callback: {:?}", veilid_update);
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -25,7 +25,7 @@ pub async fn test_attach_detach() {
|
|||||||
api.attach().await.unwrap();
|
api.attach().await.unwrap();
|
||||||
intf::sleep(5000).await;
|
intf::sleep(5000).await;
|
||||||
api.detach().await.unwrap();
|
api.detach().await.unwrap();
|
||||||
api.wait_for_state(VeilidState::Attachment(AttachmentState::Detached))
|
api.wait_for_update(VeilidUpdate::Attachment(AttachmentState::Detached), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
api.shutdown().await;
|
api.shutdown().await;
|
||||||
|
@ -5,7 +5,7 @@ pub use debug::*;
|
|||||||
|
|
||||||
pub use crate::rpc_processor::InfoAnswer;
|
pub use crate::rpc_processor::InfoAnswer;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use attachment_manager::AttachmentManager;
|
use attachment_manager::*;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use network_manager::NetworkManager;
|
use network_manager::NetworkManager;
|
||||||
use routing_table::*;
|
use routing_table::*;
|
||||||
@ -106,6 +106,18 @@ macro_rules! parse_error {
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum VeilidUpdate {
|
||||||
|
Attachment(AttachmentState),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct VeilidState {
|
||||||
|
pub attachment: AttachmentState,
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
#[derive(Clone, Debug, Default, PartialOrd, PartialEq, Eq, Ord)]
|
#[derive(Clone, Debug, Default, PartialOrd, PartialEq, Eq, Ord)]
|
||||||
pub struct NodeId {
|
pub struct NodeId {
|
||||||
pub key: DHTKey,
|
pub key: DHTKey,
|
||||||
@ -1100,12 +1112,13 @@ impl VeilidAPI {
|
|||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
// Attach/Detach
|
// Attach/Detach
|
||||||
|
|
||||||
// issue state changed updates for updating clients
|
// get a full copy of the current state
|
||||||
pub async fn send_state_update(&self) -> Result<(), VeilidAPIError> {
|
pub async fn get_state(&self) -> Result<VeilidState, VeilidAPIError> {
|
||||||
trace!("VeilidCore::send_state_update");
|
trace!("VeilidCore::get_state");
|
||||||
let attachment_manager = self.attachment_manager()?;
|
let attachment_manager = self.attachment_manager()?;
|
||||||
attachment_manager.send_state_update().await;
|
Ok(VeilidState {
|
||||||
Ok(())
|
attachment: attachment_manager.get_state(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// connect to the network
|
// connect to the network
|
||||||
@ -1124,12 +1137,17 @@ impl VeilidAPI {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for state change
|
// wait for a matching update
|
||||||
// xxx: should have optional timeout
|
pub async fn wait_for_update(
|
||||||
pub async fn wait_for_state(&self, state: VeilidState) -> Result<(), VeilidAPIError> {
|
&self,
|
||||||
match state {
|
update: VeilidUpdate,
|
||||||
VeilidState::Attachment(cs) => {
|
timeout_ms: Option<u32>,
|
||||||
self.attachment_manager()?.wait_for_state(cs).await;
|
) -> Result<(), VeilidAPIError> {
|
||||||
|
match update {
|
||||||
|
VeilidUpdate::Attachment(cs) => {
|
||||||
|
self.attachment_manager()?
|
||||||
|
.wait_for_state(cs, timeout_ms)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -7,27 +7,14 @@ use crate::xx::*;
|
|||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(target_arch = "wasm32")] {
|
if #[cfg(target_arch = "wasm32")] {
|
||||||
pub type StateChangeCallback = Arc<dyn Fn(VeilidStateChange) -> SystemPinBoxFuture<()>>;
|
pub type UpdateCallback = Arc<dyn Fn(VeilidUpdate) -> SystemPinBoxFuture<()>>;
|
||||||
} else {
|
} else {
|
||||||
pub type StateChangeCallback = Arc<dyn Fn(VeilidStateChange) -> SystemPinBoxFuture<()> + Send + Sync>;
|
pub type UpdateCallback = Arc<dyn Fn(VeilidUpdate) -> SystemPinBoxFuture<()> + Send + Sync>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum VeilidStateChange {
|
|
||||||
Attachment {
|
|
||||||
old_state: AttachmentState,
|
|
||||||
new_state: AttachmentState,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum VeilidState {
|
|
||||||
Attachment(AttachmentState),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct VeilidCoreSetup {
|
pub struct VeilidCoreSetup {
|
||||||
pub state_change_callback: StateChangeCallback,
|
pub update_callback: UpdateCallback,
|
||||||
pub config_callback: ConfigCallback,
|
pub config_callback: ConfigCallback,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,16 +126,13 @@ impl VeilidCore {
|
|||||||
|
|
||||||
// Set up attachment manager
|
// Set up attachment manager
|
||||||
trace!("VeilidCore::internal_startup init attachment manager");
|
trace!("VeilidCore::internal_startup init attachment manager");
|
||||||
let cb = setup.state_change_callback;
|
let cb = setup.update_callback;
|
||||||
let attachment_manager =
|
let attachment_manager =
|
||||||
AttachmentManager::new(config.clone(), table_store.clone(), crypto.clone());
|
AttachmentManager::new(config.clone(), table_store.clone(), crypto.clone());
|
||||||
attachment_manager
|
attachment_manager
|
||||||
.init(Arc::new(
|
.init(Arc::new(
|
||||||
move |old_state: AttachmentState, new_state: AttachmentState| {
|
move |_old_state: AttachmentState, new_state: AttachmentState| {
|
||||||
cb(VeilidStateChange::Attachment {
|
cb(VeilidUpdate::Attachment(new_state))
|
||||||
old_state,
|
|
||||||
new_state,
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -13,6 +13,7 @@ dependencies:
|
|||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_web_plugins:
|
flutter_web_plugins:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
flutter_rust_bridge: ^1.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
64
veilid-flutter/rust/.gitignore
vendored
Normal file
64
veilid-flutter/rust/.gitignore
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
##############################################################################
|
||||||
|
### MacOS
|
||||||
|
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
# Windows thumbnail cache files
|
||||||
|
Thumbs.db
|
||||||
|
Thumbs.db:encryptable
|
||||||
|
ehthumbs.db
|
||||||
|
ehthumbs_vista.db
|
||||||
|
|
||||||
|
# Dump file
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
[Dd]esktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
### Rust
|
||||||
|
target/
|
||||||
|
logs/
|
||||||
|
|
12
veilid-flutter/rust/Cargo.toml
Normal file
12
veilid-flutter/rust/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "veilid-flutter"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
veilid-core = { path="../../veilid-core" }
|
||||||
|
flutter_rust_bridge = "^1"
|
||||||
|
|
204
veilid-flutter/rust/src/api.rs
Normal file
204
veilid-flutter/rust/src/api.rs
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
use flutter_rust_bridge::*;
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
// Config Settings
|
||||||
|
// Not all settings available through Veilid API are available to Flutter applications
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
pub struct VeilidConfigUDP {
|
||||||
|
pub enabled: bool,
|
||||||
|
pub socket_pool_size: u32,
|
||||||
|
pub listen_address: String,
|
||||||
|
pub public_address: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
pub struct VeilidConfigTCP {
|
||||||
|
pub connect: bool,
|
||||||
|
pub listen: bool,
|
||||||
|
pub max_connections: u32,
|
||||||
|
pub listen_address: String,
|
||||||
|
pub public_address: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
pub struct VeilidConfigWS {
|
||||||
|
pub connect: bool,
|
||||||
|
pub listen: bool,
|
||||||
|
pub max_connections: u32,
|
||||||
|
pub listen_address: String,
|
||||||
|
pub path: String,
|
||||||
|
pub url: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
pub struct VeilidConfigWSS {
|
||||||
|
pub connect: bool,
|
||||||
|
pub max_connections: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
pub struct VeilidConfigProtocol {
|
||||||
|
pub udp: VeilidConfigUDP,
|
||||||
|
pub tcp: VeilidConfigTCP,
|
||||||
|
pub ws: VeilidConfigWS,
|
||||||
|
pub wss: VeilidConfigWSS,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
pub struct VeilidConfigDHT {
|
||||||
|
pub resolve_node_timeout: Option<u64>,
|
||||||
|
pub resolve_node_count: u32,
|
||||||
|
pub resolve_node_fanout: u32,
|
||||||
|
pub max_find_node_count: u32,
|
||||||
|
pub get_value_timeout: Option<u64>,
|
||||||
|
pub get_value_count: u32,
|
||||||
|
pub get_value_fanout: u32,
|
||||||
|
pub set_value_timeout: Option<u64>,
|
||||||
|
pub set_value_count: u32,
|
||||||
|
pub set_value_fanout: u32,
|
||||||
|
pub min_peer_count: u32,
|
||||||
|
pub min_peer_refresh_time: u64,
|
||||||
|
pub validate_dial_info_receipt_time: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
pub struct VeilidConfigRPC {
|
||||||
|
pub concurrency: u32,
|
||||||
|
pub queue_size: u32,
|
||||||
|
pub max_timestamp_behind: Option<u64>,
|
||||||
|
pub max_timestamp_ahead: Option<u64>,
|
||||||
|
pub timeout: u64,
|
||||||
|
pub max_route_hop_count: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
pub struct VeilidConfigLeases {
|
||||||
|
pub max_server_signal_leases: u32,
|
||||||
|
pub max_server_relay_leases: u32,
|
||||||
|
pub max_client_signal_leases: u32,
|
||||||
|
pub max_client_relay_leases: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
pub struct VeilidConfigNetwork {
|
||||||
|
pub max_connections: u32,
|
||||||
|
pub connection_initial_timeout: u64,
|
||||||
|
pub node_id: key::DHTKey,
|
||||||
|
pub node_id_secret: key::DHTKeySecret,
|
||||||
|
pub bootstrap: Vec<String>,
|
||||||
|
pub rpc: VeilidConfigRPC,
|
||||||
|
pub dht: VeilidConfigDHT,
|
||||||
|
pub upnp: bool,
|
||||||
|
pub natpmp: bool,
|
||||||
|
pub enable_local_peer_scope: bool,
|
||||||
|
pub restricted_nat_retries: u32,
|
||||||
|
pub tls: VeilidConfigTLS,
|
||||||
|
pub protocol: VeilidConfigProtocol,
|
||||||
|
pub leases: VeilidConfigLeases,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone)]
|
||||||
|
pub struct VeilidConfigTableStore {
|
||||||
|
pub directory: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone)]
|
||||||
|
pub struct VeilidConfigProtectedStore {
|
||||||
|
pub allow_insecure_fallback: bool,
|
||||||
|
pub always_use_insecure_storage: bool,
|
||||||
|
pub insecure_fallback_directory: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone)]
|
||||||
|
pub struct VeilidConfigCapabilities {
|
||||||
|
pub protocol_udp: bool,
|
||||||
|
pub protocol_connect_tcp: bool,
|
||||||
|
pub protocol_accept_tcp: bool,
|
||||||
|
pub protocol_connect_ws: bool,
|
||||||
|
pub protocol_accept_ws: bool,
|
||||||
|
pub protocol_connect_wss: bool,
|
||||||
|
pub protocol_accept_wss: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone)]
|
||||||
|
pub struct VeilidConfig {
|
||||||
|
pub program_name: String,
|
||||||
|
pub namespace: String,
|
||||||
|
pub capabilities: VeilidConfigCapabilities,
|
||||||
|
pub protected_store: VeilidConfigProtectedStore,
|
||||||
|
pub table_store: VeilidConfigTableStore,
|
||||||
|
pub network: VeilidConfigNetwork,
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum APIErrorKind {
|
||||||
|
AlreadyInitialized,
|
||||||
|
NotInitialized,
|
||||||
|
InvalidConfig,
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct VeilidAPIError {
|
||||||
|
kind: APIErrorKind,
|
||||||
|
message: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum AttachmentState {
|
||||||
|
Detached,
|
||||||
|
Attaching,
|
||||||
|
AttachedWeak,
|
||||||
|
AttachedGood,
|
||||||
|
AttachedStrong,
|
||||||
|
FullyAttached,
|
||||||
|
OverAttached,
|
||||||
|
Detaching,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum VeilidUpdate {
|
||||||
|
Attachment (AttachmentState),
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
///
|
||||||
|
pub fn startup_veilid_core(sink: StreamSink<VeilidUpdate>, config: VeilidConfig) -> Result<(), VeilidAPIError> {
|
||||||
|
let core = veilid_core::VeilidCore::new();
|
||||||
|
|
||||||
|
core.
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_veilid_state() -> Result<VeilidState, VeilidAPIError> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// xxx api functions
|
||||||
|
|
||||||
|
pub fn shutdown_veilid_core() -> Result<(), VeilidAPIError> {
|
||||||
|
|
||||||
|
}
|
2
veilid-flutter/rust/src/lib.rs
Normal file
2
veilid-flutter/rust/src/lib.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
mod api;
|
||||||
|
mod bridge_generated;
|
@ -11,21 +11,19 @@ enum AttachmentState {
|
|||||||
detaching @7;
|
detaching @7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Attachment {
|
||||||
|
state @0 :AttachmentState;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VeilidUpdate {
|
||||||
|
union {
|
||||||
|
attachment @0 :Attachment;
|
||||||
|
dummy @1 :Void;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct VeilidState {
|
struct VeilidState {
|
||||||
# union {
|
attachment @0 :Attachment;
|
||||||
attachment @0 :AttachmentState;
|
|
||||||
# }
|
|
||||||
}
|
|
||||||
|
|
||||||
struct AttachmentStateChange {
|
|
||||||
oldState @0 :AttachmentState;
|
|
||||||
newState @1 :AttachmentState;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct VeilidStateChange {
|
|
||||||
# union {
|
|
||||||
attachment @0 :AttachmentStateChange;
|
|
||||||
# }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Registration {}
|
interface Registration {}
|
||||||
@ -33,18 +31,17 @@ interface Registration {}
|
|||||||
interface VeilidServer {
|
interface VeilidServer {
|
||||||
|
|
||||||
register @0 (veilidClient: VeilidClient) -> (registration: Registration);
|
register @0 (veilidClient: VeilidClient) -> (registration: Registration);
|
||||||
|
debug @1 (what: Text) -> (output: Text);
|
||||||
|
|
||||||
attach @1 ();
|
attach @2 ();
|
||||||
detach @2 ();
|
detach @3 ();
|
||||||
shutdown @3 ();
|
shutdown @4 ();
|
||||||
|
getState @5 () -> (state: VeilidState);
|
||||||
debug @4 (what: Text) -> (output: Text);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface VeilidClient {
|
interface VeilidClient {
|
||||||
|
|
||||||
stateChanged @0 (changed: VeilidStateChange);
|
update @0 (veilidUpdate: VeilidUpdate);
|
||||||
logMessage @1 (message: Text);
|
logMessage @1 (message: Text);
|
||||||
|
|
||||||
}
|
}
|
@ -17,6 +17,40 @@ use veilid_core::xx::Eventual;
|
|||||||
#[fail(display = "Client API error: {}", _0)]
|
#[fail(display = "Client API error: {}", _0)]
|
||||||
pub struct ClientAPIError(String);
|
pub struct ClientAPIError(String);
|
||||||
|
|
||||||
|
fn convert_attachment_state(state: &veilid_core::AttachmentState) -> AttachmentState {
|
||||||
|
match 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_update(
|
||||||
|
update: &veilid_core::VeilidUpdate,
|
||||||
|
rpc_update: crate::veilid_client_capnp::veilid_update::Builder,
|
||||||
|
) {
|
||||||
|
match update {
|
||||||
|
veilid_core::VeilidUpdate::Attachment(state) => {
|
||||||
|
let mut att = rpc_update.init_attachment();
|
||||||
|
att.set_state(convert_attachment_state(state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_state(
|
||||||
|
state: &veilid_core::VeilidState,
|
||||||
|
rpc_state: crate::veilid_client_capnp::veilid_state::Builder,
|
||||||
|
) {
|
||||||
|
rpc_state
|
||||||
|
.init_attachment()
|
||||||
|
.set_state(convert_attachment_state(&state.attachment));
|
||||||
|
}
|
||||||
|
|
||||||
// --- interface Registration ---------------------------------
|
// --- interface Registration ---------------------------------
|
||||||
|
|
||||||
struct RegistrationHandle {
|
struct RegistrationHandle {
|
||||||
@ -104,13 +138,25 @@ impl veilid_server::Server for VeilidServerImpl {
|
|||||||
|
|
||||||
self.next_id += 1;
|
self.next_id += 1;
|
||||||
|
|
||||||
// Send state update
|
Promise::ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn debug(
|
||||||
|
&mut self,
|
||||||
|
params: veilid_server::DebugParams,
|
||||||
|
mut results: veilid_server::DebugResults,
|
||||||
|
) -> Promise<(), ::capnp::Error> {
|
||||||
|
trace!("VeilidServerImpl::debug");
|
||||||
let veilid_api = self.veilid_api.clone();
|
let veilid_api = self.veilid_api.clone();
|
||||||
|
let what = pry!(pry!(params.get()).get_what()).to_owned();
|
||||||
|
|
||||||
Promise::from_future(async move {
|
Promise::from_future(async move {
|
||||||
veilid_api
|
let output = veilid_api
|
||||||
.send_state_update()
|
.debug(what)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ::capnp::Error::failed(format!("{:?}", e)))
|
.map_err(|e| ::capnp::Error::failed(format!("{:?}", e)))?;
|
||||||
|
results.get().set_output(output.as_str());
|
||||||
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +174,7 @@ impl veilid_server::Server for VeilidServerImpl {
|
|||||||
.map_err(|e| ::capnp::Error::failed(format!("{:?}", e)))
|
.map_err(|e| ::capnp::Error::failed(format!("{:?}", e)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detach(
|
fn detach(
|
||||||
&mut self,
|
&mut self,
|
||||||
_params: veilid_server::DetachParams,
|
_params: veilid_server::DetachParams,
|
||||||
@ -142,6 +189,7 @@ impl veilid_server::Server for VeilidServerImpl {
|
|||||||
.map_err(|e| ::capnp::Error::failed(format!("{:?}", e)))
|
.map_err(|e| ::capnp::Error::failed(format!("{:?}", e)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shutdown(
|
fn shutdown(
|
||||||
&mut self,
|
&mut self,
|
||||||
_params: veilid_server::ShutdownParams,
|
_params: veilid_server::ShutdownParams,
|
||||||
@ -161,21 +209,21 @@ impl veilid_server::Server for VeilidServerImpl {
|
|||||||
Promise::ok(())
|
Promise::ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn debug(
|
fn get_state(
|
||||||
&mut self,
|
&mut self,
|
||||||
params: veilid_server::DebugParams,
|
_params: veilid_server::GetStateParams,
|
||||||
mut results: veilid_server::DebugResults,
|
mut results: veilid_server::GetStateResults,
|
||||||
) -> Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
trace!("VeilidServerImpl::debug");
|
trace!("VeilidServerImpl::get_state");
|
||||||
let veilid_api = self.veilid_api.clone();
|
let veilid_api = self.veilid_api.clone();
|
||||||
let what = pry!(pry!(params.get()).get_what()).to_owned();
|
|
||||||
|
|
||||||
Promise::from_future(async move {
|
Promise::from_future(async move {
|
||||||
let output = veilid_api
|
let state = veilid_api
|
||||||
.debug(what)
|
.get_state()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ::capnp::Error::failed(format!("{:?}", e)))?;
|
.map_err(|e| ::capnp::Error::failed(format!("{:?}", e)))?;
|
||||||
results.get().set_output(output.as_str());
|
|
||||||
|
let rpc_state = results.get().init_state();
|
||||||
|
convert_state(&state, rpc_state);
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -260,35 +308,6 @@ impl ClientApi {
|
|||||||
incoming_loop.await
|
incoming_loop.await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_attachment_state(state: &veilid_core::AttachmentState) -> AttachmentState {
|
|
||||||
match 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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn convert_state_changed(
|
|
||||||
changed: &veilid_core::VeilidStateChange,
|
|
||||||
rpc_changed: crate::veilid_client_capnp::veilid_state_change::Builder,
|
|
||||||
) {
|
|
||||||
match changed {
|
|
||||||
veilid_core::VeilidStateChange::Attachment {
|
|
||||||
old_state,
|
|
||||||
new_state,
|
|
||||||
} => {
|
|
||||||
let mut att = rpc_changed.init_attachment();
|
|
||||||
att.set_old_state(ClientApi::convert_attachment_state(old_state));
|
|
||||||
att.set_new_state(ClientApi::convert_attachment_state(new_state));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_request_to_all_clients<F, T>(self: Rc<Self>, request: F)
|
fn send_request_to_all_clients<F, T>(self: Rc<Self>, request: F)
|
||||||
where
|
where
|
||||||
F: Fn(u64, &mut RegistrationHandle) -> ::capnp::capability::RemotePromise<T>,
|
F: Fn(u64, &mut RegistrationHandle) -> ::capnp::capability::RemotePromise<T>,
|
||||||
@ -326,11 +345,11 @@ impl ClientApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_state_change(self: Rc<Self>, changed: veilid_core::VeilidStateChange) {
|
pub fn handle_update(self: Rc<Self>, veilid_update: veilid_core::VeilidUpdate) {
|
||||||
self.send_request_to_all_clients(|_id, registration| {
|
self.send_request_to_all_clients(|_id, registration| {
|
||||||
let mut request = registration.client.state_changed_request();
|
let mut request = registration.client.update_request();
|
||||||
let rpc_changed = request.get().init_changed();
|
let rpc_veilid_update = request.get().init_veilid_update();
|
||||||
ClientApi::convert_state_changed(&changed, rpc_changed);
|
convert_update(&veilid_update, rpc_veilid_update);
|
||||||
request.send()
|
request.send()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -29,18 +29,18 @@ pub async fn run_veilid_server(settings: Settings, logs: VeilidLogs) -> Result<(
|
|||||||
|
|
||||||
// Create client api state change pipe
|
// Create client api state change pipe
|
||||||
let (sender, receiver): (
|
let (sender, receiver): (
|
||||||
Sender<veilid_core::VeilidStateChange>,
|
Sender<veilid_core::VeilidUpdate>,
|
||||||
Receiver<veilid_core::VeilidStateChange>,
|
Receiver<veilid_core::VeilidUpdate>,
|
||||||
) = bounded(1);
|
) = bounded(1);
|
||||||
|
|
||||||
// Create VeilidCore setup
|
// Create VeilidCore setup
|
||||||
let vcs = veilid_core::VeilidCoreSetup {
|
let vcs = veilid_core::VeilidCoreSetup {
|
||||||
state_change_callback: Arc::new(
|
update_callback: Arc::new(
|
||||||
move |change: veilid_core::VeilidStateChange| -> veilid_core::SystemPinBoxFuture<()> {
|
move |change: veilid_core::VeilidUpdate| -> veilid_core::SystemPinBoxFuture<()> {
|
||||||
let sender = sender.clone();
|
let sender = sender.clone();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
if sender.send(change).await.is_err() {
|
if sender.send(change).await.is_err() {
|
||||||
error!("error sending state change callback");
|
error!("error sending veilid update callback");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@ -70,10 +70,10 @@ pub async fn run_veilid_server(settings: Settings, logs: VeilidLogs) -> Result<(
|
|||||||
drop(settingsr);
|
drop(settingsr);
|
||||||
|
|
||||||
// Handle state changes on main thread for capnproto rpc
|
// Handle state changes on main thread for capnproto rpc
|
||||||
let state_change_receiver_jh = capi.clone().map(|capi| {
|
let update_receiver_jh = capi.clone().map(|capi| {
|
||||||
async_std::task::spawn_local(async move {
|
async_std::task::spawn_local(async move {
|
||||||
while let Ok(change) = receiver.recv().await {
|
while let Ok(change) = receiver.recv().await {
|
||||||
capi.clone().handle_state_change(change);
|
capi.clone().handle_update(change);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
@ -147,9 +147,9 @@ pub async fn run_veilid_server(settings: Settings, logs: VeilidLogs) -> Result<(
|
|||||||
client_log_channel_closer.close();
|
client_log_channel_closer.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for state change receiver to exit
|
// Wait for update receiver to exit
|
||||||
if let Some(state_change_receiver_jh) = state_change_receiver_jh {
|
if let Some(update_receiver_jh) = update_receiver_jh {
|
||||||
state_change_receiver_jh.await;
|
update_receiver_jh.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for client api log receiver to exit
|
// Wait for client api log receiver to exit
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
install:
|
|
||||||
- appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
|
|
||||||
- if not defined RUSTFLAGS rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain nightly
|
|
||||||
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
|
|
||||||
- rustc -V
|
|
||||||
- cargo -V
|
|
||||||
|
|
||||||
build: false
|
|
||||||
|
|
||||||
test_script:
|
|
||||||
- cargo test --locked
|
|
5
veilid-wasm/.gitignore
vendored
5
veilid-wasm/.gitignore
vendored
@ -1,5 +0,0 @@
|
|||||||
/target
|
|
||||||
**/*.rs.bk
|
|
||||||
bin/
|
|
||||||
pkg/
|
|
||||||
wasm-pack.log
|
|
@ -1,69 +0,0 @@
|
|||||||
language: rust
|
|
||||||
sudo: false
|
|
||||||
|
|
||||||
cache: cargo
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
|
|
||||||
# Builds with wasm-pack.
|
|
||||||
- rust: beta
|
|
||||||
env: RUST_BACKTRACE=1
|
|
||||||
addons:
|
|
||||||
firefox: latest
|
|
||||||
chrome: stable
|
|
||||||
before_script:
|
|
||||||
- (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update)
|
|
||||||
- (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate)
|
|
||||||
- cargo install-update -a
|
|
||||||
- curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f
|
|
||||||
script:
|
|
||||||
- cargo generate --git . --name testing
|
|
||||||
# Having a broken Cargo.toml (in that it has curlies in fields) anywhere
|
|
||||||
# in any of our parent dirs is problematic.
|
|
||||||
- mv Cargo.toml Cargo.toml.tmpl
|
|
||||||
- cd testing
|
|
||||||
- wasm-pack build
|
|
||||||
- wasm-pack test --chrome --firefox --headless
|
|
||||||
|
|
||||||
# Builds on nightly.
|
|
||||||
- rust: nightly
|
|
||||||
env: RUST_BACKTRACE=1
|
|
||||||
before_script:
|
|
||||||
- (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update)
|
|
||||||
- (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate)
|
|
||||||
- cargo install-update -a
|
|
||||||
- rustup target add wasm32-unknown-unknown
|
|
||||||
script:
|
|
||||||
- cargo generate --git . --name testing
|
|
||||||
- mv Cargo.toml Cargo.toml.tmpl
|
|
||||||
- cd testing
|
|
||||||
- cargo check
|
|
||||||
- cargo check --target wasm32-unknown-unknown
|
|
||||||
- cargo check --no-default-features
|
|
||||||
- cargo check --target wasm32-unknown-unknown --no-default-features
|
|
||||||
- cargo check --no-default-features --features console_error_panic_hook
|
|
||||||
- cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook
|
|
||||||
- cargo check --no-default-features --features "console_error_panic_hook wee_alloc"
|
|
||||||
- cargo check --target wasm32-unknown-unknown --no-default-features --features "console_error_panic_hook wee_alloc"
|
|
||||||
|
|
||||||
# Builds on beta.
|
|
||||||
- rust: beta
|
|
||||||
env: RUST_BACKTRACE=1
|
|
||||||
before_script:
|
|
||||||
- (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update)
|
|
||||||
- (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate)
|
|
||||||
- cargo install-update -a
|
|
||||||
- rustup target add wasm32-unknown-unknown
|
|
||||||
script:
|
|
||||||
- cargo generate --git . --name testing
|
|
||||||
- mv Cargo.toml Cargo.toml.tmpl
|
|
||||||
- cd testing
|
|
||||||
- cargo check
|
|
||||||
- cargo check --target wasm32-unknown-unknown
|
|
||||||
- cargo check --no-default-features
|
|
||||||
- cargo check --target wasm32-unknown-unknown --no-default-features
|
|
||||||
- cargo check --no-default-features --features console_error_panic_hook
|
|
||||||
- cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook
|
|
||||||
# Note: no enabling the `wee_alloc` feature here because it requires
|
|
||||||
# nightly for now.
|
|
2868
veilid-wasm/Cargo.lock
generated
2868
veilid-wasm/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,27 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "veilid-wasm"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["John Smith <jsmith@example.com>"]
|
|
||||||
edition = "2018"
|
|
||||||
license = "LGPL-2.0-or-later OR MPL-2.0 OR (MIT AND BSD-3-Clause)"
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
crate-type = ["cdylib", "rlib"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
wasm-bindgen = "^0"
|
|
||||||
console_error_panic_hook = "^0"
|
|
||||||
wee_alloc = "^0"
|
|
||||||
wasm-logger = "^0"
|
|
||||||
log = "^0"
|
|
||||||
veilid-core = { path = "../veilid-core" }
|
|
||||||
cfg-if = "^1"
|
|
||||||
wasm-bindgen-futures = "^0"
|
|
||||||
js-sys = "^0"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
wasm-bindgen-test = "^0"
|
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
# Tell `rustc` to optimize for small code size.
|
|
||||||
opt-level = "s"
|
|
@ -1,176 +0,0 @@
|
|||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
@ -1,25 +0,0 @@
|
|||||||
Copyright (c) 2018 John Smith <jsmith@example.com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any
|
|
||||||
person obtaining a copy of this software and associated
|
|
||||||
documentation files (the "Software"), to deal in the
|
|
||||||
Software without restriction, including without
|
|
||||||
limitation the rights to use, copy, modify, merge,
|
|
||||||
publish, distribute, sublicense, and/or sell copies of
|
|
||||||
the Software, and to permit persons to whom the Software
|
|
||||||
is furnished to do so, subject to the following
|
|
||||||
conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice
|
|
||||||
shall be included in all copies or substantial portions
|
|
||||||
of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
|
||||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
||||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
|
||||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
|
||||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
DEALINGS IN THE SOFTWARE.
|
|
@ -1,69 +0,0 @@
|
|||||||
<div align="center">
|
|
||||||
|
|
||||||
<h1><code>wasm-pack-template</code></h1>
|
|
||||||
|
|
||||||
<strong>A template for kick starting a Rust and WebAssembly project using <a href="https://github.com/rustwasm/wasm-pack">wasm-pack</a>.</strong>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="https://travis-ci.org/rustwasm/wasm-pack-template"><img src="https://img.shields.io/travis/rustwasm/wasm-pack-template.svg?style=flat-square" alt="Build Status" /></a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>
|
|
||||||
<a href="https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html">Tutorial</a>
|
|
||||||
<span> | </span>
|
|
||||||
<a href="https://discordapp.com/channels/442252698964721669/443151097398296587">Chat</a>
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<sub>Built with 🦀🕸 by <a href="https://rustwasm.github.io/">The Rust and WebAssembly Working Group</a></sub>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
[**📚 Read this template tutorial! 📚**][template-docs]
|
|
||||||
|
|
||||||
This template is designed for compiling Rust libraries into WebAssembly and
|
|
||||||
publishing the resulting package to NPM.
|
|
||||||
|
|
||||||
Be sure to check out [other `wasm-pack` tutorials online][tutorials] for other
|
|
||||||
templates and usages of `wasm-pack`.
|
|
||||||
|
|
||||||
[tutorials]: https://rustwasm.github.io/docs/wasm-pack/tutorials/index.html
|
|
||||||
[template-docs]: https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html
|
|
||||||
|
|
||||||
## 🚴 Usage
|
|
||||||
|
|
||||||
### 🐑 Use `cargo generate` to Clone this Template
|
|
||||||
|
|
||||||
[Learn more about `cargo generate` here.](https://github.com/ashleygwilliams/cargo-generate)
|
|
||||||
|
|
||||||
```
|
|
||||||
cargo generate --git https://github.com/rustwasm/wasm-pack-template.git --name my-project
|
|
||||||
cd my-project
|
|
||||||
```
|
|
||||||
|
|
||||||
### 🛠️ Build with `wasm-pack build`
|
|
||||||
|
|
||||||
```
|
|
||||||
wasm-pack build
|
|
||||||
```
|
|
||||||
|
|
||||||
### 🔬 Test in Headless Browsers with `wasm-pack test`
|
|
||||||
|
|
||||||
```
|
|
||||||
wasm-pack test --headless --firefox
|
|
||||||
```
|
|
||||||
|
|
||||||
### 🎁 Publish to NPM with `wasm-pack publish`
|
|
||||||
|
|
||||||
```
|
|
||||||
wasm-pack publish
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔋 Batteries Included
|
|
||||||
|
|
||||||
* [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) for communicating
|
|
||||||
between WebAssembly and JavaScript.
|
|
||||||
* [`console_error_panic_hook`](https://github.com/rustwasm/console_error_panic_hook)
|
|
||||||
for logging panic messages to the developer console.
|
|
||||||
* [`wee_alloc`](https://github.com/rustwasm/wee_alloc), an allocator optimized
|
|
||||||
for small code size.
|
|
@ -1,289 +0,0 @@
|
|||||||
use crate::*;
|
|
||||||
pub use wasm_bindgen_futures::*;
|
|
||||||
|
|
||||||
#[wasm_bindgen(js_name = VeilidStateChange)]
|
|
||||||
pub struct JsVeilidStateChange {
|
|
||||||
kind: String, // "attachment" => AttachmentState(String)
|
|
||||||
from: JsValue,
|
|
||||||
to: JsValue,
|
|
||||||
}
|
|
||||||
#[wasm_bindgen(js_name = VeilidState)]
|
|
||||||
pub struct JsVeilidState {
|
|
||||||
kind: String, // "attachment" => AttachmentState(String)
|
|
||||||
state: JsValue,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen(js_name = VeilidCore)]
|
|
||||||
pub struct JsVeilidCore {
|
|
||||||
core: VeilidCore,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen(js_class = VeilidCore)]
|
|
||||||
impl JsVeilidCore {
|
|
||||||
#[wasm_bindgen(constructor)]
|
|
||||||
pub fn new() -> Self {
|
|
||||||
set_panic_hook();
|
|
||||||
JsVeilidCore {
|
|
||||||
core: VeilidCore::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn value_to_string(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
|
||||||
Ok(Box::new(val.as_string().ok_or(())?))
|
|
||||||
}
|
|
||||||
fn value_to_option_string(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
|
||||||
if val.is_null() || val.is_undefined() {
|
|
||||||
return Ok(Box::new(Option::<String>::None));
|
|
||||||
}
|
|
||||||
Ok(Box::new(Some(val.as_string().ok_or(())?)))
|
|
||||||
}
|
|
||||||
fn value_to_bool(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
|
||||||
Ok(Box::new(val.is_truthy()))
|
|
||||||
}
|
|
||||||
fn value_to_u8(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
|
||||||
Ok(Box::new(f64_try_to_unsigned::<u8>(
|
|
||||||
val.as_f64().ok_or(())?,
|
|
||||||
)?))
|
|
||||||
}
|
|
||||||
fn value_to_u32(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
|
||||||
Ok(Box::new(f64_try_to_unsigned::<u32>(
|
|
||||||
val.as_f64().ok_or(())?,
|
|
||||||
)?))
|
|
||||||
}
|
|
||||||
fn value_to_u64(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
|
||||||
Ok(Box::new(f64_try_to_unsigned::<u64>(
|
|
||||||
val.as_f64().ok_or(())?,
|
|
||||||
)?))
|
|
||||||
}
|
|
||||||
fn value_to_option_u64(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
|
||||||
if val.is_null() || val.is_undefined() {
|
|
||||||
return Ok(Box::new(Option::<u64>::None));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Box::new(Some(f64_try_to_unsigned::<u64>(
|
|
||||||
val.as_f64().ok_or(())?,
|
|
||||||
)?)))
|
|
||||||
}
|
|
||||||
fn value_to_dht_key(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
|
||||||
Ok(Box::new(
|
|
||||||
DHTKey::try_decode(val.as_string().ok_or(())?.as_str()).map_err(drop)?,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
fn value_to_dht_key_secret(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
|
||||||
Ok(Box::new(
|
|
||||||
DHTKeySecret::try_decode(val.as_string().ok_or(())?.as_str()).map_err(drop)?,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
fn value_to_vec_string(val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
|
||||||
let arrval = val.dyn_into::<Array>().map_err(drop)?.to_vec();
|
|
||||||
let mut out = Vec::<String>::with_capacity(arrval.len());
|
|
||||||
for v in arrval {
|
|
||||||
out.push(v.as_string().ok_or(())?);
|
|
||||||
}
|
|
||||||
Ok(Box::new(out))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn translate_config_callback(key: &str, val: JsValue) -> Result<Box<dyn core::any::Any>, ()> {
|
|
||||||
match key {
|
|
||||||
// xxx: lots of missing keys here
|
|
||||||
"namespace" => Self::value_to_string(val),
|
|
||||||
"capabilities.protocol_udp" => Self::value_to_bool(val),
|
|
||||||
"capabilities.protocol_connect_tcp" => Self::value_to_bool(val),
|
|
||||||
"capabilities.protocol_accept_tcp" => Self::value_to_bool(val),
|
|
||||||
"capabilities.protocol_connect_ws" => Self::value_to_bool(val),
|
|
||||||
"capabilities.protocol_accept_ws" => Self::value_to_bool(val),
|
|
||||||
"capabilities.protocol_connect_wss" => Self::value_to_bool(val),
|
|
||||||
"capabilities.protocol_accept_wss" => Self::value_to_bool(val),
|
|
||||||
"table_store.directory" => Self::value_to_string(val),
|
|
||||||
"protected_store.allow_insecure_fallback" => Self::value_to_bool(val),
|
|
||||||
"protected_store.always_use_insecure_storage" => Self::value_to_bool(val),
|
|
||||||
"protected_store.insecure_fallback_directory" => Self::value_to_string(val),
|
|
||||||
"network.max_connections" => Self::value_to_u32(val),
|
|
||||||
"network.node_id" => Self::value_to_dht_key(val),
|
|
||||||
"network.node_id_secret" => Self::value_to_dht_key_secret(val),
|
|
||||||
"network.bootstrap" => Self::value_to_vec_string(val),
|
|
||||||
"network.rpc.concurrency" => Self::value_to_u32(val),
|
|
||||||
"network.rpc.queue_size" => Self::value_to_u32(val),
|
|
||||||
"network.rpc.max_timestamp_behind" => Self::value_to_option_u64(val),
|
|
||||||
"network.rpc.max_timestamp_ahead" => Self::value_to_option_u64(val),
|
|
||||||
"network.rpc.timeout" => Self::value_to_u64(val),
|
|
||||||
"network.rpc.max_route_hop_count" => Self::value_to_u8(val),
|
|
||||||
"network.dht.resolve_node_timeout" => Self::value_to_option_u64(val),
|
|
||||||
"network.dht.resolve_node_count" => Self::value_to_u32(val),
|
|
||||||
"network.dht.resolve_node_fanout" => Self::value_to_u32(val),
|
|
||||||
"network.dht.max_find_node_count" => Self::value_to_u32(val),
|
|
||||||
"network.dht.get_value_timeout" => Self::value_to_option_u64(val),
|
|
||||||
"network.dht.get_value_count" => Self::value_to_u32(val),
|
|
||||||
"network.dht.get_value_fanout" => Self::value_to_u32(val),
|
|
||||||
"network.dht.set_value_timeout" => Self::value_to_option_u64(val),
|
|
||||||
"network.dht.set_value_count" => Self::value_to_u32(val),
|
|
||||||
"network.dht.set_value_fanout" => Self::value_to_u32(val),
|
|
||||||
"network.dht.min_peer_count" => Self::value_to_u32(val),
|
|
||||||
"network.dht.min_peer_refresh_time" => Self::value_to_u64(val),
|
|
||||||
"network.dht.validate_dial_info_receipt_time" => Self::value_to_u64(val),
|
|
||||||
"network.upnp" => Self::value_to_bool(val),
|
|
||||||
"network.natpmp" => Self::value_to_bool(val),
|
|
||||||
"network.enable_local_peer_scope" => Self::value_to_bool(val),
|
|
||||||
"network.restricted_nat_retries" => Self::value_to_u32(val),
|
|
||||||
"network.tls.certificate_path" => Self::value_to_string(val),
|
|
||||||
"network.tls.private_key_path" => Self::value_to_string(val),
|
|
||||||
"network.application.path" => Self::value_to_string(val),
|
|
||||||
"network.application.https.enabled" => Self::value_to_bool(val),
|
|
||||||
"network.application.https.listen_address" => Self::value_to_string(val),
|
|
||||||
"network.application.http.enabled" => Self::value_to_bool(val),
|
|
||||||
"network.application.http.listen_address" => Self::value_to_string(val),
|
|
||||||
"network.protocol.udp.enabled" => Self::value_to_bool(val),
|
|
||||||
"network.protocol.udp.socket_pool_size" => Self::value_to_u32(val),
|
|
||||||
"network.protocol.udp.listen_address" => Self::value_to_string(val),
|
|
||||||
"network.protocol.udp.public_address" => Self::value_to_option_string(val),
|
|
||||||
"network.protocol.tcp.connect" => Self::value_to_bool(val),
|
|
||||||
"network.protocol.tcp.listen" => Self::value_to_bool(val),
|
|
||||||
"network.protocol.tcp.max_connections" => Self::value_to_u32(val),
|
|
||||||
"network.protocol.tcp.listen_address" => Self::value_to_string(val),
|
|
||||||
"network.protocol.tcp.public_address" => Self::value_to_option_string(val),
|
|
||||||
"network.protocol.ws.connect" => Self::value_to_bool(val),
|
|
||||||
"network.protocol.ws.listen" => Self::value_to_bool(val),
|
|
||||||
"network.protocol.ws.max_connections" => Self::value_to_u32(val),
|
|
||||||
"network.protocol.ws.listen_address" => Self::value_to_string(val),
|
|
||||||
"network.protocol.ws.path" => Self::value_to_string(val),
|
|
||||||
"network.protocol.ws.public_address" => Self::value_to_option_string(val),
|
|
||||||
"network.protocol.wss.connect" => Self::value_to_bool(val),
|
|
||||||
"network.protocol.wss.listen" => Self::value_to_bool(val),
|
|
||||||
"network.protocol.wss.max_connections" => Self::value_to_u32(val),
|
|
||||||
"network.protocol.wss.listen_address" => Self::value_to_string(val),
|
|
||||||
"network.protocol.wss.path" => Self::value_to_string(val),
|
|
||||||
"network.protocol.wss.public_address" => Self::value_to_option_string(val),
|
|
||||||
_ => return Err(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn translate_veilid_state(state: JsVeilidState) -> Result<VeilidState, JsValue> {
|
|
||||||
Ok(match state.kind.as_str() {
|
|
||||||
"attachment" => {
|
|
||||||
let state_string = state
|
|
||||||
.state
|
|
||||||
.as_string()
|
|
||||||
.ok_or(JsValue::from_str("state should be a string"))?;
|
|
||||||
let astate = AttachmentState::try_from(state_string)
|
|
||||||
.map_err(|e| JsValue::from_str(format!("invalid state: {:?}", e).as_str()))?;
|
|
||||||
VeilidState::Attachment(astate)
|
|
||||||
}
|
|
||||||
_ => return Err(JsValue::from_str("unknown state kind")),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// xxx rework this for new veilid_api mechanism which should be its own js object now
|
|
||||||
pub fn startup(
|
|
||||||
&self,
|
|
||||||
js_state_change_callback: Function,
|
|
||||||
js_config_callback: Function,
|
|
||||||
) -> Promise {
|
|
||||||
let core = self.core.clone();
|
|
||||||
future_to_promise(async move {
|
|
||||||
let vcs = VeilidCoreSetup {
|
|
||||||
state_change_callback: Arc::new(
|
|
||||||
move |change: VeilidStateChange| -> SystemPinBoxFuture<()> {
|
|
||||||
let js_state_change_callback = js_state_change_callback.clone();
|
|
||||||
Box::pin(async move {
|
|
||||||
let js_change = match change {
|
|
||||||
VeilidStateChange::Attachment {
|
|
||||||
old_state,
|
|
||||||
new_state,
|
|
||||||
} => JsVeilidStateChange {
|
|
||||||
kind: "attachment".to_owned(),
|
|
||||||
from: JsValue::from_str(old_state.to_string().as_str()),
|
|
||||||
to: JsValue::from_str(new_state.to_string().as_str()),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let ret = match Function::call1(
|
|
||||||
&js_state_change_callback,
|
|
||||||
&JsValue::UNDEFINED,
|
|
||||||
&JsValue::from(js_change),
|
|
||||||
) {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => {
|
|
||||||
error!("calling state change callback failed: {:?}", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let retp: Promise = match ret.dyn_into() {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => {
|
|
||||||
error!(
|
|
||||||
"state change callback did not return a promise: {:?}",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
match JsFuture::from(retp).await {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(e) => {
|
|
||||||
error!("state change callback returned an error: {:?}", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
})
|
|
||||||
},
|
|
||||||
),
|
|
||||||
config_callback: Arc::new(
|
|
||||||
move |key: String| -> Result<Box<dyn core::any::Any>, String> {
|
|
||||||
let val = Function::call1(
|
|
||||||
&js_config_callback,
|
|
||||||
&JsValue::UNDEFINED,
|
|
||||||
&JsValue::from_str(key.as_str()),
|
|
||||||
)
|
|
||||||
.map_err(|_| {
|
|
||||||
format!("Failed to get config from callback for key '{}'", key)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Self::translate_config_callback(key.as_str(), val)
|
|
||||||
.map_err(|_| format!("invalid value type for config key '{}'", key))
|
|
||||||
},
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
match core.startup(vcs).await {
|
|
||||||
Ok(_) => Ok(JsValue::UNDEFINED),
|
|
||||||
Err(e) => Err(JsValue::from_str(
|
|
||||||
format!("VeilidCore startup() failed: {}", e.to_string()).as_str(),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_state_update(&self) {
|
|
||||||
self.core.send_state_update();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn shutdown(&self) -> Promise {
|
|
||||||
let core = self.core.clone();
|
|
||||||
future_to_promise(async move {
|
|
||||||
core.shutdown().await;
|
|
||||||
Ok(JsValue::UNDEFINED)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn attach(&self) -> Promise {
|
|
||||||
let core = self.core.clone();
|
|
||||||
future_to_promise(async move {
|
|
||||||
core.attach();
|
|
||||||
Ok(JsValue::UNDEFINED)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn detach(&self) -> Promise {
|
|
||||||
let core = self.core.clone();
|
|
||||||
future_to_promise(async move {
|
|
||||||
core.detach();
|
|
||||||
Ok(JsValue::UNDEFINED)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wait_for_state(&self, state: JsVeilidState) -> Promise {
|
|
||||||
let core = self.core.clone();
|
|
||||||
future_to_promise(async move {
|
|
||||||
let state = Self::translate_veilid_state(state)?;
|
|
||||||
core.wait_for_state(state).await;
|
|
||||||
Ok(JsValue::UNDEFINED)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
#![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;
|
|
@ -1,38 +0,0 @@
|
|||||||
#![cfg(target_arch = "wasm32")]
|
|
||||||
use cfg_if::*;
|
|
||||||
use wasm_bindgen::prelude::*;
|
|
||||||
//use wasm_bindgen_futures::*;
|
|
||||||
|
|
||||||
cfg_if! {
|
|
||||||
if #[cfg(feature = "wee_alloc")] {
|
|
||||||
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
|
|
||||||
// allocator.
|
|
||||||
extern crate wee_alloc;
|
|
||||||
#[global_allocator]
|
|
||||||
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern "C" {
|
|
||||||
#[wasm_bindgen(js_namespace = console, js_name = log)]
|
|
||||||
pub fn console_log(s: &str);
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
pub fn alert(s: &str);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_panic_hook() {
|
|
||||||
#[cfg(feature = "console_error_panic_hook")]
|
|
||||||
console_error_panic_hook::set_once();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn f64_try_to_unsigned<T>(f: f64) -> Result<T,()>
|
|
||||||
where T: core::convert::TryFrom<u64>
|
|
||||||
{
|
|
||||||
let rf = f.floor();
|
|
||||||
if rf < 0.0 {
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
T::try_from(rf as u64).map_err(drop)
|
|
||||||
}
|
|
@ -1,182 +0,0 @@
|
|||||||
//! Test suite for the Web and headless browsers.
|
|
||||||
#![cfg(target_arch = "wasm32")]
|
|
||||||
|
|
||||||
extern crate alloc;
|
|
||||||
extern crate wasm_bindgen_test;
|
|
||||||
use core::sync::atomic::AtomicBool;
|
|
||||||
use veilid_wasm::*;
|
|
||||||
use wasm_bindgen_test::*;
|
|
||||||
|
|
||||||
wasm_bindgen_test_configure!(run_in_browser);
|
|
||||||
|
|
||||||
static SETUP_ONCE: AtomicBool = AtomicBool::new(false);
|
|
||||||
pub fn setup() -> () {
|
|
||||||
if SETUP_ONCE
|
|
||||||
.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
|
|
||||||
.is_ok()
|
|
||||||
{
|
|
||||||
console_log("setup()");
|
|
||||||
console_error_panic_hook::set_once();
|
|
||||||
wasm_logger::init(wasm_logger::Config::new(Level::Trace));
|
|
||||||
init_callbacks();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// xxx needs updating to new keys and veilid_api object
|
|
||||||
fn init_callbacks() {
|
|
||||||
assert_eq!(js_sys::eval(r#"
|
|
||||||
window.sleep = (milliseconds) => { return new Promise(resolve => setTimeout(resolve, milliseconds)) };
|
|
||||||
window.stateChangeCallback = async (stateChange) => { console.log("State change: " + stateChange); };
|
|
||||||
window.configCallback = (configKey) => {
|
|
||||||
switch(configKey) {
|
|
||||||
case "namespace": return "";
|
|
||||||
case "capabilities.protocol_udp": return false;
|
|
||||||
case "capabilities.protocol_connect_tcp": return false;
|
|
||||||
case "capabilities.protocol_accept_tcp": return false;
|
|
||||||
case "capabilities.protocol_connect_ws": return true;
|
|
||||||
case "capabilities.protocol_accept_ws": return false;
|
|
||||||
case "capabilities.protocol_connect_wss": return true;
|
|
||||||
case "capabilities.protocol_accept_wss": return false;
|
|
||||||
case "table_store.directory": return "";
|
|
||||||
case "protected_store.allow_insecure_fallback": return true;
|
|
||||||
case "protected_store.always_use_insecure_storage": return false;
|
|
||||||
case "protected_store.insecure_fallback_directory": return "";
|
|
||||||
case "network.max_connections": return 16;
|
|
||||||
case "network.node_id": return "ZLd4uMYdP4qYLtxF6GqrzBb32Z6T3rE2FWMkWup1pdY";
|
|
||||||
case "network.node_id_secret": return "s2Gvq6HJOxgQh-3xIgfWSL3I-DWZ2c1RjZLJl2Xmg2E";
|
|
||||||
case "network.bootstrap": return [];
|
|
||||||
case "network.rpc.concurrency": return 2;
|
|
||||||
case "network.rpc.queue_size": return 128;
|
|
||||||
case "network.rpc.max_timestamp_behind": return 10000000;
|
|
||||||
case "network.rpc.max_timestamp_ahead": return 10000000;
|
|
||||||
case "network.rpc.timeout": return 10000000;
|
|
||||||
case "network.rpc.max_route_hop_count": return 7;
|
|
||||||
case "network.dht.resolve_node_timeout": return null;
|
|
||||||
case "network.dht.resolve_node_count": return 20;
|
|
||||||
case "network.dht.resolve_node_fanout": return 3;
|
|
||||||
case "network.dht.max_find_node_count": return 20;
|
|
||||||
case "network.dht.get_value_timeout": return null;
|
|
||||||
case "network.dht.get_value_count": return 20;
|
|
||||||
case "network.dht.get_value_fanout": return 3;
|
|
||||||
case "network.dht.set_value_timeout": return null;
|
|
||||||
case "network.dht.set_value_count": return 20;
|
|
||||||
case "network.dht.set_value_fanout": return 5;
|
|
||||||
case "network.dht.min_peer_count": return 20;
|
|
||||||
case "network.dht.min_peer_refresh_time": return 2000000;
|
|
||||||
case "network.dht.validate_dial_info_receipt_time": return 5000000;
|
|
||||||
case "network.upnp": return false;
|
|
||||||
case "network.natpmp": return false;
|
|
||||||
case "network.enable_local_peer_scope": return false;
|
|
||||||
case "network.restricted_nat_retries": return 3;
|
|
||||||
case "network.tls.certificate_path": return "";
|
|
||||||
case "network.tls.private_key_path": return "";
|
|
||||||
case "network.application.path": return "/app";
|
|
||||||
case "network.application.https.enabled": return false;
|
|
||||||
case "network.application.https.listen_address": return "";
|
|
||||||
case "network.application.http.enabled": return false;
|
|
||||||
case "network.application.http.listen_address": return "";
|
|
||||||
case "network.protocol.udp.enabled": return false;
|
|
||||||
case "network.protocol.udp.socket_pool_size": return 0;
|
|
||||||
case "network.protocol.udp.listen_address": return "";
|
|
||||||
case "network.protocol.udp.public_address": return "";
|
|
||||||
case "network.protocol.tcp.connect": return false;
|
|
||||||
case "network.protocol.tcp.listen": return false;
|
|
||||||
case "network.protocol.tcp.max_connections": return 32;
|
|
||||||
case "network.protocol.tcp.listen_address": return "";
|
|
||||||
case "network.protocol.tcp.public_address": return "";
|
|
||||||
case "network.protocol.ws.connect": return true;
|
|
||||||
case "network.protocol.ws.listen": return false;
|
|
||||||
case "network.protocol.ws.max_connections": return 16;
|
|
||||||
case "network.protocol.ws.listen_address": return "";
|
|
||||||
case "network.protocol.ws.path": return "/ws";
|
|
||||||
case "network.protocol.ws.public_address": return "";
|
|
||||||
case "network.protocol.wss.connect": return true;
|
|
||||||
case "network.protocol.wss.listen": return false;
|
|
||||||
case "network.protocol.wss.max_connections": return 16;
|
|
||||||
case "network.protocol.wss.listen_address": return "";
|
|
||||||
case "network.protocol.wss.path": return "/ws";
|
|
||||||
case "network.protocol.wss.public_address": return "";
|
|
||||||
default:
|
|
||||||
console.log("config key '" + key +"' doesn't exist"); break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
true
|
|
||||||
"#).expect("failed to eval"), JsValue::TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
///
|
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
|
||||||
fn test_construct() {
|
|
||||||
setup();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
js_sys::eval(
|
|
||||||
r#"
|
|
||||||
let vc = new VeilidCore();
|
|
||||||
true
|
|
||||||
"#
|
|
||||||
)
|
|
||||||
.expect("failed to eval"),
|
|
||||||
JsValue::TRUE
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen_test(async)]
|
|
||||||
async fn test_startup_shutdown() {
|
|
||||||
setup();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
JsFuture::from(
|
|
||||||
js_sys::eval(
|
|
||||||
r#"
|
|
||||||
(async function() {
|
|
||||||
let vc = new VeilidCore();
|
|
||||||
await vc.startup(window.stateChangeCallback, window.configCallback);
|
|
||||||
await vc.shutdown();
|
|
||||||
return true;
|
|
||||||
})().then(v => {
|
|
||||||
console.log("finished: " + v);
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
"#
|
|
||||||
)
|
|
||||||
.expect("failed to eval")
|
|
||||||
.dyn_into::<Promise>()
|
|
||||||
.unwrap()
|
|
||||||
)
|
|
||||||
.await,
|
|
||||||
Ok(JsValue::TRUE)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen_test(async)]
|
|
||||||
async fn test_attach_detach() {
|
|
||||||
setup();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
JsFuture::from(
|
|
||||||
js_sys::eval(
|
|
||||||
r#"
|
|
||||||
(async function() {
|
|
||||||
let vc = new VeilidCore();
|
|
||||||
await vc.startup(window.stateChangeCallback, window.configCallback);
|
|
||||||
await vc.attach();
|
|
||||||
await window.sleep(1000);
|
|
||||||
await vc.detach();
|
|
||||||
await vc.shutdown();
|
|
||||||
return true;
|
|
||||||
})().then(v => {
|
|
||||||
console.log("finished: " + v);
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
"#
|
|
||||||
)
|
|
||||||
.expect("failed to eval")
|
|
||||||
.dyn_into::<Promise>()
|
|
||||||
.unwrap()
|
|
||||||
)
|
|
||||||
.await,
|
|
||||||
Ok(JsValue::TRUE)
|
|
||||||
);
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user