From 1fba8831e8f1ce41c58ca4788c95ad086bbcaec6 Mon Sep 17 00:00:00 2001 From: John Smith Date: Sat, 25 Feb 2023 22:02:13 -0500 Subject: [PATCH] more refactor --- veilid-core/proto/veilid.capnp | 10 +- veilid-core/src/routing_table/debug.rs | 10 +- .../src/routing_table/route_spec_store/mod.rs | 1 - .../route_spec_store/route_spec_store.rs | 73 +++++++++---- veilid-core/src/rpc_processor/destination.rs | 9 +- veilid-core/src/veilid_api/api.rs | 42 +++----- veilid-core/src/veilid_api/debug.rs | 101 +++++++++++------- veilid-core/src/veilid_api/error.rs | 20 ++-- veilid-core/src/veilid_api/routing_context.rs | 38 ++++--- veilid-core/src/veilid_api/types.rs | 26 +++-- 10 files changed, 203 insertions(+), 127 deletions(-) diff --git a/veilid-core/proto/veilid.capnp b/veilid-core/proto/veilid.capnp index bb727a7d..2dc3d2a0 100644 --- a/veilid-core/proto/veilid.capnp +++ b/veilid-core/proto/veilid.capnp @@ -324,7 +324,7 @@ struct ValueData @0xb4b7416f169f2a3d { } struct OperationGetValueQ @0xf88a5b6da5eda5d0 { - publicKey @0 :TypedKey; # the location of the value + key @0 :TypedKey; # the location of the value subkey @1 :Subkey; # the index of the subkey (0 for the default subkey) } @@ -336,7 +336,7 @@ struct OperationGetValueA @0xd896bb46f2e0249f { } struct OperationSetValueQ @0xbac06191ff8bdbc5 { - publicKey @0 :TypedKey; # the location of the value + key @0 :TypedKey; # the location of the value subkey @1 :Subkey; # the index of the subkey (0 for the default subkey) value @2 :ValueData; # value or subvalue contents (older or equal seq number gets dropped) } @@ -349,10 +349,10 @@ struct OperationSetValueA @0x9378d0732dc95be2 { } struct OperationWatchValueQ @0xf9a5a6c547b9b228 { - publicKey @0 :TypedKey; # key for value to watch + key @0 :TypedKey; # key for value to watch subkeys @1 :List(SubkeyRange); # subkey range to watch, if empty, watch everything expiration @2 :UInt64; # requested timestamp when this watch will expire in usec since epoch (can be return less, 0 for max) - count @3 :UInt32; # requested number of changes to watch for (0 = continuous, 1 = single shot, 2+ = counter) + count @3 :UInt32; # requested number of changes to watch for (0 = cancel, 1 = single shot, 2+ = counter, UINT32_MAX = continuous) } struct OperationWatchValueA @0xa726cab7064ba893 { @@ -361,7 +361,7 @@ struct OperationWatchValueA @0xa726cab7064ba893 { } struct OperationValueChanged @0xd1c59ebdd8cc1bf6 { - publicKey @0 :TypedKey; # key for value that changed + key @0 :TypedKey; # key for value that changed subkeys @1 :List(SubkeyRange); # subkey range that changed (up to 512 ranges at a time) count @2 :UInt32; # remaining changes left (0 means watch has expired) value @3 :ValueData; # first value that changed (the rest can be gotten with getvalue) diff --git a/veilid-core/src/routing_table/debug.rs b/veilid-core/src/routing_table/debug.rs index 355ede7e..a3409bb3 100644 --- a/veilid-core/src/routing_table/debug.rs +++ b/veilid-core/src/routing_table/debug.rs @@ -159,15 +159,9 @@ impl RoutingTable { out } - pub(crate) fn debug_info_entry(&self, node_id: TypedKey) -> String { + pub(crate) fn debug_info_entry(&self, node_ref: NodeRef) -> String { let mut out = String::new(); - out += &format!("Entry {:?}:\n", node_id); - if let Some(nr) = self.lookup_node_ref(node_id) { - out += &nr.operate(|_rt, e| format!("{:#?}\n", e)); - } else { - out += "Entry not found\n"; - } - + out += &node_ref.operate(|_rt, e| format!("{:#?}\n", e)); out } diff --git a/veilid-core/src/routing_table/route_spec_store/mod.rs b/veilid-core/src/routing_table/route_spec_store/mod.rs index 545fdaee..302b2b6f 100644 --- a/veilid-core/src/routing_table/route_spec_store/mod.rs +++ b/veilid-core/src/routing_table/route_spec_store/mod.rs @@ -8,7 +8,6 @@ mod route_spec_store_cache; mod route_spec_store_content; mod route_stats; -pub use permutation::*; pub use remote_private_route_info::*; pub use route_set_spec_detail::*; pub use route_spec_store::*; diff --git a/veilid-core/src/routing_table/route_spec_store/route_spec_store.rs b/veilid-core/src/routing_table/route_spec_store/route_spec_store.rs index 62adaf85..8033b36a 100644 --- a/veilid-core/src/routing_table/route_spec_store/route_spec_store.rs +++ b/veilid-core/src/routing_table/route_spec_store/route_spec_store.rs @@ -1134,32 +1134,17 @@ impl RouteSpecStore { )?) } - /// Assemble private route for publication - /// Returns a PrivateRoute object for an allocated private route - #[instrument(level = "trace", skip(self), err)] - pub fn assemble_private_route( - &self, - key: &PublicKey, - optimized: Option, - ) -> EyreResult { - let inner = &*self.inner.lock(); + fn assemble_private_route_inner(&self, inner: &RouteSpecStoreInner, key: &PublicKey, rsd: &RouteSpecDetail, optimized: bool) -> EyreResult + { let routing_table = self.unlocked_inner.routing_table.clone(); let rti = &*routing_table.inner.read(); - // Get the route spec detail for the requested private route - let rsd = Self::detail(inner, key).ok_or_else(|| eyre!("route does not exist"))?; - // Ensure we get the crypto for it let crypto = routing_table.network_manager().crypto(); let Some(vcrypto) = crypto.get(rsd.crypto_kind) else { bail!("crypto not supported for route"); }; - // See if we can optimize this compilation yet - // We don't want to include full nodeinfo if we don't have to - let optimized = optimized - .unwrap_or(rsd.stats.last_tested_ts.is_some() || rsd.stats.last_received_ts.is_some()); - // Make innermost route hop to our own node let mut route_hop = RouteHop { node: if optimized { @@ -1234,6 +1219,58 @@ impl RouteSpecStore { }; Ok(private_route) } + + /// Assemble a single private route for publication + /// Returns a PrivateRoute object for an allocated private route key + #[instrument(level = "trace", skip(self), err)] + pub fn assemble_private_route( + &self, + key: &PublicKey, + optimized: Option, + ) -> EyreResult { + let inner = &*self.inner.lock(); + let Some(rsid) = inner.content.get_id_by_key(key) else { + bail!("route key does not exist"); + }; + let Some(rssd) = inner.content.get_detail(&rsid) else { + bail!("route id does not exist"); + }; + + // See if we can optimize this compilation yet + // We don't want to include full nodeinfo if we don't have to + let optimized = optimized + .unwrap_or(rssd.get_stats().last_tested_ts.is_some() || rssd.get_stats().last_received_ts.is_some()); + + let rsd = rssd.get_route_by_key(key).expect("route key index is broken"); + + self.assemble_private_route_inner(inner, key, rsd, optimized) + } + + + /// Assemble private route set for publication + /// Returns a vec of PrivateRoute objects for an allocated private route + #[instrument(level = "trace", skip(self), err)] + pub fn assemble_private_routes( + &self, + id: &RouteId, + optimized: Option, + ) -> EyreResult> { + let inner = &*self.inner.lock(); + let Some(rssd) = inner.content.get_detail(id) else { + bail!("route id does not exist"); + }; + + // See if we can optimize this compilation yet + // We don't want to include full nodeinfo if we don't have to + let optimized = optimized + .unwrap_or(rssd.get_stats().last_tested_ts.is_some() || rssd.get_stats().last_received_ts.is_some()); + + let mut out = Vec::new(); + for (key, rsd) in rssd.iter_route_set() { + out.push(self.assemble_private_route_inner(inner, key, rsd, optimized)?); + } + Ok(out) + } /// Import a remote private route for compilation /// It is safe to import the same route more than once and it will return the same route id @@ -1407,7 +1444,7 @@ impl RouteSpecStore { /// Mark route as published /// When first deserialized, routes must be re-published in order to ensure they remain /// in the RouteSpecStore. - pub fn mark_route_published(&self, id: &String, published: bool) -> EyreResult<()> { + pub fn mark_route_published(&self, id: &RouteId, published: bool) -> EyreResult<()> { let inner = &mut *self.inner.lock(); let Some(rssd) = inner.content.get_detail_mut(id) else { bail!("route does not exist"); diff --git a/veilid-core/src/rpc_processor/destination.rs b/veilid-core/src/rpc_processor/destination.rs index 5321b17d..9c6bdbc0 100644 --- a/veilid-core/src/rpc_processor/destination.rs +++ b/veilid-core/src/rpc_processor/destination.rs @@ -162,6 +162,9 @@ impl RPCProcessor { } SafetySelection::Safe(safety_spec) => { // Sent directly but with a safety route, respond to private route + +xxx continue here. ensure crypto kind makes sense with get_private_route_for_safety_spec and then make it work. + let ck = target.best_node_id().kind; let Some(pr_key) = rss .get_private_route_for_safety_spec(ck, safety_spec, &target.node_ids()) @@ -222,7 +225,7 @@ impl RPCProcessor { // Determine if we can use optimized nodeinfo let route_node = match rss - .has_remote_private_route_seen_our_node_info(&private_route.public_key.key) + .has_remote_private_route_seen_our_node_info(&private_route_id) { true => { if !routing_table.has_valid_own_node_info(RoutingDomain::PublicInternet) { @@ -247,10 +250,10 @@ impl RPCProcessor { // Sent to a private route via a safety route, respond to private route // Check for loopback test - let pr_key = if safety_spec.preferred_route - == Some(private_route.public_key.key) + let pr_key = if safety_spec.preferred_route == Some(private_route_id) { // Private route is also safety route during loopback test + xxx build loopback routine? get_private_route_for_loopback_test? private_route.public_key.key } else { // Get the private route to respond to that matches the safety route spec we sent the request with diff --git a/veilid-core/src/veilid_api/api.rs b/veilid-core/src/veilid_api/api.rs index 5719a0c8..ec50636e 100644 --- a/veilid-core/src/veilid_api/api.rs +++ b/veilid-core/src/veilid_api/api.rs @@ -165,10 +165,10 @@ impl VeilidAPI { // Private route allocation /// Allocate a new private route set with default cryptography and network options - /// Returns a set of keys and a publishable 'blob' with the route encrypted with each crypto kind + /// 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<(TypedKeySet, Vec), VeilidAPIError> { + pub async fn new_private_route(&self) -> Result<(RouteId, Vec), VeilidAPIError> { self.new_custom_private_route( &VALID_CRYPTO_KINDS, Stability::default(), @@ -184,7 +184,7 @@ impl VeilidAPI { crypto_kinds: &[CryptoKind], stability: Stability, sequencing: Sequencing, - ) -> Result<(TypedKeySet, Vec), VeilidAPIError> { + ) -> Result<(RouteId, Vec), VeilidAPIError> { let default_route_hop_count: usize = { let config = self.config()?; let c = config.get(); @@ -202,56 +202,48 @@ impl VeilidAPI { &[], ) .map_err(VeilidAPIError::internal)?; - let Some(pr_keys) = r else { + let Some(route_id) = r else { apibail_generic!("unable to allocate route"); }; if !rss - .test_route(&pr_keys) + .test_route(route_id.clone()) .await .map_err(VeilidAPIError::no_connection)? { - rss.release_route(&pr_pubkey); + rss.release_route(route_id); apibail_generic!("allocated route failed to test"); } - let private_route = rss - .assemble_private_route(&pr_pubkey, Some(true)) + let private_routes = rss + .assemble_private_routes(&route_id, Some(true)) .map_err(VeilidAPIError::generic)?; - let blob = match RouteSpecStore::private_route_to_blob(&private_route) { + let blob = match RouteSpecStore::private_routes_to_blob(&private_routes) { Ok(v) => v, Err(e) => { - rss.release_route(&pr_pubkey); + rss.release_route(route_id); apibail_internal!(e); } }; - rss.mark_route_published(&pr_pubkey, true) + rss.mark_route_published(&route_id, true) .map_err(VeilidAPIError::internal)?; - Ok((pr_pubkey, blob)) + Ok((route_id, blob)) } #[instrument(level = "debug", skip(self))] - pub fn import_remote_private_route( - &self, - blob: Vec, - ) -> Result { + pub fn import_remote_private_route(&self, blob: Vec) -> Result { 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, key: &PublicKey) -> Result<(), VeilidAPIError> { + pub fn release_private_route(&self, route_id: RouteId) -> Result<(), VeilidAPIError> { let rss = self.routing_table()?.route_spec_store(); - if rss.release_route(key) { - Ok(()) - } else { - Err(VeilidAPIError::invalid_argument( - "release_private_route", - "key", - key, - )) + if !rss.release_route(route_id) { + apibail_invalid_argument!("release_private_route", "key", route_id); } + Ok(()) } //////////////////////////////////////////////////////////////// diff --git a/veilid-core/src/veilid_api/debug.rs b/veilid-core/src/veilid_api/debug.rs index 36b6018e..0229f7f0 100644 --- a/veilid-core/src/veilid_api/debug.rs +++ b/veilid-core/src/veilid_api/debug.rs @@ -7,7 +7,7 @@ use routing_table::*; #[derive(Default, Debug)] struct DebugCache { - imported_routes: Vec, + imported_routes: Vec, } static DEBUG_CACHE: Mutex = Mutex::new(DebugCache { @@ -30,12 +30,12 @@ fn get_string(text: &str) -> Option { Some(text.to_owned()) } -fn get_route_id(rss: RouteSpecStore) -> impl Fn(&str) -> Option { +fn get_route_id(rss: RouteSpecStore) -> impl Fn(&str) -> Option { return move |text: &str| { if text.is_empty() { return None; } - match PublicKey::from_str(text).ok() { + match RouteId::from_str(text).ok() { Some(key) => { let routes = rss.list_allocated_routes(|k, _| Some(*k)); if routes.contains(&key) { @@ -128,38 +128,20 @@ fn get_destination(routing_table: RoutingTable) -> impl FnOnce(&str) -> Option 5 { - let fcc = &text[0..4]; - if &text[4..5] != ":" { - return None; - } - let ck = match FourCC::from_str(fcc) { - Ok(v) => v, - Err(_) => { - return None; - } - }; - text = &text[5..]; - Some(ck) - } else { - None - }; + let text = &text[1..]; let n = get_number(text)?; let mut dc = DEBUG_CACHE.lock(); - let pr_pubkey = match opt_crypto_kind { - Some(ck) => dc.imported_routes.get(n)?.get(ck)?, - None => dc.imported_routes.get(n)?.best()?, - }; + let private_route_id = dc.imported_routes.get(n)?.clone(); + let rss = routing_table.route_spec_store(); - let Some(private_route) = rss.get_remote_private_route(&pr_pubkey.key) else { + if !rss.is_valid_remote_private_route(&private_route_id) { // Remove imported route dc.imported_routes.remove(n); info!("removed dead imported route {}", n); return None; }; Some(Destination::private_route( - private_route, + private_route_id, ss.unwrap_or(SafetySelection::Unsafe(Sequencing::default())), )) } else { @@ -381,12 +363,19 @@ impl VeilidAPI { async fn debug_entry(&self, args: String) -> Result { let args: Vec = args.split_whitespace().map(|s| s.to_owned()).collect(); + let routing_table = self.network_manager()?.routing_table(); - let node_id = get_debug_argument_at(&args, 0, "debug_entry", "node_id", get_typed_key)?; + let node_ref = get_debug_argument_at( + &args, + 0, + "debug_entry", + "node_id", + get_node_ref(routing_table), + )?; // Dump routing table entry let routing_table = self.network_manager()?.routing_table(); - Ok(routing_table.debug_info_entry(node_id)) + Ok(routing_table.debug_info_entry(node_ref)) } async fn debug_nodeinfo(&self, _args: String) -> Result { @@ -655,10 +644,16 @@ impl VeilidAPI { let routing_table = netman.routing_table(); let rss = routing_table.route_spec_store(); - let route_id = get_debug_argument_at(&args, 1, "debug_route", "route_id", get_typed_key)?; + let route_id = get_debug_argument_at( + &args, + 1, + "debug_route", + "route_id", + get_route_id(rss.clone()), + )?; // Release route - let out = match rss.release_route(&route_id) { + let out = match rss.release_route(route_id) { true => "Released".to_owned(), false => "Route does not exist".to_owned(), }; @@ -671,7 +666,13 @@ impl VeilidAPI { let routing_table = netman.routing_table(); let rss = routing_table.route_spec_store(); - let route_id = get_debug_argument_at(&args, 1, "debug_route", "route_id", get_typed_key)?; + let route_id = get_debug_argument_at( + &args, + 1, + "debug_route", + "route_id", + get_route_id(rss.clone()), + )?; let full = { if args.len() > 2 { let full_val = get_debug_argument_at(&args, 2, "debug_route", "full", get_string)? @@ -687,13 +688,13 @@ impl VeilidAPI { }; // Publish route - let out = match rss.assemble_private_route(&route_id, Some(!full)) { - Ok(private_route) => { + let out = match rss.assemble_private_routes(&route_id, Some(!full)) { + Ok(private_routes) => { if let Err(e) = rss.mark_route_published(&route_id, true) { return Ok(format!("Couldn't mark route published: {}", e)); } // Convert to blob - let blob_data = RouteSpecStore::private_route_to_blob(&private_route) + let blob_data = RouteSpecStore::private_routes_to_blob(&private_routes) .map_err(VeilidAPIError::internal)?; let out = BASE64URL_NOPAD.encode(&blob_data); info!( @@ -717,7 +718,13 @@ impl VeilidAPI { let routing_table = netman.routing_table(); let rss = routing_table.route_spec_store(); - let route_id = get_debug_argument_at(&args, 1, "debug_route", "route_id", get_public_key)?; + let route_id = get_debug_argument_at( + &args, + 1, + "debug_route", + "route_id", + get_route_id(rss.clone()), + )?; // Unpublish route let out = if let Err(e) = rss.mark_route_published(&route_id, false) { @@ -733,7 +740,13 @@ impl VeilidAPI { let routing_table = netman.routing_table(); let rss = routing_table.route_spec_store(); - let route_id = get_debug_argument_at(&args, 1, "debug_route", "route_id", get_public_key)?; + let route_id = get_debug_argument_at( + &args, + 1, + "debug_route", + "route_id", + get_route_id(rss.clone()), + )?; match rss.debug_route(&route_id) { Some(s) => Ok(s), @@ -771,14 +784,14 @@ impl VeilidAPI { .decode(blob.as_bytes()) .map_err(VeilidAPIError::generic)?; let rss = self.routing_table()?.route_spec_store(); - let pr_pubkey = rss + let route_id = rss .import_remote_private_route(blob_dec) .map_err(VeilidAPIError::generic)?; let mut dc = DEBUG_CACHE.lock(); let n = dc.imported_routes.len(); - let out = format!("Private route #{} imported: {}", n, pr_pubkey); - dc.imported_routes.push(pr_pubkey); + let out = format!("Private route #{} imported: {}", n, route_id); + dc.imported_routes.push(route_id); return Ok(out); } @@ -789,10 +802,16 @@ impl VeilidAPI { let routing_table = netman.routing_table(); let rss = routing_table.route_spec_store(); - let route_id = get_debug_argument_at(&args, 1, "debug_route", "route_id", get_typed_key)?; + let route_id = get_debug_argument_at( + &args, + 1, + "debug_route", + "route_id", + get_route_id(rss.clone()), + )?; let success = rss - .test_route(&route_id) + .test_route(route_id) .await .map_err(VeilidAPIError::internal)?; diff --git a/veilid-core/src/veilid_api/error.rs b/veilid-core/src/veilid_api/error.rs index d7b57e5c..7e04b947 100644 --- a/veilid-core/src/veilid_api/error.rs +++ b/veilid-core/src/veilid_api/error.rs @@ -66,9 +66,17 @@ macro_rules! apibail_no_connection { #[allow(unused_macros)] #[macro_export] -macro_rules! apibail_key_not_found { +macro_rules! apibail_invalid_target { + () => { + return Err(VeilidAPIError::invalid_target()) + }; +} + +#[allow(unused_macros)] +#[macro_export] +macro_rules! apibail_route_not_found { ($x:expr) => { - return Err(VeilidAPIError::key_not_found($x)) + return Err(VeilidAPIError::route_not_found($x)) }; } @@ -107,8 +115,8 @@ pub enum VeilidAPIError { TryAgain, #[error("Shutdown")] Shutdown, - #[error("Key not found: {key}")] - KeyNotFound { key: PublicKey }, + #[error("Invalid target")] + InvalidTarget, #[error("No connection: {message}")] NoConnection { message: String }, #[error("No peer info: {node_id}")] @@ -147,8 +155,8 @@ impl VeilidAPIError { pub fn shutdown() -> Self { Self::Shutdown } - pub fn key_not_found(key: PublicKey) -> Self { - Self::KeyNotFound { key } + pub fn invalid_target() -> Self { + Self::InvalidTarget } pub fn no_connection(msg: T) -> Self { Self::NoConnection { diff --git a/veilid-core/src/veilid_api/routing_context.rs b/veilid-core/src/veilid_api/routing_context.rs index 66a03f44..f1a8affe 100644 --- a/veilid-core/src/veilid_api/routing_context.rs +++ b/veilid-core/src/veilid_api/routing_context.rs @@ -4,8 +4,8 @@ use super::*; #[derive(Clone, Debug)] pub enum Target { - NodeId(PublicKey), // Node by any of its public keys - PrivateRoute(RouteId), // Remote private route by its id + NodeId(PublicKey), // Node by any of its public keys + PrivateRoute(RouteId), // Remote private route by its id } pub struct RoutingContextInner {} @@ -66,7 +66,7 @@ impl RoutingContext { }), }) } - + pub fn with_sequencing(self, sequencing: Sequencing) -> Self { Self { api: self.api.clone(), @@ -107,7 +107,7 @@ impl RoutingContext { // Resolve node let mut nr = match rpc_processor.resolve_node(node_id).await { Ok(Some(nr)) => nr, - Ok(None) => apibail_key_not_found!(node_id), + Ok(None) => apibail_invalid_target!(), Err(e) => return Err(e.into()), }; // Apply sequencing to match safety selection @@ -121,10 +121,9 @@ impl RoutingContext { Target::PrivateRoute(rsid) => { // Get remote private route let rss = self.api.routing_table()?.route_spec_store(); - if !rss.is_valid_remote_private_route(&rsid) - else { - apibail_key_not_found!(pr); - }; + if !rss.is_valid_remote_private_route(&rsid) { + apibail_invalid_target!(); + }; Ok(rpc_processor::Destination::PrivateRoute { private_route_id: rsid, @@ -197,27 +196,38 @@ impl RoutingContext { /////////////////////////////////// /// DHT Values - pub async fn get_value(&self, _value_key: ValueKey) -> Result, VeilidAPIError> { + pub async fn get_value( + &self, + _key: TypedKey, + _subkey: ValueSubkey, + ) -> Result { panic!("unimplemented"); } pub async fn set_value( &self, - _value_key: ValueKey, - _value: Vec, + _key: TypedKey, + _subkey: ValueSubkey, + _value: ValueData, ) -> Result { panic!("unimplemented"); } pub async fn watch_value( &self, - _value_key: ValueKey, - _callback: ValueChangeCallback, + _key: TypedKey, + _subkeys: &[ValueSubkeyRange], + _expiration: Timestamp, + _count: u32, ) -> Result { panic!("unimplemented"); } - pub async fn cancel_watch_value(&self, _value_key: ValueKey) -> Result { + pub async fn cancel_watch_value( + &self, + _key: TypedKey, + _subkeys: &[ValueSubkeyRange], + ) -> Result { panic!("unimplemented"); } diff --git a/veilid-core/src/veilid_api/types.rs b/veilid-core/src/veilid_api/types.rs index c10d217e..5bae479c 100644 --- a/veilid-core/src/veilid_api/types.rs +++ b/veilid-core/src/veilid_api/types.rs @@ -17,6 +17,12 @@ pub type ByteCount = AlignedU64; pub type TunnelId = AlignedU64; /// Value schema pub type ValueSchema = FourCC; +/// Value subkey +pub type ValueSubkey = u32; +/// Value subkey range +pub type ValueSubkeyRange = (u32, u32); +/// Value sequence number +pub type ValueSeqNum = u32; /// FOURCC code #[derive( @@ -291,6 +297,17 @@ 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, + count: u32, + value: ValueData, +} + #[derive(Debug, Clone, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)] #[archive_attr(repr(u8), derive(CheckBytes))] #[serde(tag = "kind")] @@ -302,6 +319,7 @@ pub enum VeilidUpdate { Network(VeilidStateNetwork), Config(VeilidStateConfig), Route(VeilidStateRoute), + ValueChange(VeilidValueChange), Shutdown, } @@ -332,7 +350,7 @@ pub struct VeilidState { )] #[archive_attr(repr(C), derive(CheckBytes))] pub struct ValueData { - pub seq: u32, + pub seq: ValueSeqNum, pub schema: ValueSchema, pub data: Vec, } @@ -344,7 +362,7 @@ impl ValueData { data, } } - pub fn new_with_seq(seq: u32, schema: ValueSchema, data: Vec) -> Self { + pub fn new_with_seq(seq: ValueSeqNum, schema: ValueSchema, data: Vec) -> Self { Self { seq, schema, data } } pub fn change(&mut self, data: Vec) { @@ -2378,10 +2396,6 @@ pub struct PeerStats { pub transfer: TransferStatsDownUp, // Stats for communications with the peer } -pub type ValueChangeCallback = Arc< - dyn Fn(TypedKey, Vec<(u32, u32)>, u32, Vec) -> SendPinBoxFuture<()> + Send + Sync + 'static, ->; - ///////////////////////////////////////////////////////////////////////////////////////////////////// #[derive(Clone, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)]