From 8229ed081b438da2062e677c01fc37940bc2b0c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rytis=20Karpu=C5=A1ka?= Date: Thu, 12 Dec 2024 12:13:38 +0200 Subject: [PATCH] Add event dedublication to src/device.rs --- src/device.rs | 59 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/src/device.rs b/src/device.rs index 2f672bbb4..7ee9ec995 100644 --- a/src/device.rs +++ b/src/device.rs @@ -453,6 +453,11 @@ struct Runtime { /// Some of the events are time based, so just poll the whole state from time to time polling_interval: Interval, + /// Store most recent reported event to the apps per node + /// + /// TODO: This is planned to be refactored into a bit better solution in https://github.com/NordSecurity/libtelio/pull/1021 + last_transmitted_event: HashMap, + #[cfg(test)] /// MockedAdapter (tests) test_env: telio_wg::tests::Env, @@ -1275,6 +1280,7 @@ impl Runtime { derp_events_publisher: derp_events.tx, }, polling_interval, + last_transmitted_event: Default::default(), #[cfg(test)] test_env: wg::tests::Env { analytics: analytics_ch, @@ -2323,6 +2329,21 @@ impl Runtime { } } } + + fn is_dublicated_event(&mut self, node: &Node) -> bool { + match self.last_transmitted_event.get(&node.public_key) { + None => node.state == PeerState::Disconnected, + Some(last_node) => *node == *last_node, + } + } + + fn remember_last_transmitted_node_event(&mut self, node: Node) { + if node.state == PeerState::Disconnected { + self.last_transmitted_event.remove(&node.public_key); + } else { + self.last_transmitted_event.insert(node.public_key, node); + } + } } #[async_trait] @@ -2385,11 +2406,13 @@ impl TaskRuntime for Runtime { if let Some(node) = node { // Publish WG event to app - let event = Event::builder::().set(node).build(); - if let Some(event) = event { - let _ = self.event_publishers.libtelio_event_publisher.send( - Box::new(event) - ); + if let Some(event) = Event::builder::().set(node.clone()).build() { + if !self.is_dublicated_event(&node) { + let _ = self.event_publishers.libtelio_event_publisher.send( + Box::new(event) + ); + self.remember_last_transmitted_node_event(node); + } } } @@ -2439,26 +2462,36 @@ impl TaskRuntime for Runtime { match (&pq_event, &self.requested_state.exit_node, &self.requested_state.last_exit_node) { (telio_pq::Event::Connecting(pubkey), Some(exit), _) if exit.public_key == *pubkey => { - let body = Node { + let node = Node { state: PeerState::Connecting, link_state: Some(LinkState::Down), ..node_from_exit_node(exit) }; - let _ = self.event_publishers.libtelio_event_publisher.send( - Box::new(Event::Node { body }) - ); + if let Some(event) = Event::builder::().set(node.clone()).build() { + if !self.is_dublicated_event(&node) { + let _ = self.event_publishers.libtelio_event_publisher.send( + Box::new(event) + ); + self.remember_last_transmitted_node_event(node); + } + } }, (telio_pq::Event::Disconnected(pubkey), _, Some(last_exit)) if last_exit.public_key == *pubkey => { - let body = Node { + let node = Node { state: PeerState::Disconnected, link_state: Some(LinkState::Down), ..node_from_exit_node(last_exit) }; - let _ = self.event_publishers.libtelio_event_publisher.send( - Box::new(Event::Node { body }) - ); + if let Some(event) = Event::builder::().set(node.clone()).build() { + if !self.is_dublicated_event(&node) { + let _ = self.event_publishers.libtelio_event_publisher.send( + Box::new(event) + ); + self.remember_last_transmitted_node_event(node); + } + } }, _ => (), }