removing dev branch, many changes
This commit is contained in:
@@ -49,75 +49,82 @@ impl VeilidAPI {
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Accessors
|
||||
pub fn config(&self) -> Result<VeilidConfig, VeilidAPIError> {
|
||||
pub fn config(&self) -> VeilidAPIResult<VeilidConfig> {
|
||||
let inner = self.inner.lock();
|
||||
if let Some(context) = &inner.context {
|
||||
return Ok(context.config.clone());
|
||||
}
|
||||
Err(VeilidAPIError::NotInitialized)
|
||||
}
|
||||
pub fn crypto(&self) -> Result<Crypto, VeilidAPIError> {
|
||||
pub fn crypto(&self) -> VeilidAPIResult<Crypto> {
|
||||
let inner = self.inner.lock();
|
||||
if let Some(context) = &inner.context {
|
||||
return Ok(context.crypto.clone());
|
||||
}
|
||||
Err(VeilidAPIError::NotInitialized)
|
||||
}
|
||||
pub fn table_store(&self) -> Result<TableStore, VeilidAPIError> {
|
||||
pub fn table_store(&self) -> VeilidAPIResult<TableStore> {
|
||||
let inner = self.inner.lock();
|
||||
if let Some(context) = &inner.context {
|
||||
return Ok(context.table_store.clone());
|
||||
}
|
||||
Err(VeilidAPIError::not_initialized())
|
||||
}
|
||||
pub fn block_store(&self) -> Result<BlockStore, VeilidAPIError> {
|
||||
pub fn block_store(&self) -> VeilidAPIResult<BlockStore> {
|
||||
let inner = self.inner.lock();
|
||||
if let Some(context) = &inner.context {
|
||||
return Ok(context.block_store.clone());
|
||||
}
|
||||
Err(VeilidAPIError::not_initialized())
|
||||
}
|
||||
pub fn protected_store(&self) -> Result<ProtectedStore, VeilidAPIError> {
|
||||
pub fn protected_store(&self) -> VeilidAPIResult<ProtectedStore> {
|
||||
let inner = self.inner.lock();
|
||||
if let Some(context) = &inner.context {
|
||||
return Ok(context.protected_store.clone());
|
||||
}
|
||||
Err(VeilidAPIError::not_initialized())
|
||||
}
|
||||
pub fn attachment_manager(&self) -> Result<AttachmentManager, VeilidAPIError> {
|
||||
pub fn attachment_manager(&self) -> VeilidAPIResult<AttachmentManager> {
|
||||
let inner = self.inner.lock();
|
||||
if let Some(context) = &inner.context {
|
||||
return Ok(context.attachment_manager.clone());
|
||||
}
|
||||
Err(VeilidAPIError::not_initialized())
|
||||
}
|
||||
pub fn network_manager(&self) -> Result<NetworkManager, VeilidAPIError> {
|
||||
pub fn network_manager(&self) -> VeilidAPIResult<NetworkManager> {
|
||||
let inner = self.inner.lock();
|
||||
if let Some(context) = &inner.context {
|
||||
return Ok(context.attachment_manager.network_manager());
|
||||
}
|
||||
Err(VeilidAPIError::not_initialized())
|
||||
}
|
||||
pub fn rpc_processor(&self) -> Result<RPCProcessor, VeilidAPIError> {
|
||||
pub fn rpc_processor(&self) -> VeilidAPIResult<RPCProcessor> {
|
||||
let inner = self.inner.lock();
|
||||
if let Some(context) = &inner.context {
|
||||
return Ok(context.attachment_manager.network_manager().rpc_processor());
|
||||
}
|
||||
Err(VeilidAPIError::NotInitialized)
|
||||
}
|
||||
pub fn routing_table(&self) -> Result<RoutingTable, VeilidAPIError> {
|
||||
pub fn routing_table(&self) -> VeilidAPIResult<RoutingTable> {
|
||||
let inner = self.inner.lock();
|
||||
if let Some(context) = &inner.context {
|
||||
return Ok(context.attachment_manager.network_manager().routing_table());
|
||||
}
|
||||
Err(VeilidAPIError::NotInitialized)
|
||||
}
|
||||
pub fn storage_manager(&self) -> VeilidAPIResult<StorageManager> {
|
||||
let inner = self.inner.lock();
|
||||
if let Some(context) = &inner.context {
|
||||
return Ok(context.storage_manager.clone());
|
||||
}
|
||||
Err(VeilidAPIError::NotInitialized)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Attach/Detach
|
||||
|
||||
/// Get a full copy of the current state
|
||||
pub async fn get_state(&self) -> Result<VeilidState, VeilidAPIError> {
|
||||
pub async fn get_state(&self) -> VeilidAPIResult<VeilidState> {
|
||||
let attachment_manager = self.attachment_manager()?;
|
||||
let network_manager = attachment_manager.network_manager();
|
||||
let config = self.config()?;
|
||||
@@ -135,7 +142,7 @@ impl VeilidAPI {
|
||||
|
||||
/// Connect to the network
|
||||
#[instrument(level = "debug", err, skip_all)]
|
||||
pub async fn attach(&self) -> Result<(), VeilidAPIError> {
|
||||
pub async fn attach(&self) -> VeilidAPIResult<()> {
|
||||
let attachment_manager = self.attachment_manager()?;
|
||||
if !attachment_manager.attach().await {
|
||||
apibail_generic!("Already attached");
|
||||
@@ -145,7 +152,7 @@ impl VeilidAPI {
|
||||
|
||||
/// Disconnect from the network
|
||||
#[instrument(level = "debug", err, skip_all)]
|
||||
pub async fn detach(&self) -> Result<(), VeilidAPIError> {
|
||||
pub async fn detach(&self) -> VeilidAPIResult<()> {
|
||||
let attachment_manager = self.attachment_manager()?;
|
||||
if !attachment_manager.detach().await {
|
||||
apibail_generic!("Already detached");
|
||||
@@ -168,7 +175,7 @@ impl VeilidAPI {
|
||||
/// Returns a route id and a publishable 'blob' with the route encrypted with each crypto kind
|
||||
/// Those nodes importing the blob will have their choice of which crypto kind to use
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub async fn new_private_route(&self) -> Result<(RouteId, Vec<u8>), VeilidAPIError> {
|
||||
pub async fn new_private_route(&self) -> VeilidAPIResult<(RouteId, Vec<u8>)> {
|
||||
self.new_custom_private_route(
|
||||
&VALID_CRYPTO_KINDS,
|
||||
Stability::default(),
|
||||
@@ -184,7 +191,7 @@ impl VeilidAPI {
|
||||
crypto_kinds: &[CryptoKind],
|
||||
stability: Stability,
|
||||
sequencing: Sequencing,
|
||||
) -> Result<(RouteId, Vec<u8>), VeilidAPIError> {
|
||||
) -> VeilidAPIResult<(RouteId, Vec<u8>)> {
|
||||
let default_route_hop_count: usize = {
|
||||
let config = self.config()?;
|
||||
let c = config.get();
|
||||
@@ -231,14 +238,14 @@ impl VeilidAPI {
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub fn import_remote_private_route(&self, blob: Vec<u8>) -> Result<RouteId, VeilidAPIError> {
|
||||
pub fn import_remote_private_route(&self, blob: Vec<u8>) -> VeilidAPIResult<RouteId> {
|
||||
let rss = self.routing_table()?.route_spec_store();
|
||||
rss.import_remote_private_route(blob)
|
||||
.map_err(|e| VeilidAPIError::invalid_argument(e, "blob", "private route blob"))
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub fn release_private_route(&self, route_id: RouteId) -> Result<(), VeilidAPIError> {
|
||||
pub fn release_private_route(&self, route_id: RouteId) -> VeilidAPIResult<()> {
|
||||
let rss = self.routing_table()?.route_spec_store();
|
||||
if !rss.release_route(route_id) {
|
||||
apibail_invalid_argument!("release_private_route", "key", route_id);
|
||||
@@ -250,11 +257,7 @@ impl VeilidAPI {
|
||||
// App Calls
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub async fn app_call_reply(
|
||||
&self,
|
||||
id: OperationId,
|
||||
message: Vec<u8>,
|
||||
) -> Result<(), VeilidAPIError> {
|
||||
pub async fn app_call_reply(&self, id: OperationId, message: Vec<u8>) -> VeilidAPIResult<()> {
|
||||
let rpc_processor = self.rpc_processor()?;
|
||||
rpc_processor
|
||||
.app_call_reply(id, message)
|
||||
@@ -270,7 +273,7 @@ impl VeilidAPI {
|
||||
&self,
|
||||
_endpoint_mode: TunnelMode,
|
||||
_depth: u8,
|
||||
) -> Result<PartialTunnel, VeilidAPIError> {
|
||||
) -> VeilidAPIResult<PartialTunnel> {
|
||||
panic!("unimplemented");
|
||||
}
|
||||
|
||||
@@ -280,12 +283,12 @@ impl VeilidAPI {
|
||||
_endpoint_mode: TunnelMode,
|
||||
_depth: u8,
|
||||
_partial_tunnel: PartialTunnel,
|
||||
) -> Result<FullTunnel, VeilidAPIError> {
|
||||
) -> VeilidAPIResult<FullTunnel> {
|
||||
panic!("unimplemented");
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", err, skip(self))]
|
||||
pub async fn cancel_tunnel(&self, _tunnel_id: TunnelId) -> Result<bool, VeilidAPIError> {
|
||||
pub async fn cancel_tunnel(&self, _tunnel_id: TunnelId) -> VeilidAPIResult<bool> {
|
||||
panic!("unimplemented");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
use super::*;
|
||||
use data_encoding::BASE64URL_NOPAD;
|
||||
use network_manager::*;
|
||||
use routing_table::*;
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
@@ -304,7 +305,7 @@ fn get_debug_argument<T, G: FnOnce(&str) -> Option<T>>(
|
||||
context: &str,
|
||||
argument: &str,
|
||||
getter: G,
|
||||
) -> Result<T, VeilidAPIError> {
|
||||
) -> VeilidAPIResult<T> {
|
||||
let Some(val) = getter(value) else {
|
||||
apibail_invalid_argument!(context, argument, value);
|
||||
};
|
||||
@@ -316,7 +317,7 @@ fn get_debug_argument_at<T, G: FnOnce(&str) -> Option<T>>(
|
||||
context: &str,
|
||||
argument: &str,
|
||||
getter: G,
|
||||
) -> Result<T, VeilidAPIError> {
|
||||
) -> VeilidAPIResult<T> {
|
||||
if pos >= debug_args.len() {
|
||||
apibail_missing_argument!(context, argument);
|
||||
}
|
||||
@@ -328,7 +329,7 @@ fn get_debug_argument_at<T, G: FnOnce(&str) -> Option<T>>(
|
||||
}
|
||||
|
||||
impl VeilidAPI {
|
||||
async fn debug_buckets(&self, args: String) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_buckets(&self, args: String) -> VeilidAPIResult<String> {
|
||||
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
||||
let mut min_state = BucketEntryState::Unreliable;
|
||||
if args.len() == 1 {
|
||||
@@ -344,19 +345,19 @@ impl VeilidAPI {
|
||||
Ok(routing_table.debug_info_buckets(min_state))
|
||||
}
|
||||
|
||||
async fn debug_dialinfo(&self, _args: String) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_dialinfo(&self, _args: String) -> VeilidAPIResult<String> {
|
||||
// Dump routing table dialinfo
|
||||
let routing_table = self.network_manager()?.routing_table();
|
||||
Ok(routing_table.debug_info_dialinfo())
|
||||
}
|
||||
|
||||
async fn debug_txtrecord(&self, _args: String) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_txtrecord(&self, _args: String) -> VeilidAPIResult<String> {
|
||||
// Dump routing table txt record
|
||||
let routing_table = self.network_manager()?.routing_table();
|
||||
Ok(routing_table.debug_info_txtrecord().await)
|
||||
}
|
||||
|
||||
async fn debug_entries(&self, args: String) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_entries(&self, args: String) -> VeilidAPIResult<String> {
|
||||
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
||||
|
||||
let mut min_state = BucketEntryState::Unreliable;
|
||||
@@ -373,7 +374,7 @@ impl VeilidAPI {
|
||||
Ok(routing_table.debug_info_entries(min_state))
|
||||
}
|
||||
|
||||
async fn debug_entry(&self, args: String) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_entry(&self, args: String) -> VeilidAPIResult<String> {
|
||||
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
||||
let routing_table = self.network_manager()?.routing_table();
|
||||
|
||||
@@ -390,13 +391,13 @@ impl VeilidAPI {
|
||||
Ok(routing_table.debug_info_entry(node_ref))
|
||||
}
|
||||
|
||||
async fn debug_nodeinfo(&self, _args: String) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_nodeinfo(&self, _args: String) -> VeilidAPIResult<String> {
|
||||
// Dump routing table entry
|
||||
let routing_table = self.network_manager()?.routing_table();
|
||||
Ok(routing_table.debug_info_nodeinfo())
|
||||
}
|
||||
|
||||
async fn debug_config(&self, args: String) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_config(&self, args: String) -> VeilidAPIResult<String> {
|
||||
let config = self.config()?;
|
||||
let args = args.trim_start();
|
||||
if args.is_empty() {
|
||||
@@ -425,7 +426,7 @@ impl VeilidAPI {
|
||||
Ok("Config value set".to_owned())
|
||||
}
|
||||
|
||||
async fn debug_restart(&self, args: String) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_restart(&self, args: String) -> VeilidAPIResult<String> {
|
||||
let args = args.trim_start();
|
||||
if args.is_empty() {
|
||||
apibail_missing_argument!("debug_restart", "arg_0");
|
||||
@@ -451,7 +452,7 @@ impl VeilidAPI {
|
||||
}
|
||||
}
|
||||
|
||||
async fn debug_purge(&self, args: String) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_purge(&self, args: String) -> VeilidAPIResult<String> {
|
||||
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
||||
if !args.is_empty() {
|
||||
if args[0] == "buckets" {
|
||||
@@ -503,7 +504,7 @@ impl VeilidAPI {
|
||||
}
|
||||
}
|
||||
|
||||
async fn debug_attach(&self, _args: String) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_attach(&self, _args: String) -> VeilidAPIResult<String> {
|
||||
if !matches!(
|
||||
self.get_state().await?.attachment.state,
|
||||
AttachmentState::Detached
|
||||
@@ -516,7 +517,7 @@ impl VeilidAPI {
|
||||
Ok("Attached".to_owned())
|
||||
}
|
||||
|
||||
async fn debug_detach(&self, _args: String) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_detach(&self, _args: String) -> VeilidAPIResult<String> {
|
||||
if matches!(
|
||||
self.get_state().await?.attachment.state,
|
||||
AttachmentState::Detaching
|
||||
@@ -529,7 +530,7 @@ impl VeilidAPI {
|
||||
Ok("Detached".to_owned())
|
||||
}
|
||||
|
||||
async fn debug_contact(&self, args: String) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_contact(&self, args: String) -> VeilidAPIResult<String> {
|
||||
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
||||
|
||||
let network_manager = self.network_manager()?;
|
||||
@@ -550,7 +551,7 @@ impl VeilidAPI {
|
||||
Ok(format!("{:#?}", cm))
|
||||
}
|
||||
|
||||
async fn debug_ping(&self, args: String) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_ping(&self, args: String) -> VeilidAPIResult<String> {
|
||||
let netman = self.network_manager()?;
|
||||
let routing_table = netman.routing_table();
|
||||
let rpc = netman.rpc_processor();
|
||||
@@ -592,7 +593,7 @@ impl VeilidAPI {
|
||||
Ok(format!("{:#?}", out))
|
||||
}
|
||||
|
||||
async fn debug_route_allocate(&self, args: Vec<String>) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_route_allocate(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
||||
// [ord|*ord] [rel] [<count>] [in|out] [avoid_node_id]
|
||||
|
||||
let netman = self.network_manager()?;
|
||||
@@ -651,7 +652,7 @@ impl VeilidAPI {
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
async fn debug_route_release(&self, args: Vec<String>) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_route_release(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
||||
// <route id>
|
||||
let netman = self.network_manager()?;
|
||||
let routing_table = netman.routing_table();
|
||||
@@ -683,7 +684,7 @@ impl VeilidAPI {
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
async fn debug_route_publish(&self, args: Vec<String>) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_route_publish(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
||||
// <route id> [full]
|
||||
let netman = self.network_manager()?;
|
||||
let routing_table = netman.routing_table();
|
||||
@@ -735,7 +736,7 @@ impl VeilidAPI {
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
async fn debug_route_unpublish(&self, args: Vec<String>) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_route_unpublish(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
||||
// <route id>
|
||||
let netman = self.network_manager()?;
|
||||
let routing_table = netman.routing_table();
|
||||
@@ -757,7 +758,7 @@ impl VeilidAPI {
|
||||
};
|
||||
Ok(out)
|
||||
}
|
||||
async fn debug_route_print(&self, args: Vec<String>) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_route_print(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
||||
// <route id>
|
||||
let netman = self.network_manager()?;
|
||||
let routing_table = netman.routing_table();
|
||||
@@ -776,7 +777,7 @@ impl VeilidAPI {
|
||||
None => Ok("Route does not exist".to_owned()),
|
||||
}
|
||||
}
|
||||
async fn debug_route_list(&self, _args: Vec<String>) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_route_list(&self, _args: Vec<String>) -> VeilidAPIResult<String> {
|
||||
//
|
||||
let netman = self.network_manager()?;
|
||||
let routing_table = netman.routing_table();
|
||||
@@ -799,7 +800,7 @@ impl VeilidAPI {
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
async fn debug_route_import(&self, args: Vec<String>) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_route_import(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
||||
// <blob>
|
||||
|
||||
let blob = get_debug_argument_at(&args, 1, "debug_route", "blob", get_string)?;
|
||||
@@ -819,7 +820,7 @@ impl VeilidAPI {
|
||||
return Ok(out);
|
||||
}
|
||||
|
||||
async fn debug_route_test(&self, args: Vec<String>) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_route_test(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
||||
// <route id>
|
||||
let netman = self.network_manager()?;
|
||||
let routing_table = netman.routing_table();
|
||||
@@ -847,7 +848,7 @@ impl VeilidAPI {
|
||||
return Ok(out);
|
||||
}
|
||||
|
||||
async fn debug_route(&self, args: String) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_route(&self, args: String) -> VeilidAPIResult<String> {
|
||||
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
||||
|
||||
let command = get_debug_argument_at(&args, 0, "debug_route", "command", get_string)?;
|
||||
@@ -873,7 +874,40 @@ impl VeilidAPI {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn debug_help(&self, _args: String) -> Result<String, VeilidAPIError> {
|
||||
async fn debug_record_list(&self, args: Vec<String>) -> VeilidAPIResult<String> {
|
||||
// <local|remote>
|
||||
let storage_manager = self.storage_manager()?;
|
||||
|
||||
let scope = get_debug_argument_at(&args, 1, "debug_record_list", "scope", get_string)?;
|
||||
let out = match scope.as_str() {
|
||||
"local" => {
|
||||
let mut out = format!("Local Records:\n");
|
||||
out += &storage_manager.debug_local_records().await;
|
||||
out
|
||||
}
|
||||
"remote" => {
|
||||
let mut out = format!("Remote Records:\n");
|
||||
out += &storage_manager.debug_remote_records().await;
|
||||
out
|
||||
}
|
||||
_ => "Invalid scope\n".to_owned(),
|
||||
};
|
||||
return Ok(out);
|
||||
}
|
||||
|
||||
async fn debug_record(&self, args: String) -> VeilidAPIResult<String> {
|
||||
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
||||
|
||||
let command = get_debug_argument_at(&args, 0, "debug_record", "command", get_string)?;
|
||||
|
||||
if command == "list" {
|
||||
self.debug_record_list(args).await
|
||||
} else {
|
||||
Ok(">>> Unknown command\n".to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn debug_help(&self, _args: String) -> VeilidAPIResult<String> {
|
||||
Ok(r#">>> Debug commands:
|
||||
help
|
||||
buckets [dead|reliable]
|
||||
@@ -896,6 +930,7 @@ impl VeilidAPI {
|
||||
list
|
||||
import <blob>
|
||||
test <route>
|
||||
record list <local|remote>
|
||||
|
||||
<destination> is:
|
||||
* direct: <node>[+<safety>][<modifiers>]
|
||||
@@ -912,7 +947,7 @@ impl VeilidAPI {
|
||||
.to_owned())
|
||||
}
|
||||
|
||||
pub async fn debug(&self, args: String) -> Result<String, VeilidAPIError> {
|
||||
pub async fn debug(&self, args: String) -> VeilidAPIResult<String> {
|
||||
let res = {
|
||||
let args = args.trim_start();
|
||||
if args.is_empty() {
|
||||
@@ -952,6 +987,8 @@ impl VeilidAPI {
|
||||
self.debug_restart(rest).await
|
||||
} else if arg == "route" {
|
||||
self.debug_route(rest).await
|
||||
} else if arg == "record" {
|
||||
self.debug_record(rest).await
|
||||
} else {
|
||||
Err(VeilidAPIError::generic("Unknown debug command"))
|
||||
}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
use super::*;
|
||||
|
||||
#[allow(unused_macros)]
|
||||
#[macro_export]
|
||||
macro_rules! apibail_not_initialized {
|
||||
() => {
|
||||
return Err(VeilidAPIError::not_initialized())
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
#[macro_export]
|
||||
macro_rules! apibail_timeout {
|
||||
@@ -64,6 +72,14 @@ macro_rules! apibail_no_connection {
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
#[macro_export]
|
||||
macro_rules! apibail_key_not_found {
|
||||
($x:expr) => {
|
||||
return Err(VeilidAPIError::key_not_found($x))
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
#[macro_export]
|
||||
macro_rules! apibail_invalid_target {
|
||||
@@ -119,8 +135,8 @@ pub enum VeilidAPIError {
|
||||
InvalidTarget,
|
||||
#[error("No connection: {message}")]
|
||||
NoConnection { message: String },
|
||||
#[error("No peer info: {node_id}")]
|
||||
NoPeerInfo { node_id: TypedKey },
|
||||
#[error("Key not found: {key}")]
|
||||
KeyNotFound { key: TypedKey },
|
||||
#[error("Internal: {message}")]
|
||||
Internal { message: String },
|
||||
#[error("Unimplemented: {message}")]
|
||||
@@ -163,8 +179,8 @@ impl VeilidAPIError {
|
||||
message: msg.to_string(),
|
||||
}
|
||||
}
|
||||
pub fn no_peer_info(node_id: TypedKey) -> Self {
|
||||
Self::NoPeerInfo { node_id }
|
||||
pub fn key_not_found(key: TypedKey) -> Self {
|
||||
Self::KeyNotFound { key }
|
||||
}
|
||||
pub fn internal<T: ToString>(msg: T) -> Self {
|
||||
Self::Internal {
|
||||
@@ -205,3 +221,36 @@ impl VeilidAPIError {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type VeilidAPIResult<T> = Result<T, VeilidAPIError>;
|
||||
|
||||
impl From<std::io::Error> for VeilidAPIError {
|
||||
fn from(e: std::io::Error) -> Self {
|
||||
match e.kind() {
|
||||
std::io::ErrorKind::TimedOut => VeilidAPIError::timeout(),
|
||||
std::io::ErrorKind::ConnectionRefused => VeilidAPIError::no_connection(e.to_string()),
|
||||
std::io::ErrorKind::ConnectionReset => VeilidAPIError::no_connection(e.to_string()),
|
||||
#[cfg(feature = "io_error_more")]
|
||||
std::io::ErrorKind::HostUnreachable => VeilidAPIError::no_connection(e.to_string()),
|
||||
#[cfg(feature = "io_error_more")]
|
||||
std::io::ErrorKind::NetworkUnreachable => VeilidAPIError::no_connection(e.to_string()),
|
||||
std::io::ErrorKind::ConnectionAborted => VeilidAPIError::no_connection(e.to_string()),
|
||||
std::io::ErrorKind::NotConnected => VeilidAPIError::no_connection(e.to_string()),
|
||||
std::io::ErrorKind::AddrInUse => VeilidAPIError::no_connection(e.to_string()),
|
||||
std::io::ErrorKind::AddrNotAvailable => VeilidAPIError::no_connection(e.to_string()),
|
||||
#[cfg(feature = "io_error_more")]
|
||||
std::io::ErrorKind::NetworkDown => VeilidAPIError::no_connection(e.to_string()),
|
||||
#[cfg(feature = "io_error_more")]
|
||||
std::io::ErrorKind::ReadOnlyFilesystem => VeilidAPIError::internal(e.to_string()),
|
||||
#[cfg(feature = "io_error_more")]
|
||||
std::io::ErrorKind::NotSeekable => VeilidAPIError::internal(e.to_string()),
|
||||
#[cfg(feature = "io_error_more")]
|
||||
std::io::ErrorKind::FilesystemQuotaExceeded => VeilidAPIError::internal(e.to_string()),
|
||||
#[cfg(feature = "io_error_more")]
|
||||
std::io::ErrorKind::Deadlock => VeilidAPIError::internal(e.to_string()),
|
||||
std::io::ErrorKind::Unsupported => VeilidAPIError::internal(e.to_string()),
|
||||
std::io::ErrorKind::OutOfMemory => VeilidAPIError::internal(e.to_string()),
|
||||
_ => VeilidAPIError::generic(e.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
mod aligned_u64;
|
||||
mod api;
|
||||
mod debug;
|
||||
mod error;
|
||||
@@ -8,7 +7,8 @@ mod routing_context;
|
||||
mod serialize_helpers;
|
||||
mod types;
|
||||
|
||||
pub use aligned_u64::*;
|
||||
pub mod tests;
|
||||
|
||||
pub use api::*;
|
||||
pub use debug::*;
|
||||
pub use error::*;
|
||||
@@ -22,17 +22,15 @@ pub use core::str::FromStr;
|
||||
pub use crypto::*;
|
||||
pub use intf::BlockStore;
|
||||
pub use intf::ProtectedStore;
|
||||
pub use intf::{TableDB, TableDBTransaction, TableStore};
|
||||
pub use network_manager::NetworkManager;
|
||||
pub use routing_table::{NodeRef, NodeRefBase};
|
||||
pub use table_store::{TableDB, TableDBTransaction, TableStore};
|
||||
|
||||
use crate::*;
|
||||
use core::fmt;
|
||||
use core_context::{api_shutdown, VeilidCoreContext};
|
||||
use enumset::*;
|
||||
use rkyv::{Archive as RkyvArchive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
|
||||
use routing_table::{RouteSpecStore, RoutingTable};
|
||||
use routing_table::{Direction, RouteSpecStore, RoutingTable};
|
||||
use rpc_processor::*;
|
||||
use serde::*;
|
||||
use storage_manager::StorageManager;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -4,7 +4,7 @@ use super::*;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Target {
|
||||
NodeId(PublicKey), // Node by any of its public keys
|
||||
NodeId(TypedKey), // Node by its public key
|
||||
PrivateRoute(RouteId), // Remote private route by its id
|
||||
}
|
||||
|
||||
@@ -45,11 +45,11 @@ impl RoutingContext {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_privacy(self) -> Result<Self, VeilidAPIError> {
|
||||
pub fn with_privacy(self) -> VeilidAPIResult<Self> {
|
||||
self.with_custom_privacy(Stability::default())
|
||||
}
|
||||
|
||||
pub fn with_custom_privacy(self, stability: Stability) -> Result<Self, VeilidAPIError> {
|
||||
pub fn with_custom_privacy(self, stability: Stability) -> VeilidAPIResult<Self> {
|
||||
let config = self.api.config()?;
|
||||
let c = config.get();
|
||||
|
||||
@@ -96,16 +96,16 @@ impl RoutingContext {
|
||||
self.api.clone()
|
||||
}
|
||||
|
||||
async fn get_destination(
|
||||
&self,
|
||||
target: Target,
|
||||
) -> Result<rpc_processor::Destination, VeilidAPIError> {
|
||||
async fn get_destination(&self, target: Target) -> VeilidAPIResult<rpc_processor::Destination> {
|
||||
let rpc_processor = self.api.rpc_processor()?;
|
||||
|
||||
match target {
|
||||
Target::NodeId(node_id) => {
|
||||
// Resolve node
|
||||
let mut nr = match rpc_processor.resolve_node(node_id).await {
|
||||
let mut nr = match rpc_processor
|
||||
.resolve_node(node_id, self.unlocked_inner.safety_selection)
|
||||
.await
|
||||
{
|
||||
Ok(Some(nr)) => nr,
|
||||
Ok(None) => apibail_invalid_target!(),
|
||||
Err(e) => return Err(e.into()),
|
||||
@@ -138,11 +138,7 @@ impl RoutingContext {
|
||||
// App-level Messaging
|
||||
|
||||
#[instrument(level = "debug", err, skip(self))]
|
||||
pub async fn app_call(
|
||||
&self,
|
||||
target: Target,
|
||||
request: Vec<u8>,
|
||||
) -> Result<Vec<u8>, VeilidAPIError> {
|
||||
pub async fn app_call(&self, target: Target, request: Vec<u8>) -> VeilidAPIResult<Vec<u8>> {
|
||||
let rpc_processor = self.api.rpc_processor()?;
|
||||
|
||||
// Get destination
|
||||
@@ -167,11 +163,7 @@ impl RoutingContext {
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", err, skip(self))]
|
||||
pub async fn app_message(
|
||||
&self,
|
||||
target: Target,
|
||||
message: Vec<u8>,
|
||||
) -> Result<(), VeilidAPIError> {
|
||||
pub async fn app_message(&self, target: Target, message: Vec<u8>) -> VeilidAPIResult<()> {
|
||||
let rpc_processor = self.api.rpc_processor()?;
|
||||
|
||||
// Get destination
|
||||
@@ -195,51 +187,114 @@ impl RoutingContext {
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
/// DHT Values
|
||||
/// DHT Records
|
||||
|
||||
pub async fn get_value(
|
||||
/// Creates a new DHT record a specified crypto kind and schema
|
||||
/// Returns the newly allocated DHT record's key if successful. The records is considered 'open' after the create operation succeeds.
|
||||
pub async fn create_dht_record(
|
||||
&self,
|
||||
_key: TypedKey,
|
||||
_subkey: ValueSubkey,
|
||||
) -> Result<ValueData, VeilidAPIError> {
|
||||
panic!("unimplemented");
|
||||
kind: CryptoKind,
|
||||
schema: DHTSchema,
|
||||
) -> VeilidAPIResult<DHTRecordDescriptor> {
|
||||
let storage_manager = self.api.storage_manager()?;
|
||||
storage_manager
|
||||
.create_record(kind, schema, self.unlocked_inner.safety_selection)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn set_value(
|
||||
/// Opens a DHT record at a specific key. Associates a secret if one is provided to provide writer capability.
|
||||
/// Returns the DHT record descriptor for the opened record if successful
|
||||
/// Records may only be opened or created . To re-open with a different routing context, first close the value.
|
||||
pub async fn open_dht_record(
|
||||
&self,
|
||||
_key: TypedKey,
|
||||
_subkey: ValueSubkey,
|
||||
_value: ValueData,
|
||||
) -> Result<bool, VeilidAPIError> {
|
||||
panic!("unimplemented");
|
||||
key: TypedKey,
|
||||
writer: Option<KeyPair>,
|
||||
) -> VeilidAPIResult<DHTRecordDescriptor> {
|
||||
let storage_manager = self.api.storage_manager()?;
|
||||
storage_manager
|
||||
.open_record(key, writer, self.unlocked_inner.safety_selection)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn watch_value(
|
||||
&self,
|
||||
_key: TypedKey,
|
||||
_subkeys: &[ValueSubkeyRange],
|
||||
_expiration: Timestamp,
|
||||
_count: u32,
|
||||
) -> Result<bool, VeilidAPIError> {
|
||||
panic!("unimplemented");
|
||||
/// Closes a DHT record at a specific key that was opened with create_dht_record or open_dht_record.
|
||||
/// Closing a record allows you to re-open it with a different routing context
|
||||
pub async fn close_dht_record(&self, key: TypedKey) -> VeilidAPIResult<()> {
|
||||
let storage_manager = self.api.storage_manager()?;
|
||||
storage_manager.close_record(key).await
|
||||
}
|
||||
|
||||
pub async fn cancel_watch_value(
|
||||
/// Deletes a DHT record at a specific key. If the record is opened, it must be closed before it is deleted.
|
||||
/// Deleting a record does not delete it from the network, but will remove the storage of the record
|
||||
/// locally, and will prevent its value from being refreshed on the network by this node.
|
||||
pub async fn delete_dht_record(&self, key: TypedKey) -> VeilidAPIResult<()> {
|
||||
let storage_manager = self.api.storage_manager()?;
|
||||
storage_manager.delete_record(key).await
|
||||
}
|
||||
|
||||
/// Gets the latest value of a subkey
|
||||
/// May pull the latest value from the network, but by settings 'force_refresh' you can force a network data refresh
|
||||
/// Returns None if the value subkey has not yet been set
|
||||
/// Returns Some(data) if the value subkey has valid data
|
||||
pub async fn get_dht_value(
|
||||
&self,
|
||||
_key: TypedKey,
|
||||
_subkeys: &[ValueSubkeyRange],
|
||||
) -> Result<bool, VeilidAPIError> {
|
||||
panic!("unimplemented");
|
||||
key: TypedKey,
|
||||
subkey: ValueSubkey,
|
||||
force_refresh: bool,
|
||||
) -> VeilidAPIResult<Option<ValueData>> {
|
||||
let storage_manager = self.api.storage_manager()?;
|
||||
storage_manager.get_value(key, subkey, force_refresh).await
|
||||
}
|
||||
|
||||
/// Pushes a changed subkey value to the network
|
||||
/// Returns None if the value was successfully put
|
||||
/// Returns Some(data) if the value put was older than the one available on the network
|
||||
pub async fn set_dht_value(
|
||||
&self,
|
||||
key: TypedKey,
|
||||
subkey: ValueSubkey,
|
||||
data: Vec<u8>,
|
||||
) -> VeilidAPIResult<Option<ValueData>> {
|
||||
let storage_manager = self.api.storage_manager()?;
|
||||
storage_manager.set_value(key, subkey, data).await
|
||||
}
|
||||
|
||||
/// Watches changes to an opened or created value
|
||||
/// Changes to subkeys within the subkey range are returned via a ValueChanged callback
|
||||
/// If the subkey range is empty, all subkey changes are considered
|
||||
/// Expiration can be infinite to keep the watch for the maximum amount of time
|
||||
/// Return value upon success is the amount of time allowed for the watch
|
||||
pub async fn watch_dht_values(
|
||||
&self,
|
||||
key: TypedKey,
|
||||
subkeys: ValueSubkeyRangeSet,
|
||||
expiration: Timestamp,
|
||||
count: u32,
|
||||
) -> VeilidAPIResult<Timestamp> {
|
||||
let storage_manager = self.api.storage_manager()?;
|
||||
storage_manager
|
||||
.watch_values(key, subkeys, expiration, count)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Cancels a watch early
|
||||
/// This is a convenience function that cancels watching all subkeys in a range
|
||||
pub async fn cancel_dht_watch(
|
||||
&self,
|
||||
key: TypedKey,
|
||||
subkeys: ValueSubkeyRangeSet,
|
||||
) -> VeilidAPIResult<bool> {
|
||||
let storage_manager = self.api.storage_manager()?;
|
||||
storage_manager.cancel_watch_values(key, subkeys).await
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
/// Block Store
|
||||
|
||||
pub async fn find_block(&self, _block_id: PublicKey) -> Result<Vec<u8>, VeilidAPIError> {
|
||||
pub async fn find_block(&self, _block_id: PublicKey) -> VeilidAPIResult<Vec<u8>> {
|
||||
panic!("unimplemented");
|
||||
}
|
||||
|
||||
pub async fn supply_block(&self, _block_id: PublicKey) -> Result<bool, VeilidAPIError> {
|
||||
pub async fn supply_block(&self, _block_id: PublicKey) -> VeilidAPIResult<bool> {
|
||||
panic!("unimplemented");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
mod rkyv_enum_set;
|
||||
mod rkyv_range_set_blaze;
|
||||
pub mod serialize_arc;
|
||||
mod serialize_json;
|
||||
pub mod serialize_range_set_blaze;
|
||||
mod veilid_rkyv;
|
||||
|
||||
use super::*;
|
||||
use core::fmt::Debug;
|
||||
|
||||
pub use rkyv_enum_set::*;
|
||||
pub use rkyv_range_set_blaze::*;
|
||||
pub use serialize_json::*;
|
||||
pub use veilid_rkyv::*;
|
||||
@@ -0,0 +1,53 @@
|
||||
use super::*;
|
||||
|
||||
pub struct RkyvEnumSet;
|
||||
|
||||
impl<T> rkyv::with::ArchiveWith<EnumSet<T>> for RkyvEnumSet
|
||||
where
|
||||
T: EnumSetType + EnumSetTypeWithRepr,
|
||||
<T as EnumSetTypeWithRepr>::Repr: rkyv::Archive,
|
||||
{
|
||||
type Archived = rkyv::Archived<<T as EnumSetTypeWithRepr>::Repr>;
|
||||
type Resolver = rkyv::Resolver<<T as EnumSetTypeWithRepr>::Repr>;
|
||||
|
||||
#[inline]
|
||||
unsafe fn resolve_with(
|
||||
field: &EnumSet<T>,
|
||||
pos: usize,
|
||||
resolver: Self::Resolver,
|
||||
out: *mut Self::Archived,
|
||||
) {
|
||||
let r = field.as_repr();
|
||||
r.resolve(pos, resolver, out);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S> rkyv::with::SerializeWith<EnumSet<T>, S> for RkyvEnumSet
|
||||
where
|
||||
S: rkyv::Fallible + ?Sized,
|
||||
T: EnumSetType + EnumSetTypeWithRepr,
|
||||
<T as EnumSetTypeWithRepr>::Repr: rkyv::Serialize<S>,
|
||||
{
|
||||
fn serialize_with(field: &EnumSet<T>, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
|
||||
let r = field.as_repr();
|
||||
r.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, D>
|
||||
rkyv::with::DeserializeWith<rkyv::Archived<<T as EnumSetTypeWithRepr>::Repr>, EnumSet<T>, D>
|
||||
for RkyvEnumSet
|
||||
where
|
||||
D: rkyv::Fallible + ?Sized,
|
||||
T: EnumSetType + EnumSetTypeWithRepr,
|
||||
<T as EnumSetTypeWithRepr>::Repr: rkyv::Archive,
|
||||
rkyv::Archived<<T as EnumSetTypeWithRepr>::Repr>:
|
||||
rkyv::Deserialize<<T as EnumSetTypeWithRepr>::Repr, D>,
|
||||
{
|
||||
fn deserialize_with(
|
||||
field: &rkyv::Archived<<T as EnumSetTypeWithRepr>::Repr>,
|
||||
deserializer: &mut D,
|
||||
) -> Result<EnumSet<T>, D::Error> {
|
||||
Ok(EnumSet::<T>::from_repr(field.deserialize(deserializer)?))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
use super::*;
|
||||
|
||||
use range_set_blaze::*;
|
||||
|
||||
pub struct RkyvRangeSetBlaze;
|
||||
|
||||
impl<T> rkyv::with::ArchiveWith<RangeSetBlaze<T>> for RkyvRangeSetBlaze
|
||||
where
|
||||
T: rkyv::Archive + Integer,
|
||||
{
|
||||
type Archived = rkyv::Archived<Vec<T>>;
|
||||
type Resolver = rkyv::Resolver<Vec<T>>;
|
||||
|
||||
#[inline]
|
||||
unsafe fn resolve_with(
|
||||
field: &RangeSetBlaze<T>,
|
||||
pos: usize,
|
||||
resolver: Self::Resolver,
|
||||
out: *mut Self::Archived,
|
||||
) {
|
||||
let mut r = Vec::<T>::with_capacity(field.ranges_len() * 2);
|
||||
for range in field.ranges() {
|
||||
r.push(*range.start());
|
||||
r.push(*range.end());
|
||||
}
|
||||
r.resolve(pos, resolver, out);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S> rkyv::with::SerializeWith<RangeSetBlaze<T>, S> for RkyvRangeSetBlaze
|
||||
where
|
||||
S: rkyv::Fallible + ?Sized,
|
||||
Vec<T>: rkyv::Serialize<S>,
|
||||
T: rkyv::Archive + Integer,
|
||||
{
|
||||
fn serialize_with(
|
||||
field: &RangeSetBlaze<T>,
|
||||
serializer: &mut S,
|
||||
) -> Result<Self::Resolver, S::Error> {
|
||||
let mut r = Vec::<T>::with_capacity(field.ranges_len() * 2);
|
||||
for range in field.ranges() {
|
||||
r.push(*range.start());
|
||||
r.push(*range.end());
|
||||
}
|
||||
r.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, D> rkyv::with::DeserializeWith<rkyv::Archived<Vec<T>>, RangeSetBlaze<T>, D>
|
||||
for RkyvRangeSetBlaze
|
||||
where
|
||||
D: rkyv::Fallible + ?Sized,
|
||||
T: rkyv::Archive + Integer,
|
||||
rkyv::Archived<T>: rkyv::Deserialize<T, D>,
|
||||
D::Error: From<String>,
|
||||
{
|
||||
fn deserialize_with(
|
||||
field: &rkyv::Archived<Vec<T>>,
|
||||
deserializer: &mut D,
|
||||
) -> Result<RangeSetBlaze<T>, D::Error> {
|
||||
let mut out = RangeSetBlaze::<T>::new();
|
||||
if field.len() % 2 == 1 {
|
||||
return Err("invalid range set length".to_owned().into());
|
||||
}
|
||||
let f = field.as_slice();
|
||||
for i in 0..field.len() / 2 {
|
||||
let l: T = f[i * 2].deserialize(deserializer)?;
|
||||
let u: T = f[i * 2 + 1].deserialize(deserializer)?;
|
||||
out.ranges_insert(l..=u);
|
||||
}
|
||||
Ok(out)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
use alloc::sync::Arc;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
pub fn serialize<T: Serialize, S: Serializer>(v: &Arc<T>, s: S) -> Result<S::Ok, S::Error> {
|
||||
T::serialize(v.as_ref(), s)
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, T: Deserialize<'de>, D: Deserializer<'de>>(
|
||||
d: D,
|
||||
) -> Result<Arc<T>, D::Error> {
|
||||
Ok(Arc::new(T::deserialize(d)?))
|
||||
}
|
||||
+2
-101
@@ -1,16 +1,9 @@
|
||||
use super::*;
|
||||
pub use bytecheck::CheckBytes;
|
||||
use core::fmt::Debug;
|
||||
use rkyv::Archive as RkyvArchive;
|
||||
use rkyv::Deserialize as RkyvDeserialize;
|
||||
use rkyv::Serialize as RkyvSerialize;
|
||||
|
||||
// Don't trace these functions as they are used in the transfer of API logs, which will recurse!
|
||||
|
||||
// #[instrument(level = "trace", ret, err)]
|
||||
pub fn deserialize_json<'a, T: de::Deserialize<'a> + Debug>(
|
||||
arg: &'a str,
|
||||
) -> Result<T, VeilidAPIError> {
|
||||
pub fn deserialize_json<'a, T: de::Deserialize<'a> + Debug>(arg: &'a str) -> VeilidAPIResult<T> {
|
||||
serde_json::from_str(arg).map_err(|e| VeilidAPIError::ParseError {
|
||||
message: e.to_string(),
|
||||
value: format!(
|
||||
@@ -24,7 +17,7 @@ pub fn deserialize_json<'a, T: de::Deserialize<'a> + Debug>(
|
||||
// #[instrument(level = "trace", ret, err)]
|
||||
pub fn deserialize_opt_json<T: de::DeserializeOwned + Debug>(
|
||||
arg: Option<String>,
|
||||
) -> Result<T, VeilidAPIError> {
|
||||
) -> VeilidAPIResult<T> {
|
||||
let arg = arg.as_ref().ok_or_else(|| VeilidAPIError::ParseError {
|
||||
message: "invalid null string".to_owned(),
|
||||
value: format!(
|
||||
@@ -117,95 +110,3 @@ pub mod opt_json_as_string {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod arc_serialize {
|
||||
use alloc::sync::Arc;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
pub fn serialize<T: Serialize, S: Serializer>(v: &Arc<T>, s: S) -> Result<S::Ok, S::Error> {
|
||||
T::serialize(v.as_ref(), s)
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, T: Deserialize<'de>, D: Deserializer<'de>>(
|
||||
d: D,
|
||||
) -> Result<Arc<T>, D::Error> {
|
||||
Ok(Arc::new(T::deserialize(d)?))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_rkyv<T>(v: &T) -> EyreResult<Vec<u8>>
|
||||
where
|
||||
T: RkyvSerialize<rkyv::ser::serializers::AllocSerializer<1024>>,
|
||||
{
|
||||
Ok(rkyv::to_bytes::<T, 1024>(v)
|
||||
.wrap_err("failed to freeze object")?
|
||||
.to_vec())
|
||||
}
|
||||
|
||||
pub fn from_rkyv<T>(v: Vec<u8>) -> EyreResult<T>
|
||||
where
|
||||
T: RkyvArchive,
|
||||
<T as RkyvArchive>::Archived:
|
||||
for<'t> bytecheck::CheckBytes<rkyv::validation::validators::DefaultValidator<'t>>,
|
||||
<T as RkyvArchive>::Archived:
|
||||
rkyv::Deserialize<T, rkyv::de::deserializers::SharedDeserializeMap>,
|
||||
{
|
||||
match rkyv::from_bytes::<T>(&v) {
|
||||
Ok(v) => Ok(v),
|
||||
Err(e) => {
|
||||
bail!("failed to deserialize frozen object: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RkyvEnumSet;
|
||||
|
||||
impl<T> rkyv::with::ArchiveWith<EnumSet<T>> for RkyvEnumSet
|
||||
where
|
||||
T: EnumSetType + EnumSetTypeWithRepr,
|
||||
<T as EnumSetTypeWithRepr>::Repr: rkyv::Archive,
|
||||
{
|
||||
type Archived = rkyv::Archived<<T as EnumSetTypeWithRepr>::Repr>;
|
||||
type Resolver = rkyv::Resolver<<T as EnumSetTypeWithRepr>::Repr>;
|
||||
|
||||
#[inline]
|
||||
unsafe fn resolve_with(
|
||||
field: &EnumSet<T>,
|
||||
pos: usize,
|
||||
resolver: Self::Resolver,
|
||||
out: *mut Self::Archived,
|
||||
) {
|
||||
let r = field.as_repr();
|
||||
r.resolve(pos, resolver, out);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S> rkyv::with::SerializeWith<EnumSet<T>, S> for RkyvEnumSet
|
||||
where
|
||||
S: rkyv::Fallible + ?Sized,
|
||||
T: EnumSetType + EnumSetTypeWithRepr,
|
||||
<T as EnumSetTypeWithRepr>::Repr: rkyv::Serialize<S>,
|
||||
{
|
||||
fn serialize_with(field: &EnumSet<T>, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
|
||||
let r = field.as_repr();
|
||||
r.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, D>
|
||||
rkyv::with::DeserializeWith<rkyv::Archived<<T as EnumSetTypeWithRepr>::Repr>, EnumSet<T>, D>
|
||||
for RkyvEnumSet
|
||||
where
|
||||
D: rkyv::Fallible + ?Sized,
|
||||
T: EnumSetType + EnumSetTypeWithRepr,
|
||||
<T as EnumSetTypeWithRepr>::Repr: rkyv::Archive,
|
||||
rkyv::Archived<<T as EnumSetTypeWithRepr>::Repr>:
|
||||
rkyv::Deserialize<<T as EnumSetTypeWithRepr>::Repr, D>,
|
||||
{
|
||||
fn deserialize_with(
|
||||
field: &rkyv::Archived<<T as EnumSetTypeWithRepr>::Repr>,
|
||||
deserializer: &mut D,
|
||||
) -> Result<EnumSet<T>, D::Error> {
|
||||
Ok(EnumSet::<T>::from_repr(field.deserialize(deserializer)?))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
use core::fmt;
|
||||
use core::marker::PhantomData;
|
||||
use range_set_blaze::*;
|
||||
use serde::{
|
||||
de::SeqAccess, de::Visitor, ser::SerializeSeq, Deserialize, Deserializer, Serialize, Serializer,
|
||||
};
|
||||
|
||||
pub fn serialize<T: Integer + Serialize, S: Serializer>(
|
||||
v: &RangeSetBlaze<T>,
|
||||
s: S,
|
||||
) -> Result<S::Ok, S::Error> {
|
||||
let cnt = v.ranges_len() * 2;
|
||||
let mut seq = s.serialize_seq(Some(cnt))?;
|
||||
for range in v.ranges() {
|
||||
seq.serialize_element(range.start())?;
|
||||
seq.serialize_element(range.end())?;
|
||||
}
|
||||
seq.end()
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, T: Integer + Deserialize<'de>, D: Deserializer<'de>>(
|
||||
d: D,
|
||||
) -> Result<RangeSetBlaze<T>, D::Error> {
|
||||
struct RangeSetBlazeVisitor<T> {
|
||||
marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<'de, T> Visitor<'de> for RangeSetBlazeVisitor<T>
|
||||
where
|
||||
T: Deserialize<'de> + Integer,
|
||||
{
|
||||
type Value = RangeSetBlaze<T>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a RangeSetBlaze")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
let mut values = RangeSetBlaze::<T>::new();
|
||||
|
||||
while let Some(start) = seq.next_element()? {
|
||||
let Some(end) = seq.next_element()? else {
|
||||
break;
|
||||
};
|
||||
values.ranges_insert(start..=end);
|
||||
}
|
||||
|
||||
Ok(values)
|
||||
}
|
||||
}
|
||||
|
||||
let visitor = RangeSetBlazeVisitor {
|
||||
marker: PhantomData,
|
||||
};
|
||||
|
||||
d.deserialize_seq(visitor)
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
use super::*;
|
||||
use rkyv::ser::Serializer;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pub struct VeilidRkyvSerializer<S> {
|
||||
inner: S,
|
||||
}
|
||||
|
||||
impl<S> VeilidRkyvSerializer<S> {
|
||||
pub fn into_inner(self) -> S {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: rkyv::Fallible> rkyv::Fallible for VeilidRkyvSerializer<S> {
|
||||
type Error = VeilidRkyvError<S::Error>;
|
||||
}
|
||||
|
||||
impl<S: rkyv::ser::ScratchSpace> rkyv::ser::ScratchSpace for VeilidRkyvSerializer<S> {
|
||||
unsafe fn push_scratch(
|
||||
&mut self,
|
||||
layout: core::alloc::Layout,
|
||||
) -> Result<core::ptr::NonNull<[u8]>, Self::Error> {
|
||||
self.inner
|
||||
.push_scratch(layout)
|
||||
.map_err(VeilidRkyvError::Inner)
|
||||
}
|
||||
unsafe fn pop_scratch(
|
||||
&mut self,
|
||||
ptr: core::ptr::NonNull<u8>,
|
||||
layout: core::alloc::Layout,
|
||||
) -> Result<(), Self::Error> {
|
||||
self.inner
|
||||
.pop_scratch(ptr, layout)
|
||||
.map_err(VeilidRkyvError::Inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: rkyv::ser::Serializer> rkyv::ser::Serializer for VeilidRkyvSerializer<S> {
|
||||
#[inline]
|
||||
fn pos(&self) -> usize {
|
||||
self.inner.pos()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write(&mut self, bytes: &[u8]) -> Result<(), Self::Error> {
|
||||
self.inner.write(bytes).map_err(VeilidRkyvError::Inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Default> Default for VeilidRkyvSerializer<S> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
inner: S::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type DefaultVeilidRkyvSerializer =
|
||||
VeilidRkyvSerializer<rkyv::ser::serializers::AllocSerializer<1024>>;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct VeilidSharedDeserializeMap {
|
||||
inner: SharedDeserializeMap,
|
||||
}
|
||||
|
||||
impl VeilidSharedDeserializeMap {
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
inner: SharedDeserializeMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl rkyv::Fallible for VeilidSharedDeserializeMap {
|
||||
type Error = VeilidRkyvError<rkyv::de::deserializers::SharedDeserializeMapError>;
|
||||
}
|
||||
|
||||
impl rkyv::de::SharedDeserializeRegistry for VeilidSharedDeserializeMap {
|
||||
fn get_shared_ptr(&mut self, ptr: *const u8) -> Option<&dyn rkyv::de::SharedPointer> {
|
||||
self.inner.get_shared_ptr(ptr)
|
||||
}
|
||||
|
||||
fn add_shared_ptr(
|
||||
&mut self,
|
||||
ptr: *const u8,
|
||||
shared: Box<dyn rkyv::de::SharedPointer>,
|
||||
) -> Result<(), Self::Error> {
|
||||
self.inner
|
||||
.add_shared_ptr(ptr, shared)
|
||||
.map_err(VeilidRkyvError::Inner)
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum VeilidRkyvError<E> {
|
||||
Inner(E),
|
||||
StringError(String),
|
||||
}
|
||||
|
||||
impl<E: Debug> From<String> for VeilidRkyvError<E> {
|
||||
fn from(s: String) -> Self {
|
||||
Self::StringError(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Debug + fmt::Display> fmt::Display for VeilidRkyvError<E> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
VeilidRkyvError::Inner(e) => write!(f, "Inner: {}", e),
|
||||
VeilidRkyvError::StringError(s) => write!(f, "StringError: {}", s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Debug + fmt::Display> std::error::Error for VeilidRkyvError<E> {}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pub fn to_rkyv<T>(value: &T) -> VeilidAPIResult<Vec<u8>>
|
||||
where
|
||||
T: RkyvSerialize<DefaultVeilidRkyvSerializer>,
|
||||
{
|
||||
let mut serializer = DefaultVeilidRkyvSerializer::default();
|
||||
serializer
|
||||
.serialize_value(value)
|
||||
.map_err(|e| VeilidAPIError::generic(format!("failed to serialize object: {}", e)))?;
|
||||
Ok(serializer
|
||||
.into_inner()
|
||||
.into_serializer()
|
||||
.into_inner()
|
||||
.to_vec())
|
||||
}
|
||||
|
||||
pub fn from_rkyv<T>(bytes: Vec<u8>) -> VeilidAPIResult<T>
|
||||
where
|
||||
T: RkyvArchive,
|
||||
<T as RkyvArchive>::Archived:
|
||||
for<'t> CheckBytes<rkyv::validation::validators::DefaultValidator<'t>>,
|
||||
<T as RkyvArchive>::Archived: RkyvDeserialize<T, VeilidSharedDeserializeMap>,
|
||||
{
|
||||
rkyv::check_archived_root::<T>(&bytes)
|
||||
.map_err(|e| VeilidAPIError::generic(format!("checkbytes failed: {}", e)))?
|
||||
.deserialize(&mut VeilidSharedDeserializeMap::default())
|
||||
.map_err(|e| VeilidAPIError::generic(format!("failed to deserialize: {}", e)))
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod test_serialize_rkyv;
|
||||
@@ -0,0 +1,16 @@
|
||||
use crate::*;
|
||||
|
||||
pub async fn test_simple_string() {
|
||||
let plain = "basic string".to_string();
|
||||
let serialized = b"basic string\x0c\x00\x00\x00\xf4\xff\xff\xff".to_vec();
|
||||
|
||||
let a = to_rkyv(&plain);
|
||||
assert_eq!(a.unwrap(), serialized);
|
||||
|
||||
let b = from_rkyv::<String>(serialized);
|
||||
assert_eq!(b.unwrap(), plain);
|
||||
}
|
||||
|
||||
pub async fn test_all() {
|
||||
test_simple_string().await;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+14
@@ -120,3 +120,17 @@ impl AlignedU64 {
|
||||
Self(self.0.saturating_sub(rhs.0))
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Microseconds since epoch
|
||||
pub type Timestamp = AlignedU64;
|
||||
pub fn get_aligned_timestamp() -> Timestamp {
|
||||
get_timestamp().into()
|
||||
}
|
||||
/// Microseconds duration
|
||||
pub type TimestampDuration = AlignedU64;
|
||||
/// Request/Response matching id
|
||||
pub type OperationId = AlignedU64;
|
||||
/// Number of bytes
|
||||
pub type ByteCount = AlignedU64;
|
||||
@@ -0,0 +1,65 @@
|
||||
use super::*;
|
||||
|
||||
/// Direct statement blob passed to hosting application for processing
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct VeilidAppMessage {
|
||||
/// Some(sender) if the message was sent directly, None if received via a private/safety route
|
||||
#[serde(with = "opt_json_as_string")]
|
||||
sender: Option<TypedKey>,
|
||||
/// The content of the message to deliver to the application
|
||||
#[serde(with = "json_as_base64")]
|
||||
message: Vec<u8>,
|
||||
}
|
||||
|
||||
impl VeilidAppMessage {
|
||||
pub fn new(sender: Option<TypedKey>, message: Vec<u8>) -> Self {
|
||||
Self { sender, message }
|
||||
}
|
||||
|
||||
pub fn sender(&self) -> Option<&TypedKey> {
|
||||
self.sender.as_ref()
|
||||
}
|
||||
pub fn message(&self) -> &[u8] {
|
||||
&self.message
|
||||
}
|
||||
}
|
||||
|
||||
/// Direct question blob passed to hosting application for processing to send an eventual AppReply
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct VeilidAppCall {
|
||||
/// Some(sender) if the request was sent directly, None if received via a private/safety route
|
||||
#[serde(with = "opt_json_as_string")]
|
||||
sender: Option<TypedKey>,
|
||||
/// The content of the request to deliver to the application
|
||||
#[serde(with = "json_as_base64")]
|
||||
message: Vec<u8>,
|
||||
/// The id to reply to
|
||||
#[serde(with = "json_as_string")]
|
||||
id: OperationId,
|
||||
}
|
||||
|
||||
impl VeilidAppCall {
|
||||
pub fn new(sender: Option<TypedKey>, message: Vec<u8>, id: OperationId) -> Self {
|
||||
Self {
|
||||
sender,
|
||||
message,
|
||||
id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sender(&self) -> Option<&TypedKey> {
|
||||
self.sender.as_ref()
|
||||
}
|
||||
pub fn message(&self) -> &[u8] {
|
||||
&self.message
|
||||
}
|
||||
pub fn id(&self) -> OperationId {
|
||||
self.id
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
use super::*;
|
||||
|
||||
/// DHT Record Descriptor
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct DHTRecordDescriptor {
|
||||
/// DHT Key = Hash(ownerKeyKind) of: [ ownerKeyValue, schema ]
|
||||
key: TypedKey,
|
||||
/// The public key of the owner
|
||||
owner: PublicKey,
|
||||
/// If this key is being created: Some(the secret key of the owner)
|
||||
/// If this key is just being opened: None
|
||||
owner_secret: Option<SecretKey>,
|
||||
/// The schema in use associated with the key
|
||||
schema: DHTSchema,
|
||||
}
|
||||
|
||||
impl DHTRecordDescriptor {
|
||||
pub fn new(
|
||||
key: TypedKey,
|
||||
owner: PublicKey,
|
||||
owner_secret: Option<SecretKey>,
|
||||
schema: DHTSchema,
|
||||
) -> Self {
|
||||
Self {
|
||||
key,
|
||||
owner,
|
||||
owner_secret,
|
||||
schema,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn owner(&self) -> &PublicKey {
|
||||
&self.owner
|
||||
}
|
||||
|
||||
pub fn owner_secret(&self) -> Option<&SecretKey> {
|
||||
self.owner_secret.as_ref()
|
||||
}
|
||||
|
||||
pub fn schema(&self) -> &DHTSchema {
|
||||
&self.schema
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
mod dht_record_descriptor;
|
||||
mod schema;
|
||||
mod value_data;
|
||||
mod value_subkey_range_set;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub use dht_record_descriptor::*;
|
||||
pub use schema::*;
|
||||
pub use value_data::*;
|
||||
pub use value_subkey_range_set::*;
|
||||
|
||||
/// Value subkey
|
||||
pub type ValueSubkey = u32;
|
||||
/// Value subkey range
|
||||
pub type ValueSubkeyRange = (u32, u32);
|
||||
/// Value sequence number
|
||||
pub type ValueSeqNum = u32;
|
||||
@@ -0,0 +1,84 @@
|
||||
use super::*;
|
||||
|
||||
/// Default DHT Schema (DFLT)
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Ord,
|
||||
PartialOrd,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct DHTSchemaDFLT {
|
||||
/// Owner subkey count
|
||||
pub o_cnt: u16,
|
||||
}
|
||||
|
||||
impl DHTSchemaDFLT {
|
||||
pub const FCC: [u8; 4] = *b"DFLT";
|
||||
pub const FIXED_SIZE: usize = 6;
|
||||
|
||||
/// Build the data representation of the schema
|
||||
pub fn compile(&self) -> Vec<u8> {
|
||||
let mut out = Vec::<u8>::with_capacity(Self::FIXED_SIZE);
|
||||
// kind
|
||||
out.extend_from_slice(&Self::FCC);
|
||||
// o_cnt
|
||||
out.extend_from_slice(&self.o_cnt.to_le_bytes());
|
||||
out
|
||||
}
|
||||
|
||||
/// Get the number of subkeys this schema allocates
|
||||
pub fn subkey_count(&self) -> usize {
|
||||
self.o_cnt as usize
|
||||
}
|
||||
/// Get the data size of this schema beyond the size of the structure itself
|
||||
pub fn data_size(&self) -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
/// Check a subkey value data against the schema
|
||||
pub fn check_subkey_value_data(
|
||||
&self,
|
||||
owner: &PublicKey,
|
||||
subkey: ValueSubkey,
|
||||
value_data: &ValueData,
|
||||
) -> bool {
|
||||
let subkey = subkey as usize;
|
||||
|
||||
// Check is subkey is in owner range
|
||||
if subkey < (self.o_cnt as usize) {
|
||||
// Check value data has valid writer
|
||||
if value_data.writer() == owner {
|
||||
return true;
|
||||
}
|
||||
// Wrong writer
|
||||
return false;
|
||||
}
|
||||
|
||||
// Subkey out of range
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for DHTSchemaDFLT {
|
||||
type Error = VeilidAPIError;
|
||||
fn try_from(b: &[u8]) -> Result<Self, Self::Error> {
|
||||
if b.len() != Self::FIXED_SIZE {
|
||||
apibail_generic!("invalid size");
|
||||
}
|
||||
if &b[0..4] != &Self::FCC {
|
||||
apibail_generic!("wrong fourcc");
|
||||
}
|
||||
|
||||
let o_cnt = u16::from_le_bytes(b[4..6].try_into().map_err(VeilidAPIError::internal)?);
|
||||
|
||||
Ok(Self { o_cnt })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
mod dflt;
|
||||
mod smpl;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub use dflt::*;
|
||||
pub use smpl::*;
|
||||
|
||||
/// Enum over all the supported DHT Schemas
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Ord,
|
||||
PartialOrd,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(u8), derive(CheckBytes))]
|
||||
#[serde(tag = "kind")]
|
||||
pub enum DHTSchema {
|
||||
DFLT(DHTSchemaDFLT),
|
||||
SMPL(DHTSchemaSMPL),
|
||||
}
|
||||
|
||||
impl DHTSchema {
|
||||
pub fn dflt(o_cnt: u16) -> DHTSchema {
|
||||
DHTSchema::DFLT(DHTSchemaDFLT { o_cnt })
|
||||
}
|
||||
pub fn smpl(o_cnt: u16, members: Vec<DHTSchemaSMPLMember>) -> DHTSchema {
|
||||
DHTSchema::SMPL(DHTSchemaSMPL { o_cnt, members })
|
||||
}
|
||||
|
||||
/// Build the data representation of the schema
|
||||
pub fn compile(&self) -> Vec<u8> {
|
||||
match self {
|
||||
DHTSchema::DFLT(d) => d.compile(),
|
||||
DHTSchema::SMPL(s) => s.compile(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the number of subkeys this schema allocates
|
||||
pub fn subkey_count(&self) -> usize {
|
||||
match self {
|
||||
DHTSchema::DFLT(d) => d.subkey_count(),
|
||||
DHTSchema::SMPL(s) => s.subkey_count(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the data size of this schema beyond the size of the structure itself
|
||||
pub fn data_size(&self) -> usize {
|
||||
match self {
|
||||
DHTSchema::DFLT(d) => d.data_size(),
|
||||
DHTSchema::SMPL(s) => s.data_size(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Check a subkey value data against the schema
|
||||
pub fn check_subkey_value_data(
|
||||
&self,
|
||||
owner: &PublicKey,
|
||||
subkey: ValueSubkey,
|
||||
value_data: &ValueData,
|
||||
) -> bool {
|
||||
match self {
|
||||
DHTSchema::DFLT(d) => d.check_subkey_value_data(owner, subkey, value_data),
|
||||
DHTSchema::SMPL(s) => s.check_subkey_value_data(owner, subkey, value_data),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for DHTSchema {
|
||||
fn default() -> Self {
|
||||
Self::dflt(1)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for DHTSchema {
|
||||
type Error = VeilidAPIError;
|
||||
fn try_from(b: &[u8]) -> Result<Self, Self::Error> {
|
||||
if b.len() < 4 {
|
||||
apibail_generic!("invalid size");
|
||||
}
|
||||
let fcc: [u8; 4] = b[0..4].try_into().unwrap();
|
||||
match fcc {
|
||||
DHTSchemaDFLT::FCC => Ok(DHTSchema::DFLT(DHTSchemaDFLT::try_from(b)?)),
|
||||
DHTSchemaSMPL::FCC => Ok(DHTSchema::SMPL(DHTSchemaSMPL::try_from(b)?)),
|
||||
_ => {
|
||||
apibail_generic!("unknown fourcc");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
use super::*;
|
||||
|
||||
/// Simple DHT Schema (SMPL) Member
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct DHTSchemaSMPLMember {
|
||||
/// Member key
|
||||
pub m_key: PublicKey,
|
||||
/// Member subkey count
|
||||
pub m_cnt: u16,
|
||||
}
|
||||
|
||||
/// Simple DHT Schema (SMPL)
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Ord,
|
||||
PartialOrd,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct DHTSchemaSMPL {
|
||||
/// Owner subkey count
|
||||
pub o_cnt: u16,
|
||||
/// Members
|
||||
pub members: Vec<DHTSchemaSMPLMember>,
|
||||
}
|
||||
|
||||
impl DHTSchemaSMPL {
|
||||
pub const FCC: [u8; 4] = *b"SMPL";
|
||||
pub const FIXED_SIZE: usize = 6;
|
||||
|
||||
/// Build the data representation of the schema
|
||||
pub fn compile(&self) -> Vec<u8> {
|
||||
let mut out = Vec::<u8>::with_capacity(
|
||||
Self::FIXED_SIZE + (self.members.len() * (PUBLIC_KEY_LENGTH + 2)),
|
||||
);
|
||||
// kind
|
||||
out.extend_from_slice(&Self::FCC);
|
||||
// o_cnt
|
||||
out.extend_from_slice(&self.o_cnt.to_le_bytes());
|
||||
// members
|
||||
for m in &self.members {
|
||||
// m_key
|
||||
out.extend_from_slice(&m.m_key.bytes);
|
||||
// m_cnt
|
||||
out.extend_from_slice(&m.m_cnt.to_le_bytes());
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
/// Get the number of subkeys this schema allocates
|
||||
pub fn subkey_count(&self) -> usize {
|
||||
self.members
|
||||
.iter()
|
||||
.fold(self.o_cnt as usize, |acc, x| acc + (x.m_cnt as usize))
|
||||
}
|
||||
|
||||
/// Get the data size of this schema beyond the size of the structure itself
|
||||
pub fn data_size(&self) -> usize {
|
||||
self.members.len() * mem::size_of::<DHTSchemaSMPLMember>()
|
||||
}
|
||||
|
||||
/// Check a subkey value data against the schema
|
||||
pub fn check_subkey_value_data(
|
||||
&self,
|
||||
owner: &PublicKey,
|
||||
subkey: ValueSubkey,
|
||||
value_data: &ValueData,
|
||||
) -> bool {
|
||||
let mut cur_subkey = subkey as usize;
|
||||
|
||||
// Check is subkey is in owner range
|
||||
if cur_subkey < (self.o_cnt as usize) {
|
||||
// Check value data has valid writer
|
||||
if value_data.writer() == owner {
|
||||
return true;
|
||||
}
|
||||
// Wrong writer
|
||||
return false;
|
||||
}
|
||||
cur_subkey -= self.o_cnt as usize;
|
||||
|
||||
// Check all member ranges
|
||||
for m in &self.members {
|
||||
// Check if subkey is in member range
|
||||
if cur_subkey < (m.m_cnt as usize) {
|
||||
// Check value data has valid writer
|
||||
if value_data.writer() == &m.m_key {
|
||||
return true;
|
||||
}
|
||||
// Wrong writer
|
||||
return false;
|
||||
}
|
||||
cur_subkey -= m.m_cnt as usize;
|
||||
}
|
||||
|
||||
// Subkey out of range
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for DHTSchemaSMPL {
|
||||
type Error = VeilidAPIError;
|
||||
fn try_from(b: &[u8]) -> Result<Self, Self::Error> {
|
||||
if b.len() != Self::FIXED_SIZE {
|
||||
apibail_generic!("invalid size");
|
||||
}
|
||||
if &b[0..4] != &Self::FCC {
|
||||
apibail_generic!("wrong fourcc");
|
||||
}
|
||||
if (b.len() - Self::FIXED_SIZE) % (PUBLIC_KEY_LENGTH + 2) != 0 {
|
||||
apibail_generic!("invalid member length");
|
||||
}
|
||||
|
||||
let o_cnt = u16::from_le_bytes(b[4..6].try_into().map_err(VeilidAPIError::internal)?);
|
||||
|
||||
let members_len = (b.len() - Self::FIXED_SIZE) / (PUBLIC_KEY_LENGTH + 2);
|
||||
let mut members: Vec<DHTSchemaSMPLMember> = Vec::with_capacity(members_len);
|
||||
for n in 0..members_len {
|
||||
let mstart = Self::FIXED_SIZE + n * (PUBLIC_KEY_LENGTH + 2);
|
||||
let m_key = PublicKey::try_from(&b[mstart..mstart + PUBLIC_KEY_LENGTH])
|
||||
.map_err(VeilidAPIError::internal)?;
|
||||
let m_cnt = u16::from_le_bytes(
|
||||
b[mstart + PUBLIC_KEY_LENGTH..mstart + PUBLIC_KEY_LENGTH + 2]
|
||||
.try_into()
|
||||
.map_err(VeilidAPIError::internal)?,
|
||||
);
|
||||
members.push(DHTSchemaSMPLMember { m_key, m_cnt });
|
||||
}
|
||||
|
||||
Ok(Self { o_cnt, members })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
use super::*;
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Default,
|
||||
PartialOrd,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Ord,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct ValueData {
|
||||
seq: ValueSeqNum,
|
||||
data: Vec<u8>,
|
||||
writer: PublicKey,
|
||||
}
|
||||
impl ValueData {
|
||||
pub const MAX_LEN: usize = 32768;
|
||||
|
||||
pub fn new(data: Vec<u8>, writer: PublicKey) -> Self {
|
||||
assert!(data.len() <= Self::MAX_LEN);
|
||||
Self {
|
||||
seq: 0,
|
||||
data,
|
||||
writer,
|
||||
}
|
||||
}
|
||||
pub fn new_with_seq(seq: ValueSeqNum, data: Vec<u8>, writer: PublicKey) -> Self {
|
||||
assert!(data.len() <= Self::MAX_LEN);
|
||||
Self { seq, data, writer }
|
||||
}
|
||||
|
||||
pub fn seq(&self) -> ValueSeqNum {
|
||||
self.seq
|
||||
}
|
||||
|
||||
pub fn writer(&self) -> &PublicKey {
|
||||
&self.writer
|
||||
}
|
||||
|
||||
pub fn data(&self) -> &[u8] {
|
||||
&self.data
|
||||
}
|
||||
|
||||
pub fn total_size(&self) -> usize {
|
||||
mem::size_of::<Self>() + self.data.len()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
use super::*;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use range_set_blaze::*;
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Default,
|
||||
PartialOrd,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Ord,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct ValueSubkeyRangeSet {
|
||||
#[with(RkyvRangeSetBlaze)]
|
||||
#[serde(with = "serialize_range_set_blaze")]
|
||||
data: RangeSetBlaze<ValueSubkey>,
|
||||
}
|
||||
|
||||
impl ValueSubkeyRangeSet {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
data: Default::default(),
|
||||
}
|
||||
}
|
||||
pub fn single(value: ValueSubkey) -> Self {
|
||||
let mut data = RangeSetBlaze::new();
|
||||
data.insert(value);
|
||||
Self { data }
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for ValueSubkeyRangeSet {
|
||||
type Target = RangeSetBlaze<ValueSubkey>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for ValueSubkeyRangeSet {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.data
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
use super::*;
|
||||
|
||||
/// FOURCC code
|
||||
#[derive(
|
||||
Copy,
|
||||
Default,
|
||||
Clone,
|
||||
Hash,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes, PartialOrd, Ord, PartialEq, Eq, Hash))]
|
||||
pub struct FourCC(pub [u8; 4]);
|
||||
|
||||
impl From<[u8; 4]> for FourCC {
|
||||
fn from(b: [u8; 4]) -> Self {
|
||||
Self(b)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for FourCC {
|
||||
fn from(u: u32) -> Self {
|
||||
Self(u.to_be_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FourCC> for u32 {
|
||||
fn from(u: FourCC) -> Self {
|
||||
u32::from_be_bytes(u.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for FourCC {
|
||||
type Error = VeilidAPIError;
|
||||
fn try_from(b: &[u8]) -> Result<Self, Self::Error> {
|
||||
Ok(Self(b.try_into().map_err(VeilidAPIError::generic)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for FourCC {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
write!(f, "{}", String::from_utf8_lossy(&self.0))
|
||||
}
|
||||
}
|
||||
impl fmt::Debug for FourCC {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
write!(f, "{}", String::from_utf8_lossy(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for FourCC {
|
||||
type Err = VeilidAPIError;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(Self(
|
||||
s.as_bytes().try_into().map_err(VeilidAPIError::generic)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
mod aligned_u64;
|
||||
mod app_message_call;
|
||||
mod dht;
|
||||
mod fourcc;
|
||||
mod safety;
|
||||
mod stats;
|
||||
mod tunnel;
|
||||
mod veilid_log;
|
||||
mod veilid_state;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub use aligned_u64::*;
|
||||
pub use app_message_call::*;
|
||||
pub use dht::*;
|
||||
pub use fourcc::*;
|
||||
pub use safety::*;
|
||||
pub use stats::*;
|
||||
pub use tunnel::*;
|
||||
pub use veilid_log::*;
|
||||
pub use veilid_state::*;
|
||||
@@ -0,0 +1,125 @@
|
||||
use super::*;
|
||||
|
||||
// Ordering here matters, >= is used to check strength of sequencing requirement
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Hash,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(u8), derive(CheckBytes))]
|
||||
pub enum Sequencing {
|
||||
NoPreference,
|
||||
PreferOrdered,
|
||||
EnsureOrdered,
|
||||
}
|
||||
|
||||
impl Default for Sequencing {
|
||||
fn default() -> Self {
|
||||
Self::NoPreference
|
||||
}
|
||||
}
|
||||
|
||||
// Ordering here matters, >= is used to check strength of stability requirement
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Hash,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(u8), derive(CheckBytes))]
|
||||
pub enum Stability {
|
||||
LowLatency,
|
||||
Reliable,
|
||||
}
|
||||
|
||||
impl Default for Stability {
|
||||
fn default() -> Self {
|
||||
Self::LowLatency
|
||||
}
|
||||
}
|
||||
|
||||
/// The choice of safety route to include in compiled routes
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Hash,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(u8), derive(CheckBytes))]
|
||||
pub enum SafetySelection {
|
||||
/// Don't use a safety route, only specify the sequencing preference
|
||||
Unsafe(Sequencing),
|
||||
/// Use a safety route and parameters specified by a SafetySpec
|
||||
Safe(SafetySpec),
|
||||
}
|
||||
|
||||
impl SafetySelection {
|
||||
pub fn get_sequencing(&self) -> Sequencing {
|
||||
match self {
|
||||
SafetySelection::Unsafe(seq) => *seq,
|
||||
SafetySelection::Safe(ss) => ss.sequencing,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SafetySelection {
|
||||
fn default() -> Self {
|
||||
Self::Unsafe(Sequencing::NoPreference)
|
||||
}
|
||||
}
|
||||
|
||||
/// Options for safety routes (sender privacy)
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Hash,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct SafetySpec {
|
||||
/// preferred safety route set id if it still exists
|
||||
pub preferred_route: Option<RouteId>,
|
||||
/// must be greater than 0
|
||||
pub hop_count: usize,
|
||||
/// prefer reliability over speed
|
||||
pub stability: Stability,
|
||||
/// prefer connection-oriented sequenced protocols
|
||||
pub sequencing: Sequencing,
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
use super::*;
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Default,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct LatencyStats {
|
||||
#[serde(with = "json_as_string")]
|
||||
pub fastest: TimestampDuration, // fastest latency in the ROLLING_LATENCIES_SIZE last latencies
|
||||
#[serde(with = "json_as_string")]
|
||||
pub average: TimestampDuration, // average latency over the ROLLING_LATENCIES_SIZE last latencies
|
||||
#[serde(with = "json_as_string")]
|
||||
pub slowest: TimestampDuration, // slowest latency in the ROLLING_LATENCIES_SIZE last latencies
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Default,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct TransferStats {
|
||||
#[serde(with = "json_as_string")]
|
||||
pub total: ByteCount, // total amount transferred ever
|
||||
#[serde(with = "json_as_string")]
|
||||
pub maximum: ByteCount, // maximum rate over the ROLLING_TRANSFERS_SIZE last amounts
|
||||
#[serde(with = "json_as_string")]
|
||||
pub average: ByteCount, // average rate over the ROLLING_TRANSFERS_SIZE last amounts
|
||||
#[serde(with = "json_as_string")]
|
||||
pub minimum: ByteCount, // minimum rate over the ROLLING_TRANSFERS_SIZE last amounts
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Default,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct TransferStatsDownUp {
|
||||
pub down: TransferStats,
|
||||
pub up: TransferStats,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Default,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct RPCStats {
|
||||
pub messages_sent: u32, // number of rpcs that have been sent in the total_time range
|
||||
pub messages_rcvd: u32, // number of rpcs that have been received in the total_time range
|
||||
pub questions_in_flight: u32, // number of questions issued that have yet to be answered
|
||||
#[serde(with = "opt_json_as_string")]
|
||||
pub last_question_ts: Option<Timestamp>, // when the peer was last questioned (either successfully or not) and we wanted an answer
|
||||
#[serde(with = "opt_json_as_string")]
|
||||
pub last_seen_ts: Option<Timestamp>, // when the peer was last seen for any reason, including when we first attempted to reach out to it
|
||||
#[serde(with = "opt_json_as_string")]
|
||||
pub first_consecutive_seen_ts: Option<Timestamp>, // the timestamp of the first consecutive proof-of-life for this node (an answer or received question)
|
||||
pub recent_lost_answers: u32, // number of answers that have been lost since we lost reliability
|
||||
pub failed_to_send: u32, // number of messages that have failed to send since we last successfully sent one
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Default,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct PeerStats {
|
||||
#[serde(with = "json_as_string")]
|
||||
pub time_added: Timestamp, // when the peer was added to the routing table
|
||||
pub rpc_stats: RPCStats, // information about RPCs
|
||||
pub latency: Option<LatencyStats>, // latencies for communications with the peer
|
||||
pub transfer: TransferStatsDownUp, // Stats for communications with the peer
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
use super::*;
|
||||
|
||||
/// Tunnel identifier
|
||||
pub type TunnelId = AlignedU64;
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
PartialOrd,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Ord,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(u8), derive(CheckBytes))]
|
||||
pub enum TunnelMode {
|
||||
Raw,
|
||||
Turn,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
PartialOrd,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Ord,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(u8), derive(CheckBytes))]
|
||||
pub enum TunnelError {
|
||||
BadId, // Tunnel ID was rejected
|
||||
NoEndpoint, // Endpoint was unreachable
|
||||
RejectedMode, // Endpoint couldn't provide mode
|
||||
NoCapacity, // Endpoint is full
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct TunnelEndpoint {
|
||||
pub mode: TunnelMode,
|
||||
pub description: String, // XXX: TODO
|
||||
}
|
||||
|
||||
impl Default for TunnelEndpoint {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
mode: TunnelMode::Raw,
|
||||
description: "".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone, Debug, Default, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct FullTunnel {
|
||||
pub id: TunnelId,
|
||||
pub timeout: TimestampDuration,
|
||||
pub local: TunnelEndpoint,
|
||||
pub remote: TunnelEndpoint,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone, Debug, Default, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct PartialTunnel {
|
||||
pub id: TunnelId,
|
||||
pub timeout: TimestampDuration,
|
||||
pub local: TunnelEndpoint,
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
use super::*;
|
||||
|
||||
/// Log level for VeilidCore
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Copy,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(u8), derive(CheckBytes))]
|
||||
pub enum VeilidLogLevel {
|
||||
Error = 1,
|
||||
Warn,
|
||||
Info,
|
||||
Debug,
|
||||
Trace,
|
||||
}
|
||||
|
||||
impl VeilidLogLevel {
|
||||
pub fn from_tracing_level(level: tracing::Level) -> VeilidLogLevel {
|
||||
match level {
|
||||
tracing::Level::ERROR => VeilidLogLevel::Error,
|
||||
tracing::Level::WARN => VeilidLogLevel::Warn,
|
||||
tracing::Level::INFO => VeilidLogLevel::Info,
|
||||
tracing::Level::DEBUG => VeilidLogLevel::Debug,
|
||||
tracing::Level::TRACE => VeilidLogLevel::Trace,
|
||||
}
|
||||
}
|
||||
pub fn from_log_level(level: log::Level) -> VeilidLogLevel {
|
||||
match level {
|
||||
log::Level::Error => VeilidLogLevel::Error,
|
||||
log::Level::Warn => VeilidLogLevel::Warn,
|
||||
log::Level::Info => VeilidLogLevel::Info,
|
||||
log::Level::Debug => VeilidLogLevel::Debug,
|
||||
log::Level::Trace => VeilidLogLevel::Trace,
|
||||
}
|
||||
}
|
||||
pub fn to_tracing_level(&self) -> tracing::Level {
|
||||
match self {
|
||||
Self::Error => tracing::Level::ERROR,
|
||||
Self::Warn => tracing::Level::WARN,
|
||||
Self::Info => tracing::Level::INFO,
|
||||
Self::Debug => tracing::Level::DEBUG,
|
||||
Self::Trace => tracing::Level::TRACE,
|
||||
}
|
||||
}
|
||||
pub fn to_log_level(&self) -> log::Level {
|
||||
match self {
|
||||
Self::Error => log::Level::Error,
|
||||
Self::Warn => log::Level::Warn,
|
||||
Self::Info => log::Level::Info,
|
||||
Self::Debug => log::Level::Debug,
|
||||
Self::Trace => log::Level::Trace,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for VeilidLogLevel {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
let text = match self {
|
||||
Self::Error => "ERROR",
|
||||
Self::Warn => "WARN",
|
||||
Self::Info => "INFO",
|
||||
Self::Debug => "DEBUG",
|
||||
Self::Trace => "TRACE",
|
||||
};
|
||||
write!(f, "{}", text)
|
||||
}
|
||||
}
|
||||
|
||||
/// A VeilidCore log message with optional backtrace
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct VeilidLog {
|
||||
pub log_level: VeilidLogLevel,
|
||||
pub message: String,
|
||||
pub backtrace: Option<String>,
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
use super::*;
|
||||
|
||||
/// Attachment abstraction for network 'signal strength'
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Clone,
|
||||
Copy,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
RkyvArchive,
|
||||
RkyvSerialize,
|
||||
RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(u8), derive(CheckBytes))]
|
||||
pub enum AttachmentState {
|
||||
Detached,
|
||||
Attaching,
|
||||
AttachedWeak,
|
||||
AttachedGood,
|
||||
AttachedStrong,
|
||||
FullyAttached,
|
||||
OverAttached,
|
||||
Detaching,
|
||||
}
|
||||
|
||||
impl fmt::Display for AttachmentState {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
let out = match self {
|
||||
AttachmentState::Attaching => "attaching".to_owned(),
|
||||
AttachmentState::AttachedWeak => "attached_weak".to_owned(),
|
||||
AttachmentState::AttachedGood => "attached_good".to_owned(),
|
||||
AttachmentState::AttachedStrong => "attached_strong".to_owned(),
|
||||
AttachmentState::FullyAttached => "fully_attached".to_owned(),
|
||||
AttachmentState::OverAttached => "over_attached".to_owned(),
|
||||
AttachmentState::Detaching => "detaching".to_owned(),
|
||||
AttachmentState::Detached => "detached".to_owned(),
|
||||
};
|
||||
write!(f, "{}", out)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for AttachmentState {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
Ok(match s.as_str() {
|
||||
"attaching" => AttachmentState::Attaching,
|
||||
"attached_weak" => AttachmentState::AttachedWeak,
|
||||
"attached_good" => AttachmentState::AttachedGood,
|
||||
"attached_strong" => AttachmentState::AttachedStrong,
|
||||
"fully_attached" => AttachmentState::FullyAttached,
|
||||
"over_attached" => AttachmentState::OverAttached,
|
||||
"detaching" => AttachmentState::Detaching,
|
||||
"detached" => AttachmentState::Detached,
|
||||
_ => return Err(()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct VeilidStateAttachment {
|
||||
pub state: AttachmentState,
|
||||
pub public_internet_ready: bool,
|
||||
pub local_network_ready: bool,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct PeerTableData {
|
||||
pub node_ids: Vec<TypedKey>,
|
||||
pub peer_address: String,
|
||||
pub peer_stats: PeerStats,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct VeilidStateNetwork {
|
||||
pub started: bool,
|
||||
#[serde(with = "json_as_string")]
|
||||
pub bps_down: ByteCount,
|
||||
#[serde(with = "json_as_string")]
|
||||
pub bps_up: ByteCount,
|
||||
pub peers: Vec<PeerTableData>,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct VeilidRouteChange {
|
||||
pub dead_routes: Vec<RouteId>,
|
||||
pub dead_remote_routes: Vec<RouteId>,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct VeilidStateConfig {
|
||||
pub config: VeilidConfigInner,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
|
||||
)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct VeilidValueChange {
|
||||
key: TypedKey,
|
||||
subkeys: Vec<ValueSubkey>,
|
||||
count: u32,
|
||||
value: ValueData,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
|
||||
#[archive_attr(repr(u8), derive(CheckBytes))]
|
||||
#[serde(tag = "kind")]
|
||||
pub enum VeilidUpdate {
|
||||
Log(VeilidLog),
|
||||
AppMessage(VeilidAppMessage),
|
||||
AppCall(VeilidAppCall),
|
||||
Attachment(VeilidStateAttachment),
|
||||
Network(VeilidStateNetwork),
|
||||
Config(VeilidStateConfig),
|
||||
RouteChange(VeilidRouteChange),
|
||||
ValueChange(VeilidValueChange),
|
||||
Shutdown,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
|
||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||
pub struct VeilidState {
|
||||
pub attachment: VeilidStateAttachment,
|
||||
pub network: VeilidStateNetwork,
|
||||
pub config: VeilidStateConfig,
|
||||
}
|
||||
Reference in New Issue
Block a user