This commit is contained in:
John Smith
2022-11-16 12:49:53 -05:00
parent 28c31fe424
commit 688995ed0d
17 changed files with 534 additions and 122 deletions

View File

@@ -177,7 +177,7 @@ impl VeilidCoreContext {
// Set up config from callback
trace!("setup config with callback");
let mut config = VeilidConfig::new();
config.setup(config_callback)?;
config.setup(config_callback, update_callback.clone())?;
Self::new_common(update_callback, config).await
}
@@ -190,7 +190,7 @@ impl VeilidCoreContext {
// Set up config from callback
trace!("setup config with json");
let mut config = VeilidConfig::new();
config.setup_from_json(config_json)?;
config.setup_from_json(config_json, update_callback.clone())?;
Self::new_common(update_callback, config).await
}

View File

@@ -271,6 +271,34 @@ impl RPCProcessor {
)
}
}
#[instrument(level = "trace", skip_all, err)]
pub(crate) async fn process_private_route_first_hop(
&self,
operation: RoutedOperation,
sr_pubkey: DHTKey,
private_route: &PrivateRoute,
) -> Result<(), RPCError> {
let PrivateRouteHops::FirstHop(pr_first_hop) = &private_route.hops else {
return Err(RPCError::protocol("switching from safety route to private route requires first hop"));
};
// Switching to private route from safety route
self.process_route_private_route_hop(
operation,
pr_first_hop.node.clone(),
sr_pubkey,
PrivateRoute {
public_key: private_route.public_key,
hop_count: private_route.hop_count - 1,
hops: pr_first_hop
.next_hop
.clone()
.map(|rhd| PrivateRouteHops::Data(rhd))
.unwrap_or(PrivateRouteHops::Empty),
},
)
.await
}
#[instrument(level = "trace", skip(self, msg), err)]
pub(crate) async fn process_route(&self, msg: RPCMessage) -> Result<(), RPCError> {
@@ -332,24 +360,11 @@ impl RPCProcessor {
decode_private_route(&pr_reader)?
};
// Get the next hop node ref
let PrivateRouteHops::FirstHop(pr_first_hop) = private_route.hops else {
return Err(RPCError::protocol("switching from safety route to private route requires first hop"));
};
// Switching to private route from safety route
self.process_route_private_route_hop(
// Switching from full safety route to private route first hop
self.process_private_route_first_hop(
route.operation,
pr_first_hop.node,
route.safety_route.public_key,
PrivateRoute {
public_key: private_route.public_key,
hop_count: private_route.hop_count - 1,
hops: pr_first_hop
.next_hop
.map(|rhd| PrivateRouteHops::Data(rhd))
.unwrap_or(PrivateRouteHops::Empty),
},
&private_route,
)
.await?;
} else if blob_tag == 0 {
@@ -361,6 +376,7 @@ impl RPCProcessor {
decode_route_hop(&rh_reader)?
};
// Continue the full safety route with another hop
self.process_route_safety_route_hop(route, route_hop)
.await?;
} else {
@@ -372,7 +388,13 @@ impl RPCProcessor {
// See if we have a hop, if not, we are at the end of the private route
match &private_route.hops {
PrivateRouteHops::FirstHop(_) => {
return Err(RPCError::protocol("should not have first hop here"));
// Safety route was a stub, start with the beginning of the private route
self.process_private_route_first_hop(
route.operation,
route.safety_route.public_key,
private_route,
)
.await?;
}
PrivateRouteHops::Data(route_hop_data) => {
// Decrypt the blob with DEC(nonce, DH(the PR's public key, this hop's secret)

View File

@@ -156,13 +156,12 @@ cfg_if! {
}
}
fn update_callback(update: VeilidUpdate) {
println!("update_callback: {:?}", update);
}
pub fn setup_veilid_core() -> (UpdateCallback, ConfigCallback) {
(
Arc::new(move |veilid_update: VeilidUpdate| {
println!("update_callback: {:?}", veilid_update);
}),
Arc::new(config_callback),
)
(Arc::new(update_callback), Arc::new(config_callback))
}
fn config_callback(key: String) -> ConfigCallbackReturn {
@@ -268,7 +267,7 @@ fn config_callback(key: String) -> ConfigCallbackReturn {
pub fn get_config() -> VeilidConfig {
let mut vc = VeilidConfig::new();
match vc.setup(Arc::new(config_callback)) {
match vc.setup(Arc::new(config_callback), Arc::new(update_callback)) {
Ok(()) => (),
Err(e) => {
error!("Error: {}", e);
@@ -280,7 +279,7 @@ pub fn get_config() -> VeilidConfig {
pub async fn test_config() {
let mut vc = VeilidConfig::new();
match vc.setup(Arc::new(config_callback)) {
match vc.setup(Arc::new(config_callback), Arc::new(update_callback)) {
Ok(()) => (),
Err(e) => {
error!("Error: {}", e);

View File

@@ -319,6 +319,14 @@ pub struct VeilidStateNetwork {
pub peers: Vec<PeerTableData>,
}
#[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, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
#[archive_attr(repr(u8), derive(CheckBytes))]
#[serde(tag = "kind")]
@@ -328,6 +336,7 @@ pub enum VeilidUpdate {
AppCall(VeilidAppCall),
Attachment(VeilidStateAttachment),
Network(VeilidStateNetwork),
Config(VeilidStateConfig),
Shutdown,
}
@@ -336,6 +345,7 @@ pub enum VeilidUpdate {
pub struct VeilidState {
pub attachment: VeilidStateAttachment,
pub network: VeilidStateNetwork,
pub config: VeilidStateConfig,
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -2679,13 +2689,16 @@ impl VeilidAPI {
pub async fn get_state(&self) -> Result<VeilidState, VeilidAPIError> {
let attachment_manager = self.attachment_manager()?;
let network_manager = attachment_manager.network_manager();
let config = self.config()?;
let attachment = attachment_manager.get_veilid_state();
let network = network_manager.get_veilid_state();
let config = config.get_veilid_state();
Ok(VeilidState {
attachment,
network,
config,
})
}

View File

@@ -1,5 +1,6 @@
use crate::xx::*;
use crate::*;
use rkyv::{Archive as RkyvArchive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
use serde::*;
////////////////////////////////////////////////////////////////////////////////////////////////
@@ -16,7 +17,18 @@ pub type ConfigCallback = Arc<dyn Fn(String) -> ConfigCallbackReturn + Send + Sy
/// url: 'https://localhost:5150'
/// ```
///
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derive(
Default,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub struct VeilidConfigHTTPS {
pub enabled: bool,
pub listen_address: String,
@@ -34,7 +46,18 @@ pub struct VeilidConfigHTTPS {
/// url: 'https://localhost:5150'
/// ```
///
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derive(
Default,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub struct VeilidConfigHTTP {
pub enabled: bool,
pub listen_address: String,
@@ -48,7 +71,18 @@ pub struct VeilidConfigHTTP {
///
/// To be implemented...
///
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derive(
Default,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub struct VeilidConfigApplication {
pub https: VeilidConfigHTTPS,
pub http: VeilidConfigHTTP,
@@ -64,7 +98,18 @@ pub struct VeilidConfigApplication {
/// public_address: ''
/// ```
///
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derive(
Default,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub struct VeilidConfigUDP {
pub enabled: bool,
pub socket_pool_size: u32,
@@ -82,7 +127,18 @@ pub struct VeilidConfigUDP {
/// listen_address: ':5150'
/// public_address: ''
///
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derive(
Default,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub struct VeilidConfigTCP {
pub connect: bool,
pub listen: bool,
@@ -102,7 +158,18 @@ pub struct VeilidConfigTCP {
/// path: 'ws'
/// url: 'ws://localhost:5150/ws'
///
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derive(
Default,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub struct VeilidConfigWS {
pub connect: bool,
pub listen: bool,
@@ -123,7 +190,18 @@ pub struct VeilidConfigWS {
/// path: 'ws'
/// url: ''
///
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derive(
Default,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub struct VeilidConfigWSS {
pub connect: bool,
pub listen: bool,
@@ -140,7 +218,18 @@ pub struct VeilidConfigWSS {
/// All protocols are available by default, and the Veilid node will
/// sort out which protocol is used for each peer connection.
///
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derive(
Default,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub struct VeilidConfigProtocol {
pub udp: VeilidConfigUDP,
pub tcp: VeilidConfigTCP,
@@ -156,7 +245,18 @@ pub struct VeilidConfigProtocol {
/// private_key_path: /path/to/private/key
/// connection_initial_timeout_ms: 2000
///
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derive(
Default,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub struct VeilidConfigTLS {
pub certificate_path: String,
pub private_key_path: String,
@@ -165,7 +265,18 @@ pub struct VeilidConfigTLS {
/// Configure the Distributed Hash Table (DHT)
///
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derive(
Default,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub struct VeilidConfigDHT {
pub resolve_node_timeout_ms: Option<u32>,
pub resolve_node_count: u32,
@@ -184,7 +295,18 @@ pub struct VeilidConfigDHT {
/// Configure RPC
///
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derive(
Default,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub struct VeilidConfigRPC {
pub concurrency: u32,
pub queue_size: u32,
@@ -197,7 +319,18 @@ pub struct VeilidConfigRPC {
/// Configure the network routing table
///
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derive(
Default,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub struct VeilidConfigRoutingTable {
pub limit_over_attached: u32,
pub limit_fully_attached: u32,
@@ -206,7 +339,18 @@ pub struct VeilidConfigRoutingTable {
pub limit_attached_weak: u32,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derive(
Default,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub struct VeilidConfigNetwork {
pub connection_initial_timeout_ms: u32,
pub connection_inactivity_timeout_ms: u32,
@@ -233,19 +377,52 @@ pub struct VeilidConfigNetwork {
pub protocol: VeilidConfigProtocol,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derive(
Default,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub struct VeilidConfigTableStore {
pub directory: String,
pub delete: bool,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derive(
Default,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub struct VeilidConfigBlockStore {
pub directory: String,
pub delete: bool,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derive(
Default,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub struct VeilidConfigProtectedStore {
pub allow_insecure_fallback: bool,
pub always_use_insecure_storage: bool,
@@ -253,7 +430,18 @@ pub struct VeilidConfigProtectedStore {
pub delete: bool,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derive(
Default,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub struct VeilidConfigCapabilities {
pub protocol_udp: bool,
pub protocol_connect_tcp: bool,
@@ -264,7 +452,18 @@ pub struct VeilidConfigCapabilities {
pub protocol_accept_wss: bool,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)]
#[derive(
Clone,
Copy,
PartialEq,
Eq,
Debug,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub enum VeilidConfigLogLevel {
Off,
Error,
@@ -322,7 +521,18 @@ impl Default for VeilidConfigLogLevel {
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derive(
Default,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub struct VeilidConfigInner {
pub program_name: String,
pub namespace: String,
@@ -338,6 +548,7 @@ pub struct VeilidConfigInner {
/// Veilid is configured
#[derive(Clone)]
pub struct VeilidConfig {
update_cb: Option<UpdateCallback>,
inner: Arc<RwLock<VeilidConfigInner>>,
}
@@ -362,23 +573,29 @@ impl VeilidConfig {
pub fn new() -> Self {
Self {
update_cb: None,
inner: Arc::new(RwLock::new(Self::new_inner())),
}
}
pub fn setup_from_json(&mut self, config: String) -> Result<(), VeilidAPIError> {
{
let mut inner = self.inner.write();
pub fn setup_from_json(
&mut self,
config: String,
update_cb: UpdateCallback,
) -> Result<(), VeilidAPIError> {
self.update_cb = Some(update_cb);
self.with_mut(|inner| {
*inner = serde_json::from_str(&config).map_err(VeilidAPIError::generic)?;
}
// Validate settings
self.validate()?;
Ok(())
Ok(())
})
}
pub fn setup(&mut self, cb: ConfigCallback) -> Result<(), VeilidAPIError> {
pub fn setup(
&mut self,
cb: ConfigCallback,
update_cb: UpdateCallback,
) -> Result<(), VeilidAPIError> {
macro_rules! get_config {
($key:expr) => {
let keyname = &stringify!($key)[6..];
@@ -389,8 +606,9 @@ impl VeilidConfig {
})?;
};
}
{
let mut inner = self.inner.write();
self.update_cb = Some(update_cb);
self.with_mut(|inner| {
get_config!(inner.program_name);
get_config!(inner.namespace);
get_config!(inner.capabilities.protocol_udp);
@@ -482,19 +700,44 @@ impl VeilidConfig {
get_config!(inner.network.protocol.wss.listen_address);
get_config!(inner.network.protocol.wss.path);
get_config!(inner.network.protocol.wss.url);
}
// Validate settings
self.validate()?;
Ok(())
})
}
Ok(())
pub fn get_veilid_state(&self) -> VeilidStateConfig {
let inner = self.inner.read();
VeilidStateConfig {
config: inner.clone(),
}
}
pub fn get(&self) -> RwLockReadGuard<VeilidConfigInner> {
self.inner.read()
}
pub fn get_mut(&self) -> RwLockWriteGuard<VeilidConfigInner> {
self.inner.write()
pub fn with_mut<F, R>(&self, f: F) -> Result<R, VeilidAPIError>
where
F: FnOnce(&mut VeilidConfigInner) -> Result<R, VeilidAPIError>,
{
let (out, config) = {
let inner = &mut *self.inner.write();
// Edit a copy
let mut editedinner = inner.clone();
// Make changes
let out = f(&mut editedinner)?;
// Validate
Self::validate(&mut editedinner)?;
// Commit changes
*inner = editedinner.clone();
(out, editedinner)
};
// Send configuration update to clients
if let Some(update_cb) = &self.update_cb {
update_cb(VeilidUpdate::Config(VeilidStateConfig { config }));
}
Ok(out)
}
pub fn get_key_json(&self, key: &str) -> Result<String, VeilidAPIError> {
@@ -521,47 +764,43 @@ impl VeilidConfig {
}
}
pub fn set_key_json(&self, key: &str, value: &str) -> Result<(), VeilidAPIError> {
let mut c = self.get_mut();
self.with_mut(|c| {
// Split key into path parts
let keypath: Vec<&str> = key.split('.').collect();
// Split key into path parts
let keypath: Vec<&str> = key.split('.').collect();
// Convert value into jsonvalue
let newval = json::parse(value).map_err(VeilidAPIError::generic)?;
// Convert value into jsonvalue
let newval = json::parse(value).map_err(VeilidAPIError::generic)?;
// Generate json from whole config
let jc = serde_json::to_string(&*c).map_err(VeilidAPIError::generic)?;
let mut jvc = json::parse(&jc).map_err(VeilidAPIError::generic)?;
// Generate json from whole config
let jc = serde_json::to_string(&*c).map_err(VeilidAPIError::generic)?;
let mut jvc = json::parse(&jc).map_err(VeilidAPIError::generic)?;
// Find requested subkey
let newconfigstring = if let Some((objkeyname, objkeypath)) = keypath.split_last() {
// Replace subkey
let mut out = &mut jvc;
for k in objkeypath {
if !out.has_key(*k) {
apibail_parse!(format!("invalid subkey in key '{}'", key), k);
// Find requested subkey
let newconfigstring = if let Some((objkeyname, objkeypath)) = keypath.split_last() {
// Replace subkey
let mut out = &mut jvc;
for k in objkeypath {
if !out.has_key(*k) {
apibail_parse!(format!("invalid subkey in key '{}'", key), k);
}
out = &mut out[*k];
}
out = &mut out[*k];
}
if !out.has_key(objkeyname) {
apibail_parse!(format!("invalid subkey in key '{}'", key), objkeyname);
}
out[*objkeyname] = newval;
jvc.to_string()
} else {
newval.to_string()
};
// Generate and validate new config
let mut newconfig = VeilidConfig::new();
newconfig.setup_from_json(newconfigstring)?;
// Replace whole config
*c = newconfig.get().clone();
Ok(())
if !out.has_key(objkeyname) {
apibail_parse!(format!("invalid subkey in key '{}'", key), objkeyname);
}
out[*objkeyname] = newval;
jvc.to_string()
} else {
newval.to_string()
};
// Generate new config
*c = serde_json::from_str(&newconfigstring).map_err(VeilidAPIError::generic)?;
Ok(())
})
}
fn validate(&self) -> Result<(), VeilidAPIError> {
let inner = self.inner.read();
fn validate(inner: &VeilidConfigInner) -> Result<(), VeilidAPIError> {
if inner.program_name.is_empty() {
apibail_generic!("Program name must not be empty in 'program_name'");
}
@@ -731,8 +970,11 @@ impl VeilidConfig {
.await
.map_err(VeilidAPIError::internal)?;
self.inner.write().network.node_id = Some(node_id);
self.inner.write().network.node_id_secret = Some(node_id_secret);
self.with_mut(|c| {
c.network.node_id = Some(node_id);
c.network.node_id_secret = Some(node_id_secret);
Ok(())
})?;
trace!("init_node_id complete");