use std::marker::PhantomData; use std::sync::Arc; use arc_swap::ArcSwapOption; use async_trait::async_trait; use serde::{Deserialize, Serialize}; use crate::error::Error; use crate::netapp::*; use crate::proto::*; use crate::util::*; /// This trait should be implemented by all messages your application /// wants to handle (click to read more). pub trait Message: Serialize + for<'de> Deserialize<'de> + Send + Sync { type Response: Serialize + for<'de> Deserialize<'de> + Send + Sync; } pub(crate) type DynEndpoint = Box; #[async_trait] pub trait EndpointHandler: Send + Sync where M: Message, { async fn handle(self: &Arc, m: M, from: NodeID) -> M::Response; } pub struct Endpoint where M: Message, H: EndpointHandler, { phantom: PhantomData, netapp: Arc, path: String, handler: ArcSwapOption, } impl Endpoint where M: Message, H: EndpointHandler, { pub(crate) fn new(netapp: Arc, path: String) -> Self { Self { phantom: PhantomData::default(), netapp, path, handler: ArcSwapOption::from(None), } } pub fn set_handler(&self, h: Arc) { self.handler.swap(Some(h)); } pub async fn call( &self, target: &NodeID, req: M, prio: RequestPriority, ) -> Result<::Response, Error> { if *target == self.netapp.id { match self.handler.load_full() { None => Err(Error::NoHandler), Some(h) => Ok(h.handle(req, self.netapp.id).await), } } else { let conn = self .netapp .client_conns .read() .unwrap() .get(target) .cloned(); match conn { None => Err(Error::Message(format!( "Not connected: {}", hex::encode(target) ))), Some(c) => c.call(req, self.path.as_str(), prio).await, } } } } #[async_trait] pub(crate) trait GenericEndpoint { async fn handle(&self, buf: &[u8], from: NodeID) -> Result, Error>; fn clear_handler(&self); fn clone_endpoint(&self) -> DynEndpoint; } #[derive(Clone)] pub(crate) struct EndpointArc(pub(crate) Arc>) where M: Message, H: EndpointHandler; #[async_trait] impl GenericEndpoint for EndpointArc where M: Message + 'static, H: EndpointHandler + 'static, { async fn handle(&self, buf: &[u8], from: NodeID) -> Result, Error> { match self.0.handler.load_full() { None => Err(Error::NoHandler), Some(h) => { let req = rmp_serde::decode::from_read_ref::<_, M>(buf)?; let res = h.handle(req, from).await; let res_bytes = rmp_to_vec_all_named(&res)?; Ok(res_bytes) } } } fn clear_handler(&self) { self.0.handler.swap(None); } fn clone_endpoint(&self) -> DynEndpoint { Box::new(Self(self.0.clone())) } }