checkpoint

This commit is contained in:
John Smith
2022-07-11 08:37:08 -04:00
parent 7e0d7dad06
commit b73511142a
12 changed files with 128 additions and 110 deletions

View File

@@ -5,13 +5,13 @@ use crate::veilid_api::*;
use crate::veilid_config::*;
use crate::xx::*;
cfg_if! {
if #[cfg(target_arch = "wasm32")] {
pub type UpdateCallback = Arc<dyn Fn(VeilidUpdate)>;
} else {
pub type UpdateCallback = Arc<dyn Fn(VeilidUpdate) + Send + Sync>;
}
}
// cfg_if! {
// if #[cfg(target_arch = "wasm32")] {
// pub type UpdateCallback = Arc<dyn Fn(VeilidUpdate)>;
// } else {
pub type UpdateCallback = Arc<dyn Fn(VeilidUpdate) + Send + Sync>;
// }
// }
struct ServicesContext {
pub config: VeilidConfig,

View File

@@ -135,7 +135,7 @@ impl ProtectedStore {
{
Ok(v) => Ok(Some(v)),
Err(KeyringError::NoPasswordFound) => Ok(None),
Err(e) => Err(eyre!("Failed to load user secret")),
Err(e) => Err(eyre!("Failed to load user secret: {}", e)),
}
}
@@ -150,7 +150,7 @@ impl ProtectedStore {
{
Ok(_) => Ok(true),
Err(KeyringError::NoPasswordFound) => Ok(false),
Err(e) => Err(eyre!("Failed to remove user secret")),
Err(e) => Err(eyre!("Failed to remove user secret: {}", e)),
}
}

View File

@@ -100,12 +100,7 @@ impl TableDB {
return Ok(None);
}
};
let obj = match serde_cbor::from_slice::<T>(&b) {
Ok(value) => value,
Err(e) => {
bail!("failed to deserialize");
}
};
let obj = serde_cbor::from_slice::<T>(&b).wrap_err("failed to deserialize")?;
Ok(Some(obj))
}

View File

@@ -9,3 +9,4 @@ pub use block_store::*;
pub use protected_store::*;
pub use system::*;
pub use table_store::*;
use utils::*;

View File

@@ -1,10 +1,11 @@
use super::utils;
use super::*;
use crate::xx::*;
use crate::*;
use data_encoding::BASE64URL_NOPAD;
use js_sys::*;
use wasm_bindgen_futures::*;
use web_sys::*;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(catch, js_name = setPassword, js_namespace = ["global", "wasmhost", "keytar"])]
@@ -69,10 +70,11 @@ impl ProtectedStore {
}
pub async fn save_user_secret_string(&self, key: &str, value: &str) -> EyreResult<bool> {
if utils::is_nodejs() {
if is_nodejs() {
let prev = match JsFuture::from(
keytar_getPassword(self.keyring_name().as_str(), key)
.wrap_err("exception thrown")?,
.map_err(map_jsvalue_error)
.wrap_err("exception thrown")?,
)
.await
{
@@ -82,7 +84,8 @@ impl ProtectedStore {
match JsFuture::from(
keytar_setPassword(self.keyring_name().as_str(), key, value)
.wrap_err("exception thrown")?,
.map_err(map_jsvalue_error)
.wrap_err("exception thrown")?,
)
.await
{
@@ -91,7 +94,7 @@ impl ProtectedStore {
}
Ok(prev)
} else if utils::is_browser() {
} else if is_browser() {
let win = match window() {
Some(w) => w,
None => {
@@ -101,6 +104,7 @@ impl ProtectedStore {
let ls = match win
.local_storage()
.map_err(map_jsvalue_error)
.wrap_err("exception getting local storage")?
{
Some(l) => l,
@@ -113,6 +117,7 @@ impl ProtectedStore {
let prev = match ls
.get_item(&vkey)
.map_err(map_jsvalue_error)
.wrap_err("exception_thrown")?
{
Some(_) => true,
@@ -120,6 +125,7 @@ impl ProtectedStore {
};
ls.set_item(&vkey, value)
.map_err(map_jsvalue_error)
.wrap_err("exception_thrown")?;
Ok(prev)
@@ -129,9 +135,10 @@ impl ProtectedStore {
}
pub async fn load_user_secret_string(&self, key: &str) -> EyreResult<Option<String>> {
if utils::is_nodejs() {
if is_nodejs() {
let prev = match JsFuture::from(
keytar_getPassword(self.keyring_name().as_str(), key)
.map_err(map_jsvalue_error)
.wrap_err("exception thrown")?,
)
.await
@@ -145,7 +152,7 @@ impl ProtectedStore {
}
Ok(prev.as_string())
} else if utils::is_browser() {
} else if is_browser() {
let win = match window() {
Some(w) => w,
None => {
@@ -155,6 +162,7 @@ impl ProtectedStore {
let ls = match win
.local_storage()
.map_err(map_jsvalue_error)
.wrap_err("exception getting local storage")?
{
Some(l) => l,
@@ -166,6 +174,7 @@ impl ProtectedStore {
let vkey = self.browser_key_name(key);
ls.get_item(&vkey)
.map_err(map_jsvalue_error)
.wrap_err("exception_thrown")
} else {
unimplemented!();
@@ -173,16 +182,18 @@ impl ProtectedStore {
}
pub async fn remove_user_secret_string(&self, key: &str) -> EyreResult<bool> {
if utils::is_nodejs() {
if is_nodejs() {
match JsFuture::from(
keytar_deletePassword(self.keyring_name().as_str(), key).wrap_err("exception thrown")?,
keytar_deletePassword(self.keyring_name().as_str(), key)
.map_err(map_jsvalue_error)
.wrap_err("exception thrown")?,
)
.await
{
Ok(v) => Ok(v.is_truthy()),
Err(_) => bail!("Failed to delete"),
}
} else if utils::is_browser() {
} else if is_browser() {
let win = match window() {
Some(w) => w,
None => {
@@ -192,6 +203,7 @@ impl ProtectedStore {
let ls = match win
.local_storage()
.map_err(map_jsvalue_error)
.wrap_err("exception getting local storage")?
{
Some(l) => l,
@@ -204,10 +216,12 @@ impl ProtectedStore {
match ls
.get_item(&vkey)
.map_err(map_jsvalue_error)
.wrap_err("exception_thrown")?
{
Some(_) => {
ls.delete(&vkey)
.map_err(map_jsvalue_error)
.wrap_err("exception_thrown")?;
Ok(true)
}

View File

@@ -2,7 +2,6 @@ use super::utils;
use crate::xx::*;
use crate::*;
use async_executors::{Bindgen, LocalSpawnHandleExt /*, SpawnHandleExt*/};
use core::fmt;
use futures_util::future::{select, Either};
use js_sys::*;
use wasm_bindgen_futures::*;

View File

@@ -28,7 +28,7 @@ impl TableStore {
}
}
pub async fn init(&self) -> Result<(), String> {
pub async fn init(&self) -> EyreResult<()> {
Ok(())
}
@@ -49,12 +49,12 @@ impl TableStore {
}
}
fn get_table_name(&self, table: &str) -> Result<String, String> {
fn get_table_name(&self, table: &str) -> EyreResult<String> {
if !table
.chars()
.all(|c| char::is_alphanumeric(c) || c == '_' || c == '-')
{
return Err(format!("table name '{}' is invalid", table));
bail!("table name '{}' is invalid", table);
}
let c = self.config.get();
let namespace = c.namespace.clone();
@@ -65,7 +65,7 @@ impl TableStore {
})
}
pub async fn open(&self, name: &str, column_count: u32) -> Result<TableDB, String> {
pub async fn open(&self, name: &str, column_count: u32) -> EyreResult<TableDB> {
let table_name = self.get_table_name(name)?;
let mut inner = self.inner.lock();
@@ -81,7 +81,7 @@ impl TableStore {
}
let db = Database::open(table_name.clone(), column_count)
.await
.map_err(|e| format!("failed to open tabledb at: {} ({})", table_name, e))?;
.wrap_err("failed to open tabledb")?;
info!("opened table store '{}' with table name '{:?}' with {} columns", name, table_name, column_count);
let table_db = TableDB::new(table_name.clone(), self.clone(), db);
@@ -91,7 +91,7 @@ impl TableStore {
Ok(table_db)
}
pub async fn delete(&self, name: &str) -> Result<bool, String> {
pub async fn delete(&self, name: &str) -> EyreResult<bool> {
trace!("TableStore::delete {}", name);
let table_name = self.get_table_name(name)?;
@@ -101,11 +101,11 @@ impl TableStore {
"TableStore::delete {}: Not deleting, still open.",
table_name
);
return Err("Not deleting table that is still opened".to_owned());
bail!("Not deleting table that is still opened");
}
if utils::is_nodejs() {
Err("unimplemented".to_owned())
unimplemented!();
} else if utils::is_browser() {
let out = match Database::delete(table_name.clone()).await {
Ok(_) => true,
@@ -115,7 +115,7 @@ impl TableStore {
trace!("TableStore::deleted {}", table_name);
Ok(out)
} else {
Err("unimplemented".to_owned())
unimplemented!();
}
}
}

View File

@@ -77,3 +77,11 @@ pub fn node_require(module: &str) -> JsValue {
}
}
}
#[derive(ThisError, Debug, Clone, Eq, PartialEq)]
#[error("JsValue error")]
pub struct JsValueError(String);
pub fn map_jsvalue_error(x: JsValue) -> JsValueError {
JsValueError(x.as_string().unwrap_or_default())
}

View File

@@ -34,14 +34,17 @@ impl Network {
}
}
pub fn new(network_manager: NetworkManager) -> Self {
pub fn new(
network_manager: NetworkManager,
routing_table: RoutingTable,
connection_manager: ConnectionManager,
) -> Self {
Self {
config: network_manager.config(),
inner: Arc::new(Mutex::new(Self::new_inner(network_manager))),
}
}
fn network_manager(&self) -> NetworkManager {
self.inner.lock().network_manager.clone()
}
@@ -61,14 +64,15 @@ impl Network {
let res = match dial_info.protocol_type() {
ProtocolType::UDP => {
return Err("no support for UDP protocol".to_owned()).map_err(logthru_net!(error))
bail!("no support for UDP protocol")
}
ProtocolType::TCP => {
return Err("no support for TCP protocol".to_owned()).map_err(logthru_net!(error))
bail!("no support for TCP protocol")
}
ProtocolType::WS | ProtocolType::WSS => {
WebsocketProtocolHandler::send_unbound_message(dial_info.clone(), data)
.await
.wrap_err("failed to send unbound message")
}
};
if res.is_ok() {
@@ -94,10 +98,10 @@ impl Network {
let data_len = data.len();
let out = match dial_info.protocol_type() {
ProtocolType::UDP => {
return Err("no support for UDP protocol".to_owned()).map_err(logthru_net!(error))
bail!("no support for UDP protocol")
}
ProtocolType::TCP => {
return Err("no support for TCP protocol".to_owned()).map_err(logthru_net!(error))
bail!("no support for TCP protocol")
}
ProtocolType::WS | ProtocolType::WSS => {
WebsocketProtocolHandler::send_recv_unbound_message(
@@ -128,14 +132,14 @@ impl Network {
let data_len = data.len();
match descriptor.protocol_type() {
ProtocolType::UDP => {
return Err("no support for udp protocol".to_owned()).map_err(logthru_net!(error))
bail!("no support for UDP protocol")
}
ProtocolType::TCP => {
return Err("no support for tcp protocol".to_owned()).map_err(logthru_net!(error))
bail!("no support for TCP protocol")
}
_ => {}
}
// Handle connection-oriented protocols
// Try to send to the exact existing connection if one exists
@@ -164,10 +168,10 @@ impl Network {
) -> EyreResult<()> {
let data_len = data.len();
if dial_info.protocol_type() == ProtocolType::UDP {
return Err("no support for UDP protocol".to_owned()).map_err(logthru_net!(error))
bail!("no support for UDP protocol");
}
if dial_info.protocol_type() == ProtocolType::TCP {
return Err("no support for TCP protocol".to_owned()).map_err(logthru_net!(error))
bail!("no support for TCP protocol");
}
// Handle connection-oriented protocols
@@ -176,7 +180,7 @@ impl Network {
.get_or_create_connection(None, dial_info.clone())
.await?;
let res = conn.send_async(data).await.map_err(logthru_net!(error));
let res = conn.send_async(data).await;
if res.is_ok() {
// Network accounting
self.network_manager()
@@ -215,7 +219,7 @@ impl Network {
pub fn is_started(&self) -> bool {
self.inner.lock().network_started
}
pub fn restart_network(&self) {
self.inner.lock().network_needs_restart = true;
}
@@ -247,8 +251,7 @@ impl Network {
pub async fn check_interface_addresses(&self) -> Result<bool, String> {
Ok(false)
}
//////////////////////////////////////////
pub fn get_network_class(&self) -> Option<NetworkClass> {
// xxx eventually detect tor browser?

View File

@@ -3,6 +3,7 @@ pub mod ws;
use super::*;
use crate::xx::*;
use std::io;
#[derive(Debug)]
pub enum ProtocolNetworkConnection {

View File

@@ -1,7 +1,7 @@
use super::*;
use ws_stream_wasm::*;
use futures_util::{StreamExt, SinkExt};
use futures_util::{SinkExt, StreamExt};
use std::io;
use ws_stream_wasm::*;
struct WebsocketNetworkConnectionInner {
ws_meta: WsMeta,
@@ -9,9 +9,7 @@ struct WebsocketNetworkConnectionInner {
}
fn to_io(err: WsErr) -> io::Error {
let kind = match err {
WsErr::InvalidWsState {supplied:_} => io::ErrorKind::
}
io::Error::new(io::ErrorKind::Other, err.to_string())
}
#[derive(Clone)]
@@ -27,9 +25,7 @@ impl fmt::Debug for WebsocketNetworkConnection {
}
impl WebsocketNetworkConnection {
pub fn new(
descriptor: ConnectionDescriptor,
ws_meta: WsMeta, ws_stream: WsStream) -> Self {
pub fn new(descriptor: ConnectionDescriptor, ws_meta: WsMeta, ws_stream: WsStream) -> Self {
Self {
descriptor,
inner: Arc::new(WebsocketNetworkConnectionInner {
@@ -53,28 +49,29 @@ impl WebsocketNetworkConnection {
if message.len() > MAX_MESSAGE_SIZE {
bail_io_error_other!("sending too large WS message");
}
self.inner.ws_stream.clone()
.send(WsMessage::Binary(message)).await
.map_err(|_| "failed to send to websocket".to_owned())
.map_err(logthru_net!(error))
self.inner
.ws_stream
.clone()
.send(WsMessage::Binary(message))
.await
.map_err(to_io)
}
#[instrument(level = "trace", err, skip(self), fields(ret.len))]
pub async fn recv(&self) -> Result<Vec<u8>, String> {
pub async fn recv(&self) -> io::Result<Vec<u8>> {
let out = match self.inner.ws_stream.clone().next().await {
Some(WsMessage::Binary(v)) => v,
Some(x) => {
return Err(format!("Unexpected WS message type: {:?}", x));
bail_io_error_other!("Unexpected WS message type");
}
None => {
return Err("WS stream closed".to_owned()).map_err(logthru_net!(error));
bail_io_error_other!("WS stream closed");
}
};
if out.len() > MAX_MESSAGE_SIZE {
Err("sending too large WS message".to_owned()).map_err(logthru_net!(error))
} else {
Ok(out)
bail_io_error_other!("sending too large WS message")
}
Ok(out)
}
}
@@ -88,8 +85,7 @@ impl WebsocketProtocolHandler {
pub async fn connect(
local_address: Option<SocketAddr>,
dial_info: DialInfo,
) -> Result<ProtocolNetworkConnection, String> {
) -> io::Result<ProtocolNetworkConnection> {
assert!(local_address.is_none());
// Split dial info up
@@ -99,34 +95,33 @@ impl WebsocketProtocolHandler {
_ => panic!("invalid dialinfo for WS/WSS protocol"),
};
let request = dial_info.request().unwrap();
let split_url = SplitUrl::from_str(&request)?;
let split_url = SplitUrl::from_str(&request).map_err(to_io_error_other)?;
if split_url.scheme != scheme {
return Err("invalid websocket url scheme".to_string());
bail_io_error_other!("invalid websocket url scheme");
}
let (wsmeta, wsio) = WsMeta::connect(request, None)
.await
.map_err(map_to_string)
.map_err(logthru_net!(error))?;
let (wsmeta, wsio) = WsMeta::connect(request, None).await.map_err(to_io)?;
// Make our connection descriptor
Ok(ProtocolNetworkConnection::Ws(WebsocketNetworkConnection::new(ConnectionDescriptor::new_no_local(
dial_info.to_peer_address(),
), wsmeta, wsio)))
Ok(ProtocolNetworkConnection::Ws(
WebsocketNetworkConnection::new(
ConnectionDescriptor::new_no_local(dial_info.to_peer_address()),
wsmeta,
wsio,
),
))
}
#[instrument(level = "trace", err, skip(data), fields(data.len = data.len()))]
pub async fn send_unbound_message(dial_info: DialInfo, data: Vec<u8>) -> Result<(), String> {
pub async fn send_unbound_message(dial_info: DialInfo, data: Vec<u8>) -> io::Result<()> {
if data.len() > MAX_MESSAGE_SIZE {
return Err("sending too large unbound WS message".to_owned());
bail_io_error_other!("sending too large unbound WS message");
}
// Make the real connection
let conn = Self::connect(None, dial_info)
.await
.map_err(|e| format!("failed to connect websocket for unbound message: {}", e))?;
conn.send(data).await
// Make the real connection
let conn = Self::connect(None, dial_info).await?;
conn.send(data).await
}
#[instrument(level = "trace", err, skip(data), fields(data.len = data.len(), ret.len))]
@@ -134,23 +129,19 @@ impl WebsocketProtocolHandler {
dial_info: DialInfo,
data: Vec<u8>,
timeout_ms: u32,
) -> Result<Vec<u8>, String> {
) -> io::Result<Vec<u8>> {
if data.len() > MAX_MESSAGE_SIZE {
return Err("sending too large unbound WS message".to_owned());
bail_io_error_other!("sending too large unbound WS message");
}
let conn = Self::connect(None, dial_info.clone())
.await
.map_err(|e| format!("failed to connect websocket for unbound message: {}", e))?;
let conn = Self::connect(None, dial_info.clone()).await?;
conn.send(data).await?;
let out = timeout(timeout_ms, conn.recv())
.await
.map_err(map_to_string)??;
.map_err(|e| e.to_io())??;
tracing::Span::current().record("ret.len", &out.len());
Ok(out)
}
}