This commit is contained in:
John Smith
2022-07-10 17:36:50 -04:00
parent cd0cd78e30
commit 7e0d7dad06
108 changed files with 1378 additions and 1535 deletions

View File

@@ -22,7 +22,7 @@ impl BlockStore {
}
}
pub async fn init(&self) -> Result<(), String> {
pub async fn init(&self) -> EyreResult<()> {
// Ensure permissions are correct
// ensure_file_private_owner(&dbpath)?;

View File

@@ -3,7 +3,6 @@ use crate::*;
use data_encoding::BASE64URL_NOPAD;
use keyring_manager::*;
use std::path::Path;
use std::result::Result;
pub struct ProtectedStoreInner {
keyring_manager: Option<KeyringManager>,
@@ -30,7 +29,7 @@ impl ProtectedStore {
}
#[instrument(level = "trace", skip(self), err)]
pub async fn delete_all(&self) -> Result<(), String> {
pub async fn delete_all(&self) -> EyreResult<()> {
// Delete all known keys
if self.remove_user_secret_string("node_id").await? {
debug!("deleted protected_store key 'node_id'");
@@ -45,7 +44,7 @@ impl ProtectedStore {
}
#[instrument(level = "debug", skip(self), err)]
pub async fn init(&self) -> Result<(), String> {
pub async fn init(&self) -> EyreResult<()> {
let delete = {
let c = self.config.get();
let mut inner = self.inner.lock();
@@ -80,12 +79,11 @@ impl ProtectedStore {
// Open the insecure keyring
inner.keyring_manager = Some(
KeyringManager::new_insecure(&c.program_name, &insecure_keyring_file)
.map_err(map_to_string)
.map_err(logthru_pstore!(error))?,
.wrap_err("failed to create insecure keyring")?,
);
}
if inner.keyring_manager.is_none() {
return Err("Could not initialize the protected store.".to_owned());
bail!("Could not initialize the protected store.");
}
c.protected_store.delete
};
@@ -112,56 +110,52 @@ impl ProtectedStore {
}
#[instrument(level = "trace", skip(self, value), ret, err)]
pub async fn save_user_secret_string(&self, key: &str, value: &str) -> Result<bool, String> {
pub async fn save_user_secret_string(&self, key: &str, value: &str) -> EyreResult<bool> {
let inner = self.inner.lock();
inner
.keyring_manager
.as_ref()
.ok_or_else(|| "Protected store not initialized".to_owned())?
.ok_or_else(|| eyre!("Protected store not initialized"))?
.with_keyring(&self.service_name(), key, |kr| {
let existed = kr.get_value().is_ok();
kr.set_value(value)
.map_err(|e| format!("Failed to save user secret: {}", e))?;
kr.set_value(value)?;
Ok(existed)
})
.map_err(map_to_string)
.map_err(logthru_pstore!())
.wrap_err("failed to save user secret")
}
#[instrument(level = "trace", skip(self), err)]
pub async fn load_user_secret_string(&self, key: &str) -> Result<Option<String>, String> {
pub async fn load_user_secret_string(&self, key: &str) -> EyreResult<Option<String>> {
let inner = self.inner.lock();
match inner
.keyring_manager
.as_ref()
.ok_or_else(|| "Protected store not initialized".to_owned())?
.ok_or_else(|| eyre!("Protected store not initialized"))?
.with_keyring(&self.service_name(), key, |kr| kr.get_value())
.map_err(logthru_pstore!())
{
Ok(v) => Ok(Some(v)),
Err(KeyringError::NoPasswordFound) => Ok(None),
Err(e) => Err(format!("Failed to load user secret: {}", e)),
Err(e) => Err(eyre!("Failed to load user secret")),
}
}
#[instrument(level = "trace", skip(self), ret, err)]
pub async fn remove_user_secret_string(&self, key: &str) -> Result<bool, String> {
pub async fn remove_user_secret_string(&self, key: &str) -> EyreResult<bool> {
let inner = self.inner.lock();
match inner
.keyring_manager
.as_ref()
.ok_or_else(|| "Protected store not initialized".to_owned())?
.ok_or_else(|| eyre!("Protected store not initialized"))?
.with_keyring(&self.service_name(), key, |kr| kr.delete_value())
.map_err(logthru_pstore!())
{
Ok(_) => Ok(true),
Err(KeyringError::NoPasswordFound) => Ok(false),
Err(e) => Err(format!("Failed to remove user secret: {}", e)),
Err(e) => Err(eyre!("Failed to remove user secret")),
}
}
#[instrument(level = "trace", skip(self, value), ret, err)]
pub async fn save_user_secret(&self, key: &str, value: &[u8]) -> Result<bool, String> {
pub async fn save_user_secret(&self, key: &str, value: &[u8]) -> EyreResult<bool> {
let mut s = BASE64URL_NOPAD.encode(value);
s.push('!');
@@ -169,7 +163,7 @@ impl ProtectedStore {
}
#[instrument(level = "trace", skip(self), err)]
pub async fn load_user_secret(&self, key: &str) -> Result<Option<Vec<u8>>, String> {
pub async fn load_user_secret(&self, key: &str) -> EyreResult<Option<Vec<u8>>> {
let mut s = match self.load_user_secret_string(key).await? {
Some(s) => s,
None => {
@@ -178,7 +172,7 @@ impl ProtectedStore {
};
if s.pop() != Some('!') {
return Err("User secret is not a buffer".to_owned());
bail!("User secret is not a buffer");
}
let mut bytes = Vec::<u8>::new();
@@ -188,19 +182,19 @@ impl ProtectedStore {
bytes.resize(l, 0u8);
}
Err(_) => {
return Err("Failed to decode".to_owned());
bail!("Failed to decode");
}
}
let res = BASE64URL_NOPAD.decode_mut(s.as_bytes(), &mut bytes);
match res {
Ok(_) => Ok(Some(bytes)),
Err(_) => Err("Failed to decode".to_owned()),
Err(_) => bail!("Failed to decode"),
}
}
#[instrument(level = "trace", skip(self), ret, err)]
pub async fn remove_user_secret(&self, key: &str) -> Result<bool, String> {
pub async fn remove_user_secret(&self, key: &str) -> EyreResult<bool> {
self.remove_user_secret_string(key).await
}
}

View File

@@ -16,9 +16,9 @@ pub fn get_timestamp_string() -> String {
dt.time().format("%H:%M:%S.3f").to_string()
}
pub fn random_bytes(dest: &mut [u8]) -> Result<(), String> {
pub fn random_bytes(dest: &mut [u8]) -> EyreResult<()> {
let mut rng = rand::thread_rng();
rng.try_fill_bytes(dest).map_err(|err| format!("{:?}", err))
rng.try_fill_bytes(dest).wrap_err("failed to fill bytes")
}
pub fn get_random_u32() -> u32 {
@@ -137,23 +137,15 @@ where
})
}
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>
where
F: Future<Output = T>,
{
cfg_if! {
if #[cfg(feature="rt-async-std")] {
async_std::future::timeout(Duration::from_millis(dur_ms as u64), f).await
async_std::future::timeout(Duration::from_millis(dur_ms as u64), f).await.map_err(|e| e.into())
} else if #[cfg(feature="rt-tokio")] {
tokio::time::timeout(Duration::from_millis(dur_ms as u64), f).await
tokio::time::timeout(Duration::from_millis(dur_ms as u64), f).await.map_err(|e| e.into())
}
}
}
@@ -228,7 +220,7 @@ cfg_if! {
cfg_if! {
if #[cfg(not(target_os = "windows"))] {
async fn get_resolver() -> Result<AsyncResolver, String> {
async fn get_resolver() -> EyreResult<AsyncResolver> {
let mut resolver_lock = RESOLVER.lock().await;
if let Some(r) = &*resolver_lock {
Ok(r.clone())
@@ -250,7 +242,7 @@ cfg_if! {
}
}
pub async fn txt_lookup<S: AsRef<str>>(host: S) -> Result<Vec<String>, String> {
pub async fn txt_lookup<S: AsRef<str>>(host: S) -> EyreResult<Vec<String>> {
cfg_if! {
if #[cfg(target_os = "windows")] {
use core::ffi::c_void;
@@ -263,7 +255,7 @@ pub async fn txt_lookup<S: AsRef<str>>(host: S) -> Result<Vec<String>, String> {
let mut p_query_results: *mut DNS_RECORDA = core::ptr::null_mut();
let status = DnsQuery_UTF8(host.as_ref(), DNS_TYPE_TEXT as u16, DNS_QUERY_STANDARD, core::ptr::null_mut(), &mut p_query_results as *mut *mut DNS_RECORDA, core::ptr::null_mut());
if status != 0 {
return Err("Failed to resolve TXT record".to_owned());
bail!("Failed to resolve TXT record");
}
let mut p_record: *mut DNS_RECORDA = p_query_results;
@@ -290,12 +282,11 @@ pub async fn txt_lookup<S: AsRef<str>>(host: S) -> Result<Vec<String>, String> {
let resolver = get_resolver().await?;
let txt_result = resolver
.txt_lookup(host.as_ref())
.await
.map_err(|e| e.to_string())?;
.await?;
let mut out = Vec::new();
for x in txt_result.iter() {
for s in x.txt_data() {
out.push(String::from_utf8(s.to_vec()).map_err(|e| e.to_string())?);
out.push(String::from_utf8(s.to_vec()).wrap_err("utf8 conversion error")?);
}
}
Ok(out)
@@ -303,7 +294,7 @@ pub async fn txt_lookup<S: AsRef<str>>(host: S) -> Result<Vec<String>, String> {
}
}
pub async fn ptr_lookup(ip_addr: IpAddr) -> Result<String, String> {
pub async fn ptr_lookup(ip_addr: IpAddr) -> EyreResult<String> {
cfg_if! {
if #[cfg(target_os = "windows")] {
use core::ffi::c_void;
@@ -329,7 +320,7 @@ pub async fn ptr_lookup(ip_addr: IpAddr) -> Result<String, String> {
let mut p_query_results: *mut DNS_RECORDA = core::ptr::null_mut();
let status = DnsQuery_UTF8(host, DNS_TYPE_PTR as u16, DNS_QUERY_STANDARD, core::ptr::null_mut(), &mut p_query_results as *mut *mut DNS_RECORDA, core::ptr::null_mut());
if status != 0 {
return Err("Failed to resolve PTR record".to_owned());
bail!("Failed to resolve PTR record");
}
let mut p_record: *mut DNS_RECORDA = p_query_results;
@@ -346,17 +337,17 @@ pub async fn ptr_lookup(ip_addr: IpAddr) -> Result<String, String> {
}
DnsFree(p_query_results as *const c_void, DnsFreeRecordList);
}
return Err("No records returned".to_owned());
bail!("No records returned");
} else {
let resolver = get_resolver().await?;
let ptr_result = resolver
.reverse_lookup(ip_addr)
.await
.map_err(|e| e.to_string())?;
.wrap_err("resolver error")?;
if let Some(r) = ptr_result.iter().next() {
Ok(r.to_string().trim_end_matches('.').to_string())
} else {
Err("PTR lookup returned an empty string".to_owned())
bail!("PTR lookup returned an empty string");
}
}
}

View File

@@ -27,13 +27,13 @@ impl TableStore {
}
}
pub async fn delete_all(&self) -> Result<(), String> {
pub async fn delete_all(&self) -> EyreResult<()> {
// Delete all known keys
self.delete("crypto_caches").await?;
Ok(())
}
pub async fn init(&self) -> Result<(), String> {
pub async fn init(&self) -> EyreResult<()> {
Ok(())
}
@@ -51,28 +51,27 @@ impl TableStore {
}
}
fn get_dbpath(&self, table: &str) -> Result<PathBuf, String> {
fn get_dbpath(&self, table: &str) -> EyreResult<PathBuf> {
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 tablestoredir = c.table_store.directory.clone();
std::fs::create_dir_all(&tablestoredir)
.map_err(|e| format!("failed to create tablestore path: {}", e))?;
std::fs::create_dir_all(&tablestoredir).wrap_err("failed to create tablestore path")?;
let dbpath: PathBuf = [tablestoredir, String::from(table)].iter().collect();
Ok(dbpath)
}
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();
@@ -83,7 +82,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();
@@ -104,8 +103,7 @@ impl TableStore {
ensure_file_private_owner(&dbpath)?;
let cfg = DatabaseConfig::with_columns(column_count);
let db =
Database::open(&dbpath, cfg).map_err(|e| format!("failed to open tabledb: {}", e))?;
let db = Database::open(&dbpath, cfg).wrap_err("failed to open tabledb")?;
// Ensure permissions are correct
ensure_file_private_owner(&dbpath)?;
@@ -123,12 +121,12 @@ impl TableStore {
Ok(table_db)
}
pub async fn delete(&self, name: &str) -> Result<bool, String> {
pub async fn delete(&self, name: &str) -> EyreResult<bool> {
let table_name = self.get_table_name(name)?;
let inner = self.inner.lock();
if inner.opened.contains_key(&table_name) {
return Err("Not deleting table that is still opened".to_owned());
bail!("Not deleting table that is still opened");
}
let dbpath = self.get_dbpath(&table_name)?;
let ret = std::fs::remove_file(dbpath).is_ok();

View File

@@ -266,13 +266,13 @@ pub struct PlatformSupportApple {
}
impl PlatformSupportApple {
pub fn new() -> Result<Self, String> {
pub fn new() -> EyreResult<Self> {
Ok(PlatformSupportApple {
default_route_interfaces: BTreeSet::new(),
})
}
async fn refresh_default_route_interfaces(&mut self) -> Result<(), String> {
async fn refresh_default_route_interfaces(&mut self) -> EyreResult<()> {
self.default_route_interfaces.clear();
let mut mib = [CTL_NET, PF_ROUTE, 0, 0, NET_RT_FLAGS, RTF_GATEWAY];
@@ -292,7 +292,7 @@ impl PlatformSupportApple {
)
} < 0
{
return Err("Unable to get memory size for routing table".to_owned());
bail!("Unable to get memory size for routing table");
}
// Allocate a buffer
@@ -310,7 +310,7 @@ impl PlatformSupportApple {
)
} < 0
{
return Err("Unable to get memory size for routing table".to_owned());
bail!("Unable to get memory size for routing table");
}
// Process each routing message
@@ -363,7 +363,7 @@ impl PlatformSupportApple {
Ok(())
}
fn get_interface_flags(&self, index: u32, flags: c_int) -> Result<InterfaceFlags, String> {
fn get_interface_flags(&self, index: u32, flags: c_int) -> EyreResult<InterfaceFlags> {
Ok(InterfaceFlags {
is_loopback: (flags & IFF_LOOPBACK) != 0,
is_running: (flags & IFF_RUNNING) != 0,
@@ -371,23 +371,23 @@ impl PlatformSupportApple {
})
}
fn get_address_flags(ifname: &str, addr: sockaddr_in6) -> Result<AddressFlags, String> {
fn get_address_flags(ifname: &str, addr: sockaddr_in6) -> EyreResult<AddressFlags> {
let mut req = in6_ifreq::from_name(&ifname).unwrap();
req.set_addr(addr);
let sock = unsafe { socket(AF_INET6, SOCK_DGRAM, 0) };
if sock < 0 {
return Err(format!("Socket error {:?}", io::Error::last_os_error()));
bail!("Socket error {:?}", io::Error::last_os_error());
}
let res = unsafe { ioctl(sock, SIOCGIFAFLAG_IN6, &mut req) };
unsafe { close(sock) };
if res < 0 {
return Err(format!(
bail!(
"SIOCGIFAFLAG_IN6 failed with error on device '{}': {:?}",
ifname,
io::Error::last_os_error()
));
);
}
let flags = req.get_flags6();
@@ -404,12 +404,12 @@ impl PlatformSupportApple {
pub async fn get_interfaces(
&mut self,
interfaces: &mut BTreeMap<String, NetworkInterface>,
) -> Result<(), String> {
) -> EyreResult<()> {
self.refresh_default_route_interfaces().await?;
// If we have no routes, this isn't going to work
if self.default_route_interfaces.is_empty() {
return Err("no routes available for NetworkInterfaces".to_owned());
bail!("no routes available for NetworkInterfaces");
}
// Ask for all the addresses we have

View File

@@ -329,7 +329,7 @@ impl NetworkInterfaces {
self.valid = false;
}
// returns Ok(false) if refresh had no changes, Ok(true) if changes were present
pub async fn refresh(&mut self) -> Result<bool, String> {
pub async fn refresh(&mut self) -> EyreResult<bool> {
self.valid = false;
let last_interfaces = core::mem::take(&mut self.interfaces);

View File

@@ -25,16 +25,16 @@ use std::io;
use std::os::raw::c_int;
use tools::*;
fn get_interface_name(index: u32) -> Result<String, String> {
fn get_interface_name(index: u32) -> EyreResult<String> {
let mut ifnamebuf = [0u8; (IF_NAMESIZE + 1)];
cfg_if! {
if #[cfg(all(any(target_os = "android", target_os="linux"), any(target_arch = "arm", target_arch = "aarch64")))] {
if unsafe { if_indextoname(index, ifnamebuf.as_mut_ptr()) }.is_null() {
return Err("if_indextoname returned null".to_owned());
bail!("if_indextoname returned null");
}
} else {
if unsafe { if_indextoname(index, ifnamebuf.as_mut_ptr() as *mut i8) }.is_null() {
return Err("if_indextoname returned null".to_owned());
bail!("if_indextoname returned null");
}
}
}
@@ -42,11 +42,11 @@ fn get_interface_name(index: u32) -> Result<String, String> {
let ifnamebuflen = ifnamebuf
.iter()
.position(|c| *c == 0u8)
.ok_or_else(|| "null not found in interface name".to_owned())?;
.ok_or_else(|| eyre!("null not found in interface name"))?;
let ifname_str = CStr::from_bytes_with_nul(&ifnamebuf[0..=ifnamebuflen])
.map_err(map_to_string)?
.wrap_err("failed to convert interface name")?
.to_str()
.map_err(map_to_string)?;
.wrap_err("invalid characters in interface name")?;
Ok(ifname_str.to_owned())
}
@@ -67,7 +67,7 @@ pub struct PlatformSupportNetlink {
}
impl PlatformSupportNetlink {
pub fn new() -> Result<Self, String> {
pub fn new() -> EyreResult<Self> {
Ok(PlatformSupportNetlink {
connection_jh: None,
handle: None,
@@ -76,7 +76,7 @@ impl PlatformSupportNetlink {
}
// 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) -> EyreResult<()> {
self.default_route_interfaces.clear();
let mut routesv4 = self
.handle
@@ -111,12 +111,12 @@ impl PlatformSupportNetlink {
Ok(())
}
fn get_interface_flags(&self, index: u32, ifname: &str) -> Result<InterfaceFlags, String> {
let mut req = ifreq::from_name(ifname).map_err(map_to_string)?;
fn get_interface_flags(&self, index: u32, ifname: &str) -> EyreResult<InterfaceFlags> {
let mut req = ifreq::from_name(ifname).wrap_err("failed to convert interface name")?;
let sock = unsafe { socket(AF_INET as i32, SOCK_DGRAM, 0) };
if sock < 0 {
return Err(io::Error::last_os_error()).map_err(map_to_string);
return Err(io::Error::last_os_error()).wrap_err("failed to create socket");
}
cfg_if! {
@@ -128,7 +128,7 @@ impl PlatformSupportNetlink {
}
unsafe { close(sock) };
if res < 0 {
return Err(io::Error::last_os_error()).map_err(map_to_string);
return Err(io::Error::last_os_error()).wrap_err("failed to close socket");
}
let flags = req.get_flags() as c_int;
@@ -242,13 +242,13 @@ impl PlatformSupportNetlink {
async fn get_interfaces_internal(
&mut self,
interfaces: &mut BTreeMap<String, NetworkInterface>,
) -> Result<(), String> {
) -> EyreResult<()> {
// Refresh the routes
self.refresh_default_route_interfaces().await?;
// If we have no routes, this isn't going to work
if self.default_route_interfaces.is_empty() {
return Err("no routes available for NetworkInterfaces".to_owned());
bail!("no routes available for NetworkInterfaces");
}
// Ask for all the addresses we have
@@ -257,8 +257,7 @@ impl PlatformSupportNetlink {
while let Some(msg) = addresses
.try_next()
.await
.map_err(map_to_string)
.map_err(logthru_net!(error))?
.wrap_err("failed to iterate interface addresses")?
{
// Have we seen this interface index yet?
// Get the name from the index, cached, if we can
@@ -268,7 +267,7 @@ impl PlatformSupportNetlink {
let ifname = match get_interface_name(msg.header.index) {
Ok(v) => v,
Err(e) => {
log_net!(
log_net!(warn
"couldn't get interface name for index {}: {}",
msg.header.index,
e
@@ -317,11 +316,10 @@ impl PlatformSupportNetlink {
pub async fn get_interfaces(
&mut self,
interfaces: &mut BTreeMap<String, NetworkInterface>,
) -> Result<(), String> {
) -> EyreResult<()> {
// Get the netlink connection
let (connection, handle, _) = new_connection_with_socket::<RTNetLinkSocket>()
.map_err(map_to_string)
.map_err(logthru_net!(error))?;
.wrap_err("failed to create rtnetlink socket")?;
// Spawn a connection handler
let connection_jh = intf::spawn(connection);

View File

@@ -28,7 +28,7 @@ use winapi::um::iptypes::{
pub struct PlatformSupportWindows {}
impl PlatformSupportWindows {
pub fn new() -> Result<Self, String> {
pub fn new() -> EyreResult<Self> {
Ok(PlatformSupportWindows {})
}
@@ -54,7 +54,7 @@ impl PlatformSupportWindows {
pub async fn get_interfaces(
&mut self,
interfaces: &mut BTreeMap<String, NetworkInterface>,
) -> Result<(), String> {
) -> EyreResult<()> {
//self.refresh_default_route_interfaces().await?;
// If we have no routes, this isn't going to work
@@ -63,7 +63,7 @@ impl PlatformSupportWindows {
// }
// Iterate all the interfaces
let windows_interfaces = WindowsInterfaces::new().map_err(map_to_string)?;
let windows_interfaces = WindowsInterfaces::new().wrap_err("failed to get windows interfaces")?;
for windows_interface in windows_interfaces.iter() {
// Get name
let intf_name = windows_interface.name();

View File

@@ -48,58 +48,52 @@ impl TableDB {
Arc::downgrade(&self.inner)
}
pub async fn get_column_count(&self) -> Result<u32, String> {
pub async fn get_column_count(&self) -> EyreResult<u32> {
let db = &self.inner.lock().database;
db.num_columns()
.map_err(|e| format!("failed to get column count: {}", e))
db.num_columns().wrap_err("failed to get column count: {}")
}
pub async fn get_keys(&self, col: u32) -> Result<Vec<Box<[u8]>>, String> {
pub async fn get_keys(&self, col: u32) -> EyreResult<Vec<Box<[u8]>>> {
let db = &self.inner.lock().database;
let mut out: Vec<Box<[u8]>> = Vec::new();
db.iter(col, None, &mut |kv| {
out.push(kv.0.clone().into_boxed_slice());
Ok(true)
})
.map_err(|e| format!("failed to get keys for column {}: {}", col, e))?;
.wrap_err("failed to get keys for column")?;
Ok(out)
}
pub async fn store(&self, col: u32, key: &[u8], value: &[u8]) -> Result<(), String> {
pub async fn store(&self, col: u32, key: &[u8], value: &[u8]) -> EyreResult<()> {
let db = &self.inner.lock().database;
let mut dbt = db.transaction();
dbt.put(col, key, value);
db.write(dbt)
.map_err(|e| format!("failed to store key {:?}: {}", key, e))
db.write(dbt).wrap_err("failed to store key")
}
pub async fn store_cbor<T>(&self, col: u32, key: &[u8], value: &T) -> Result<(), String>
pub async fn store_cbor<T>(&self, col: u32, key: &[u8], value: &T) -> EyreResult<()>
where
T: Serialize,
{
let v = serde_cbor::to_vec(value).map_err(|_| "couldn't store as CBOR".to_owned())?;
let v = serde_cbor::to_vec(value).wrap_err("couldn't store as CBOR")?;
let db = &self.inner.lock().database;
let mut dbt = db.transaction();
dbt.put(col, key, v.as_slice());
db.write(dbt)
.map_err(|e| format!("failed to store key {:?}: {}", key, e))
db.write(dbt).wrap_err("failed to store key")
}
pub async fn load(&self, col: u32, key: &[u8]) -> Result<Option<Vec<u8>>, String> {
pub async fn load(&self, col: u32, key: &[u8]) -> EyreResult<Option<Vec<u8>>> {
let db = &self.inner.lock().database;
db.get(col, key)
.map_err(|e| format!("failed to get key {:?}: {}", key, e))
db.get(col, key).wrap_err("failed to get key")
}
pub async fn load_cbor<T>(&self, col: u32, key: &[u8]) -> Result<Option<T>, String>
pub async fn load_cbor<T>(&self, col: u32, key: &[u8]) -> EyreResult<Option<T>>
where
T: for<'de> Deserialize<'de>,
{
let db = &self.inner.lock().database;
let out = db
.get(col, key)
.map_err(|e| format!("failed to get key {:?}: {}", key, e))?;
let out = db.get(col, key).wrap_err("failed to get key")?;
let b = match out {
Some(v) => v,
None => {
@@ -109,24 +103,21 @@ impl TableDB {
let obj = match serde_cbor::from_slice::<T>(&b) {
Ok(value) => value,
Err(e) => {
return Err(format!("failed to deserialize: {}", e));
bail!("failed to deserialize");
}
};
Ok(Some(obj))
}
pub async fn delete(&self, col: u32, key: &[u8]) -> Result<bool, String> {
pub async fn delete(&self, col: u32, key: &[u8]) -> EyreResult<bool> {
let db = &self.inner.lock().database;
let found = db
.get(col, key)
.map_err(|e| format!("failed to get key {:?}: {}", key, e))?;
let found = db.get(col, key).wrap_err("failed to get key")?;
match found {
None => Ok(false),
Some(_) => {
let mut dbt = db.transaction();
dbt.delete(col, key);
db.write(dbt)
.map_err(|e| format!("failed to delete key {:?}: {}", key, e))?;
db.write(dbt).wrap_err("failed to delete key")?;
Ok(true)
}
}

View File

@@ -23,7 +23,7 @@ impl BlockStore {
}
}
pub async fn init(&self) -> Result<(), String> {
pub async fn init(&self) -> EyreResult<()> {
Ok(())
}

View File

@@ -30,7 +30,7 @@ impl ProtectedStore {
}
}
pub async fn delete_all(&self) -> Result<(), String> {
pub async fn delete_all(&self) -> EyreResult<()> {
// Delete all known keys
if self.remove_user_secret_string("node_id").await? {
debug!("deleted protected_store key 'node_id'");
@@ -44,7 +44,7 @@ impl ProtectedStore {
Ok(())
}
pub async fn init(&self) -> Result<(), String> {
pub async fn init(&self) -> EyreResult<()> {
Ok(())
}
@@ -68,11 +68,11 @@ impl ProtectedStore {
}
}
pub async fn save_user_secret_string(&self, key: &str, value: &str) -> Result<bool, String> {
pub async fn save_user_secret_string(&self, key: &str, value: &str) -> EyreResult<bool> {
if utils::is_nodejs() {
let prev = match JsFuture::from(
keytar_getPassword(self.keyring_name().as_str(), key)
.map_err(|_| "exception thrown".to_owned())?,
.wrap_err("exception thrown")?,
)
.await
{
@@ -82,12 +82,12 @@ impl ProtectedStore {
match JsFuture::from(
keytar_setPassword(self.keyring_name().as_str(), key, value)
.map_err(|_| "exception thrown".to_owned())?,
.wrap_err("exception thrown")?,
)
.await
{
Ok(_) => {}
Err(_) => return Err("Failed to set password".to_owned()),
Err(_) => bail!("Failed to set password"),
}
Ok(prev)
@@ -95,17 +95,17 @@ impl ProtectedStore {
let win = match window() {
Some(w) => w,
None => {
return Err("failed to get window".to_owned());
bail!("failed to get window");
}
};
let ls = match win
.local_storage()
.map_err(|_| "exception getting local storage".to_owned())?
.wrap_err("exception getting local storage")?
{
Some(l) => l,
None => {
return Err("failed to get local storage".to_owned());
bail!("failed to get local storage");
}
};
@@ -113,26 +113,26 @@ impl ProtectedStore {
let prev = match ls
.get_item(&vkey)
.map_err(|_| "exception_thrown".to_owned())?
.wrap_err("exception_thrown")?
{
Some(_) => true,
None => false,
};
ls.set_item(&vkey, value)
.map_err(|_| "exception_thrown".to_owned())?;
.wrap_err("exception_thrown")?;
Ok(prev)
} else {
Err("unimplemented".to_owned())
unimplemented!()
}
}
pub async fn load_user_secret_string(&self, key: &str) -> Result<Option<String>, String> {
pub async fn load_user_secret_string(&self, key: &str) -> EyreResult<Option<String>> {
if utils::is_nodejs() {
let prev = match JsFuture::from(
keytar_getPassword(self.keyring_name().as_str(), key)
.map_err(|_| "exception thrown".to_owned())?,
.wrap_err("exception thrown")?,
)
.await
{
@@ -149,54 +149,54 @@ impl ProtectedStore {
let win = match window() {
Some(w) => w,
None => {
return Err("failed to get window".to_owned());
bail!("failed to get window");
}
};
let ls = match win
.local_storage()
.map_err(|_| "exception getting local storage".to_owned())?
.wrap_err("exception getting local storage")?
{
Some(l) => l,
None => {
return Err("failed to get local storage".to_owned());
bail!("failed to get local storage");
}
};
let vkey = self.browser_key_name(key);
ls.get_item(&vkey)
.map_err(|_| "exception_thrown".to_owned())
.wrap_err("exception_thrown")
} else {
Err("unimplemented".to_owned())
unimplemented!();
}
}
pub async fn remove_user_secret_string(&self, key: &str) -> Result<bool, String> {
pub async fn remove_user_secret_string(&self, key: &str) -> EyreResult<bool> {
if utils::is_nodejs() {
match JsFuture::from(
keytar_deletePassword(self.keyring_name().as_str(), key).map_err(|_| "exception thrown".to_owned())?,
keytar_deletePassword(self.keyring_name().as_str(), key).wrap_err("exception thrown")?,
)
.await
{
Ok(v) => Ok(v.is_truthy()),
Err(_) => Err("Failed to delete".to_owned()),
Err(_) => bail!("Failed to delete"),
}
} else if utils::is_browser() {
let win = match window() {
Some(w) => w,
None => {
return Err("failed to get window".to_owned());
bail!("failed to get window");
}
};
let ls = match win
.local_storage()
.map_err(|_| "exception getting local storage".to_owned())?
.wrap_err("exception getting local storage")?
{
Some(l) => l,
None => {
return Err("failed to get local storage".to_owned());
bail!("failed to get local storage");
}
};
@@ -204,28 +204,28 @@ impl ProtectedStore {
match ls
.get_item(&vkey)
.map_err(|_| "exception_thrown".to_owned())?
.wrap_err("exception_thrown")?
{
Some(_) => {
ls.delete(&vkey)
.map_err(|_| "exception_thrown".to_owned())?;
.wrap_err("exception_thrown")?;
Ok(true)
}
None => Ok(false),
}
} else {
Err("unimplemented".to_owned())
unimplemented!();
}
}
pub async fn save_user_secret(&self, key: &str, value: &[u8]) -> Result<bool, String> {
pub async fn save_user_secret(&self, key: &str, value: &[u8]) -> EyreResult<bool> {
let mut s = BASE64URL_NOPAD.encode(value);
s.push('!');
self.save_user_secret_string(key, s.as_str()).await
}
pub async fn load_user_secret(&self, key: &str) -> Result<Option<Vec<u8>>, String> {
pub async fn load_user_secret(&self, key: &str) -> EyreResult<Option<Vec<u8>>> {
let mut s = match self.load_user_secret_string(key).await? {
Some(s) => s,
None => {
@@ -234,7 +234,7 @@ impl ProtectedStore {
};
if s.pop() != Some('!') {
return Err("User secret is not a buffer".to_owned());
bail!("User secret is not a buffer");
}
let mut bytes = Vec::<u8>::new();
@@ -244,18 +244,18 @@ impl ProtectedStore {
bytes.resize(l, 0u8);
}
Err(_) => {
return Err("Failed to decode".to_owned());
bail!("Failed to decode");
}
}
let res = BASE64URL_NOPAD.decode_mut(s.as_bytes(), &mut bytes);
match res {
Ok(_) => Ok(Some(bytes)),
Err(_) => Err("Failed to decode".to_owned()),
Err(_) => bail!("Failed to decode"),
}
}
pub async fn remove_user_secret(&self, key: &str) -> Result<bool, String> {
pub async fn remove_user_secret(&self, key: &str) -> EyreResult<bool> {
self.remove_user_secret_string(key).await
}
}

View File

@@ -39,7 +39,7 @@ pub fn get_timestamp_string() -> String {
)
}
pub fn random_bytes(dest: &mut [u8]) -> Result<(), String> {
pub fn random_bytes(dest: &mut [u8]) -> EyreResult<()> {
let len = dest.len();
let u32len = len / 4;
let remlen = len % 4;
@@ -161,25 +161,12 @@ where
})
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct TimeoutError {
_private: (),
}
//impl Error for TimeoutError {}
impl fmt::Display for TimeoutError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
"future has timed out".fmt(f)
}
}
pub async fn timeout<F, T>(dur_ms: u32, f: F) -> Result<T, TimeoutError>
where
F: Future<Output = T>,
{
match select(Box::pin(intf::sleep(dur_ms)), Box::pin(f)).await {
Either::Left((_x, _b)) => Err(TimeoutError { _private: () }),
Either::Left((_x, _b)) => Err(TimeoutError()),
Either::Right((y, _a)) => Ok(y),
}
}
@@ -227,10 +214,10 @@ pub async fn get_outbound_relay_peer() -> Option<crate::veilid_api::PeerInfo> {
// }
pub async fn txt_lookup<S: AsRef<str>>(_host: S) -> Result<Vec<String>, String> {
Err("wasm does not support txt lookup".to_owned())
pub async fn txt_lookup<S: AsRef<str>>(_host: S) -> EyreResult<Vec<String>> {
bail!("wasm does not support txt lookup")
}
pub async fn ptr_lookup(_ip_addr: IpAddr) -> Result<String, String> {
Err("wasm does not support ptr lookup".to_owned())
pub async fn ptr_lookup(_ip_addr: IpAddr) -> EyreResult<String> {
bail!("wasm does not support ptr lookup")
}