executor work

This commit is contained in:
John Smith 2022-06-27 23:46:29 -04:00
parent ebea72c9db
commit fdbb4c6397
59 changed files with 726 additions and 640 deletions

20
Cargo.lock generated
View File

@ -366,7 +366,6 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5c45a0dd44b7e6533ac4e7acc38ead1a3b39885f5bbb738140d30ea528abc7c" checksum = "a5c45a0dd44b7e6533ac4e7acc38ead1a3b39885f5bbb738140d30ea528abc7c"
dependencies = [ dependencies = [
"async-std",
"futures-io", "futures-io",
"futures-util", "futures-util",
"log", "log",
@ -380,7 +379,6 @@ version = "0.17.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1b71b31561643aa8e7df3effe284fa83ab1a840e52294c5f4bd7bfd8b2becbb" checksum = "a1b71b31561643aa8e7df3effe284fa83ab1a840e52294c5f4bd7bfd8b2becbb"
dependencies = [ dependencies = [
"async-std",
"async-tls", "async-tls",
"futures-io", "futures-io",
"futures-util", "futures-util",
@ -402,6 +400,7 @@ dependencies = [
"futures-util", "futures-util",
"pin-project 1.0.10", "pin-project 1.0.10",
"rustc_version", "rustc_version",
"tokio",
"wasm-bindgen-futures", "wasm-bindgen-futures",
] ]
@ -2763,6 +2762,7 @@ dependencies = [
"futures", "futures",
"libc", "libc",
"log", "log",
"tokio",
] ]
[[package]] [[package]]
@ -3040,6 +3040,8 @@ dependencies = [
"pin-project 1.0.10", "pin-project 1.0.10",
"rand 0.8.5", "rand 0.8.5",
"thiserror", "thiserror",
"tokio",
"tokio-stream",
] ]
[[package]] [[package]]
@ -3759,6 +3761,7 @@ dependencies = [
"netlink-proto", "netlink-proto",
"nix 0.22.3", "nix 0.22.3",
"thiserror", "thiserror",
"tokio",
] ]
[[package]] [[package]]
@ -4531,6 +4534,7 @@ checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507"
dependencies = [ dependencies = [
"bytes 1.1.0", "bytes 1.1.0",
"futures-core", "futures-core",
"futures-io",
"futures-sink", "futures-sink",
"log", "log",
"pin-project-lite", "pin-project-lite",
@ -4786,6 +4790,7 @@ dependencies = [
"smallvec", "smallvec",
"thiserror", "thiserror",
"tinyvec", "tinyvec",
"tokio",
"url", "url",
] ]
@ -4805,6 +4810,7 @@ dependencies = [
"resolv-conf", "resolv-conf",
"smallvec", "smallvec",
"thiserror", "thiserror",
"tokio",
"trust-dns-proto", "trust-dns-proto",
] ]
@ -4983,7 +4989,6 @@ version = "0.1.0"
dependencies = [ dependencies = [
"async-std", "async-std",
"async-tungstenite 0.8.0", "async-tungstenite 0.8.0",
"async_executors",
"bugsalot", "bugsalot",
"capnp", "capnp",
"capnp-rpc", "capnp-rpc",
@ -5004,6 +5009,8 @@ dependencies = [
"serde_derive", "serde_derive",
"serial_test", "serial_test",
"thiserror", "thiserror",
"tokio",
"tokio-util 0.6.10",
"veilid-core", "veilid-core",
] ]
@ -5081,10 +5088,14 @@ dependencies = [
"static_assertions", "static_assertions",
"stop-token", "stop-token",
"thiserror", "thiserror",
"tokio",
"tokio-stream",
"tokio-util 0.6.10",
"tracing", "tracing",
"tracing-error", "tracing-error",
"tracing-subscriber", "tracing-subscriber",
"tracing-wasm", "tracing-wasm",
"trust-dns-resolver",
"wasm-bindgen", "wasm-bindgen",
"wasm-bindgen-futures", "wasm-bindgen-futures",
"wasm-bindgen-test", "wasm-bindgen-test",
@ -5104,7 +5115,6 @@ name = "veilid-flutter"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"allo-isolate", "allo-isolate",
"async-std",
"backtrace", "backtrace",
"ffi-support", "ffi-support",
"futures", "futures",
@ -5117,6 +5127,7 @@ dependencies = [
"parking_lot 0.12.1", "parking_lot 0.12.1",
"serde", "serde",
"serde_json", "serde_json",
"tokio",
"tracing", "tracing",
"tracing-opentelemetry", "tracing-opentelemetry",
"tracing-subscriber", "tracing-subscriber",
@ -5157,6 +5168,7 @@ dependencies = [
"serial_test", "serial_test",
"signal-hook", "signal-hook",
"signal-hook-async-std", "signal-hook-async-std",
"tokio",
"tracing", "tracing",
"tracing-appender", "tracing-appender",
"tracing-journald", "tracing-journald",

View File

@ -10,6 +10,11 @@ license = "LGPL-2.0-or-later OR MPL-2.0 OR (MIT AND BSD-3-Clause)"
name = "veilid-cli" name = "veilid-cli"
path = "src/main.rs" path = "src/main.rs"
[features]
default = [ "rt-tokio" ]
rt-async-std = [ "async-std", "veilid-core/rt-async-std" ]
rt-tokio = [ "tokio", "tokio-util", "veilid-core/rt-tokio" ]
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]
cursive = { path = "../external/cursive/cursive", default-features = false, features = ["ncurses-backend", "toml", "rt-async-std"]} cursive = { path = "../external/cursive/cursive", default-features = false, features = ["ncurses-backend", "toml", "rt-async-std"]}
@ -17,9 +22,10 @@ cursive = { path = "../external/cursive/cursive", default-features = false, feat
cursive = { path = "../external/cursive/cursive", default-features = false, features = ["crossterm-backend", "toml", "rt-async-std"]} cursive = { path = "../external/cursive/cursive", default-features = false, features = ["crossterm-backend", "toml", "rt-async-std"]}
[dependencies] [dependencies]
async-std = { version = "^1.9", features = ["unstable", "attributes"] } async-std = { version = "^1.9", features = ["unstable", "attributes"], optional = true }
async-tungstenite = { version = "^0.8", features = ["async-std-runtime"] } tokio = { version = "^1", features = ["full"], optional = true }
async_executors = { version = "^0", default-features = false, features = [ "async_std" ]} tokio-util = { version = "^0", features = ["compat"], optional = true}
async-tungstenite = { version = "^0.8" }
cursive-flexi-logger-view = { path = "../external/cursive-flexi-logger-view" } cursive-flexi-logger-view = { path = "../external/cursive-flexi-logger-view" }
cursive_buffered_backend = { path = "../external/cursive_buffered_backend" } cursive_buffered_backend = { path = "../external/cursive_buffered_backend" }
# cursive-multiplex = "0.4.0" # cursive-multiplex = "0.4.0"
@ -41,7 +47,7 @@ bugsalot = "^0"
flexi_logger = { version = "^0", features = ["use_chrono_for_offset"] } flexi_logger = { version = "^0", features = ["use_chrono_for_offset"] }
thiserror = "^1" thiserror = "^1"
crossbeam-channel = "^0" crossbeam-channel = "^0"
veilid-core = { path = "../veilid-core" } veilid-core = { path = "../veilid-core", default_features = false}
[dev-dependencies] [dev-dependencies]
serial_test = "^0" serial_test = "^0"

View File

@ -1,9 +1,8 @@
use crate::command_processor::*; use crate::command_processor::*;
use crate::tools::*;
use crate::veilid_client_capnp::*; use crate::veilid_client_capnp::*;
use async_executors::{AsyncStd, LocalSpawnHandleExt};
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::io::AsyncReadExt;
use std::cell::RefCell; use std::cell::RefCell;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::rc::Rc; use std::rc::Rc;
@ -140,9 +139,7 @@ impl ClientApiConnection {
)); ));
} }
let rpc_jh = AsyncStd let rpc_jh = spawn_local(rpc_system);
.spawn_handle_local(rpc_system)
.map_err(|e| format!("failed to spawn rpc system: {}", e))?;
// Send the request and get the state object and the registration object // Send the request and get the state object and the registration object
let response = request let response = request
@ -173,23 +170,43 @@ impl ClientApiConnection {
// object mapping from the server which we need for the update backchannel // object mapping from the server which we need for the update backchannel
// Wait until rpc system completion or disconnect was requested // Wait until rpc system completion or disconnect was requested
rpc_jh
.await cfg_if! {
.map_err(|e| format!("client RPC system error: {}", e)) if #[cfg(feature="rt-async-std")] {
rpc_jh
.await
.map_err(|e| format!("client RPC system error: {}", e))
} else if #[cfg(feature="rt-tokio")] {
rpc_jh
.await
.map_err(|e| format!("join error: {}", e))?
.map_err(|e| format!("client RPC system error: {}", e))
}
}
} }
async fn handle_connection(&mut self) -> Result<(), String> { 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) let stream = TcpStream::connect(connect_addr)
.await .await
.map_err(map_to_string)?; .map_err(map_to_string)?;
// If it succeed, disable nagle algorithm // If it succeed, disable nagle algorithm
stream.set_nodelay(true).map_err(map_to_string)?; stream.set_nodelay(true).map_err(map_to_string)?;
// Create the VAT network // Create the VAT network
let (reader, writer) = stream.split();
cfg_if! {
if #[cfg(feature="rt-async-std")] {
let (reader, writer) = stream.split();
} else if #[cfg(feature="rt-tokio")] {
let (reader, writer) = stream.into_split();
let reader = reader.compat();
let writer = writer.compat_write();
}
}
let rpc_network = Box::new(twoparty::VatNetwork::new( let rpc_network = Box::new(twoparty::VatNetwork::new(
reader, reader,
writer, writer,

View File

@ -1,7 +1,7 @@
use crate::client_api_connection::*; use crate::client_api_connection::*;
use crate::settings::Settings; use crate::settings::Settings;
use crate::tools::*;
use crate::ui::*; use crate::ui::*;
use async_std::prelude::FutureExt;
use log::*; use log::*;
use std::cell::*; use std::cell::*;
use std::net::SocketAddr; use std::net::SocketAddr;
@ -116,7 +116,7 @@ debug - send a debugging command to the Veilid server
trace!("CommandProcessor::cmd_shutdown"); trace!("CommandProcessor::cmd_shutdown");
let mut capi = self.capi(); let mut capi = self.capi();
let ui = self.ui(); let ui = self.ui();
async_std::task::spawn_local(async move { spawn_detached_local(async move {
if let Err(e) = capi.server_shutdown().await { if let Err(e) = capi.server_shutdown().await {
error!("Server command 'shutdown' failed to execute: {}", e); error!("Server command 'shutdown' failed to execute: {}", e);
} }
@ -129,7 +129,7 @@ debug - send a debugging command to the Veilid server
trace!("CommandProcessor::cmd_attach"); trace!("CommandProcessor::cmd_attach");
let mut capi = self.capi(); let mut capi = self.capi();
let ui = self.ui(); let ui = self.ui();
async_std::task::spawn_local(async move { spawn_detached_local(async move {
if let Err(e) = capi.server_attach().await { if let Err(e) = capi.server_attach().await {
error!("Server command 'attach' failed to execute: {}", e); error!("Server command 'attach' failed to execute: {}", e);
} }
@ -142,7 +142,7 @@ debug - send a debugging command to the Veilid server
trace!("CommandProcessor::cmd_detach"); trace!("CommandProcessor::cmd_detach");
let mut capi = self.capi(); let mut capi = self.capi();
let ui = self.ui(); let ui = self.ui();
async_std::task::spawn_local(async move { spawn_detached_local(async move {
if let Err(e) = capi.server_detach().await { if let Err(e) = capi.server_detach().await {
error!("Server command 'detach' failed to execute: {}", e); error!("Server command 'detach' failed to execute: {}", e);
} }
@ -155,7 +155,7 @@ debug - send a debugging command to the Veilid server
trace!("CommandProcessor::cmd_disconnect"); trace!("CommandProcessor::cmd_disconnect");
let mut capi = self.capi(); let mut capi = self.capi();
let ui = self.ui(); let ui = self.ui();
async_std::task::spawn_local(async move { spawn_detached_local(async move {
capi.disconnect().await; capi.disconnect().await;
ui.send_callback(callback); ui.send_callback(callback);
}); });
@ -166,7 +166,7 @@ debug - send a debugging command to the Veilid server
trace!("CommandProcessor::cmd_debug"); trace!("CommandProcessor::cmd_debug");
let mut capi = self.capi(); let mut capi = self.capi();
let ui = self.ui(); let ui = self.ui();
async_std::task::spawn_local(async move { spawn_detached_local(async move {
match capi.server_debug(rest.unwrap_or_default()).await { match capi.server_debug(rest.unwrap_or_default()).await {
Ok(output) => ui.display_string_dialog("Debug Output", output, callback), Ok(output) => ui.display_string_dialog("Debug Output", output, callback),
Err(e) => { Err(e) => {
@ -248,9 +248,7 @@ debug - send a debugging command to the Veilid server
debug!("Connection lost, retrying in 2 seconds"); debug!("Connection lost, retrying in 2 seconds");
{ {
let waker = self.inner_mut().connection_waker.instance_clone(()); let waker = self.inner_mut().connection_waker.instance_clone(());
waker let _ = timeout(Duration::from_millis(2000), waker).await;
.race(async_std::task::sleep(Duration::from_millis(2000)))
.await;
} }
self.inner_mut().connection_waker.reset(); self.inner_mut().connection_waker.reset();
first = false; first = false;
@ -306,7 +304,7 @@ debug - send a debugging command to the Veilid server
// pub fn stop_connection(&mut self) { // pub fn stop_connection(&mut self) {
// self.inner_mut().reconnect = false; // self.inner_mut().reconnect = false;
// let mut capi = self.capi().clone(); // let mut capi = self.capi().clone();
// async_std::task::spawn_local(async move { // spawn_detached(async move {
// capi.disconnect().await; // capi.disconnect().await;
// }); // });
// } // }
@ -327,7 +325,7 @@ debug - send a debugging command to the Veilid server
trace!("CommandProcessor::attach"); trace!("CommandProcessor::attach");
let mut capi = self.capi(); let mut capi = self.capi();
async_std::task::spawn_local(async move { spawn_detached_local(async move {
if let Err(e) = capi.server_attach().await { if let Err(e) = capi.server_attach().await {
error!("Server command 'attach' failed to execute: {}", e); error!("Server command 'attach' failed to execute: {}", e);
} }
@ -338,7 +336,7 @@ debug - send a debugging command to the Veilid server
trace!("CommandProcessor::detach"); trace!("CommandProcessor::detach");
let mut capi = self.capi(); let mut capi = self.capi();
async_std::task::spawn_local(async move { spawn_detached_local(async move {
if let Err(e) = capi.server_detach().await { if let Err(e) = capi.server_detach().await {
error!("Server command 'detach' failed to execute: {}", e); error!("Server command 'detach' failed to execute: {}", e);
} }

View File

@ -3,16 +3,17 @@
use veilid_core::xx::*; use veilid_core::xx::*;
use async_std::prelude::*;
use clap::{Arg, ColorChoice, Command}; use clap::{Arg, ColorChoice, Command};
use flexi_logger::*; use flexi_logger::*;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::net::ToSocketAddrs; use std::net::ToSocketAddrs;
use std::path::Path; use std::path::Path;
use tools::*;
mod client_api_connection; mod client_api_connection;
mod command_processor; mod command_processor;
mod settings; mod settings;
mod tools;
mod ui; mod ui;
#[allow(clippy::all)] #[allow(clippy::all)]
@ -60,8 +61,7 @@ fn parse_command_line(default_config_path: &OsStr) -> Result<clap::ArgMatches, S
Ok(matches) Ok(matches)
} }
#[async_std::main] fn main() -> Result<(), String> {
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())?;
@ -170,17 +170,29 @@ async fn main() -> Result<(), String> {
comproc.set_server_address(server_addr); comproc.set_server_address(server_addr);
let mut comproc2 = comproc.clone(); let mut comproc2 = comproc.clone();
let connection_future = comproc.connection_manager(); let connection_future = comproc.connection_manager();
// Start UI
let ui_future = async_std::task::spawn_local(async move {
sivui.run_async().await;
// When UI quits, close connection and command processor cleanly // Start async
comproc2.quit(); block_on(async move {
capi.disconnect().await; // Start UI
let ui_future = async move {
sivui.run_async().await;
// When UI quits, close connection and command processor cleanly
comproc2.quit();
capi.disconnect().await;
};
cfg_if! {
if #[cfg(feature="rt-async-std")] {
use async_std::prelude::*;
// Wait for ui and connection to complete
let _ = ui_future.join(connection_future).await;
} else if #[cfg(feature="rt-tokio")] {
// Wait for ui and connection to complete
let _ = tokio::join!(ui_future, connection_future);
}
}
}); });
// Wait for ui and connection to complete
ui_future.join(connection_future).await;
Ok(()) Ok(())
} }

40
veilid-cli/src/tools.rs Normal file
View File

@ -0,0 +1,40 @@
use cfg_if::*;
use core::future::Future;
cfg_if! {
if #[cfg(feature="rt-async-std")] {
pub use async_std::task::JoinHandle;
pub use async_std::net::TcpStream;
pub use async_std::future::TimeoutError;
pub fn spawn_local<F: Future<Output = T> + 'static, T: 'static>(f: F) -> JoinHandle<T> {
async_std::task::spawn_local(f)
}
pub fn spawn_detached_local<F: Future<Output = T> + 'static, T: 'static>(f: F) {
let _ = async_std::task::spawn_local(f);
}
pub use async_std::task::sleep;
pub use async_std::future::timeout;
pub fn block_on<F: Future<Output = T>, T>(f: F) -> T {
async_std::task::block_on(f)
}
} else if #[cfg(feature="rt-tokio")] {
pub use tokio::task::JoinHandle;
pub use tokio::net::TcpStream;
pub use tokio_util::compat::*;
pub use tokio::time::error::Elapsed as TimeoutError;
pub fn spawn_local<F: Future<Output = T> + 'static, T: 'static>(f: F) -> JoinHandle<T> {
tokio::task::spawn_local(f)
}
pub fn spawn_detached_local<F: Future<Output = T> + 'static, T: 'static>(f: F) {
let _ = tokio::task::spawn_local(f);
}
pub use tokio::time::sleep;
pub use tokio::time::timeout;
pub fn block_on<F: Future<Output = T>, T>(f: F) -> T {
let rt = tokio::runtime::Runtime::new().unwrap();
let local = tokio::task::LocalSet::new();
local.block_on(&rt, f)
}
}
}

View File

@ -10,11 +10,13 @@ license = "LGPL-2.0-or-later OR MPL-2.0 OR (MIT AND BSD-3-Clause)"
crate-type = ["cdylib", "staticlib", "rlib"] crate-type = ["cdylib", "staticlib", "rlib"]
[features] [features]
default = [ "rt-async-std" ] default = []
rt-async-std = [ "async-std", "async-std-resolver", "async_executors/async_std", "rtnetlink?/smol_socket" ]
rt-tokio = [ "tokio", "tokio-util", "tokio-stream", "trust-dns-resolver/tokio-runtime", "async_executors/tokio_tp", "async_executors/tokio_io", "async_executors/tokio_timer", "rtnetlink?/tokio_socket" ]
android_tests = [] android_tests = []
ios_tests = [ "simplelog", "backtrace" ] ios_tests = [ "simplelog", "backtrace" ]
tracking = [ "backtrace" ] tracking = [ "backtrace" ]
rt-async-std = [ "async-std", "async-tungstenite/async-std-runtime", "async-std-resolver", "async_executors/async_std", "rtnetlink?/smol_socket" ]
[dependencies] [dependencies]
tracing = { version = "^0", features = ["log", "attributes"] } tracing = { version = "^0", features = ["log", "attributes"] }
@ -59,9 +61,13 @@ rtnetlink = { version = "^0", default-features = false, optional = true }
# Linux, Windows, Mac, iOS, Android # Linux, Windows, Mac, iOS, Android
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
async-std = { version = "^1", features = ["unstable"], optional = true} async-std = { version = "^1", features = ["unstable"], optional = true}
tokio = { version = "^1", features = ["full"], optional = true}
tokio-util = { version = "^0", features = ["compat"], optional = true}
tokio-stream = { version = "^0", features = ["net"], optional = true}
async-io = { version = "^1" } async-io = { version = "^1" }
async-tungstenite = { version = "^0", features = ["async-tls"] } async-tungstenite = { version = "^0", features = ["async-tls"] }
async-std-resolver = { version = "^0", optional = true } async-std-resolver = { version = "^0", optional = true }
trust-dns-resolver = { version = "^0", optional = true }
maplit = "^1" maplit = "^1"
config = { version = "^0", features = ["yaml"] } config = { version = "^0", features = ["yaml"] }
keyring-manager = { path = "../external/keyring-manager" } keyring-manager = { path = "../external/keyring-manager" }
@ -77,7 +83,6 @@ data-encoding = { version = "^2" }
serde = { version = "^1", features = ["derive" ] } serde = { version = "^1", features = ["derive" ] }
serde_cbor = { version = "^0" } serde_cbor = { version = "^0" }
serde_json = { version = "^1" } serde_json = { version = "^1" }
async_executors = { version = "^0", default-features = false }
socket2 = "^0" socket2 = "^0"
bugsalot = "^0" bugsalot = "^0"
chrono = "^0" chrono = "^0"

View File

@ -97,24 +97,6 @@ impl ApiTracingLayer {
} }
} }
fn display_current_thread_id() -> String {
cfg_if! {
if #[cfg(target_arch = "wasm32")] {
"".to_owned()
} else {
format!("({}:{:?})",
if let Some(n) = async_std::task::current().name() {
n.to_string()
}
else {
async_std::task::current().id().to_string()
},
std::thread::current().id()
)
}
}
}
impl<S: Subscriber + for<'a> registry::LookupSpan<'a>> Layer<S> for ApiTracingLayer { impl<S: Subscriber + for<'a> registry::LookupSpan<'a>> Layer<S> for ApiTracingLayer {
fn enabled(&self, metadata: &tracing::Metadata<'_>, _: layer::Context<'_, S>) -> bool { fn enabled(&self, metadata: &tracing::Metadata<'_>, _: layer::Context<'_, S>) -> bool {
if let Some(inner) = &mut *self.inner.lock() { if let Some(inner) = &mut *self.inner.lock() {
@ -188,7 +170,7 @@ impl<S: Subscriber + for<'a> registry::LookupSpan<'a>> Layer<S> for ApiTracingLa
.and_then(|file| meta.line().map(|ln| format!("{}:{}", file, ln))) .and_then(|file| meta.line().map(|ln| format!("{}:{}", file, ln)))
.unwrap_or_default(); .unwrap_or_default();
let message = format!("{}{} {}", origin, display_current_thread_id(), recorder); let message = format!("{} {}", origin, recorder);
(inner.update_callback)(VeilidUpdate::Log(VeilidStateLog { (inner.update_callback)(VeilidUpdate::Log(VeilidStateLog {
log_level, log_level,

View File

@ -1,6 +1,5 @@
use crate::callback_state_machine::*; use crate::callback_state_machine::*;
use crate::dht::Crypto; use crate::dht::Crypto;
use crate::intf::*;
use crate::network_manager::*; use crate::network_manager::*;
use crate::routing_table::*; use crate::routing_table::*;
use crate::xx::*; use crate::xx::*;
@ -306,9 +305,8 @@ impl AttachmentManager {
// Create long-running connection maintenance routine // Create long-running connection maintenance routine
let this = self.clone(); let this = self.clone();
self.inner.lock().maintain_peers = true; self.inner.lock().maintain_peers = true;
self.inner.lock().attachment_maintainer_jh = Some(MustJoinHandle::new(intf::spawn( self.inner.lock().attachment_maintainer_jh =
this.attachment_maintainer(), Some(intf::spawn(this.attachment_maintainer()));
)));
} }
#[instrument(level = "trace", skip(self))] #[instrument(level = "trace", skip(self))]

View File

@ -1,7 +1,6 @@
use crate::api_tracing_layer::*; use crate::api_tracing_layer::*;
use crate::attachment_manager::*; use crate::attachment_manager::*;
use crate::dht::Crypto; use crate::dht::Crypto;
use crate::intf::*;
use crate::veilid_api::*; use crate::veilid_api::*;
use crate::veilid_config::*; use crate::veilid_config::*;
use crate::xx::*; use crate::xx::*;
@ -10,7 +9,6 @@ cfg_if! {
if #[cfg(target_arch = "wasm32")] { if #[cfg(target_arch = "wasm32")] {
pub type UpdateCallback = Arc<dyn Fn(VeilidUpdate)>; pub type UpdateCallback = Arc<dyn Fn(VeilidUpdate)>;
} else { } else {
pub type UpdateCallback = Arc<dyn Fn(VeilidUpdate) + Send + Sync>; pub type UpdateCallback = Arc<dyn Fn(VeilidUpdate) + Send + Sync>;
} }
} }
@ -255,7 +253,9 @@ impl VeilidCoreContext {
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
static INITIALIZED: AsyncMutex<bool> = AsyncMutex::new(false); lazy_static::lazy_static! {
static ref INITIALIZED: AsyncMutex<bool> = AsyncMutex::new(false);
}
#[instrument(err, skip_all)] #[instrument(err, skip_all)]
pub async fn api_startup( pub async fn api_startup(

View File

@ -1,5 +1,4 @@
use super::key::*; use super::key::*;
use crate::intf::*;
use crate::xx::*; use crate::xx::*;
use crate::*; use crate::*;
use chacha20::cipher::{KeyIvInit, StreamCipher}; use chacha20::cipher::{KeyIvInit, StreamCipher};
@ -124,7 +123,7 @@ impl Crypto {
// Schedule flushing // Schedule flushing
let this = self.clone(); let this = self.clone();
let flush_future = interval(60000, move || { let flush_future = intf::interval(60000, move || {
let this = this.clone(); let this = this.clone();
async move { async move {
if let Err(e) = this.flush().await { if let Err(e) = this.flush().await {
@ -214,13 +213,13 @@ impl Crypto {
pub fn get_random_nonce() -> Nonce { pub fn get_random_nonce() -> Nonce {
let mut nonce = [0u8; 24]; let mut nonce = [0u8; 24];
random_bytes(&mut nonce).unwrap(); intf::random_bytes(&mut nonce).unwrap();
nonce nonce
} }
pub fn get_random_secret() -> SharedSecret { pub fn get_random_secret() -> SharedSecret {
let mut s = [0u8; 32]; let mut s = [0u8; 32];
random_bytes(&mut s).unwrap(); intf::random_bytes(&mut s).unwrap();
s s
} }

View File

@ -1,5 +1,4 @@
mod table_db; mod table_db;
use crate::xx::*;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
mod wasm; mod wasm;

View File

@ -1,4 +1,4 @@
use crate::intf::*; use crate::xx::*;
use crate::*; use crate::*;
struct BlockStoreInner { struct BlockStoreInner {

View File

@ -1,14 +1,33 @@
#![allow(dead_code)] #![allow(dead_code)]
use crate::xx::*; use crate::xx::*;
pub use async_executors::JoinHandle; cfg_if! {
use async_executors::{AsyncStd, LocalSpawnHandleExt, SpawnHandleExt}; if #[cfg(feature="rt-async-std")] {
use async_std_resolver::{config, resolver, resolver_from_system_conf, AsyncStdResolver}; use async_std_resolver::{config, resolver, resolver_from_system_conf, AsyncStdResolver as AsyncResolver};
} else if #[cfg(feature="rt-tokio")] {
use trust_dns_resolver::{config, TokioAsyncResolver as AsyncResolver, error::ResolveError};
pub async fn resolver(
config: config::ResolverConfig,
options: config::ResolverOpts,
) -> Result<AsyncResolver, ResolveError> {
AsyncResolver::tokio(config, options)
}
/// Constructs a new async-std based Resolver with the system configuration.
///
/// This will use `/etc/resolv.conf` on Unix OSes and the registry on Windows.
#[cfg(any(unix, target_os = "windows"))]
pub async fn resolver_from_system_conf() -> Result<AsyncResolver, ResolveError> {
AsyncResolver::tokio_from_system_conf()
}
}
}
use rand::prelude::*; use rand::prelude::*;
use std::time::{Duration, SystemTime, UNIX_EPOCH}; use std::time::{Duration, SystemTime, UNIX_EPOCH};
lazy_static::lazy_static! { lazy_static::lazy_static! {
static ref RESOLVER: Arc<AsyncMutex<Option<AsyncStdResolver>>> = Arc::new(AsyncMutex::new(None)); static ref RESOLVER: Arc<AsyncMutex<Option<AsyncResolver>>> = Arc::new(AsyncMutex::new(None));
} }
pub fn get_timestamp() -> u64 { pub fn get_timestamp() -> u64 {
@ -40,9 +59,21 @@ pub fn get_random_u64() -> u64 {
pub async fn sleep(millis: u32) { pub async fn sleep(millis: u32) {
if millis == 0 { if millis == 0 {
async_std::task::yield_now().await; cfg_if! {
if #[cfg(feature="rt-async-std")] {
async_std::task::yield_now().await;
} else if #[cfg(feature="rt-tokio")] {
tokio::task::yield_now().await;
}
}
} else { } else {
async_std::task::sleep(Duration::from_millis(u64::from(millis))).await; cfg_if! {
if #[cfg(feature="rt-async-std")] {
async_std::task::sleep(Duration::from_millis(u64::from(millis))).await;
} else if #[cfg(feature="rt-tokio")] {
tokio::time::sleep(Duration::from_millis(u64::from(millis))).await;
}
}
} }
} }
@ -52,22 +83,64 @@ pub fn system_boxed<'a, Out>(
Box::pin(future) Box::pin(future)
} }
pub fn spawn<Out>(future: impl Future<Output = Out> + Send + 'static) -> JoinHandle<Out> pub fn spawn<Out>(future: impl Future<Output = Out> + Send + 'static) -> MustJoinHandle<Out>
where where
Out: Send + 'static, Out: Send + 'static,
{ {
AsyncStd cfg_if! {
.spawn_handle(future) if #[cfg(feature="rt-async-std")] {
.expect("async-std spawn should never error out") MustJoinHandle::new(async_std::task::spawn(future))
} else if #[cfg(feature="rt-tokio")] {
MustJoinHandle::new(tokio::task::spawn(future))
}
}
} }
pub fn spawn_local<Out>(future: impl Future<Output = Out> + 'static) -> JoinHandle<Out> pub fn spawn_local<Out>(future: impl Future<Output = Out> + 'static) -> MustJoinHandle<Out>
where where
Out: 'static, Out: 'static,
{ {
AsyncStd cfg_if! {
.spawn_handle_local(future) if #[cfg(feature="rt-async-std")] {
.expect("async-std spawn_local should never error out") MustJoinHandle::new(async_std::task::spawn_local(future))
} else if #[cfg(feature="rt-tokio")] {
MustJoinHandle::new(tokio::task::spawn_local(future))
}
}
}
pub fn spawn_with_local_set<Out>(
future: impl Future<Output = Out> + Send + 'static,
) -> MustJoinHandle<Out>
where
Out: Send + 'static,
{
cfg_if! {
if #[cfg(feature="rt-async-std")] {
spawn(future)
} else if #[cfg(feature="rt-tokio")] {
MustJoinHandle::new(tokio::task::spawn_blocking(move || {
let rt = tokio::runtime::Handle::current();
rt.block_on(async {
let local = tokio::task::LocalSet::new();
local.run_until(future).await
})
}))
}
}
}
pub fn spawn_detached<Out>(future: impl Future<Output = Out> + Send + 'static)
where
Out: Send + 'static,
{
cfg_if! {
if #[cfg(feature="rt-async-std")] {
drop(async_std::task::spawn(future));
} else if #[cfg(feature="rt-tokio")] {
drop(tokio::task::spawn(future));
}
}
} }
pub fn interval<F, FUT>(freq_ms: u32, callback: F) -> SystemPinBoxFuture<()> pub fn interval<F, FUT>(freq_ms: u32, callback: F) -> SystemPinBoxFuture<()>
@ -90,13 +163,25 @@ where
}) })
} }
pub use async_std::future::TimeoutError; cfg_if! {
if #[cfg(feature="rt-async-std")] {
pub use async_std::future::TimeoutError;
} else if #[cfg(feature="rt-tokio")] {
pub use tokio::time::error::Elapsed as TimeoutError;
}
}
pub async fn timeout<F, T>(dur_ms: u32, f: F) -> Result<T, TimeoutError> pub async fn timeout<F, T>(dur_ms: u32, f: F) -> Result<T, TimeoutError>
where where
F: Future<Output = T>, F: Future<Output = T>,
{ {
async_std::future::timeout(Duration::from_millis(dur_ms as u64), f).await cfg_if! {
if #[cfg(feature="rt-async-std")] {
async_std::future::timeout(Duration::from_millis(dur_ms as u64), f).await
} else if #[cfg(feature="rt-tokio")] {
tokio::time::timeout(Duration::from_millis(dur_ms as u64), f).await
}
}
} }
pub fn get_concurrency() -> u32 { pub fn get_concurrency() -> u32 {
@ -128,7 +213,7 @@ where
} }
*/ */
async fn get_resolver() -> Result<AsyncStdResolver, String> { async fn get_resolver() -> Result<AsyncResolver, String> {
let mut resolver_lock = RESOLVER.lock().await; let mut resolver_lock = RESOLVER.lock().await;
if let Some(r) = &*resolver_lock { if let Some(r) = &*resolver_lock {
Ok(r.clone()) Ok(r.clone())

View File

@ -1,5 +1,5 @@
use crate::intf::table_db::*; use crate::intf::table_db::*;
use crate::intf::*; use crate::xx::*;
use crate::*; use crate::*;
use keyvaluedb_sqlite::*; use keyvaluedb_sqlite::*;
use std::path::PathBuf; use std::path::PathBuf;

View File

@ -11,7 +11,13 @@ use rtnetlink::packet::{
nlas::address::Nla, AddressMessage, AF_INET, AF_INET6, IFA_F_DADFAILED, IFA_F_DEPRECATED, nlas::address::Nla, AddressMessage, AF_INET, AF_INET6, IFA_F_DADFAILED, IFA_F_DEPRECATED,
IFA_F_OPTIMISTIC, IFA_F_PERMANENT, IFA_F_TEMPORARY, IFA_F_TENTATIVE, IFA_F_OPTIMISTIC, IFA_F_PERMANENT, IFA_F_TEMPORARY, IFA_F_TENTATIVE,
}; };
use rtnetlink::{new_connection_with_socket, sys::SmolSocket, Handle, IpVersion}; cfg_if! {
if #[cfg(feature="rt-async-std")] {
use rtnetlink::{new_connection_with_socket, sys::SmolSocket as RTNetLinkSocket, Handle, IpVersion};
} else if #[cfg(feature="rt-tokio")] {
use rtnetlink::{new_connection_with_socket, sys::TokioSocket as RTNetLinkSocket, Handle, IpVersion};
}
}
use std::convert::TryInto; use std::convert::TryInto;
use std::ffi::CStr; use std::ffi::CStr;
use std::io; use std::io;
@ -54,24 +60,16 @@ fn flags_to_address_flags(flags: u32) -> AddressFlags {
} }
pub struct PlatformSupportNetlink { pub struct PlatformSupportNetlink {
_connection_jh: intf::JoinHandle<()>, connection_jh: Option<MustJoinHandle<()>>,
handle: Handle, handle: Option<Handle>,
default_route_interfaces: BTreeSet<u32>, default_route_interfaces: BTreeSet<u32>,
} }
impl PlatformSupportNetlink { impl PlatformSupportNetlink {
pub fn new() -> Result<Self, String> { pub fn new() -> Result<Self, String> {
// Get the netlink connection
let (connection, handle, _) = new_connection_with_socket::<SmolSocket>()
.map_err(map_to_string)
.map_err(logthru_net!(error))?;
// Spawn a connection handler
let _connection_jh = intf::spawn(connection);
Ok(PlatformSupportNetlink { Ok(PlatformSupportNetlink {
_connection_jh, connection_jh: None,
handle, handle: None,
default_route_interfaces: BTreeSet::new(), default_route_interfaces: BTreeSet::new(),
}) })
} }
@ -79,7 +77,13 @@ impl PlatformSupportNetlink {
// Figure out which interfaces have default routes // Figure out which interfaces have default routes
async fn refresh_default_route_interfaces(&mut self) -> Result<(), String> { async fn refresh_default_route_interfaces(&mut self) -> Result<(), String> {
self.default_route_interfaces.clear(); self.default_route_interfaces.clear();
let mut routesv4 = self.handle.route().get(IpVersion::V4).execute(); let mut routesv4 = self
.handle
.as_ref()
.unwrap()
.route()
.get(IpVersion::V4)
.execute();
while let Some(routev4) = routesv4.try_next().await.unwrap_or_default() { while let Some(routev4) = routesv4.try_next().await.unwrap_or_default() {
if let Some(index) = routev4.output_interface() { if let Some(index) = routev4.output_interface() {
//println!("*** ipv4 route: {:#?}", routev4); //println!("*** ipv4 route: {:#?}", routev4);
@ -88,7 +92,13 @@ impl PlatformSupportNetlink {
} }
} }
} }
let mut routesv6 = self.handle.route().get(IpVersion::V6).execute(); let mut routesv6 = self
.handle
.as_ref()
.unwrap()
.route()
.get(IpVersion::V6)
.execute();
while let Some(routev6) = routesv6.try_next().await.unwrap_or_default() { while let Some(routev6) = routesv6.try_next().await.unwrap_or_default() {
if let Some(index) = routev6.output_interface() { if let Some(index) = routev6.output_interface() {
//println!("*** ipv6 route: {:#?}", routev6); //println!("*** ipv6 route: {:#?}", routev6);
@ -228,7 +238,7 @@ impl PlatformSupportNetlink {
)) ))
} }
pub async fn get_interfaces( async fn get_interfaces_internal(
&mut self, &mut self,
interfaces: &mut BTreeMap<String, NetworkInterface>, interfaces: &mut BTreeMap<String, NetworkInterface>,
) -> Result<(), String> { ) -> Result<(), String> {
@ -242,7 +252,7 @@ impl PlatformSupportNetlink {
// Ask for all the addresses we have // Ask for all the addresses we have
let mut names = BTreeMap::<u32, String>::new(); let mut names = BTreeMap::<u32, String>::new();
let mut addresses = self.handle.address().get().execute(); let mut addresses = self.handle.as_ref().unwrap().address().get().execute();
while let Some(msg) = addresses while let Some(msg) = addresses
.try_next() .try_next()
.await .await
@ -302,4 +312,30 @@ impl PlatformSupportNetlink {
Ok(()) Ok(())
} }
pub async fn get_interfaces(
&mut self,
interfaces: &mut BTreeMap<String, NetworkInterface>,
) -> Result<(), String> {
// Get the netlink connection
let (connection, handle, _) = new_connection_with_socket::<RTNetLinkSocket>()
.map_err(map_to_string)
.map_err(logthru_net!(error))?;
// Spawn a connection handler
let connection_jh = intf::spawn(connection);
// Save the connection
self.connection_jh = Some(connection_jh);
self.handle = Some(handle);
// Do the work
let out = self.get_interfaces_internal(interfaces).await;
// Clean up connection
drop(self.handle.take());
self.connection_jh.take().unwrap().abort().await;
out
}
} }

View File

@ -1,5 +1,5 @@
use crate::intf::*;
use crate::xx::*; use crate::xx::*;
use crate::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
cfg_if! { cfg_if! {

View File

@ -1,5 +1,4 @@
use crate::intf::*;
use crate::*; use crate::*;
struct BlockStoreInner { struct BlockStoreInner {

View File

@ -1,7 +1,6 @@
use super::utils; use super::utils;
use crate::xx::*; use crate::xx::*;
use crate::*; use crate::*;
pub use async_executors::JoinHandle;
use async_executors::{Bindgen, LocalSpawnHandleExt /*, SpawnHandleExt*/}; use async_executors::{Bindgen, LocalSpawnHandleExt /*, SpawnHandleExt*/};
use core::fmt; use core::fmt;
use futures_util::future::{select, Either}; use futures_util::future::{select, Either};
@ -105,23 +104,42 @@ pub fn system_boxed<'a, Out>(
Box::pin(future) Box::pin(future)
} }
pub fn spawn<Out>(future: impl Future<Output = Out> + 'static) -> JoinHandle<Out> pub fn spawn<Out>(future: impl Future<Output = Out> + 'static) -> MustJoinHandle<Out>
where
Out: Send + 'static,
{
MustJoinHandle::new(Bindgen
.spawn_handle_local(future)
.expect("wasm-bindgen-futures spawn should never error out"))
}
pub fn spawn_local<Out>(future: impl Future<Output = Out> + 'static) -> MustJoinHandle<Out>
where
Out: 'static,
{
MustJoinHandle::new(Bindgen
.spawn_handle_local(future)
.expect("wasm-bindgen-futures spawn_local should never error out"))
}
pub fn spawn_with_local_set<Out>(
future: impl Future<Output = Out> + 'static,
) -> MustJoinHandle<Out>
where
Out: Send + 'static,
{
spawn(future)
}
pub fn spawn_detached<Out>(future: impl Future<Output = Out> + 'static)
where where
Out: Send + 'static, Out: Send + 'static,
{ {
Bindgen Bindgen
.spawn_handle_local(future) .spawn_handle_local(future)
.expect("wasm-bindgen-futures spawn should never error out") .expect("wasm-bindgen-futures spawn_local should never error out").detach()
} }
pub fn spawn_local<Out>(future: impl Future<Output = Out> + 'static) -> JoinHandle<Out>
where
Out: 'static,
{
Bindgen
.spawn_handle_local(future)
.expect("wasm-bindgen-futures spawn_local should never error out")
}
pub fn interval<F, FUT>(freq_ms: u32, callback: F) -> SystemPinBoxFuture<()> pub fn interval<F, FUT>(freq_ms: u32, callback: F) -> SystemPinBoxFuture<()>
where where

View File

@ -1,5 +1,4 @@
use crate::intf::table_db::*; use crate::intf::table_db::*;
use crate::intf::*;
use crate::*; use crate::*;
use keyvaluedb_web::*; use keyvaluedb_web::*;

View File

@ -1,9 +1,19 @@
#![deny(clippy::all)] #![deny(clippy::all)]
#![deny(unused_must_use)] #![deny(unused_must_use)]
#[cfg(all(feature = "rt-async-std", feature = "rt-tokio"))]
compile_error!( cfg_if::cfg_if! {
"feature \"rt-async-std\" and feature \"rt-tokio\" cannot be enabled at the same time" if #[cfg(target_arch = "wasm32")] {
); #[cfg(any(feature = "rt-async-std", feature = "rt-tokio"))]
compile_error!("features \"rt-async-std\" and \"rt-tokio\" can not be specified for WASM");
} else {
#[cfg(all(feature = "rt-async-std", feature = "rt-tokio"))]
compile_error!(
"feature \"rt-async-std\" and feature \"rt-tokio\" cannot be enabled at the same time"
);
#[cfg(not(any(feature = "rt-async-std", feature = "rt-tokio")))]
compile_error!("exactly one of feature \"rt-async-std\" or feature \"rt-tokio\" must be specified");
}
}
#[macro_use] #[macro_use]
extern crate alloc; extern crate alloc;
@ -51,7 +61,9 @@ pub fn veilid_version() -> (u32, u32, u32) {
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
pub use intf::utils::android::{veilid_core_setup_android, veilid_core_setup_android_no_log}; pub use intf::utils::android::{veilid_core_setup_android, veilid_core_setup_android_no_log};
pub static DEFAULT_LOG_IGNORE_LIST: [&str; 10] = [ pub static DEFAULT_LOG_IGNORE_LIST: [&str; 12] = [
"mio",
"serial_test",
"async_std", "async_std",
"async_io", "async_io",
"polling", "polling",

View File

@ -43,12 +43,12 @@ impl ConnectionManager {
config: VeilidConfig, config: VeilidConfig,
stop_source: StopSource, stop_source: StopSource,
sender: flume::Sender<ConnectionManagerEvent>, sender: flume::Sender<ConnectionManagerEvent>,
async_processor_jh: JoinHandle<()>, async_processor_jh: MustJoinHandle<()>,
) -> ConnectionManagerInner { ) -> ConnectionManagerInner {
ConnectionManagerInner { ConnectionManagerInner {
stop_source: Some(stop_source), stop_source: Some(stop_source),
sender: sender, sender: sender,
async_processor_jh: Some(MustJoinHandle::new(async_processor_jh)), async_processor_jh: Some(async_processor_jh),
connection_table: ConnectionTable::new(config), connection_table: ConnectionTable::new(config),
} }
} }

View File

@ -5,7 +5,6 @@ mod protocol;
mod start_protocols; mod start_protocols;
use super::*; use super::*;
use crate::intf::*;
use crate::routing_table::*; use crate::routing_table::*;
use connection_manager::*; use connection_manager::*;
use network_tcp::*; use network_tcp::*;
@ -15,10 +14,9 @@ use protocol::ws::WebsocketProtocolHandler;
pub use protocol::*; pub use protocol::*;
use utils::network_interfaces::*; use utils::network_interfaces::*;
use async_std::io;
use async_std::net::*;
use async_tls::TlsAcceptor; use async_tls::TlsAcceptor;
use futures_util::StreamExt; use futures_util::StreamExt;
use std::io;
// xxx: rustls ^0.20 // xxx: rustls ^0.20
//use rustls::{server::NoClientAuth, Certificate, PrivateKey, ServerConfig}; //use rustls::{server::NoClientAuth, Certificate, PrivateKey, ServerConfig};
use rustls::{Certificate, NoClientAuth, PrivateKey, ServerConfig}; use rustls::{Certificate, NoClientAuth, PrivateKey, ServerConfig};
@ -26,7 +24,6 @@ use rustls_pemfile::{certs, pkcs8_private_keys, rsa_private_keys};
use std::fs::File; use std::fs::File;
use std::io::BufReader; use std::io::BufReader;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::time::Duration;
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
@ -558,12 +555,13 @@ impl Network {
let mut inner = self.inner.lock(); let mut inner = self.inner.lock();
// take the join handles out // take the join handles out
for h in inner.join_handles.drain(..) { for h in inner.join_handles.drain(..) {
trace!("joining: {:?}", h);
unord.push(h); unord.push(h);
} }
// Drop the stop // Drop the stop
drop(inner.stop_source.take()); drop(inner.stop_source.take());
} }
debug!("stopping {} low level network tasks", unord.len()); debug!("stopping {} low level network tasks", unord.len(),);
// Wait for everything to stop // Wait for everything to stop
while unord.next().await.is_some() {} while unord.next().await.is_some() {}

View File

@ -1,5 +1,4 @@
use super::*; use super::*;
use crate::intf::*;
use async_tls::TlsAcceptor; use async_tls::TlsAcceptor;
use sockets::*; use sockets::*;
use stop_token::future::FutureExt; use stop_token::future::FutureExt;
@ -43,46 +42,41 @@ impl Network {
&self, &self,
tls_acceptor: &TlsAcceptor, tls_acceptor: &TlsAcceptor,
stream: AsyncPeekStream, stream: AsyncPeekStream,
tcp_stream: TcpStream,
addr: SocketAddr, addr: SocketAddr,
protocol_handlers: &[Box<dyn ProtocolAcceptHandler>], protocol_handlers: &[Box<dyn ProtocolAcceptHandler>],
tls_connection_initial_timeout: u64, tls_connection_initial_timeout_ms: u32,
) -> Result<Option<ProtocolNetworkConnection>, String> { ) -> Result<Option<ProtocolNetworkConnection>, String> {
let ts = tls_acceptor let tls_stream = tls_acceptor
.accept(stream) .accept(stream)
.await .await
.map_err(map_to_string) .map_err(map_to_string)
.map_err(logthru_net!(debug "TLS stream failed handshake"))?; .map_err(logthru_net!(debug "TLS stream failed handshake"))?;
let ps = AsyncPeekStream::new(CloneStream::new(ts)); let ps = AsyncPeekStream::new(tls_stream);
let mut first_packet = [0u8; PEEK_DETECT_LEN]; let mut first_packet = [0u8; PEEK_DETECT_LEN];
// Try the handlers but first get a chunk of data for them to process // Try the handlers but first get a chunk of data for them to process
// Don't waste more than N seconds getting it though, in case someone // Don't waste more than N seconds getting it though, in case someone
// is trying to DoS us with a bunch of connections or something // is trying to DoS us with a bunch of connections or something
// read a chunk of the stream // read a chunk of the stream
io::timeout( intf::timeout(
Duration::from_micros(tls_connection_initial_timeout), tls_connection_initial_timeout_ms,
ps.peek_exact(&mut first_packet), ps.peek_exact(&mut first_packet),
) )
.await .await
.map_err(map_to_string)?
.map_err(map_to_string)?; .map_err(map_to_string)?;
self.try_handlers(ps, tcp_stream, addr, protocol_handlers) self.try_handlers(ps, addr, protocol_handlers).await
.await
} }
async fn try_handlers( async fn try_handlers(
&self, &self,
stream: AsyncPeekStream, stream: AsyncPeekStream,
tcp_stream: TcpStream,
addr: SocketAddr, addr: SocketAddr,
protocol_accept_handlers: &[Box<dyn ProtocolAcceptHandler>], protocol_accept_handlers: &[Box<dyn ProtocolAcceptHandler>],
) -> Result<Option<ProtocolNetworkConnection>, String> { ) -> Result<Option<ProtocolNetworkConnection>, String> {
for ah in protocol_accept_handlers.iter() { for ah in protocol_accept_handlers.iter() {
if let Some(nc) = ah if let Some(nc) = ah.on_accept(stream.clone(), addr).await? {
.on_accept(stream.clone(), tcp_stream.clone(), addr)
.await?
{
return Ok(Some(nc)); return Ok(Some(nc));
} }
} }
@ -92,11 +86,11 @@ impl Network {
async fn tcp_acceptor( async fn tcp_acceptor(
self, self,
tcp_stream: async_std::io::Result<TcpStream>, tcp_stream: io::Result<TcpStream>,
listener_state: Arc<RwLock<ListenerState>>, listener_state: Arc<RwLock<ListenerState>>,
connection_manager: ConnectionManager, connection_manager: ConnectionManager,
connection_initial_timeout: u64, connection_initial_timeout_ms: u32,
tls_connection_initial_timeout: u64, tls_connection_initial_timeout_ms: u32,
) { ) {
let tcp_stream = match tcp_stream { let tcp_stream = match tcp_stream {
Ok(v) => v, Ok(v) => v,
@ -125,14 +119,16 @@ impl Network {
log_net!("TCP connection from: {}", addr); log_net!("TCP connection from: {}", addr);
// Create a stream we can peek on // Create a stream we can peek on
let ps = AsyncPeekStream::new(tcp_stream.clone()); #[cfg(feature = "rt-tokio")]
let tcp_stream = tcp_stream.compat();
let ps = AsyncPeekStream::new(tcp_stream);
///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////
let mut first_packet = [0u8; PEEK_DETECT_LEN]; let mut first_packet = [0u8; PEEK_DETECT_LEN];
// read a chunk of the stream // read a chunk of the stream
if io::timeout( if timeout(
Duration::from_micros(connection_initial_timeout), connection_initial_timeout_ms,
ps.peek_exact(&mut first_packet), ps.peek_exact(&mut first_packet),
) )
.await .await
@ -153,14 +149,13 @@ impl Network {
self.try_tls_handlers( self.try_tls_handlers(
ls.tls_acceptor.as_ref().unwrap(), ls.tls_acceptor.as_ref().unwrap(),
ps, ps,
tcp_stream,
addr, addr,
&ls.tls_protocol_handlers, &ls.tls_protocol_handlers,
tls_connection_initial_timeout, tls_connection_initial_timeout_ms,
) )
.await .await
} else { } else {
self.try_handlers(ps, tcp_stream, addr, &ls.protocol_accept_handlers) self.try_handlers(ps, addr, &ls.protocol_accept_handlers)
.await .await
}; };
@ -192,11 +187,11 @@ impl Network {
async fn spawn_socket_listener(&self, addr: SocketAddr) -> Result<(), String> { async fn spawn_socket_listener(&self, addr: SocketAddr) -> Result<(), String> {
// Get config // Get config
let (connection_initial_timeout, tls_connection_initial_timeout) = { let (connection_initial_timeout_ms, tls_connection_initial_timeout_ms) = {
let c = self.config.get(); let c = self.config.get();
( (
ms_to_us(c.network.connection_initial_timeout_ms), c.network.connection_initial_timeout_ms,
ms_to_us(c.network.tls.connection_initial_timeout_ms), c.network.tls.connection_initial_timeout_ms,
) )
}; };
@ -209,7 +204,13 @@ impl Network {
// Make an async tcplistener from the socket2 socket // Make an async tcplistener from the socket2 socket
let std_listener: std::net::TcpListener = socket.into(); let std_listener: std::net::TcpListener = socket.into();
let listener = TcpListener::from(std_listener); cfg_if! {
if #[cfg(feature="rt-async-std")] {
let listener = TcpListener::from(std_listener);
} else if #[cfg(feature="rt-tokio")] {
let listener = TcpListener::from_std(std_listener).map_err(map_to_string)?;
}
}
debug!("spawn_socket_listener: binding successful to {}", addr); debug!("spawn_socket_listener: binding successful to {}", addr);
@ -229,8 +230,16 @@ impl Network {
let jh = spawn(async move { let jh = spawn(async move {
// moves listener object in and get incoming iterator // moves listener object in and get incoming iterator
// when this task exists, the listener will close the socket // when this task exists, the listener will close the socket
let _ = listener
.incoming() cfg_if! {
if #[cfg(feature="rt-async-std")] {
let incoming_stream = listener.incoming();
} else if #[cfg(feature="rt-tokio")] {
let incoming_stream = tokio_stream::wrappers::TcpListenerStream::new(listener);
}
}
let _ = incoming_stream
.for_each_concurrent(None, |tcp_stream| { .for_each_concurrent(None, |tcp_stream| {
let this = this.clone(); let this = this.clone();
let listener_state = listener_state.clone(); let listener_state = listener_state.clone();
@ -240,8 +249,8 @@ impl Network {
tcp_stream, tcp_stream,
listener_state, listener_state,
connection_manager, connection_manager,
connection_initial_timeout, connection_initial_timeout_ms,
tls_connection_initial_timeout, tls_connection_initial_timeout_ms,
) )
}) })
.timeout_at(stop_token) .timeout_at(stop_token)
@ -255,7 +264,7 @@ impl Network {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Add to join handles // Add to join handles
self.add_to_join_handles(MustJoinHandle::new(jh)); self.add_to_join_handles(jh);
Ok(()) Ok(())
} }

View File

@ -23,7 +23,7 @@ impl Network {
// Run thread task to process stream of messages // Run thread task to process stream of messages
let this = self.clone(); let this = self.clone();
let jh = spawn(async move { let jh = spawn_with_local_set(async move {
trace!("UDP listener task spawned"); trace!("UDP listener task spawned");
// Collect all our protocol handlers into a vector // Collect all our protocol handlers into a vector
@ -49,7 +49,7 @@ impl Network {
for ph in protocol_handlers { for ph in protocol_handlers {
let network_manager = network_manager.clone(); let network_manager = network_manager.clone();
let stop_token = stop_token.clone(); let stop_token = stop_token.clone();
let jh = spawn_local(async move { let jh = intf::spawn_local(async move {
let mut data = vec![0u8; 65536]; let mut data = vec![0u8; 65536];
loop { loop {
@ -112,7 +112,7 @@ impl Network {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Add to join handle // Add to join handle
self.add_to_join_handles(MustJoinHandle::new(jh)); self.add_to_join_handles(jh);
} }
Ok(()) Ok(())
@ -134,7 +134,13 @@ impl Network {
// Make an async UdpSocket from the socket2 socket // Make an async UdpSocket from the socket2 socket
let std_udp_socket: std::net::UdpSocket = socket.into(); let std_udp_socket: std::net::UdpSocket = socket.into();
let udp_socket = UdpSocket::from(std_udp_socket); cfg_if! {
if #[cfg(feature="rt-async-std")] {
let udp_socket = UdpSocket::from(std_udp_socket);
} else if #[cfg(feature="rt-tokio")] {
let udp_socket = UdpSocket::from_std(std_udp_socket).map_err(map_to_string)?;
}
}
let socket_arc = Arc::new(udp_socket); let socket_arc = Arc::new(udp_socket);
// Create protocol handler // Create protocol handler
@ -148,7 +154,13 @@ impl Network {
if let Ok(socket) = new_bound_shared_udp_socket(socket_addr_v6) { if let Ok(socket) = new_bound_shared_udp_socket(socket_addr_v6) {
// Make an async UdpSocket from the socket2 socket // Make an async UdpSocket from the socket2 socket
let std_udp_socket: std::net::UdpSocket = socket.into(); let std_udp_socket: std::net::UdpSocket = socket.into();
let udp_socket = UdpSocket::from(std_udp_socket); cfg_if! {
if #[cfg(feature="rt-async-std")] {
let udp_socket = UdpSocket::from(std_udp_socket);
} else if #[cfg(feature="rt-tokio")] {
let udp_socket = UdpSocket::from_std(std_udp_socket).map_err(map_to_string)?;
}
}
let socket_arc = Arc::new(udp_socket); let socket_arc = Arc::new(udp_socket);
// Create protocol handler // Create protocol handler
@ -168,7 +180,13 @@ impl Network {
// Make an async UdpSocket from the socket2 socket // Make an async UdpSocket from the socket2 socket
let std_udp_socket: std::net::UdpSocket = socket.into(); let std_udp_socket: std::net::UdpSocket = socket.into();
let udp_socket = UdpSocket::from(std_udp_socket); cfg_if! {
if #[cfg(feature="rt-async-std")] {
let udp_socket = UdpSocket::from(std_udp_socket);
} else if #[cfg(feature="rt-tokio")] {
let udp_socket = UdpSocket::from_std(std_udp_socket).map_err(map_to_string)?;
}
}
let socket_arc = Arc::new(udp_socket); let socket_arc = Arc::new(udp_socket);
// Create protocol handler // Create protocol handler

View File

@ -92,15 +92,15 @@ impl ProtocolNetworkConnection {
} }
} }
pub async fn close(&self) -> Result<(), String> { // pub async fn close(&self) -> Result<(), String> {
match self { // match self {
Self::Dummy(d) => d.close(), // Self::Dummy(d) => d.close(),
Self::RawTcp(t) => t.close().await, // Self::RawTcp(t) => t.close().await,
Self::WsAccepted(w) => w.close().await, // Self::WsAccepted(w) => w.close().await,
Self::Ws(w) => w.close().await, // Self::Ws(w) => w.close().await,
Self::Wss(w) => w.close().await, // Self::Wss(w) => w.close().await,
} // }
} // }
pub async fn send(&self, message: Vec<u8>) -> Result<(), String> { pub async fn send(&self, message: Vec<u8>) -> Result<(), String> {
match self { match self {

View File

@ -1,7 +1,15 @@
use crate::xx::*; use crate::xx::*;
use crate::*; use crate::*;
use async_io::Async; use async_io::Async;
use async_std::net::TcpStream; cfg_if! {
if #[cfg(feature="rt-async-std")] {
pub use async_std::net::{TcpStream, TcpListener, Shutdown, UdpSocket};
} else if #[cfg(feature="rt-tokio")] {
pub use tokio::net::{TcpStream, TcpListener, UdpSocket};
pub use tokio_util::compat::*;
}
}
use socket2::{Domain, Protocol, SockAddr, Socket, Type}; use socket2::{Domain, Protocol, SockAddr, Socket, Type};
cfg_if! { cfg_if! {
@ -218,5 +226,11 @@ pub async fn nonblocking_connect(socket: Socket, addr: SocketAddr) -> std::io::R
}?; }?;
// Convert back to inner and then return async version // Convert back to inner and then return async version
Ok(TcpStream::from(async_stream.into_inner()?)) cfg_if! {
if #[cfg(feature="rt-async-std")] {
Ok(TcpStream::from(async_stream.into_inner()?))
} else if #[cfg(feature="rt-tokio")] {
Ok(TcpStream::from_std(async_stream.into_inner()?)?)
}
}
} }

View File

@ -5,7 +5,6 @@ use sockets::*;
pub struct RawTcpNetworkConnection { pub struct RawTcpNetworkConnection {
descriptor: ConnectionDescriptor, descriptor: ConnectionDescriptor,
stream: AsyncPeekStream, stream: AsyncPeekStream,
tcp_stream: TcpStream,
} }
impl fmt::Debug for RawTcpNetworkConnection { impl fmt::Debug for RawTcpNetworkConnection {
@ -15,31 +14,33 @@ impl fmt::Debug for RawTcpNetworkConnection {
} }
impl RawTcpNetworkConnection { impl RawTcpNetworkConnection {
pub fn new( pub fn new(descriptor: ConnectionDescriptor, stream: AsyncPeekStream) -> Self {
descriptor: ConnectionDescriptor, Self { descriptor, stream }
stream: AsyncPeekStream,
tcp_stream: TcpStream,
) -> Self {
Self {
descriptor,
stream,
tcp_stream,
}
} }
pub fn descriptor(&self) -> ConnectionDescriptor { pub fn descriptor(&self) -> ConnectionDescriptor {
self.descriptor.clone() self.descriptor.clone()
} }
#[instrument(level = "trace", err, skip(self))] // #[instrument(level = "trace", err, skip(self))]
pub async fn close(&self) -> Result<(), String> { // pub async fn close(&mut self) -> Result<(), String> {
// Make an attempt to flush the stream // // Make an attempt to flush the stream
self.stream.clone().close().await.map_err(map_to_string)?; // self.stream.clone().close().await.map_err(map_to_string)?;
// Then forcibly close the socket // // Then shut down the write side of the socket to effect a clean close
self.tcp_stream // cfg_if! {
.shutdown(Shutdown::Both) // if #[cfg(feature="rt-async-std")] {
.map_err(map_to_string) // self.tcp_stream
} // .shutdown(async_std::net::Shutdown::Write)
// .map_err(map_to_string)
// } else if #[cfg(feature="rt-tokio")] {
// use tokio::io::AsyncWriteExt;
// self.tcp_stream.get_mut()
// .shutdown()
// .await
// .map_err(map_to_string)
// }
// }
// }
async fn send_internal(stream: &mut AsyncPeekStream, message: Vec<u8>) -> Result<(), String> { async fn send_internal(stream: &mut AsyncPeekStream, message: Vec<u8>) -> Result<(), String> {
log_net!("sending TCP message of size {}", message.len()); log_net!("sending TCP message of size {}", message.len());
@ -115,11 +116,10 @@ impl RawTcpProtocolHandler {
} }
} }
#[instrument(level = "trace", err, skip(self, stream, tcp_stream))] #[instrument(level = "trace", err, skip(self, stream))]
async fn on_accept_async( async fn on_accept_async(
self, self,
stream: AsyncPeekStream, stream: AsyncPeekStream,
tcp_stream: TcpStream,
socket_addr: SocketAddr, socket_addr: SocketAddr,
) -> Result<Option<ProtocolNetworkConnection>, String> { ) -> Result<Option<ProtocolNetworkConnection>, String> {
log_net!("TCP: on_accept_async: enter"); log_net!("TCP: on_accept_async: enter");
@ -139,7 +139,6 @@ impl RawTcpProtocolHandler {
let conn = ProtocolNetworkConnection::RawTcp(RawTcpNetworkConnection::new( let conn = ProtocolNetworkConnection::RawTcp(RawTcpNetworkConnection::new(
ConnectionDescriptor::new(peer_addr, SocketAddress::from_socket_addr(local_address)), ConnectionDescriptor::new(peer_addr, SocketAddress::from_socket_addr(local_address)),
stream, stream,
tcp_stream,
)); ));
log_net!(debug "TCP: on_accept_async from: {}", socket_addr); log_net!(debug "TCP: on_accept_async from: {}", socket_addr);
@ -173,7 +172,9 @@ impl RawTcpProtocolHandler {
.local_addr() .local_addr()
.map_err(map_to_string) .map_err(map_to_string)
.map_err(logthru_net!("could not get local address from TCP stream"))?; .map_err(logthru_net!("could not get local address from TCP stream"))?;
let ps = AsyncPeekStream::new(ts.clone()); #[cfg(feature = "rt-tokio")]
let ts = ts.compat();
let ps = AsyncPeekStream::new(ts);
// Wrap the stream in a network connection and return it // Wrap the stream in a network connection and return it
let conn = ProtocolNetworkConnection::RawTcp(RawTcpNetworkConnection::new( let conn = ProtocolNetworkConnection::RawTcp(RawTcpNetworkConnection::new(
@ -182,7 +183,6 @@ impl RawTcpProtocolHandler {
SocketAddress::from_socket_addr(actual_local_address), SocketAddress::from_socket_addr(actual_local_address),
), ),
ps, ps,
ts,
)); ));
Ok(conn) Ok(conn)
@ -216,7 +216,10 @@ impl RawTcpProtocolHandler {
// .local_addr() // .local_addr()
// .map_err(map_to_string) // .map_err(map_to_string)
// .map_err(logthru_net!("could not get local address from TCP stream"))?; // .map_err(logthru_net!("could not get local address from TCP stream"))?;
let mut ps = AsyncPeekStream::new(ts.clone());
#[cfg(feature = "rt-tokio")]
let ts = ts.compat();
let mut ps = AsyncPeekStream::new(ts);
// Send directly from the raw network connection // Send directly from the raw network connection
// this builds the connection and tears it down immediately after the send // this builds the connection and tears it down immediately after the send
@ -252,7 +255,9 @@ impl RawTcpProtocolHandler {
// .local_addr() // .local_addr()
// .map_err(map_to_string) // .map_err(map_to_string)
// .map_err(logthru_net!("could not get local address from TCP stream"))?; // .map_err(logthru_net!("could not get local address from TCP stream"))?;
let mut ps = AsyncPeekStream::new(ts.clone()); #[cfg(feature = "rt-tokio")]
let ts = ts.compat();
let mut ps = AsyncPeekStream::new(ts);
// Send directly from the raw network connection // Send directly from the raw network connection
// this builds the connection and tears it down immediately after the send // this builds the connection and tears it down immediately after the send
@ -271,9 +276,8 @@ impl ProtocolAcceptHandler for RawTcpProtocolHandler {
fn on_accept( fn on_accept(
&self, &self,
stream: AsyncPeekStream, stream: AsyncPeekStream,
tcp_stream: TcpStream,
peer_addr: SocketAddr, peer_addr: SocketAddr,
) -> SystemPinBoxFuture<core::result::Result<Option<ProtocolNetworkConnection>, String>> { ) -> SystemPinBoxFuture<core::result::Result<Option<ProtocolNetworkConnection>, String>> {
Box::pin(self.clone().on_accept_async(stream, tcp_stream, peer_addr)) Box::pin(self.clone().on_accept_async(stream, peer_addr))
} }
} }

View File

@ -1,4 +1,5 @@
use super::*; use super::*;
use sockets::*;
#[derive(Clone)] #[derive(Clone)]
pub struct RawUdpProtocolHandler { pub struct RawUdpProtocolHandler {

View File

@ -1,28 +1,35 @@
use super::*; use super::*;
use async_std::io;
use async_tls::TlsConnector; use async_tls::TlsConnector;
use async_tungstenite::tungstenite::protocol::Message; use async_tungstenite::tungstenite::protocol::Message;
use async_tungstenite::{accept_async, client_async, WebSocketStream}; use async_tungstenite::{accept_async, client_async, WebSocketStream};
use futures_util::SinkExt; use futures_util::{AsyncRead, AsyncWrite, SinkExt};
use sockets::*; use sockets::*;
cfg_if! {
if #[cfg(feature="rt-async-std")] {
pub type WebsocketNetworkConnectionWSS =
WebsocketNetworkConnection<async_tls::client::TlsStream<TcpStream>>;
pub type WebsocketNetworkConnectionWS = WebsocketNetworkConnection<TcpStream>;
} else if #[cfg(feature="rt-tokio")] {
pub type WebsocketNetworkConnectionWSS =
WebsocketNetworkConnection<async_tls::client::TlsStream<Compat<TcpStream>>>;
pub type WebsocketNetworkConnectionWS = WebsocketNetworkConnection<Compat<TcpStream>>;
}
}
pub type WebSocketNetworkConnectionAccepted = WebsocketNetworkConnection<AsyncPeekStream>; pub type WebSocketNetworkConnectionAccepted = WebsocketNetworkConnection<AsyncPeekStream>;
pub type WebsocketNetworkConnectionWSS =
WebsocketNetworkConnection<async_tls::client::TlsStream<TcpStream>>;
pub type WebsocketNetworkConnectionWS = WebsocketNetworkConnection<TcpStream>;
pub struct WebsocketNetworkConnection<T> pub struct WebsocketNetworkConnection<T>
where where
T: io::Read + io::Write + Send + Unpin + 'static, T: AsyncRead + AsyncWrite + Send + Unpin + 'static,
{ {
descriptor: ConnectionDescriptor, descriptor: ConnectionDescriptor,
stream: CloneStream<WebSocketStream<T>>, stream: CloneStream<WebSocketStream<T>>,
tcp_stream: TcpStream,
} }
impl<T> fmt::Debug for WebsocketNetworkConnection<T> impl<T> fmt::Debug for WebsocketNetworkConnection<T>
where where
T: io::Read + io::Write + Send + Unpin + 'static, T: AsyncRead + AsyncWrite + Send + Unpin + 'static,
{ {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", std::any::type_name::<Self>()) write!(f, "{}", std::any::type_name::<Self>())
@ -31,17 +38,12 @@ where
impl<T> WebsocketNetworkConnection<T> impl<T> WebsocketNetworkConnection<T>
where where
T: io::Read + io::Write + Send + Unpin + 'static, T: AsyncRead + AsyncWrite + Send + Unpin + 'static,
{ {
pub fn new( pub fn new(descriptor: ConnectionDescriptor, stream: WebSocketStream<T>) -> Self {
descriptor: ConnectionDescriptor,
stream: WebSocketStream<T>,
tcp_stream: TcpStream,
) -> Self {
Self { Self {
descriptor, descriptor,
stream: CloneStream::new(stream), stream: CloneStream::new(stream),
tcp_stream,
} }
} }
@ -49,15 +51,15 @@ where
self.descriptor.clone() self.descriptor.clone()
} }
#[instrument(level = "trace", err, skip(self))] // #[instrument(level = "trace", err, skip(self))]
pub async fn close(&self) -> Result<(), String> { // pub async fn close(&self) -> Result<(), String> {
// Make an attempt to flush the stream // // Make an attempt to flush the stream
self.stream.clone().close().await.map_err(map_to_string)?; // self.stream.clone().close().await.map_err(map_to_string)?;
// Then forcibly close the socket // // Then forcibly close the socket
self.tcp_stream // self.tcp_stream
.shutdown(Shutdown::Both) // .shutdown(Shutdown::Both)
.map_err(map_to_string) // .map_err(map_to_string)
} // }
#[instrument(level = "trace", err, skip(self, message), fields(message.len = message.len()))] #[instrument(level = "trace", err, skip(self, message), fields(message.len = message.len()))]
pub async fn send(&self, message: Vec<u8>) -> Result<(), String> { pub async fn send(&self, message: Vec<u8>) -> Result<(), String> {
@ -101,7 +103,7 @@ struct WebsocketProtocolHandlerArc {
tls: bool, tls: bool,
local_address: SocketAddr, local_address: SocketAddr,
request_path: Vec<u8>, request_path: Vec<u8>,
connection_initial_timeout: u64, connection_initial_timeout_ms: u32,
} }
#[derive(Clone)] #[derive(Clone)]
@ -119,10 +121,10 @@ impl WebsocketProtocolHandler {
} else { } else {
format!("GET /{}", c.network.protocol.wss.path.trim_end_matches('/')) format!("GET /{}", c.network.protocol.wss.path.trim_end_matches('/'))
}; };
let connection_initial_timeout = if tls { let connection_initial_timeout_ms = if tls {
ms_to_us(c.network.tls.connection_initial_timeout_ms) c.network.tls.connection_initial_timeout_ms
} else { } else {
ms_to_us(c.network.connection_initial_timeout_ms) c.network.connection_initial_timeout_ms
}; };
Self { Self {
@ -130,34 +132,30 @@ impl WebsocketProtocolHandler {
tls, tls,
local_address, local_address,
request_path: path.as_bytes().to_vec(), request_path: path.as_bytes().to_vec(),
connection_initial_timeout, connection_initial_timeout_ms,
}), }),
} }
} }
#[instrument(level = "trace", err, skip(self, ps, tcp_stream))] #[instrument(level = "trace", err, skip(self, ps))]
pub async fn on_accept_async( pub async fn on_accept_async(
self, self,
ps: AsyncPeekStream, ps: AsyncPeekStream,
tcp_stream: TcpStream,
socket_addr: SocketAddr, socket_addr: SocketAddr,
) -> Result<Option<ProtocolNetworkConnection>, String> { ) -> Result<Option<ProtocolNetworkConnection>, String> {
log_net!("WS: on_accept_async: enter"); log_net!("WS: on_accept_async: enter");
let request_path_len = self.arc.request_path.len() + 2; let request_path_len = self.arc.request_path.len() + 2;
let mut peekbuf: Vec<u8> = vec![0u8; request_path_len]; let mut peekbuf: Vec<u8> = vec![0u8; request_path_len];
match io::timeout( match timeout(
Duration::from_micros(self.arc.connection_initial_timeout), self.arc.connection_initial_timeout_ms,
ps.peek_exact(&mut peekbuf), ps.peek_exact(&mut peekbuf),
) )
.await .await
{ {
Ok(_) => (), Ok(_) => (),
Err(e) => { Err(e) => {
if e.kind() == io::ErrorKind::TimedOut { return Err(e.to_string());
return Err(e).map_err(map_to_string);
}
return Err(e).map_err(map_to_string);
} }
} }
@ -194,7 +192,6 @@ impl WebsocketProtocolHandler {
SocketAddress::from_socket_addr(self.arc.local_address), SocketAddress::from_socket_addr(self.arc.local_address),
), ),
ws_stream, ws_stream,
tcp_stream,
)); ));
log_net!(debug "{}: on_accept_async from: {}", if self.arc.tls { "WSS" } else { "WS" }, socket_addr); log_net!(debug "{}: on_accept_async from: {}", if self.arc.tls { "WSS" } else { "WS" }, socket_addr);
@ -238,6 +235,9 @@ impl WebsocketProtocolHandler {
// See what local address we ended up with // See what local address we ended up with
let actual_local_addr = tcp_stream.local_addr().map_err(map_to_string)?; let actual_local_addr = tcp_stream.local_addr().map_err(map_to_string)?;
#[cfg(feature = "rt-tokio")]
let tcp_stream = tcp_stream.compat();
// Make our connection descriptor // Make our connection descriptor
let descriptor = ConnectionDescriptor::new( let descriptor = ConnectionDescriptor::new(
dial_info.to_peer_address(), dial_info.to_peer_address(),
@ -247,7 +247,7 @@ impl WebsocketProtocolHandler {
if tls { if tls {
let connector = TlsConnector::default(); let connector = TlsConnector::default();
let tls_stream = connector let tls_stream = connector
.connect(domain.to_string(), tcp_stream.clone()) .connect(domain.to_string(), tcp_stream)
.await .await
.map_err(map_to_string) .map_err(map_to_string)
.map_err(logthru_net!(error))?; .map_err(logthru_net!(error))?;
@ -257,15 +257,15 @@ impl WebsocketProtocolHandler {
.map_err(logthru_net!(error))?; .map_err(logthru_net!(error))?;
Ok(ProtocolNetworkConnection::Wss( Ok(ProtocolNetworkConnection::Wss(
WebsocketNetworkConnection::new(descriptor, ws_stream, tcp_stream), WebsocketNetworkConnection::new(descriptor, ws_stream),
)) ))
} else { } else {
let (ws_stream, _response) = client_async(request, tcp_stream.clone()) let (ws_stream, _response) = client_async(request, tcp_stream)
.await .await
.map_err(map_to_string) .map_err(map_to_string)
.map_err(logthru_net!(error))?; .map_err(logthru_net!(error))?;
Ok(ProtocolNetworkConnection::Ws( Ok(ProtocolNetworkConnection::Ws(
WebsocketNetworkConnection::new(descriptor, ws_stream, tcp_stream), WebsocketNetworkConnection::new(descriptor, ws_stream),
)) ))
} }
} }
@ -319,9 +319,8 @@ impl ProtocolAcceptHandler for WebsocketProtocolHandler {
fn on_accept( fn on_accept(
&self, &self,
stream: AsyncPeekStream, stream: AsyncPeekStream,
tcp_stream: TcpStream,
peer_addr: SocketAddr, peer_addr: SocketAddr,
) -> SystemPinBoxFuture<Result<Option<ProtocolNetworkConnection>, String>> { ) -> SystemPinBoxFuture<Result<Option<ProtocolNetworkConnection>, String>> {
Box::pin(self.clone().on_accept_async(stream, tcp_stream, peer_addr)) Box::pin(self.clone().on_accept_async(stream, peer_addr))
} }
} }

View File

@ -319,7 +319,6 @@ impl Network {
// Resolve statically configured public dialinfo // Resolve statically configured public dialinfo
let mut public_sockaddrs = public_address let mut public_sockaddrs = public_address
.to_socket_addrs() .to_socket_addrs()
.await
.map_err(|e| format!("Unable to resolve address: {}\n{}", public_address, e))?; .map_err(|e| format!("Unable to resolve address: {}\n{}", public_address, e))?;
// Add all resolved addresses as public dialinfo // Add all resolved addresses as public dialinfo
@ -416,7 +415,6 @@ impl Network {
let global_socket_addrs = split_url let global_socket_addrs = split_url
.host_port(80) .host_port(80)
.to_socket_addrs() .to_socket_addrs()
.await
.map_err(map_to_string) .map_err(map_to_string)
.map_err(logthru_net!(error))?; .map_err(logthru_net!(error))?;
@ -548,7 +546,6 @@ impl Network {
let global_socket_addrs = split_url let global_socket_addrs = split_url
.host_port(443) .host_port(443)
.to_socket_addrs() .to_socket_addrs()
.await
.map_err(map_to_string) .map_err(map_to_string)
.map_err(logthru_net!(error))?; .map_err(logthru_net!(error))?;
@ -662,7 +659,6 @@ impl Network {
// Resolve statically configured public dialinfo // Resolve statically configured public dialinfo
let mut public_sockaddrs = public_address let mut public_sockaddrs = public_address
.to_socket_addrs() .to_socket_addrs()
.await
.map_err(|e| format!("Unable to resolve address: {}\n{}", public_address, e))?; .map_err(|e| format!("Unable to resolve address: {}\n{}", public_address, e))?;
// Add all resolved addresses as public dialinfo // Add all resolved addresses as public dialinfo

View File

@ -6,7 +6,6 @@ cfg_if::cfg_if! {
if #[cfg(target_arch = "wasm32")] { if #[cfg(target_arch = "wasm32")] {
// No accept support for WASM // No accept support for WASM
} else { } else {
use async_std::net::*;
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
// Accept // Accept
@ -15,7 +14,6 @@ cfg_if::cfg_if! {
fn on_accept( fn on_accept(
&self, &self,
stream: AsyncPeekStream, stream: AsyncPeekStream,
tcp_stream: TcpStream,
peer_addr: SocketAddr, peer_addr: SocketAddr,
) -> SystemPinBoxFuture<Result<Option<ProtocolNetworkConnection>, String>>; ) -> SystemPinBoxFuture<Result<Option<ProtocolNetworkConnection>, String>>;
} }
@ -139,7 +137,7 @@ impl NetworkConnection {
let local_stop_token = stop_source.token(); let local_stop_token = stop_source.token();
// Spawn connection processor and pass in protocol connection // Spawn connection processor and pass in protocol connection
let processor = MustJoinHandle::new(intf::spawn_local(Self::process_connection( let processor = intf::spawn_local(Self::process_connection(
connection_manager, connection_manager,
local_stop_token, local_stop_token,
manager_stop_token, manager_stop_token,
@ -148,7 +146,7 @@ impl NetworkConnection {
protocol_connection, protocol_connection,
inactivity_timeout, inactivity_timeout,
stats.clone(), stats.clone(),
))); ));
// Return the connection // Return the connection
Self { Self {

View File

@ -82,7 +82,7 @@ impl Bucket {
.iter() .iter()
.map(|(k, v)| (k.clone(), v.clone())) .map(|(k, v)| (k.clone(), v.clone()))
.collect(); .collect();
let cur_ts = get_timestamp(); let cur_ts = intf::get_timestamp();
sorted_entries.sort_by(|a, b| -> core::cmp::Ordering { sorted_entries.sort_by(|a, b| -> core::cmp::Ordering {
if a.0 == b.0 { if a.0 == b.0 {
return core::cmp::Ordering::Equal; return core::cmp::Ordering::Equal;

View File

@ -418,7 +418,7 @@ pub struct BucketEntry {
impl BucketEntry { impl BucketEntry {
pub(super) fn new() -> Self { pub(super) fn new() -> Self {
let now = get_timestamp(); let now = intf::get_timestamp();
Self { Self {
ref_count: AtomicU32::new(0), ref_count: AtomicU32::new(0),
inner: RwLock::new(BucketEntryInner { inner: RwLock::new(BucketEntryInner {

View File

@ -89,7 +89,7 @@ impl RoutingTable {
pub fn debug_info_entries(&self, limit: usize, min_state: BucketEntryState) -> String { pub fn debug_info_entries(&self, limit: usize, min_state: BucketEntryState) -> String {
let inner = self.inner.read(); let inner = self.inner.read();
let cur_ts = get_timestamp(); let cur_ts = intf::get_timestamp();
let mut out = String::new(); let mut out = String::new();
@ -148,7 +148,7 @@ impl RoutingTable {
pub fn debug_info_buckets(&self, min_state: BucketEntryState) -> String { pub fn debug_info_buckets(&self, min_state: BucketEntryState) -> String {
let inner = self.inner.read(); let inner = self.inner.read();
let cur_ts = get_timestamp(); let cur_ts = intf::get_timestamp();
let mut out = String::new(); let mut out = String::new();
const COLS: usize = 16; const COLS: usize = 16;

View File

@ -1,7 +1,6 @@
use super::*; use super::*;
use crate::dht::*; use crate::dht::*;
use crate::intf::*;
use crate::xx::*; use crate::xx::*;
use crate::*; use crate::*;
@ -219,7 +218,7 @@ impl RoutingTable {
F: FnMut(DHTKey, Option<Arc<BucketEntry>>) -> bool, F: FnMut(DHTKey, Option<Arc<BucketEntry>>) -> bool,
T: FnMut(DHTKey, Option<Arc<BucketEntry>>) -> O, T: FnMut(DHTKey, Option<Arc<BucketEntry>>) -> O,
{ {
let cur_ts = get_timestamp(); let cur_ts = intf::get_timestamp();
let out = self.find_peers_with_sort_and_filter( let out = self.find_peers_with_sort_and_filter(
node_count, node_count,
cur_ts, cur_ts,
@ -301,7 +300,7 @@ impl RoutingTable {
T: FnMut(DHTKey, Option<Arc<BucketEntry>>) -> O, T: FnMut(DHTKey, Option<Arc<BucketEntry>>) -> O,
F: FnMut(DHTKey, Option<Arc<BucketEntry>>) -> bool, F: FnMut(DHTKey, Option<Arc<BucketEntry>>) -> bool,
{ {
let cur_ts = get_timestamp(); let cur_ts = intf::get_timestamp();
let node_count = { let node_count = {
let c = self.config.get(); let c = self.config.get();
c.network.dht.max_find_node_count as usize c.network.dht.max_find_node_count as usize

View File

@ -7,7 +7,6 @@ mod stats_accounting;
mod tasks; mod tasks;
use crate::dht::*; use crate::dht::*;
use crate::intf::*;
use crate::network_manager::*; use crate::network_manager::*;
use crate::rpc_processor::*; use crate::rpc_processor::*;
use crate::xx::*; use crate::xx::*;

View File

@ -369,9 +369,7 @@ impl RoutingTable {
Self::with_entries(&*inner, cur_ts, BucketEntryState::Unreliable, |k, v| { Self::with_entries(&*inner, cur_ts, BucketEntryState::Unreliable, |k, v| {
if v.with(|e| e.needs_ping(&k, cur_ts, relay_node_id)) { if v.with(|e| e.needs_ping(&k, cur_ts, relay_node_id)) {
let nr = NodeRef::new(self.clone(), k, v, None); let nr = NodeRef::new(self.clone(), k, v, None);
unord.push(MustJoinHandle::new(intf::spawn_local( unord.push(intf::spawn_local(rpc.clone().rpc_call_status(nr)));
rpc.clone().rpc_call_status(nr),
)));
} }
Option::<()>::None Option::<()>::None
}); });

View File

@ -6,7 +6,6 @@ pub use debug::*;
pub use private_route::*; pub use private_route::*;
use crate::dht::*; use crate::dht::*;
use crate::intf::*;
use crate::xx::*; use crate::xx::*;
use capnp::message::ReaderSegments; use capnp::message::ReaderSegments;
use coders::*; use coders::*;
@ -228,7 +227,7 @@ impl RPCProcessor {
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
fn get_next_op_id(&self) -> OperationId { fn get_next_op_id(&self) -> OperationId {
get_random_u64() intf::get_random_u64()
} }
fn filter_peer_scope(&self, node_info: &NodeInfo) -> bool { fn filter_peer_scope(&self, node_info: &NodeInfo) -> bool {
@ -365,12 +364,12 @@ impl RPCProcessor {
let timeout_ms = u32::try_from(waitable_reply.timeout / 1000u64) let timeout_ms = u32::try_from(waitable_reply.timeout / 1000u64)
.map_err(map_error_internal!("invalid timeout"))?; .map_err(map_error_internal!("invalid timeout"))?;
// wait for eventualvalue // wait for eventualvalue
let start_ts = get_timestamp(); let start_ts = intf::get_timestamp();
let res = timeout(timeout_ms, waitable_reply.eventual.instance()) let res = intf::timeout(timeout_ms, waitable_reply.eventual.instance())
.await .await
.map_err(|_| RPCError::Timeout)?; .map_err(|_| RPCError::Timeout)?;
let rpcreader = res.take_value().unwrap(); let rpcreader = res.take_value().unwrap();
let end_ts = get_timestamp(); let end_ts = intf::get_timestamp();
Ok((rpcreader, end_ts - start_ts)) Ok((rpcreader, end_ts - start_ts))
} }
async fn wait_for_reply( async fn wait_for_reply(
@ -390,7 +389,7 @@ impl RPCProcessor {
waitable_reply.node_ref.set_seen_our_node_info(); waitable_reply.node_ref.set_seen_our_node_info();
// Reply received // Reply received
let recv_ts = get_timestamp(); let recv_ts = intf::get_timestamp();
self.routing_table().stats_answer_rcvd( self.routing_table().stats_answer_rcvd(
waitable_reply.node_ref, waitable_reply.node_ref,
waitable_reply.send_ts, waitable_reply.send_ts,
@ -554,7 +553,7 @@ impl RPCProcessor {
log_rpc!(debug "==>> REQUEST({}) -> {:?}", self.get_rpc_message_debug_info(&message), dest); log_rpc!(debug "==>> REQUEST({}) -> {:?}", self.get_rpc_message_debug_info(&message), dest);
let bytes = out.len() as u64; let bytes = out.len() as u64;
let send_ts = get_timestamp(); let send_ts = intf::get_timestamp();
let send_data_kind = match self let send_data_kind = match self
.network_manager() .network_manager()
.send_envelope(node_ref.clone(), Some(out_node_id), out) .send_envelope(node_ref.clone(), Some(out_node_id), out)
@ -745,7 +744,7 @@ impl RPCProcessor {
}, },
node_ref); node_ref);
let bytes = out.len() as u64; let bytes = out.len() as u64;
let send_ts = get_timestamp(); let send_ts = intf::get_timestamp();
self.network_manager() self.network_manager()
.send_envelope(node_ref.clone(), Some(out_node_id), out) .send_envelope(node_ref.clone(), Some(out_node_id), out)
.await .await
@ -1399,7 +1398,7 @@ impl RPCProcessor {
let mut timeout = ms_to_us(c.network.rpc.timeout_ms); let mut timeout = ms_to_us(c.network.rpc.timeout_ms);
let mut max_route_hop_count = c.network.rpc.max_route_hop_count as usize; let mut max_route_hop_count = c.network.rpc.max_route_hop_count as usize;
if concurrency == 0 { if concurrency == 0 {
concurrency = get_concurrency() / 2; concurrency = intf::get_concurrency() / 2;
if concurrency == 0 { if concurrency == 0 {
concurrency = 1; concurrency = 1;
} }
@ -1424,8 +1423,8 @@ impl RPCProcessor {
for _ in 0..concurrency { for _ in 0..concurrency {
let this = self.clone(); let this = self.clone();
let receiver = channel.1.clone(); let receiver = channel.1.clone();
let jh = spawn(Self::rpc_worker(this, inner.stop_source.as_ref().unwrap().token(), receiver)); let jh = intf::spawn(Self::rpc_worker(this, inner.stop_source.as_ref().unwrap().token(), receiver));
inner.worker_join_handles.push(MustJoinHandle::new(jh)); inner.worker_join_handles.push(jh);
} }
Ok(()) Ok(())
@ -1466,7 +1465,7 @@ impl RPCProcessor {
) -> Result<(), String> { ) -> Result<(), String> {
let msg = RPCMessage { let msg = RPCMessage {
header: RPCMessageHeader { header: RPCMessageHeader {
timestamp: get_timestamp(), timestamp: intf::get_timestamp(),
envelope, envelope,
body_len: body.len() as u64, body_len: body.len() as u64,
peer_noderef, peer_noderef,

View File

@ -465,7 +465,8 @@ cfg_if! {
let t1 = intf::get_timestamp(); let t1 = intf::get_timestamp();
let mut interfaces = intf::utils::network_interfaces::NetworkInterfaces::new(); let mut interfaces = intf::utils::network_interfaces::NetworkInterfaces::new();
let count = 100; let count = 100;
for _ in 0..count { for x in 0..count {
info!("loop {}", x);
if let Err(e) = interfaces.refresh().await { if let Err(e) = interfaces.refresh().await {
error!("error refreshing interfaces: {}", e); error!("error refreshing interfaces: {}", e);
} }
@ -508,43 +509,6 @@ pub async fn test_get_random_u32() {
); );
} }
pub async fn test_single_future() {
info!("testing single future");
let sf = SingleFuture::<u32>::new();
assert_eq!(sf.check().await, Ok(None));
assert_eq!(
sf.single_spawn(async {
intf::sleep(2000).await;
69
})
.await,
Ok((None, true))
);
assert_eq!(sf.check().await, Ok(None));
assert_eq!(sf.single_spawn(async { panic!() }).await, Ok((None, false)));
assert_eq!(sf.join().await, Ok(Some(69)));
assert_eq!(
sf.single_spawn(async {
intf::sleep(1000).await;
37
})
.await,
Ok((None, true))
);
intf::sleep(2000).await;
assert_eq!(
sf.single_spawn(async {
intf::sleep(1000).await;
27
})
.await,
Ok((Some(37), true))
);
intf::sleep(2000).await;
assert_eq!(sf.join().await, Ok(Some(27)));
assert_eq!(sf.check().await, Ok(None));
}
pub async fn test_must_join_single_future() { pub async fn test_must_join_single_future() {
info!("testing must join single future"); info!("testing must join single future");
let sf = MustJoinSingleFuture::<u32>::new(); let sf = MustJoinSingleFuture::<u32>::new();
@ -604,7 +568,6 @@ pub async fn test_all() {
test_sleep().await; test_sleep().await;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
test_network_interfaces().await; test_network_interfaces().await;
test_single_future().await;
test_must_join_single_future().await; test_must_join_single_future().await;
test_eventual().await; test_eventual().await;
test_eventual_value().await; test_eventual_value().await;

View File

@ -1,5 +1,4 @@
use super::test_veilid_config::*; use super::test_veilid_config::*;
use crate::intf::*;
use crate::xx::*; use crate::xx::*;
use crate::*; use crate::*;

View File

@ -1,5 +1,4 @@
use super::test_veilid_config::*; use super::test_veilid_config::*;
use crate::intf::*;
use crate::xx::*; use crate::xx::*;
use crate::*; use crate::*;

View File

@ -69,53 +69,64 @@ pub fn run_all_tests() {
info!("Finished unit tests"); info!("Finished unit tests");
} }
#[cfg(feature = "rt-tokio")]
fn block_on<F: Future<Output = T>, T>(f: F) -> T {
let rt = tokio::runtime::Runtime::new().unwrap();
let local = tokio::task::LocalSet::new();
local.block_on(&rt, f)
}
#[cfg(feature = "rt-async-std")]
fn block_on<F: Future<Output = T>, T>(f: F) -> T {
async_std::task::block_on(f)
}
fn exec_test_host_interface() { fn exec_test_host_interface() {
async_std::task::block_on(async { block_on(async {
test_host_interface::test_all().await; test_host_interface::test_all().await;
}); });
} }
fn exec_test_dht_key() { fn exec_test_dht_key() {
async_std::task::block_on(async { block_on(async {
test_dht_key::test_all().await; test_dht_key::test_all().await;
}); });
} }
fn exec_test_veilid_core() { fn exec_test_veilid_core() {
async_std::task::block_on(async { block_on(async {
test_veilid_core::test_all().await; test_veilid_core::test_all().await;
}); });
} }
fn exec_test_veilid_config() { fn exec_test_veilid_config() {
async_std::task::block_on(async { block_on(async {
test_veilid_config::test_all().await; test_veilid_config::test_all().await;
}) })
} }
fn exec_test_async_peek_stream() { fn exec_test_async_peek_stream() {
async_std::task::block_on(async { block_on(async {
test_async_peek_stream::test_all().await; test_async_peek_stream::test_all().await;
}) })
} }
fn exec_test_connection_table() { fn exec_test_connection_table() {
async_std::task::block_on(async { block_on(async {
test_connection_table::test_all().await; test_connection_table::test_all().await;
}) })
} }
fn exec_test_table_store() { fn exec_test_table_store() {
async_std::task::block_on(async { block_on(async {
test_table_store::test_all().await; test_table_store::test_all().await;
}) })
} }
fn exec_test_protected_store() { fn exec_test_protected_store() {
async_std::task::block_on(async { block_on(async {
test_protected_store::test_all().await; test_protected_store::test_all().await;
}) })
} }
fn exec_test_crypto() { fn exec_test_crypto() {
async_std::task::block_on(async { block_on(async {
test_crypto::test_all().await; test_crypto::test_all().await;
}) })
} }
fn exec_test_envelope_receipt() { fn exec_test_envelope_receipt() {
async_std::task::block_on(async { block_on(async {
test_envelope_receipt::test_all().await; test_envelope_receipt::test_all().await;
}) })
} }

View File

@ -1,7 +1,17 @@
use super::*; use super::*;
use async_std::net::{TcpListener, TcpStream};
use async_std::prelude::FutureExt; cfg_if! {
use async_std::task; if #[cfg(feature="rt-async-std")] {
use async_std::net::{TcpListener, TcpStream};
use async_std::prelude::FutureExt;
use async_std::task::sleep;
} else if #[cfg(feature="rt-tokio")] {
use tokio::net::{TcpListener, TcpStream};
use tokio::time::sleep;
use tokio_util::compat::*;
}
}
use futures_util::{AsyncReadExt, AsyncWriteExt}; use futures_util::{AsyncReadExt, AsyncWriteExt};
use std::io; use std::io;
@ -18,23 +28,40 @@ async fn make_tcp_loopback() -> Result<(TcpStream, TcpStream), io::Error> {
Result::<TcpStream, io::Error>::Ok(accepted_stream) Result::<TcpStream, io::Error>::Ok(accepted_stream)
}; };
let connect_future = async { let connect_future = async {
task::sleep(Duration::from_secs(1)).await; sleep(Duration::from_secs(1)).await;
let connected_stream = TcpStream::connect(local_addr).await?; let connected_stream = TcpStream::connect(local_addr).await?;
connected_stream.set_nodelay(true)?; connected_stream.set_nodelay(true)?;
Result::<TcpStream, io::Error>::Ok(connected_stream) Result::<TcpStream, io::Error>::Ok(connected_stream)
}; };
Ok(accept_future.try_join(connect_future).await?) cfg_if! {
if #[cfg(feature="rt-async-std")] {
accept_future.try_join(connect_future).await
} else if #[cfg(feature="rt-tokio")] {
tokio::try_join!(accept_future, connect_future)
}
}
} }
async fn make_async_peek_stream_loopback() -> (AsyncPeekStream, AsyncPeekStream) { async fn make_async_peek_stream_loopback() -> (AsyncPeekStream, AsyncPeekStream) {
let (acc, conn) = make_tcp_loopback().await.unwrap(); let (acc, conn) = make_tcp_loopback().await.unwrap();
#[cfg(feature = "rt-tokio")]
let acc = acc.compat();
#[cfg(feature = "rt-tokio")]
let conn = conn.compat();
let aps_a = AsyncPeekStream::new(acc); let aps_a = AsyncPeekStream::new(acc);
let aps_c = AsyncPeekStream::new(conn); let aps_c = AsyncPeekStream::new(conn);
(aps_a, aps_c) (aps_a, aps_c)
} }
#[cfg(feature = "rt-tokio")]
async fn make_stream_loopback() -> (Compat<TcpStream>, Compat<TcpStream>) {
let (a, c) = make_tcp_loopback().await.unwrap();
(a.compat(), c.compat())
}
#[cfg(feature = "rt-async-std")]
async fn make_stream_loopback() -> (TcpStream, TcpStream) { async fn make_stream_loopback() -> (TcpStream, TcpStream) {
make_tcp_loopback().await.unwrap() make_tcp_loopback().await.unwrap()
} }

View File

@ -1731,7 +1731,7 @@ impl fmt::Debug for VeilidAPIInner {
impl Drop for VeilidAPIInner { impl Drop for VeilidAPIInner {
fn drop(&mut self) { fn drop(&mut self) {
if let Some(context) = self.context.take() { if let Some(context) = self.context.take() {
intf::spawn_local(api_shutdown(context)).detach(); intf::spawn_detached(api_shutdown(context));
} }
} }
} }

View File

@ -5,17 +5,8 @@ use task::{Context, Poll};
//////// ////////
/// ///
trait SendStream: AsyncRead + AsyncWrite + Send + Unpin { trait SendStream: AsyncRead + AsyncWrite + Send + Unpin {}
fn clone_stream(&self) -> Box<dyn SendStream>; impl<S> SendStream for S where S: AsyncRead + AsyncWrite + Send + Unpin + 'static {}
}
impl<S> SendStream for S
where
S: AsyncRead + AsyncWrite + Send + Clone + Unpin + 'static,
{
fn clone_stream(&self) -> Box<dyn SendStream> {
Box::new(self.clone())
}
}
//////// ////////
/// ///
@ -126,7 +117,7 @@ where
impl AsyncPeekStream { impl AsyncPeekStream {
pub fn new<S>(stream: S) -> Self pub fn new<S>(stream: S) -> Self
where where
S: AsyncRead + AsyncWrite + Send + Clone + Unpin + 'static, S: AsyncRead + AsyncWrite + Send + Unpin + 'static,
{ {
Self { Self {
inner: Arc::new(Mutex::new(AsyncPeekStreamInner { inner: Arc::new(Mutex::new(AsyncPeekStreamInner {

View File

@ -11,7 +11,7 @@ mod log_thru;
mod must_join_handle; mod must_join_handle;
mod must_join_single_future; mod must_join_single_future;
mod mutable_future; mod mutable_future;
mod single_future; // mod single_future;
mod single_shot_eventual; mod single_shot_eventual;
mod split_url; mod split_url;
mod tick_task; mod tick_task;
@ -67,6 +67,7 @@ cfg_if! {
pub use no_std_net::{ SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs, IpAddr, Ipv4Addr, Ipv6Addr }; pub use no_std_net::{ SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs, IpAddr, Ipv4Addr, Ipv6Addr };
pub type SystemPinBoxFuture<T> = PinBox<dyn Future<Output = T> + 'static>; pub type SystemPinBoxFuture<T> = PinBox<dyn Future<Output = T> + 'static>;
pub type SystemPinBoxFutureLifetime<'a, T> = PinBox<dyn Future<Output = T> + 'a>; pub type SystemPinBoxFutureLifetime<'a, T> = PinBox<dyn Future<Output = T> + 'a>;
pub use async_executors::JoinHandle as LowLevelJoinHandle;
} else { } else {
pub use std::string::String; pub use std::string::String;
pub use std::vec::Vec; pub use std::vec::Vec;
@ -91,8 +92,17 @@ cfg_if! {
pub use std::time::Duration; pub use std::time::Duration;
pub use std::pin::Pin; pub use std::pin::Pin;
pub use std::ops::{FnOnce, FnMut, Fn}; pub use std::ops::{FnOnce, FnMut, Fn};
pub use async_std::sync::Mutex as AsyncMutex; cfg_if! {
pub use async_std::sync::MutexGuard as AsyncMutexGuard; if #[cfg(feature="rt-async-std")] {
pub use async_std::sync::Mutex as AsyncMutex;
pub use async_std::sync::MutexGuard as AsyncMutexGuard;
pub use async_std::task::JoinHandle as LowLevelJoinHandle;
} else if #[cfg(feature="rt-tokio")] {
pub use tokio::sync::Mutex as AsyncMutex;
pub use tokio::sync::MutexGuard as AsyncMutexGuard;
pub use tokio::task::JoinHandle as LowLevelJoinHandle;
}
}
pub use std::net::{ SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs, IpAddr, Ipv4Addr, Ipv6Addr }; pub use std::net::{ SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs, IpAddr, Ipv4Addr, Ipv6Addr };
pub type SystemPinBoxFuture<T> = PinBox<dyn Future<Output = T> + Send + 'static>; pub type SystemPinBoxFuture<T> = PinBox<dyn Future<Output = T> + Send + 'static>;
pub type SystemPinBoxFutureLifetime<'a, T> = PinBox<dyn Future<Output = T> + Send + 'a>; pub type SystemPinBoxFutureLifetime<'a, T> = PinBox<dyn Future<Output = T> + Send + 'a>;
@ -111,7 +121,7 @@ pub use ip_extra::*;
pub use must_join_handle::*; pub use must_join_handle::*;
pub use must_join_single_future::*; pub use must_join_single_future::*;
pub use mutable_future::*; pub use mutable_future::*;
pub use single_future::*; // pub use single_future::*;
pub use single_shot_eventual::*; pub use single_shot_eventual::*;
pub use tick_task::*; pub use tick_task::*;
pub use tools::*; pub use tools::*;

View File

@ -1,21 +1,40 @@
use async_executors::JoinHandle; use super::*;
use core::future::Future; use core::future::Future;
use core::pin::Pin; use core::pin::Pin;
use core::task::{Context, Poll}; use core::task::{Context, Poll};
#[derive(Debug)] #[derive(Debug)]
pub struct MustJoinHandle<T> { pub struct MustJoinHandle<T> {
join_handle: JoinHandle<T>, join_handle: Option<LowLevelJoinHandle<T>>,
completed: bool, completed: bool,
} }
impl<T> MustJoinHandle<T> { impl<T> MustJoinHandle<T> {
pub fn new(join_handle: JoinHandle<T>) -> Self { pub fn new(join_handle: LowLevelJoinHandle<T>) -> Self {
Self { Self {
join_handle, join_handle: Some(join_handle),
completed: false, completed: false,
} }
} }
pub async fn abort(mut self) {
if !self.completed {
cfg_if! {
if #[cfg(feature="rt-async-std")] {
if let Some(jh) = self.join_handle.take() {
jh.cancel().await;
self.completed = true;
}
} else if #[cfg(feature="rt-tokio")] {
if let Some(jh) = self.join_handle.take() {
jh.abort();
let _ = jh.await;
self.completed = true;
}
}
}
}
}
} }
impl<T> Drop for MustJoinHandle<T> { impl<T> Drop for MustJoinHandle<T> {
@ -31,10 +50,16 @@ impl<T: 'static> Future for MustJoinHandle<T> {
type Output = T; type Output = T;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match Pin::new(&mut self.join_handle).poll(cx) { match Pin::new(self.join_handle.as_mut().unwrap()).poll(cx) {
Poll::Ready(t) => { Poll::Ready(t) => {
self.completed = true; self.completed = true;
Poll::Ready(t) cfg_if! {
if #[cfg(feature="rt-async-std")] {
Poll::Ready(t)
} else if #[cfg(feature="rt-tokio")] {
Poll::Ready(t.unwrap())
}
}
} }
Poll::Pending => Poll::Pending, Poll::Pending => Poll::Pending,
} }

View File

@ -1,6 +1,5 @@
use super::*; use super::*;
use crate::intf::*; use crate::*;
use cfg_if::*;
use core::task::Poll; use core::task::Poll;
use futures_util::poll; use futures_util::poll;
@ -160,7 +159,7 @@ where
// Run if we should do that // Run if we should do that
if run { if run {
self.unlock(Some(MustJoinHandle::new(spawn_local(future)))); self.unlock(Some(intf::spawn_local(future)));
} }
// Return the prior result if we have one // Return the prior result if we have one
@ -203,7 +202,7 @@ cfg_if! {
} }
// Run if we should do that // Run if we should do that
if run { if run {
self.unlock(Some(MustJoinHandle::new(spawn(future)))); self.unlock(Some(intf::spawn_with_local_set(future)));
} }
// Return the prior result if we have one // Return the prior result if we have one
Ok((out, run)) Ok((out, run))

View File

@ -1,242 +0,0 @@
use super::*;
use crate::intf::*;
use cfg_if::*;
use core::task::Poll;
use futures_util::poll;
#[derive(Debug)]
struct SingleFutureInner<T>
where
T: 'static,
{
locked: bool,
join_handle: Option<JoinHandle<T>>,
}
/// Spawns a single background processing task idempotently, possibly returning the return value of the previously executed background task
/// This does not queue, just ensures that no more than a single copy of the task is running at a time, but allowing tasks to be retriggered
#[derive(Debug, Clone)]
pub struct SingleFuture<T>
where
T: 'static,
{
inner: Arc<Mutex<SingleFutureInner<T>>>,
}
impl<T> Default for SingleFuture<T>
where
T: 'static,
{
fn default() -> Self {
Self::new()
}
}
impl<T> SingleFuture<T>
where
T: 'static,
{
pub fn new() -> Self {
Self {
inner: Arc::new(Mutex::new(SingleFutureInner {
locked: false,
join_handle: None,
})),
}
}
fn try_lock(&self) -> Result<Option<JoinHandle<T>>, ()> {
let mut inner = self.inner.lock();
if inner.locked {
// If already locked error out
return Err(());
}
inner.locked = true;
// If we got the lock, return what we have for a join handle if anything
Ok(inner.join_handle.take())
}
fn unlock(&self, jh: Option<JoinHandle<T>>) {
let mut inner = self.inner.lock();
assert!(inner.locked);
assert!(inner.join_handle.is_none());
inner.locked = false;
inner.join_handle = jh;
}
// Check the result
pub async fn check(&self) -> Result<Option<T>, ()> {
let mut out: Option<T> = None;
// See if we have a result we can return
let maybe_jh = match self.try_lock() {
Ok(v) => v,
Err(_) => {
// If we are already polling somewhere else, don't hand back a result
return Err(());
}
};
if maybe_jh.is_some() {
let mut jh = maybe_jh.unwrap();
// See if we finished, if so, return the value of the last execution
if let Poll::Ready(r) = poll!(&mut jh) {
out = Some(r);
// Task finished, unlock with nothing
self.unlock(None);
} else {
// Still running put the join handle back so we can check on it later
self.unlock(Some(jh));
}
} else {
// No task, unlock with nothing
self.unlock(None);
}
// Return the prior result if we have one
Ok(out)
}
// Wait for the result
pub async fn join(&self) -> Result<Option<T>, ()> {
let mut out: Option<T> = None;
// See if we have a result we can return
let maybe_jh = match self.try_lock() {
Ok(v) => v,
Err(_) => {
// If we are already polling somewhere else,
// that's an error because you can only join
// these things once
return Err(());
}
};
if maybe_jh.is_some() {
let jh = maybe_jh.unwrap();
// Wait for return value of the last execution
out = Some(jh.await);
// Task finished, unlock with nothing
} else {
// No task, unlock with nothing
}
self.unlock(None);
// Return the prior result if we have one
Ok(out)
}
// Cancel
pub async fn cancel(&self) -> Result<Option<T>, ()> {
let mut out: Option<T> = None;
// See if we have a result we can return
let maybe_jh = match self.try_lock() {
Ok(v) => v,
Err(_) => {
// If we are already polling somewhere else, don't hand back a result
return Err(());
}
};
if maybe_jh.is_some() {
let mut jh = maybe_jh.unwrap();
// See if we finished, if so, return the value of the last execution
if let Poll::Ready(r) = poll!(&mut jh) {
out = Some(r);
// Task finished, unlock with nothing
} else {
// Still running but drop the join handle anyway to cancel the task, unlock with nothing
}
}
self.unlock(None);
// Return the prior result if we have one
Ok(out)
}
// Possibly spawn the future possibly returning the value of the last execution
cfg_if! {
if #[cfg(target_arch = "wasm32")] {
pub async fn single_spawn(
&self,
future: impl Future<Output = T> + 'static,
) -> Result<(Option<T>, bool), ()> {
let mut out: Option<T> = None;
// See if we have a result we can return
let maybe_jh = match self.try_lock() {
Ok(v) => v,
Err(_) => {
// If we are already polling somewhere else, don't hand back a result
return Err(());
}
};
let mut run = true;
if maybe_jh.is_some() {
let mut jh = maybe_jh.unwrap();
// See if we finished, if so, return the value of the last execution
if let Poll::Ready(r) = poll!(&mut jh) {
out = Some(r);
// Task finished, unlock with a new task
} else {
// Still running, don't run again, unlock with the current join handle
run = false;
self.unlock(Some(jh));
}
}
// Run if we should do that
if run {
self.unlock(Some(spawn_local(future)));
}
// Return the prior result if we have one
Ok((out, run))
}
}
}
}
cfg_if! {
if #[cfg(not(target_arch = "wasm32"))] {
impl<T> SingleFuture<T>
where
T: 'static + Send,
{
pub async fn single_spawn(
&self,
future: impl Future<Output = T> + Send + 'static,
) -> Result<(Option<T>, bool), ()> {
let mut out: Option<T> = None;
// See if we have a result we can return
let maybe_jh = match self.try_lock() {
Ok(v) => v,
Err(_) => {
// If we are already polling somewhere else, don't hand back a result
return Err(());
}
};
let mut run = true;
if maybe_jh.is_some() {
let mut jh = maybe_jh.unwrap();
// See if we finished, if so, return the value of the last execution
if let Poll::Ready(r) = poll!(&mut jh) {
out = Some(r);
// Task finished, unlock with a new task
} else {
// Still running, don't run again, unlock with the current join handle
run = false;
self.unlock(Some(jh));
}
}
// Run if we should do that
if run {
self.unlock(Some(spawn(future)));
}
// Return the prior result if we have one
Ok((out, run))
}
}
}
}

View File

@ -1,5 +1,5 @@
use super::*; use super::*;
use crate::intf::*; use crate::*;
use core::sync::atomic::{AtomicU64, Ordering}; use core::sync::atomic::{AtomicU64, Ordering};
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
@ -90,7 +90,7 @@ impl TickTask {
} }
pub async fn tick(&self) -> Result<(), String> { pub async fn tick(&self) -> Result<(), String> {
let now = get_timestamp(); let now = intf::get_timestamp();
let last_timestamp_us = self.last_timestamp_us.load(Ordering::Acquire); let last_timestamp_us = self.last_timestamp_us.load(Ordering::Acquire);
if last_timestamp_us != 0u64 && (now - last_timestamp_us) < self.tick_period_us { if last_timestamp_us != 0u64 && (now - last_timestamp_us) < self.tick_period_us {

View File

@ -7,7 +7,6 @@ edition = "2021"
crate-type = ["cdylib", "staticlib", "rlib"] crate-type = ["cdylib", "staticlib", "rlib"]
[dependencies] [dependencies]
veilid-core = { path="../../veilid-core" }
tracing = { version = "^0", features = ["log", "attributes"] } tracing = { version = "^0", features = ["log", "attributes"] }
tracing-subscriber = "^0" tracing-subscriber = "^0"
parking_lot = "^0" parking_lot = "^0"
@ -19,18 +18,20 @@ futures = "^0"
# Dependencies for native builds only # Dependencies for native builds only
# Linux, Windows, Mac, iOS, Android # Linux, Windows, Mac, iOS, Android
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
async-std = { version = "^1", features = ["unstable"] } veilid-core = { path="../../veilid-core", features = [ "rt-tokio" ] }
tokio = { version = "^1", features = ["full"] }
allo-isolate = "^0" allo-isolate = "^0"
ffi-support = "^0" ffi-support = "^0"
lazy_static = "^1" lazy_static = "^1"
tracing-opentelemetry = "^0" tracing-opentelemetry = "^0"
opentelemetry = { version = "^0", features = ["rt-async-std"] } opentelemetry = { version = "^0", features = ["rt-tokio"] }
opentelemetry-otlp = { version = "^0", features = ["grpc-sys"] } opentelemetry-otlp = { version = "^0" }
opentelemetry-semantic-conventions = "^0" opentelemetry-semantic-conventions = "^0"
hostname = "^0" hostname = "^0"
# Dependencies for WASM builds only # Dependencies for WASM builds only
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]
veilid-core = { path="../../veilid-core" }
# Dependencies for Android builds only # Dependencies for Android builds only
[target.'cfg(target_os = "android")'.dependencies] [target.'cfg(target_os = "android")'.dependencies]

View File

@ -11,8 +11,9 @@ name = "veilid-server"
path = "src/main.rs" path = "src/main.rs"
[features] [features]
default = [ "rt-async-std" ] default = [ "rt-tokio" ]
rt-async-std = [ "veilid-core/rt-async-std", "async-std", "async-tungstenite/async-std-runtime", "opentelemetry/rt-async-std", "opentelemetry-otlp/grpc-sys"] rt-async-std = [ "veilid-core/rt-async-std", "async-std", "opentelemetry/rt-async-std", "opentelemetry-otlp/grpc-sys"]
rt-tokio = [ "veilid-core/rt-tokio", "tokio", "opentelemetry/rt-tokio"]
tracking = ["veilid-core/tracking"] tracking = ["veilid-core/tracking"]
[dependencies] [dependencies]
@ -26,6 +27,7 @@ opentelemetry-otlp = { version = "^0" }
opentelemetry-semantic-conventions = "^0" opentelemetry-semantic-conventions = "^0"
clap = "^3" clap = "^3"
async-std = { version = "^1", features = ["unstable"], optional = true } async-std = { version = "^1", features = ["unstable"], optional = true }
tokio = { version = "^1", features = ["full"], optional = true }
async-tungstenite = { version = "^0", features = ["async-tls"] } async-tungstenite = { version = "^0", features = ["async-tls"] }
directories = "^4" directories = "^4"
capnp = "^0" capnp = "^0"

View File

@ -1,6 +1,5 @@
use crate::tools::*;
use crate::veilid_client_capnp::*; use crate::veilid_client_capnp::*;
use async_std::net::TcpListener;
use async_std::prelude::FutureExt;
use capnp::capability::Promise; use capnp::capability::Promise;
use capnp_rpc::{pry, rpc_twoparty_capnp, twoparty, RpcSystem}; use capnp_rpc::{pry, rpc_twoparty_capnp, twoparty, RpcSystem};
use failure::*; use failure::*;
@ -232,7 +231,7 @@ impl veilid_server::Server for VeilidServerImpl {
// --- Client API Server-Side --------------------------------- // --- Client API Server-Side ---------------------------------
type ClientApiAllFuturesJoinHandle = type ClientApiAllFuturesJoinHandle =
async_std::task::JoinHandle<Result<Vec<()>, Box<(dyn std::error::Error + 'static)>>>; JoinHandle<Result<Vec<()>, Box<(dyn std::error::Error + 'static)>>>;
struct ClientApiInner { struct ClientApiInner {
veilid_api: veilid_core::VeilidAPI, veilid_api: veilid_core::VeilidAPI,
@ -286,13 +285,15 @@ impl ClientApi {
let listener = TcpListener::bind(bind_addr).await?; let listener = TcpListener::bind(bind_addr).await?;
debug!("Client API listening on: {:?}", bind_addr); debug!("Client API listening on: {:?}", bind_addr);
// Get the // Process the incoming accept stream
// xxx switch to stoptoken and use stream wrapper for tokio
let mut incoming = listener.incoming(); let mut incoming = listener.incoming();
let stop = self.inner.borrow().stop.clone(); let stop = self.inner.borrow().stop.clone();
let incoming_loop = async move { let incoming_loop = async move {
while let Some(stream_result) = stop.instance_none().race(incoming.next()).await { while let Some(stream_result) = stop.instance_none().race(incoming.next()).await {
let stream = stream_result?; let stream = stream_result?;
stream.set_nodelay(true)?; stream.set_nodelay(true)?;
// xxx use tokio split code too
let (reader, writer) = stream.split(); let (reader, writer) = stream.split();
let network = twoparty::VatNetwork::new( let network = twoparty::VatNetwork::new(
reader, reader,
@ -303,7 +304,7 @@ impl ClientApi {
let rpc_system = RpcSystem::new(Box::new(network), Some(client.clone().client)); let rpc_system = RpcSystem::new(Box::new(network), Some(client.clone().client));
async_std::task::spawn_local(rpc_system.map(drop)); spawn_local(rpc_system.map(drop));
} }
Ok::<(), Box<dyn std::error::Error>>(()) Ok::<(), Box<dyn std::error::Error>>(())
}; };
@ -332,7 +333,7 @@ impl ClientApi {
if let Some(request_promise) = request(id, registration) { if let Some(request_promise) = request(id, registration) {
let registration_map2 = registration_map1.clone(); let registration_map2 = registration_map1.clone();
async_std::task::spawn_local(request_promise.promise.map(move |r| match r { spawn_local(request_promise.promise.map(move |r| match r {
Ok(_) => { Ok(_) => {
if let Some(ref mut s) = if let Some(ref mut s) =
registration_map2.borrow_mut().registrations.get_mut(&id) registration_map2.borrow_mut().registrations.get_mut(&id)
@ -385,6 +386,6 @@ impl ClientApi {
.iter() .iter()
.map(|addr| self.clone().handle_incoming(*addr, client.clone())); .map(|addr| self.clone().handle_incoming(*addr, client.clone()));
let bind_futures_join = futures::future::try_join_all(bind_futures); let bind_futures_join = futures::future::try_join_all(bind_futures);
self.inner.borrow_mut().join_handle = Some(async_std::task::spawn_local(bind_futures_join)); self.inner.borrow_mut().join_handle = Some(spawn_local(bind_futures_join));
} }
} }

View File

@ -6,15 +6,16 @@ mod client_api;
mod cmdline; mod cmdline;
mod server; mod server;
mod settings; mod settings;
mod tools;
#[cfg(unix)] #[cfg(unix)]
mod unix; mod unix;
mod veilid_logs; mod veilid_logs;
#[cfg(windows)] #[cfg(windows)]
mod windows; mod windows;
use async_std::task;
use cfg_if::*; use cfg_if::*;
use server::*; use server::*;
use tools::*;
use tracing::*; use tracing::*;
use veilid_logs::*; use veilid_logs::*;
@ -59,7 +60,7 @@ fn main() -> Result<(), String> {
// Handle non-normal server modes // Handle non-normal server modes
if !matches!(server_mode, ServerMode::Normal) { if !matches!(server_mode, ServerMode::Normal) {
// run the server to set the node id and quit // run the server to set the node id and quit
return task::block_on(async { return block_on(async {
// Init combined console/file logger // Init combined console/file logger
let _logs = VeilidLogs::setup(settings.clone())?; let _logs = VeilidLogs::setup(settings.clone())?;
@ -93,7 +94,7 @@ fn main() -> Result<(), String> {
.expect("Error setting Ctrl-C handler"); .expect("Error setting Ctrl-C handler");
// Run the server loop // Run the server loop
task::block_on(async { block_on(async {
// Init combined console/file logger // Init combined console/file logger
let _logs = VeilidLogs::setup(settings.clone())?; let _logs = VeilidLogs::setup(settings.clone())?;

View File

@ -1,5 +1,6 @@
use crate::client_api; use crate::client_api;
use crate::settings::*; use crate::settings::*;
use crate::tools::*;
use flume::{unbounded, Receiver, Sender}; use flume::{unbounded, Receiver, Sender};
use lazy_static::*; use lazy_static::*;
use parking_lot::Mutex; use parking_lot::Mutex;
@ -77,7 +78,7 @@ pub async fn run_veilid_server_internal(
// Process all updates // Process all updates
let capi2 = capi.clone(); let capi2 = capi.clone();
let update_receiver_jh = async_std::task::spawn_local(async move { let update_receiver_jh = spawn_local(async move {
while let Ok(change) = receiver.recv_async().await { while let Ok(change) = receiver.recv_async().await {
if let Some(capi) = &capi2 { if let Some(capi) = &capi2 {
// Handle state changes on main thread for capnproto rpc // Handle state changes on main thread for capnproto rpc
@ -115,7 +116,7 @@ pub async fn run_veilid_server_internal(
break; break;
} }
} }
async_std::task::sleep(Duration::from_millis(100)).await; sleep(Duration::from_millis(100)).await;
} }
match veilid_api.debug("txtrecord".to_string()).await { match veilid_api.debug("txtrecord".to_string()).await {
Ok(v) => { Ok(v) => {

View File

@ -0,0 +1,48 @@
use cfg_if::*;
use core::future::Future;
cfg_if! {
if #[cfg(feature="rt-async-std")] {
pub use async_std::task::JoinHandle;
pub use async_std::net::TcpListener;
//pub use async_std::net::TcpStream;
//pub use async_std::future::TimeoutError;
pub fn spawn<F: Future<Output = T> + Send + 'static, T: Send + 'static>(f: F) -> JoinHandle<T> {
async_std::task::spawn_local(f)
}
pub fn spawn_local<F: Future<Output = T> + 'static, T: 'static>(f: F) -> JoinHandle<T> {
async_std::task::spawn_local(f)
}
pub fn spawn_detached_local<F: Future<Output = T> + 'static, T: 'static>(f: F) {
let _ = async_std::task::spawn_local(f);
}
pub use async_std::task::sleep;
pub use async_std::future::timeout;
pub fn block_on<F: Future<Output = T>, T>(f: F) -> T {
async_std::task::block_on(f)
}
} else if #[cfg(feature="rt-tokio")] {
pub use tokio::task::JoinHandle;
pub use tokio::net::TcpListener;
//pub use tokio::net::TcpStream;
//pub use tokio_util::compat::*;
pub use tokio::time::error::Elapsed as TimeoutError;
pub fn spawn<F: Future<Output = T> + Send + 'static, T: Send + 'static>(f: F) -> JoinHandle<T> {
tokio::task::spawn(f)
}
pub fn spawn_local<F: Future<Output = T> + 'static, T: 'static>(f: F) -> JoinHandle<T> {
tokio::task::spawn_local(f)
}
pub fn spawn_detached_local<F: Future<Output = T> + 'static, T: 'static>(f: F) {
let _ = tokio::task::spawn_local(f);
}
pub use tokio::time::sleep;
pub use tokio::time::timeout;
pub fn block_on<F: Future<Output = T>, T>(f: F) -> T {
let rt = tokio::runtime::Runtime::new().unwrap();
let local = tokio::task::LocalSet::new();
local.block_on(&rt, f)
}
}
}

View File

@ -1,9 +1,9 @@
use crate::server::*; use crate::server::*;
use crate::settings::Settings; use crate::settings::Settings;
use crate::tools::*;
use crate::veilid_logs::*; use crate::veilid_logs::*;
use async_std::stream::StreamExt;
use async_std::task;
use clap::ArgMatches; use clap::ArgMatches;
use futures::StreamExt;
use signal_hook::consts::signal::*; use signal_hook::consts::signal::*;
use signal_hook_async_std::Signals; use signal_hook_async_std::Signals;
use std::io::Read; use std::io::Read;
@ -96,7 +96,7 @@ pub fn run_daemon(settings: Settings, _matches: ArgMatches) -> Result<(), String
}; };
// Now, run the server // Now, run the server
task::block_on(async { block_on(async {
// Init combined console/file logger // Init combined console/file logger
let _logs = VeilidLogs::setup(settings.clone())?; let _logs = VeilidLogs::setup(settings.clone())?;
@ -110,7 +110,7 @@ pub fn run_daemon(settings: Settings, _matches: ArgMatches) -> Result<(), String
.map_err(|e| format!("failed to init signals: {}", e))?; .map_err(|e| format!("failed to init signals: {}", e))?;
let handle = signals.handle(); let handle = signals.handle();
let signals_task = async_std::task::spawn(handle_signals(signals)); let signals_task = spawn(handle_signals(signals));
let res = run_veilid_server(settings, ServerMode::Normal).await; let res = run_veilid_server(settings, ServerMode::Normal).await;

View File

@ -1,4 +1,5 @@
use crate::settings::*; use crate::settings::*;
use crate::tools::*;
use clap::ArgMatches; use clap::ArgMatches;
use log::*; use log::*;
use std::ffi::OsString; use std::ffi::OsString;