message_subscriber.rs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. use async_std::sync::Mutex;
  2. use std::{any::Any, io::Cursor, sync::Arc};
  3. use async_trait::async_trait;
  4. use fxhash::FxHashMap;
  5. use log::{debug, warn};
  6. use rand::Rng;
  7. use crate::{Error, Result};
  8. use super::message::Message;
  9. /// 64bit identifier for message subscription.
  10. pub type MessageSubscriptionId = u64;
  11. type MessageResult<M> = Result<Arc<M>>;
  12. /// Handles message subscriptions through a subscription ID and a receiver
  13. /// channel.
  14. pub struct MessageSubscription<M: Message> {
  15. id: MessageSubscriptionId,
  16. recv_queue: smol::channel::Receiver<MessageResult<M>>,
  17. parent: Arc<MessageDispatcher<M>>,
  18. }
  19. impl<M: Message> MessageSubscription<M> {
  20. /// Start receiving messages.
  21. pub async fn receive(&self) -> MessageResult<M> {
  22. match self.recv_queue.recv().await {
  23. Ok(message) => message,
  24. Err(err) => {
  25. panic!("MessageSubscription::receive() recv_queue failed! {}", err);
  26. }
  27. }
  28. }
  29. /// Unsubscribe from a message subscription. Must be called manually.
  30. pub async fn unsubscribe(&self) {
  31. self.parent.clone().unsubscribe(self.id).await
  32. }
  33. }
  34. #[async_trait]
  35. /// Generic interface for message dispatcher.
  36. trait MessageDispatcherInterface: Send + Sync {
  37. async fn trigger(&self, payload: Vec<u8>);
  38. async fn trigger_error(&self, err: Error);
  39. fn as_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync>;
  40. }
  41. /// A dispatchers that is unique to every Message. Maintains a list of subscribers that are subscribed to that unique Message type and handles sending messages across these subscriptions.
  42. struct MessageDispatcher<M: Message> {
  43. subs: Mutex<FxHashMap<MessageSubscriptionId, smol::channel::Sender<MessageResult<M>>>>,
  44. }
  45. impl<M: Message> MessageDispatcher<M> {
  46. /// Create a new message dispatcher.
  47. fn new() -> Self {
  48. MessageDispatcher { subs: Mutex::new(FxHashMap::default()) }
  49. }
  50. /// Create a random ID.
  51. fn random_id() -> MessageSubscriptionId {
  52. let mut rng = rand::thread_rng();
  53. rng.gen()
  54. }
  55. /// Subscribe to a channel. Assigns a new ID and adds it to the list of
  56. /// subscribers.
  57. pub async fn subscribe(self: Arc<Self>) -> MessageSubscription<M> {
  58. let (sender, recvr) = smol::channel::unbounded();
  59. let sub_id = Self::random_id();
  60. self.subs.lock().await.insert(sub_id, sender);
  61. MessageSubscription { id: sub_id, recv_queue: recvr, parent: self }
  62. }
  63. /// Unsubcribe from a channel. Removes the associated ID from the subscriber
  64. /// list.
  65. async fn unsubscribe(&self, sub_id: MessageSubscriptionId) {
  66. self.subs.lock().await.remove(&sub_id);
  67. }
  68. /// Private function to transmit a message to all subscriber channels. Automatically clear inactive
  69. /// channels. Used strictly internally.
  70. async fn _trigger_all(&self, message: MessageResult<M>) {
  71. debug!(
  72. target: "net",
  73. "MessageDispatcher<M={}>::trigger_all({}) [START, subs={}]",
  74. M::name(),
  75. if message.is_ok() { "msg" } else { "err" },
  76. self.subs.lock().await.len()
  77. );
  78. let mut garbage_ids = Vec::new();
  79. for (sub_id, sub) in &*self.subs.lock().await {
  80. match sub.send(message.clone()).await {
  81. Ok(()) => {}
  82. Err(_err) => {
  83. // Automatically clean out closed channels
  84. garbage_ids.push(*sub_id);
  85. // panic!("Error returned sending message in notify() call!
  86. // {}", err);
  87. }
  88. }
  89. }
  90. self.collect_garbage(garbage_ids).await;
  91. debug!(
  92. target: "net",
  93. "MessageDispatcher<M={}>::trigger_all({}) [END, subs={}]",
  94. M::name(),
  95. if message.is_ok() { "msg" } else { "err" },
  96. self.subs.lock().await.len()
  97. );
  98. }
  99. /// Remove inactive channels.
  100. async fn collect_garbage(&self, ids: Vec<MessageSubscriptionId>) {
  101. let mut subs = self.subs.lock().await;
  102. for id in &ids {
  103. subs.remove(id);
  104. }
  105. }
  106. }
  107. #[async_trait]
  108. // Local implementation of the Message Dispatcher Interface.
  109. impl<M: Message> MessageDispatcherInterface for MessageDispatcher<M> {
  110. /// Internal function to deserialize data into a message type and dispatch it across subscriber channels.
  111. async fn trigger(&self, payload: Vec<u8>) {
  112. // deserialize data into type
  113. // send down the pipes
  114. let cursor = Cursor::new(payload);
  115. match M::decode(cursor) {
  116. Ok(message) => {
  117. let message = Ok(Arc::new(message));
  118. self._trigger_all(message).await
  119. }
  120. Err(err) => {
  121. debug!("Unable to decode data. Dropping...: {}", err);
  122. }
  123. }
  124. }
  125. /// Interal function that sends a Error message to all subscriber channels.
  126. async fn trigger_error(&self, err: Error) {
  127. self._trigger_all(Err(err)).await;
  128. }
  129. /// Converts to Any trait. Enables the dynamic modification of static types.
  130. fn as_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {
  131. self
  132. }
  133. }
  134. /// Generic publish/subscribe class that maintains a list of dispatchers. Dispatchers transmit
  135. /// messages to subscribers and are specific to one message type.
  136. pub struct MessageSubsystem {
  137. dispatchers: Mutex<FxHashMap<&'static str, Arc<dyn MessageDispatcherInterface>>>,
  138. }
  139. impl MessageSubsystem {
  140. /// Create a new message subsystem.
  141. pub fn new() -> Self {
  142. MessageSubsystem { dispatchers: Mutex::new(FxHashMap::default()) }
  143. }
  144. /// Add a new dispatcher for specified Message.
  145. pub async fn add_dispatch<M: Message>(&self) {
  146. self.dispatchers.lock().await.insert(M::name(), Arc::new(MessageDispatcher::<M>::new()));
  147. }
  148. /// Subscribes to a Message. Using the Message name, the method returns an the associated MessageDispatcher from the list of
  149. /// dispatchers and calls subscribe().
  150. pub async fn subscribe<M: Message>(&self) -> Result<MessageSubscription<M>> {
  151. let dispatcher = self.dispatchers.lock().await.get(M::name()).cloned();
  152. let sub = match dispatcher {
  153. Some(dispatcher) => {
  154. let dispatcher: Arc<MessageDispatcher<M>> = dispatcher
  155. .as_any()
  156. .downcast::<MessageDispatcher<M>>()
  157. .expect("Multiple messages registered with different names");
  158. dispatcher.subscribe().await
  159. }
  160. None => {
  161. // normall return failure here
  162. // for now panic
  163. return Err(Error::NetworkOperationFailed)
  164. }
  165. };
  166. Ok(sub)
  167. }
  168. /// Transmits a payload to a dispatcher. Returns an error if the payload
  169. /// fails to transmit.
  170. pub async fn notify(&self, command: &str, payload: Vec<u8>) {
  171. let dispatcher = self.dispatchers.lock().await.get(command).cloned();
  172. match dispatcher {
  173. Some(dispatcher) => {
  174. dispatcher.trigger(payload).await;
  175. }
  176. None => {
  177. warn!(
  178. target: "MessageSubsystem::notify",
  179. "MessageSubsystem::notify(\"{}\", payload) did not find a dispatcher",
  180. command
  181. );
  182. }
  183. }
  184. }
  185. /// Transmits an error message across dispatchers.
  186. pub async fn trigger_error(&self, err: Error) {
  187. // TODO: this could be parallelized
  188. for dispatcher in self.dispatchers.lock().await.values() {
  189. dispatcher.trigger_error(err.clone()).await;
  190. }
  191. }
  192. }
  193. impl Default for MessageSubsystem {
  194. fn default() -> Self {
  195. Self::new()
  196. }
  197. }
  198. /// Test functions for message subsystem.
  199. // This is a test function for the message subsystem code above
  200. // Normall we would use the #[test] macro but cannot since it is async code
  201. // Instead we call it using smol::block_on() in the unit test code after this
  202. // func
  203. #[cfg(test)]
  204. mod tests {
  205. use super::*;
  206. use darkfi_serial::{Decodable, Encodable};
  207. use std::io;
  208. #[async_std::test]
  209. async fn message_subscriber_test() {
  210. struct MyVersionMessage {
  211. x: u32,
  212. }
  213. impl Message for MyVersionMessage {
  214. fn name() -> &'static str {
  215. "verver"
  216. }
  217. }
  218. impl Encodable for MyVersionMessage {
  219. fn encode<S: io::Write>(&self, mut s: S) -> core::result::Result<usize, io::Error> {
  220. let mut len = 0;
  221. len += self.x.encode(&mut s)?;
  222. Ok(len)
  223. }
  224. }
  225. impl Decodable for MyVersionMessage {
  226. fn decode<D: io::Read>(mut d: D) -> core::result::Result<Self, io::Error> {
  227. Ok(Self { x: Decodable::decode(&mut d)? })
  228. }
  229. }
  230. println!("hello");
  231. let subsystem = MessageSubsystem::new();
  232. subsystem.add_dispatch::<MyVersionMessage>().await;
  233. // subscribe
  234. // 1. get dispatcher
  235. // 2. cast to specific type
  236. // 3. do sub, return sub
  237. let sub = subsystem.subscribe::<MyVersionMessage>().await.unwrap();
  238. let msg = MyVersionMessage { x: 110 };
  239. let mut payload = Vec::new();
  240. msg.encode(&mut payload).unwrap();
  241. // receive message and publish
  242. // 1. based on string, lookup relevant dispatcher interface
  243. // 2. publish data there
  244. subsystem.notify("verver", payload).await;
  245. // receive
  246. // 1. do a get easy
  247. let msg2 = sub.receive().await.unwrap();
  248. assert_eq!(msg2.x, 110);
  249. println!("{}", msg2.x);
  250. subsystem.trigger_error(Error::ChannelStopped).await;
  251. let msg2 = sub.receive().await;
  252. assert!(msg2.is_err());
  253. sub.unsubscribe().await;
  254. }
  255. }