use super::*; /////////////////////////////////////////////////////////////////////////////////////// #[derive(Clone, Debug)] pub enum Target { NodeId(NodeId), PrivateRoute(DHTKey), } pub struct RoutingContextInner {} pub struct RoutingContextUnlockedInner { /// Safety routing requirements safety_selection: SafetySelection, } impl Drop for RoutingContextInner { fn drop(&mut self) { // self.api // .borrow_mut() // .routing_contexts // //.remove(&self.id); } } #[derive(Clone)] pub struct RoutingContext { /// Veilid API handle api: VeilidAPI, inner: Arc>, unlocked_inner: Arc, } impl RoutingContext { //////////////////////////////////////////////////////////////// pub(super) fn new(api: VeilidAPI) -> Self { Self { api, inner: Arc::new(Mutex::new(RoutingContextInner {})), unlocked_inner: Arc::new(RoutingContextUnlockedInner { safety_selection: SafetySelection::Unsafe(Sequencing::NoPreference), }), } } pub fn with_default_privacy(self) -> Result { let config = self.api.config()?; let c = config.get(); Ok(Self { api: self.api.clone(), inner: Arc::new(Mutex::new(RoutingContextInner {})), unlocked_inner: Arc::new(RoutingContextUnlockedInner { safety_selection: SafetySelection::Safe(SafetySpec { preferred_route: None, hop_count: c.network.rpc.default_route_hop_count as usize, stability: Stability::LowLatency, sequencing: Sequencing::NoPreference, }), }), }) } pub fn with_privacy(self, safety_spec: SafetySpec) -> Result { Ok(Self { api: self.api.clone(), inner: Arc::new(Mutex::new(RoutingContextInner {})), unlocked_inner: Arc::new(RoutingContextUnlockedInner { safety_selection: SafetySelection::Safe(safety_spec), }), }) } pub fn with_sequencing(self, sequencing: Sequencing) -> Self { Self { api: self.api.clone(), inner: Arc::new(Mutex::new(RoutingContextInner {})), unlocked_inner: Arc::new(RoutingContextUnlockedInner { safety_selection: match self.unlocked_inner.safety_selection { SafetySelection::Unsafe(_) => SafetySelection::Unsafe(sequencing), SafetySelection::Safe(safety_spec) => SafetySelection::Safe(SafetySpec { preferred_route: safety_spec.preferred_route, hop_count: safety_spec.hop_count, stability: safety_spec.stability, sequencing, }), }, }), } } pub fn sequencing(&self) -> Sequencing { match self.unlocked_inner.safety_selection { SafetySelection::Unsafe(sequencing) => sequencing, SafetySelection::Safe(safety_spec) => safety_spec.sequencing, } } pub fn safety_spec(&self) -> Option { match self.unlocked_inner.safety_selection { SafetySelection::Unsafe(_) => None, SafetySelection::Safe(safety_spec) => Some(safety_spec.clone()), } } pub fn api(&self) -> VeilidAPI { self.api.clone() } async fn get_destination( &self, target: Target, ) -> Result { 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.key).await { Ok(Some(nr)) => nr, Ok(None) => return Err(VeilidAPIError::KeyNotFound { key: node_id.key }), Err(e) => return Err(e.into()), }; // Apply sequencing to match safety selection nr.set_sequencing(self.sequencing()); Ok(rpc_processor::Destination::Direct { target: nr, safety_selection: self.unlocked_inner.safety_selection, }) } Target::PrivateRoute(pr) => { // Get remote private route let rss = self.api.routing_table()?.route_spec_store(); let private_route = rss .get_remote_private_route(&pr) .map_err(|_| VeilidAPIError::KeyNotFound { key: pr })?; Ok(rpc_processor::Destination::PrivateRoute { private_route, safety_selection: self.unlocked_inner.safety_selection, }) } } } //////////////////////////////////////////////////////////////// // App-level Messaging #[instrument(level = "debug", err, skip(self))] pub async fn app_call( &self, target: Target, request: Vec, ) -> Result, VeilidAPIError> { let rpc_processor = self.api.rpc_processor()?; // Get destination let dest = self.get_destination(target).await?; // Send app message let answer = match rpc_processor.rpc_call_app_call(dest, request).await { Ok(NetworkResult::Value(v)) => v, Ok(NetworkResult::Timeout) => return Err(VeilidAPIError::Timeout), Ok(NetworkResult::NoConnection(e)) | Ok(NetworkResult::AlreadyExists(e)) => { return Err(VeilidAPIError::NoConnection { message: e.to_string(), }) } Ok(NetworkResult::InvalidMessage(message)) => { return Err(VeilidAPIError::Generic { message }) } Err(e) => return Err(e.into()), }; Ok(answer.answer) } #[instrument(level = "debug", err, skip(self))] pub async fn app_message( &self, target: Target, message: Vec, ) -> Result<(), VeilidAPIError> { let rpc_processor = self.api.rpc_processor()?; // Get destination let dest = self.get_destination(target).await?; // Send app message match rpc_processor.rpc_call_app_message(dest, message).await { Ok(NetworkResult::Value(())) => {} Ok(NetworkResult::Timeout) => return Err(VeilidAPIError::Timeout), Ok(NetworkResult::NoConnection(e)) | Ok(NetworkResult::AlreadyExists(e)) => { return Err(VeilidAPIError::NoConnection { message: e.to_string(), }) } Ok(NetworkResult::InvalidMessage(message)) => { return Err(VeilidAPIError::Generic { message }) } Err(e) => return Err(e.into()), }; Ok(()) } /////////////////////////////////// /// DHT Values pub async fn get_value(&self, _value_key: ValueKey) -> Result, VeilidAPIError> { panic!("unimplemented"); } pub async fn set_value( &self, _value_key: ValueKey, _value: Vec, ) -> Result { panic!("unimplemented"); } pub async fn watch_value( &self, _value_key: ValueKey, _callback: ValueChangeCallback, ) -> Result { panic!("unimplemented"); } pub async fn cancel_watch_value(&self, _value_key: ValueKey) -> Result { panic!("unimplemented"); } /////////////////////////////////// /// Block Store pub async fn find_block(&self, _block_id: BlockId) -> Result, VeilidAPIError> { panic!("unimplemented"); } pub async fn supply_block(&self, _block_id: BlockId) -> Result { panic!("unimplemented"); } }