This commit is contained in:
John Smith 2022-07-12 12:45:54 -04:00
parent c9d3f38fa0
commit 886d5bbd7c
17 changed files with 171 additions and 181 deletions

View File

@ -195,19 +195,10 @@ 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
let res = rpc_jh.await;
cfg_if! { #[cfg(feature="rt-tokio")]
if #[cfg(feature="rt-async-std")] { let res = res.map_err(|e| format!("join error: {}", e))?;
rpc_jh res.map_err(|e| format!("client RPC system error: {}", e))
.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> {

View File

@ -337,11 +337,11 @@ impl AttachmentManager {
} }
} }
async fn process_input(&self, input: &AttachmentInput) -> Result<(), String> { async fn process_input(&self, input: &AttachmentInput) -> EyreResult<()> {
let attachment_machine = self.inner.lock().attachment_machine.clone(); let attachment_machine = self.inner.lock().attachment_machine.clone();
let output = attachment_machine.consume(input).await; let output = attachment_machine.consume(input).await;
match output { match output {
Err(e) => Err(format!( Err(e) => Err(eyre!(
"invalid input '{:?}' for state machine in state '{:?}': {:?}", "invalid input '{:?}' for state machine in state '{:?}': {:?}",
input, input,
attachment_machine.state(), attachment_machine.state(),
@ -357,17 +357,17 @@ impl AttachmentManager {
} }
#[instrument(level = "trace", skip(self), err)] #[instrument(level = "trace", skip(self), err)]
pub async fn request_attach(&self) -> Result<(), String> { pub async fn request_attach(&self) -> EyreResult<()> {
self.process_input(&AttachmentInput::AttachRequested) self.process_input(&AttachmentInput::AttachRequested)
.await .await
.map_err(|e| format!("Attach request failed: {}", e)) .map_err(|e| eyre!("Attach request failed: {}", e))
} }
#[instrument(level = "trace", skip(self), err)] #[instrument(level = "trace", skip(self), err)]
pub async fn request_detach(&self) -> Result<(), String> { pub async fn request_detach(&self) -> EyreResult<()> {
self.process_input(&AttachmentInput::DetachRequested) self.process_input(&AttachmentInput::DetachRequested)
.await .await
.map_err(|e| format!("Detach request failed: {}", e)) .map_err(|e| eyre!("Detach request failed: {}", e))
} }
pub fn get_state(&self) -> AttachmentState { pub fn get_state(&self) -> AttachmentState {

View File

@ -232,13 +232,13 @@ impl Crypto {
nonce: &Nonce, nonce: &Nonce,
shared_secret: &SharedSecret, shared_secret: &SharedSecret,
associated_data: Option<&[u8]>, associated_data: Option<&[u8]>,
) -> Result<(), String> { ) -> Result<(), VeilidAPIError> {
let key = ch::Key::from(*shared_secret); let key = ch::Key::from(*shared_secret);
let xnonce = ch::XNonce::from(*nonce); let xnonce = ch::XNonce::from(*nonce);
let aead = ch::XChaCha20Poly1305::new(&key); let aead = ch::XChaCha20Poly1305::new(&key);
aead.decrypt_in_place(&xnonce, associated_data.unwrap_or(b""), body) aead.decrypt_in_place(&xnonce, associated_data.unwrap_or(b""), body)
.map_err(map_to_string) .map_err(map_to_string)
.map_err(logthru_crypto!()) .map_err(VeilidAPIError::generic)
} }
pub fn decrypt_aead( pub fn decrypt_aead(
@ -246,11 +246,11 @@ impl Crypto {
nonce: &Nonce, nonce: &Nonce,
shared_secret: &SharedSecret, shared_secret: &SharedSecret,
associated_data: Option<&[u8]>, associated_data: Option<&[u8]>,
) -> Result<Vec<u8>, String> { ) -> Result<Vec<u8>, VeilidAPIError> {
let mut out = body.to_vec(); let mut out = body.to_vec();
Self::decrypt_in_place_aead(&mut out, nonce, shared_secret, associated_data) Self::decrypt_in_place_aead(&mut out, nonce, shared_secret, associated_data)
.map_err(map_to_string) .map_err(map_to_string)
.map_err(logthru_crypto!())?; .map_err(VeilidAPIError::generic)?;
Ok(out) Ok(out)
} }
@ -259,14 +259,14 @@ impl Crypto {
nonce: &Nonce, nonce: &Nonce,
shared_secret: &SharedSecret, shared_secret: &SharedSecret,
associated_data: Option<&[u8]>, associated_data: Option<&[u8]>,
) -> Result<(), String> { ) -> Result<(), VeilidAPIError> {
let key = ch::Key::from(*shared_secret); let key = ch::Key::from(*shared_secret);
let xnonce = ch::XNonce::from(*nonce); let xnonce = ch::XNonce::from(*nonce);
let aead = ch::XChaCha20Poly1305::new(&key); let aead = ch::XChaCha20Poly1305::new(&key);
aead.encrypt_in_place(&xnonce, associated_data.unwrap_or(b""), body) aead.encrypt_in_place(&xnonce, associated_data.unwrap_or(b""), body)
.map_err(map_to_string) .map_err(map_to_string)
.map_err(logthru_crypto!()) .map_err(VeilidAPIError::generic)
} }
pub fn encrypt_aead( pub fn encrypt_aead(
@ -274,11 +274,11 @@ impl Crypto {
nonce: &Nonce, nonce: &Nonce,
shared_secret: &SharedSecret, shared_secret: &SharedSecret,
associated_data: Option<&[u8]>, associated_data: Option<&[u8]>,
) -> Result<Vec<u8>, String> { ) -> Result<Vec<u8>, VeilidAPIError> {
let mut out = body.to_vec(); let mut out = body.to_vec();
Self::encrypt_in_place_aead(&mut out, nonce, shared_secret, associated_data) Self::encrypt_in_place_aead(&mut out, nonce, shared_secret, associated_data)
.map_err(map_to_string) .map_err(map_to_string)
.map_err(logthru_crypto!())?; .map_err(VeilidAPIError::generic)?;
Ok(out) Ok(out)
} }

View File

@ -158,7 +158,7 @@ macro_rules! byte_array_type {
let res = BASE64URL_NOPAD.decode_mut(input.as_bytes(), &mut bytes); let res = BASE64URL_NOPAD.decode_mut(input.as_bytes(), &mut bytes);
match res { match res {
Ok(_) => Ok(Self::new(bytes)), Ok(_) => Ok(Self::new(bytes)),
Err(_) => apierr_generic!("Failed to decode"), Err(_) => apibail_generic!("Failed to decode"),
} }
} }
} }
@ -277,7 +277,7 @@ macro_rules! byte_array_type {
out.valid = true; out.valid = true;
Ok(out) Ok(out)
} }
Err(err) => apierr_generic!(err), Err(err) => Err(VeilidAPIError::generic(err)),
} }
} }
} }
@ -382,7 +382,8 @@ pub fn sign(
kpb[..DHT_KEY_SECRET_LENGTH].copy_from_slice(&dht_key_secret.bytes); kpb[..DHT_KEY_SECRET_LENGTH].copy_from_slice(&dht_key_secret.bytes);
kpb[DHT_KEY_SECRET_LENGTH..].copy_from_slice(&dht_key.bytes); kpb[DHT_KEY_SECRET_LENGTH..].copy_from_slice(&dht_key.bytes);
let keypair = Keypair::from_bytes(&kpb).map_err(mapapierr_parse!("Keypair is invalid"))?; let keypair = Keypair::from_bytes(&kpb)
.map_err(|e| VeilidAPIError::parse_error("Keypair is invalid", e))?;
let mut dig = Blake3Digest512::new(); let mut dig = Blake3Digest512::new();
dig.update(data); dig.update(data);
@ -402,16 +403,16 @@ pub fn verify(
) -> Result<(), VeilidAPIError> { ) -> Result<(), VeilidAPIError> {
assert!(dht_key.valid); assert!(dht_key.valid);
assert!(signature.valid); assert!(signature.valid);
let pk = let pk = PublicKey::from_bytes(&dht_key.bytes)
PublicKey::from_bytes(&dht_key.bytes).map_err(mapapierr_parse!("Public key is invalid"))?; .map_err(|e| VeilidAPIError::parse_error("Public key is invalid", e))?;
let sig = Signature::from_bytes(&signature.bytes) let sig = Signature::from_bytes(&signature.bytes)
.map_err(mapapierr_parse!("Signature is invalid"))?; .map_err(|e| VeilidAPIError::parse_error("Signature is invalid", e))?;
let mut dig = Blake3Digest512::new(); let mut dig = Blake3Digest512::new();
dig.update(data); dig.update(data);
pk.verify_prehashed(dig, None, &sig) pk.verify_prehashed(dig, None, &sig)
.map_err(mapapierr_parse!("Verification failed"))?; .map_err(|e| VeilidAPIError::parse_error("Verification failed", e))?;
Ok(()) Ok(())
} }

View File

@ -4,7 +4,7 @@ use crate::*;
use async_executors::{Bindgen, LocalSpawnHandleExt, SpawnHandleExt, Timer}; use async_executors::{Bindgen, LocalSpawnHandleExt, SpawnHandleExt, Timer};
use futures_util::future::{select, Either}; use futures_util::future::{select, Either};
use js_sys::*; use js_sys::*;
use wasm_bindgen_futures::*; //use wasm_bindgen_futures::*;
//use web_sys::*; //use web_sys::*;
#[wasm_bindgen] #[wasm_bindgen]

View File

@ -93,7 +93,7 @@ impl ProtocolNetworkConnection {
} }
} }
// pub async fn close(&self) -> Result<(), String> { // pub async fn close(&self) -> io::Result<()> {
// 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,

View File

@ -23,21 +23,19 @@ impl RawTcpNetworkConnection {
} }
// #[instrument(level = "trace", err, skip(self))] // #[instrument(level = "trace", err, skip(self))]
// pub async fn close(&mut self) -> Result<(), String> { // pub async fn close(&mut self) -> io::Result<()> {
// // 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?;
// // Then shut down the write side of the socket to effect a clean close // // Then shut down the write side of the socket to effect a clean close
// cfg_if! { // cfg_if! {
// if #[cfg(feature="rt-async-std")] { // if #[cfg(feature="rt-async-std")] {
// self.tcp_stream // self.tcp_stream
// .shutdown(async_std::net::Shutdown::Write) // .shutdown(async_std::net::Shutdown::Write)
// .map_err(map_to_string)
// } else if #[cfg(feature="rt-tokio")] { // } else if #[cfg(feature="rt-tokio")] {
// use tokio::io::AsyncWriteExt; // use tokio::io::AsyncWriteExt;
// self.tcp_stream.get_mut() // self.tcp_stream.get_mut()
// .shutdown() // .shutdown()
// .await // .await
// .map_err(map_to_string)
// } // }
// } // }
// } // }

View File

@ -71,13 +71,13 @@ where
} }
// #[instrument(level = "trace", err, skip(self))] // #[instrument(level = "trace", err, skip(self))]
// pub async fn close(&self) -> Result<(), String> { // pub async fn close(&self) -> io::Result<()> {
// // 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(to_io)?;
// // 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(to_io)
// } // }
#[instrument(level = "trace", err, skip(self, message), fields(message.len = message.len()))] #[instrument(level = "trace", err, skip(self, message), fields(message.len = message.len()))]

View File

@ -53,7 +53,7 @@ impl DummyNetworkConnection {
pub fn descriptor(&self) -> ConnectionDescriptor { pub fn descriptor(&self) -> ConnectionDescriptor {
self.descriptor.clone() self.descriptor.clone()
} }
// pub fn close(&self) -> Result<(), String> { // pub fn close(&self) -> io::Result<()> {
// Ok(()) // Ok(())
// } // }
pub fn send(&self, _message: Vec<u8>) -> io::Result<()> { pub fn send(&self, _message: Vec<u8>) -> io::Result<()> {

View File

@ -10,11 +10,9 @@ pub use protocol::*;
struct NetworkInner { struct NetworkInner {
network_manager: NetworkManager, network_manager: NetworkManager,
stop_network: Eventual,
network_started: bool, network_started: bool,
network_needs_restart: bool, network_needs_restart: bool,
protocol_config: Option<ProtocolConfig>, protocol_config: Option<ProtocolConfig>,
//join_handle: TryJoin?
} }
#[derive(Clone)] #[derive(Clone)]
@ -27,7 +25,6 @@ impl Network {
fn new_inner(network_manager: NetworkManager) -> NetworkInner { fn new_inner(network_manager: NetworkManager) -> NetworkInner {
NetworkInner { NetworkInner {
network_manager, network_manager,
stop_network: Eventual::new(),
network_started: false, network_started: false,
network_needs_restart: false, network_needs_restart: false,
protocol_config: None, //join_handle: None, protocol_config: None, //join_handle: None,
@ -248,7 +245,7 @@ impl Network {
f(&[]) f(&[])
} }
pub async fn check_interface_addresses(&self) -> Result<bool, String> { pub async fn check_interface_addresses(&self) -> EyreResult<bool> {
Ok(false) Ok(false)
} }

View File

@ -41,8 +41,8 @@ impl WebsocketNetworkConnection {
} }
// #[instrument(level = "trace", err, skip(self))] // #[instrument(level = "trace", err, skip(self))]
// pub async fn close(&self) -> Result<(), String> { // pub async fn close(&self) -> io::Result<()> {
// self.inner.ws_meta.close().await.map_err(map_to_string).map(drop) // self.inner.ws_meta.close().await.map_err(to_io).map(drop)
// } // }
#[instrument(level = "trace", err, skip(self, message), fields(message.len = message.len()))] #[instrument(level = "trace", err, skip(self, message), fields(message.len = message.len()))]
@ -62,7 +62,7 @@ impl WebsocketNetworkConnection {
pub async fn recv(&self) -> io::Result<Vec<u8>> { pub async fn recv(&self) -> io::Result<Vec<u8>> {
let out = match SendWrapper::new(self.inner.ws_stream.clone().next()).await { let out = match SendWrapper::new(self.inner.ws_stream.clone().next()).await {
Some(WsMessage::Binary(v)) => v, Some(WsMessage::Binary(v)) => v,
Some(x) => { Some(_) => {
bail_io_error_other!("Unexpected WS message type"); bail_io_error_other!("Unexpected WS message type");
} }
None => { None => {

View File

@ -390,7 +390,7 @@ impl RoutingTable {
} }
#[instrument(level = "trace", skip(self), ret, err)] #[instrument(level = "trace", skip(self), ret, err)]
pub fn register_find_node_answer(&self, peers: Vec<PeerInfo>) -> Result<Vec<NodeRef>, String> { pub fn register_find_node_answer(&self, peers: Vec<PeerInfo>) -> EyreResult<Vec<NodeRef>> {
let node_id = self.node_id(); let node_id = self.node_id();
// register nodes we'd found // register nodes we'd found
@ -403,24 +403,14 @@ impl RoutingTable {
// register the node if it's new // register the node if it's new
let nr = self let nr = self
.register_node_with_signed_node_info(p.node_id.key, p.signed_node_info.clone()) .register_node_with_signed_node_info(p.node_id.key, p.signed_node_info.clone())?;
.map_err(map_to_string)
.map_err(logthru_rtab!(
"couldn't register node {} at {:?}",
p.node_id.key,
&p.signed_node_info
))?;
out.push(nr); out.push(nr);
} }
Ok(out) Ok(out)
} }
#[instrument(level = "trace", skip(self), ret, err)] #[instrument(level = "trace", skip(self), ret, err)]
pub async fn find_node( pub async fn find_node(&self, node_ref: NodeRef, node_id: DHTKey) -> EyreResult<Vec<NodeRef>> {
&self,
node_ref: NodeRef,
node_id: DHTKey,
) -> Result<Vec<NodeRef>, String> {
let rpc_processor = self.rpc_processor(); let rpc_processor = self.rpc_processor();
let res = rpc_processor let res = rpc_processor
@ -431,22 +421,20 @@ impl RoutingTable {
None, None,
rpc_processor.make_respond_to_sender(node_ref.clone()), rpc_processor.make_respond_to_sender(node_ref.clone()),
) )
.await .await?;
.map_err(map_to_string)
.map_err(logthru_rtab!())?;
// register nodes we'd found // register nodes we'd found
self.register_find_node_answer(res.answer) self.register_find_node_answer(res.answer)
} }
#[instrument(level = "trace", skip(self), ret, err)] #[instrument(level = "trace", skip(self), ret, err)]
pub async fn find_self(&self, node_ref: NodeRef) -> Result<Vec<NodeRef>, String> { pub async fn find_self(&self, node_ref: NodeRef) -> EyreResult<Vec<NodeRef>> {
let node_id = self.node_id(); let node_id = self.node_id();
self.find_node(node_ref, node_id).await self.find_node(node_ref, node_id).await
} }
#[instrument(level = "trace", skip(self), ret, err)] #[instrument(level = "trace", skip(self), ret, err)]
pub async fn find_target(&self, node_ref: NodeRef) -> Result<Vec<NodeRef>, String> { pub async fn find_target(&self, node_ref: NodeRef) -> EyreResult<Vec<NodeRef>> {
let node_id = node_ref.node_id(); let node_id = node_ref.node_id();
self.find_node(node_ref, node_id).await self.find_node(node_ref, node_id).await
} }
@ -460,7 +448,7 @@ impl RoutingTable {
let closest_nodes = match self.find_self(node_ref.clone()).await { let closest_nodes = match self.find_self(node_ref.clone()).await {
Err(e) => { Err(e) => {
log_rtab!(error log_rtab!(error
"reverse_find_node: find_self failed for {:?}: {}", "reverse_find_node: find_self failed for {:?}: {:?}",
&node_ref, e &node_ref, e
); );
return; return;
@ -473,7 +461,7 @@ impl RoutingTable {
for closest_nr in closest_nodes { for closest_nr in closest_nodes {
if let Err(e) = self.find_self(closest_nr.clone()).await { if let Err(e) = self.find_self(closest_nr.clone()).await {
log_rtab!(error log_rtab!(error
"reverse_find_node: closest node find_self failed for {:?}: {}", "reverse_find_node: closest node find_self failed for {:?}: {:?}",
&closest_nr, e &closest_nr, e
); );
} }

View File

@ -260,7 +260,7 @@ fn config_callback(key: String) -> ConfigCallbackReturn {
_ => { _ => {
let err = format!("config key '{}' doesn't exist", key); let err = format!("config key '{}' doesn't exist", key);
debug!("{}", err); debug!("{}", err);
apierr_internal!(err) Err(VeilidAPIError::internal(err))
} }
} }
} }

View File

@ -31,43 +31,11 @@ use xx::*;
///////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////
#[allow(unused_macros)]
#[macro_export]
macro_rules! apierr_generic {
($x:expr) => {
Err(VeilidAPIError::generic($x))
};
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! apierr_internal {
($x:expr) => {
Err(VeilidAPIError::internal($x))
};
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! apierr_parse {
($x:expr, $y:expr) => {
Err(VeilidAPIError::parse_error($x, $y))
};
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! mapapierr_parse {
($x:expr) => {
|e| VeilidAPIError::parse_error($x, e)
};
}
#[allow(unused_macros)] #[allow(unused_macros)]
#[macro_export] #[macro_export]
macro_rules! apibail_generic { macro_rules! apibail_generic {
($x:expr) => { ($x:expr) => {
return Err(VeilidAPIError::generic($x)); return Err(VeilidAPIError::generic($x))
}; };
} }
@ -75,7 +43,7 @@ macro_rules! apibail_generic {
#[macro_export] #[macro_export]
macro_rules! apibail_internal { macro_rules! apibail_internal {
($x:expr) => { ($x:expr) => {
return Err(VeilidAPIError::internal($x)); return Err(VeilidAPIError::internal($x))
}; };
} }
@ -83,7 +51,7 @@ macro_rules! apibail_internal {
#[macro_export] #[macro_export]
macro_rules! apibail_parse { macro_rules! apibail_parse {
($x:expr, $y:expr) => { ($x:expr, $y:expr) => {
return Err(VeilidAPIError::parse_error($x, $y)); return Err(VeilidAPIError::parse_error($x, $y))
}; };
} }
@ -123,6 +91,18 @@ pub enum VeilidAPIError {
} }
impl VeilidAPIError { impl VeilidAPIError {
pub fn not_initialized() -> Self {
Self::NotInitialized
}
pub fn already_initialized() -> Self {
Self::AlreadyInitialized
}
pub fn timeout() -> Self {
Self::Timeout
}
pub fn shutdown() -> Self {
Self::Shutdown
}
pub fn node_not_found(node_id: NodeId) -> Self { pub fn node_not_found(node_id: NodeId) -> Self {
Self::NodeNotFound { node_id } Self::NodeNotFound { node_id }
} }
@ -172,15 +152,6 @@ impl VeilidAPIError {
} }
} }
macro_rules! parse_error {
($msg:expr, $val:expr) => {
VeilidAPIError::ParseError {
message: $msg.to_string(),
value: $val.to_string(),
}
};
}
///////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Copy, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Copy, Serialize, Deserialize)]
@ -676,7 +647,10 @@ impl FromStr for Address {
} else if let Ok(addr) = Ipv6Addr::from_str(host) { } else if let Ok(addr) = Ipv6Addr::from_str(host) {
Ok(Address::IPV6(addr)) Ok(Address::IPV6(addr))
} else { } else {
Err(parse_error!("Address::from_str failed", host)) Err(VeilidAPIError::parse_error(
"Address::from_str failed",
host,
))
} }
} }
} }
@ -732,7 +706,7 @@ impl FromStr for SocketAddress {
type Err = VeilidAPIError; type Err = VeilidAPIError;
fn from_str(s: &str) -> Result<SocketAddress, VeilidAPIError> { fn from_str(s: &str) -> Result<SocketAddress, VeilidAPIError> {
let sa = SocketAddr::from_str(s) let sa = SocketAddr::from_str(s)
.map_err(|e| parse_error!("Failed to parse SocketAddress", e))?; .map_err(|e| VeilidAPIError::parse_error("Failed to parse SocketAddress", e))?;
Ok(SocketAddress::from_socket_addr(sa)) Ok(SocketAddress::from_socket_addr(sa))
} }
} }
@ -898,9 +872,9 @@ impl fmt::Display for DialInfo {
impl FromStr for DialInfo { impl FromStr for DialInfo {
type Err = VeilidAPIError; type Err = VeilidAPIError;
fn from_str(s: &str) -> Result<DialInfo, VeilidAPIError> { fn from_str(s: &str) -> Result<DialInfo, VeilidAPIError> {
let (proto, rest) = s let (proto, rest) = s.split_once('|').ok_or_else(|| {
.split_once('|') VeilidAPIError::parse_error("DialInfo::from_str missing protocol '|' separator", s)
.ok_or_else(|| parse_error!("DialInfo::from_str missing protocol '|' separator", s))?; })?;
match proto { match proto {
"udp" => { "udp" => {
let socket_address = SocketAddress::from_str(rest)?; let socket_address = SocketAddress::from_str(rest)?;
@ -912,10 +886,14 @@ impl FromStr for DialInfo {
} }
"ws" => { "ws" => {
let url = format!("ws://{}", rest); let url = format!("ws://{}", rest);
let split_url = SplitUrl::from_str(&url) let split_url = SplitUrl::from_str(&url).map_err(|e| {
.map_err(|e| parse_error!(format!("unable to split WS url: {}", e), url))?; VeilidAPIError::parse_error(format!("unable to split WS url: {}", e), &url)
})?;
if split_url.scheme != "ws" || !url.starts_with("ws://") { if split_url.scheme != "ws" || !url.starts_with("ws://") {
return Err(parse_error!("incorrect scheme for WS dialinfo", url)); return Err(VeilidAPIError::parse_error(
"incorrect scheme for WS dialinfo",
url,
));
} }
let url_port = split_url.port.unwrap_or(80u16); let url_port = split_url.port.unwrap_or(80u16);
@ -939,15 +917,22 @@ impl FromStr for DialInfo {
} }
"wss" => { "wss" => {
let url = format!("wss://{}", rest); let url = format!("wss://{}", rest);
let split_url = SplitUrl::from_str(&url) let split_url = SplitUrl::from_str(&url).map_err(|e| {
.map_err(|e| parse_error!(format!("unable to split WSS url: {}", e), url))?; VeilidAPIError::parse_error(format!("unable to split WSS url: {}", e), &url)
})?;
if split_url.scheme != "wss" || !url.starts_with("wss://") { if split_url.scheme != "wss" || !url.starts_with("wss://") {
return Err(parse_error!("incorrect scheme for WSS dialinfo", url)); return Err(VeilidAPIError::parse_error(
"incorrect scheme for WSS dialinfo",
url,
));
} }
let url_port = split_url.port.unwrap_or(443u16); let url_port = split_url.port.unwrap_or(443u16);
let (a, rest) = rest.split_once('|').ok_or_else(|| { let (a, rest) = rest.split_once('|').ok_or_else(|| {
parse_error!("DialInfo::from_str missing socket address '|' separator", s) VeilidAPIError::parse_error(
"DialInfo::from_str missing socket address '|' separator",
s,
)
})?; })?;
let address = Address::from_str(a)?; let address = Address::from_str(a)?;
@ -956,7 +941,10 @@ impl FromStr for DialInfo {
format!("wss://{}", rest), format!("wss://{}", rest),
) )
} }
_ => Err(parse_error!("DialInfo::from_str has invalid scheme", s)), _ => Err(VeilidAPIError::parse_error(
"DialInfo::from_str has invalid scheme",
s,
)),
} }
} }
} }
@ -983,23 +971,27 @@ impl DialInfo {
}) })
} }
pub fn try_ws(socket_address: SocketAddress, url: String) -> Result<Self, VeilidAPIError> { pub fn try_ws(socket_address: SocketAddress, url: String) -> Result<Self, VeilidAPIError> {
let split_url = SplitUrl::from_str(&url) let split_url = SplitUrl::from_str(&url).map_err(|e| {
.map_err(|e| parse_error!(format!("unable to split WS url: {}", e), url))?; VeilidAPIError::parse_error(format!("unable to split WS url: {}", e), &url)
})?;
if split_url.scheme != "ws" || !url.starts_with("ws://") { if split_url.scheme != "ws" || !url.starts_with("ws://") {
return Err(parse_error!("incorrect scheme for WS dialinfo", url)); return Err(VeilidAPIError::parse_error(
"incorrect scheme for WS dialinfo",
url,
));
} }
let url_port = split_url.port.unwrap_or(80u16); let url_port = split_url.port.unwrap_or(80u16);
if url_port != socket_address.port() { if url_port != socket_address.port() {
return Err(parse_error!( return Err(VeilidAPIError::parse_error(
"socket address port doesn't match url port", "socket address port doesn't match url port",
url url,
)); ));
} }
if let SplitUrlHost::IpAddr(a) = split_url.host { if let SplitUrlHost::IpAddr(a) = split_url.host {
if socket_address.to_ip_addr() != a { if socket_address.to_ip_addr() != a {
return Err(parse_error!( return Err(VeilidAPIError::parse_error(
format!("request address does not match socket address: {}", a), format!("request address does not match socket address: {}", a),
socket_address socket_address,
)); ));
} }
} }
@ -1009,22 +1001,26 @@ impl DialInfo {
})) }))
} }
pub fn try_wss(socket_address: SocketAddress, url: String) -> Result<Self, VeilidAPIError> { pub fn try_wss(socket_address: SocketAddress, url: String) -> Result<Self, VeilidAPIError> {
let split_url = SplitUrl::from_str(&url) let split_url = SplitUrl::from_str(&url).map_err(|e| {
.map_err(|e| parse_error!(format!("unable to split WSS url: {}", e), url))?; VeilidAPIError::parse_error(format!("unable to split WSS url: {}", e), &url)
})?;
if split_url.scheme != "wss" || !url.starts_with("wss://") { if split_url.scheme != "wss" || !url.starts_with("wss://") {
return Err(parse_error!("incorrect scheme for WSS dialinfo", url)); return Err(VeilidAPIError::parse_error(
"incorrect scheme for WSS dialinfo",
url,
));
} }
let url_port = split_url.port.unwrap_or(443u16); let url_port = split_url.port.unwrap_or(443u16);
if url_port != socket_address.port() { if url_port != socket_address.port() {
return Err(parse_error!( return Err(VeilidAPIError::parse_error(
"socket address port doesn't match url port", "socket address port doesn't match url port",
url url,
)); ));
} }
if !matches!(split_url.host, SplitUrlHost::Hostname(_)) { if !matches!(split_url.host, SplitUrlHost::Hostname(_)) {
return Err(parse_error!( return Err(VeilidAPIError::parse_error(
"WSS url can not use address format, only hostname format", "WSS url can not use address format, only hostname format",
url url,
)); ));
} }
Ok(Self::WSS(DialInfoWSS { Ok(Self::WSS(DialInfoWSS {
@ -1144,7 +1140,10 @@ impl DialInfo {
let hostname = hostname.as_ref(); let hostname = hostname.as_ref();
if short.len() < 2 { if short.len() < 2 {
return Err(parse_error!("invalid short url length", short)); return Err(VeilidAPIError::parse_error(
"invalid short url length",
short,
));
} }
let url = match &short[0..1] { let url = match &short[0..1] {
"U" => { "U" => {
@ -1160,7 +1159,7 @@ impl DialInfo {
format!("wss://{}:{}", hostname, &short[1..]) format!("wss://{}:{}", hostname, &short[1..])
} }
_ => { _ => {
return Err(parse_error!("invalid short url type", short)); return Err(VeilidAPIError::parse_error("invalid short url type", short));
} }
}; };
Self::try_vec_from_url(url) Self::try_vec_from_url(url)
@ -1169,18 +1168,18 @@ impl DialInfo {
pub fn try_vec_from_url<S: AsRef<str>>(url: S) -> Result<Vec<Self>, VeilidAPIError> { pub fn try_vec_from_url<S: AsRef<str>>(url: S) -> Result<Vec<Self>, VeilidAPIError> {
let url = url.as_ref(); let url = url.as_ref();
let split_url = SplitUrl::from_str(url) let split_url = SplitUrl::from_str(url)
.map_err(|e| parse_error!(format!("unable to split url: {}", e), url))?; .map_err(|e| VeilidAPIError::parse_error(format!("unable to split url: {}", e), url))?;
let port = match split_url.scheme.as_str() { let port = match split_url.scheme.as_str() {
"udp" | "tcp" => split_url "udp" | "tcp" => split_url
.port .port
.ok_or_else(|| parse_error!("Missing port in udp url", url))?, .ok_or_else(|| VeilidAPIError::parse_error("Missing port in udp url", url))?,
"ws" => split_url.port.unwrap_or(80u16), "ws" => split_url.port.unwrap_or(80u16),
"wss" => split_url.port.unwrap_or(443u16), "wss" => split_url.port.unwrap_or(443u16),
_ => { _ => {
return Err(parse_error!( return Err(VeilidAPIError::parse_error(
"Invalid dial info url scheme", "Invalid dial info url scheme",
split_url.scheme split_url.scheme,
)); ));
} }
}; };
@ -1197,7 +1196,7 @@ impl DialInfo {
SplitUrlHost::Hostname(_) => split_url SplitUrlHost::Hostname(_) => split_url
.host_port(port) .host_port(port)
.to_socket_addrs() .to_socket_addrs()
.map_err(|_| parse_error!("couldn't resolve hostname in url", url))? .map_err(|_| VeilidAPIError::parse_error("couldn't resolve hostname in url", url))?
.collect(), .collect(),
SplitUrlHost::IpAddr(a) => vec![SocketAddr::new(a, port)], SplitUrlHost::IpAddr(a) => vec![SocketAddr::new(a, port)],
} }
@ -1359,9 +1358,9 @@ impl SignedNodeInfo {
timestamp: u64, timestamp: u64,
) -> Result<Self, VeilidAPIError> { ) -> Result<Self, VeilidAPIError> {
let mut node_info_bytes = serde_cbor::to_vec(&node_info) let mut node_info_bytes = serde_cbor::to_vec(&node_info)
.map_err(mapapierr_parse!("failed to encode node info as cbor"))?; .map_err(|e| VeilidAPIError::parse_error("failed to encode node info as cbor", e))?;
let mut timestamp_bytes = serde_cbor::to_vec(&timestamp) let mut timestamp_bytes = serde_cbor::to_vec(&timestamp)
.map_err(mapapierr_parse!("failed to encode timestamp as cbor"))?; .map_err(|e| VeilidAPIError::parse_error("failed to encode timestamp as cbor", e))?;
node_info_bytes.append(&mut timestamp_bytes); node_info_bytes.append(&mut timestamp_bytes);
@ -1381,9 +1380,9 @@ impl SignedNodeInfo {
let timestamp = intf::get_timestamp(); let timestamp = intf::get_timestamp();
let mut node_info_bytes = serde_cbor::to_vec(&node_info) let mut node_info_bytes = serde_cbor::to_vec(&node_info)
.map_err(mapapierr_parse!("failed to encode node info as cbor"))?; .map_err(|e| VeilidAPIError::parse_error("failed to encode node info as cbor", e))?;
let mut timestamp_bytes = serde_cbor::to_vec(&timestamp) let mut timestamp_bytes = serde_cbor::to_vec(&timestamp)
.map_err(mapapierr_parse!("failed to encode timestamp as cbor"))?; .map_err(|e| VeilidAPIError::parse_error("failed to encode timestamp as cbor", e))?;
node_info_bytes.append(&mut timestamp_bytes); node_info_bytes.append(&mut timestamp_bytes);
@ -1532,15 +1531,15 @@ impl FromStr for NodeDialInfo {
type Err = VeilidAPIError; type Err = VeilidAPIError;
fn from_str(s: &str) -> Result<NodeDialInfo, VeilidAPIError> { fn from_str(s: &str) -> Result<NodeDialInfo, VeilidAPIError> {
// split out node id from the dial info // split out node id from the dial info
let (node_id_str, rest) = s let (node_id_str, rest) = s.split_once('@').ok_or_else(|| {
.split_once('@') VeilidAPIError::parse_error("NodeDialInfo::from_str missing @ node id separator", s)
.ok_or_else(|| parse_error!("NodeDialInfo::from_str missing @ node id separator", s))?; })?;
// parse out node id // parse out node id
let node_id = NodeId::new(DHTKey::try_decode(node_id_str).map_err(|e| { let node_id = NodeId::new(DHTKey::try_decode(node_id_str).map_err(|e| {
parse_error!( VeilidAPIError::parse_error(
format!("NodeDialInfo::from_str couldn't parse node id: {}", e), format!("NodeDialInfo::from_str couldn't parse node id: {}", e),
s s,
) )
})?); })?);
// parse out dial info // parse out dial info
@ -1851,35 +1850,35 @@ impl VeilidAPI {
if let Some(context) = &inner.context { if let Some(context) = &inner.context {
return Ok(context.table_store.clone()); return Ok(context.table_store.clone());
} }
Err(VeilidAPIError::NotInitialized) Err(VeilidAPIError::not_initialized())
} }
pub fn block_store(&self) -> Result<BlockStore, VeilidAPIError> { pub fn block_store(&self) -> Result<BlockStore, VeilidAPIError> {
let inner = self.inner.lock(); let inner = self.inner.lock();
if let Some(context) = &inner.context { if let Some(context) = &inner.context {
return Ok(context.block_store.clone()); return Ok(context.block_store.clone());
} }
Err(VeilidAPIError::NotInitialized) Err(VeilidAPIError::not_initialized())
} }
pub fn protected_store(&self) -> Result<ProtectedStore, VeilidAPIError> { pub fn protected_store(&self) -> Result<ProtectedStore, VeilidAPIError> {
let inner = self.inner.lock(); let inner = self.inner.lock();
if let Some(context) = &inner.context { if let Some(context) = &inner.context {
return Ok(context.protected_store.clone()); return Ok(context.protected_store.clone());
} }
Err(VeilidAPIError::NotInitialized) Err(VeilidAPIError::not_initialized())
} }
pub fn attachment_manager(&self) -> Result<AttachmentManager, VeilidAPIError> { pub fn attachment_manager(&self) -> Result<AttachmentManager, VeilidAPIError> {
let inner = self.inner.lock(); let inner = self.inner.lock();
if let Some(context) = &inner.context { if let Some(context) = &inner.context {
return Ok(context.attachment_manager.clone()); return Ok(context.attachment_manager.clone());
} }
Err(VeilidAPIError::NotInitialized) Err(VeilidAPIError::not_initialized())
} }
pub fn network_manager(&self) -> Result<NetworkManager, VeilidAPIError> { pub fn network_manager(&self) -> Result<NetworkManager, VeilidAPIError> {
let inner = self.inner.lock(); let inner = self.inner.lock();
if let Some(context) = &inner.context { if let Some(context) = &inner.context {
return Ok(context.attachment_manager.network_manager()); return Ok(context.attachment_manager.network_manager());
} }
Err(VeilidAPIError::NotInitialized) Err(VeilidAPIError::not_initialized())
} }
// pub fn rpc_processor(&self) -> Result<RPCProcessor, VeilidAPIError> { // pub fn rpc_processor(&self) -> Result<RPCProcessor, VeilidAPIError> {
@ -1916,7 +1915,7 @@ impl VeilidAPI {
attachment_manager attachment_manager
.request_attach() .request_attach()
.await .await
.map_err(|e| VeilidAPIError::Internal { message: e }) .map_err(|e| VeilidAPIError::internal(e))
} }
// disconnect from the network // disconnect from the network
@ -1926,7 +1925,7 @@ impl VeilidAPI {
attachment_manager attachment_manager
.request_detach() .request_detach()
.await .await
.map_err(|e| VeilidAPIError::Internal { message: e }) .map_err(|e| VeilidAPIError::internal(e))
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////

View File

@ -7,6 +7,14 @@ cfg_if! {
} }
} }
#[derive(ThisError, Debug, Clone, PartialEq, Eq)]
pub enum BumpPortError {
#[error("Unsupported architecture")]
Unsupported,
#[error("Failure: {0}")]
Failed(String),
}
pub enum BumpPortType { pub enum BumpPortType {
UDP, UDP,
TCP, TCP,
@ -38,10 +46,10 @@ pub fn udp_port_available(addr: &SocketAddr) -> bool {
} }
} }
pub fn bump_port(addr: &mut SocketAddr, bpt: BumpPortType) -> Result<bool, String> { pub fn bump_port(addr: &mut SocketAddr, bpt: BumpPortType) -> Result<bool, BumpPortError> {
cfg_if! { cfg_if! {
if #[cfg(target_arch = "wasm32")] { if #[cfg(target_arch = "wasm32")] {
Err("unsupported architecture".to_owned()) Err(BumpPortError::Unsupported)
} }
else else
{ {
@ -65,25 +73,25 @@ pub fn bump_port(addr: &mut SocketAddr, bpt: BumpPortType) -> Result<bool, Strin
bumped = true; bumped = true;
} }
Err("no ports remaining".to_owned()) Err(BumpPortError::Failure("no ports remaining".to_owned()))
} }
} }
} }
pub fn bump_port_string(addr: &mut String, bpt: BumpPortType) -> Result<bool, String> { pub fn bump_port_string(addr: &mut String, bpt: BumpPortType) -> Result<bool, BumpPortError> {
cfg_if! { cfg_if! {
if #[cfg(target_arch = "wasm32")] { if #[cfg(target_arch = "wasm32")] {
return Err("unsupported architecture".to_owned()); return Err(BumpPortError::Unsupported);
} }
else else
{ {
let savec: Vec<SocketAddr> = addr let savec: Vec<SocketAddr> = addr
.to_socket_addrs() .to_socket_addrs()
.map_err(|x| format!("failed to resolve socket address: {}", x))? .map_err(|x| BumpPortError::Failure(format!("failed to resolve socket address: {}", x)))?
.collect(); .collect();
if savec.len() == 0 { if savec.len() == 0 {
return Err("No socket addresses resolved".to_owned()); return Err(BumpPortError::Failure("No socket addresses resolved".to_owned()));
} }
let mut sa = savec.first().unwrap().clone(); let mut sa = savec.first().unwrap().clone();

View File

@ -1,5 +1,11 @@
use super::*; use super::*;
#[derive(ThisError, Debug, Clone, PartialEq, Eq)]
pub enum EventualError {
#[error("Try failed: {0}")]
TryFailed(String),
}
pub struct EventualBaseInner<T> { pub struct EventualBaseInner<T> {
resolved: Option<T>, resolved: Option<T>,
wakers: BTreeMap<usize, task::Waker>, wakers: BTreeMap<usize, task::Waker>,
@ -92,12 +98,16 @@ impl<T> EventualBaseInner<T> {
self.resolved_freelist.clear(); self.resolved_freelist.clear();
} }
pub(super) fn try_reset(&mut self) -> Result<(), String> { pub(super) fn try_reset(&mut self) -> Result<(), EventualError> {
if !self.wakers.is_empty() { if !self.wakers.is_empty() {
return Err("Wakers not empty during reset".to_owned()); return Err(EventualError::TryFailed(
"wakers not empty during reset".to_owned(),
));
} }
if !self.resolved_wakers.is_empty() { if !self.resolved_wakers.is_empty() {
return Err("Resolved wakers not empty during reset".to_owned()); return Err(EventualError::TryFailed(
"Resolved wakers not empty during reset".to_owned(),
));
} }
self.reset(); self.reset();
Ok(()) Ok(())
@ -199,7 +209,7 @@ pub trait EventualCommon: EventualBase {
self.base_inner().reset() self.base_inner().reset()
} }
fn try_reset(&self) -> Result<(), String> { fn try_reset(&self) -> Result<(), EventualError> {
self.base_inner().try_reset() self.base_inner().try_reset()
} }
} }

View File

@ -30,13 +30,11 @@ macro_rules! bail_io_error_other {
}; };
} }
pub fn split_port(name: &str) -> Result<(String, Option<u16>), String> { pub fn split_port(name: &str) -> EyreResult<(String, Option<u16>)> {
if let Some(split) = name.rfind(':') { if let Some(split) = name.rfind(':') {
let hoststr = &name[0..split]; let hoststr = &name[0..split];
let portstr = &name[split + 1..]; let portstr = &name[split + 1..];
let port: u16 = portstr let port: u16 = portstr.parse::<u16>().wrap_err("invalid port")?;
.parse::<u16>()
.map_err(|e| format!("Invalid port: {}", e))?;
Ok((hoststr.to_string(), Some(port))) Ok((hoststr.to_string(), Some(port)))
} else { } else {