searchlight/discovery/
presence.rs1use super::{event::EventHandler, DiscoveryEvent};
2use std::{borrow::Borrow, cell::Cell, collections::HashSet, hash::Hash, net::SocketAddr, ops::Deref, sync::Arc, time::Instant};
3use trust_dns_client::op::DnsResponse;
4
5#[derive(Debug, Clone)]
6pub struct Responder {
8 pub addr: SocketAddr,
10
11 pub last_response: DnsResponse,
13
14 pub last_responded: Instant,
16}
17
18#[derive(Clone)]
19pub(super) struct ResponderMemoryEntry {
20 pub(super) inner: Arc<Responder>,
21 pub(super) ignored_packets: Cell<u8>,
22}
23impl Deref for ResponderMemoryEntry {
24 type Target = Responder;
25
26 #[inline(always)]
27 fn deref(&self) -> &Self::Target {
28 &self.inner
29 }
30}
31impl Borrow<SocketAddr> for ResponderMemoryEntry {
32 fn borrow(&self) -> &SocketAddr {
33 &self.addr
34 }
35}
36impl Hash for ResponderMemoryEntry {
37 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
38 self.addr.hash(state);
39 }
40}
41impl PartialEq for ResponderMemoryEntry {
42 fn eq(&self, other: &Self) -> bool {
43 self.addr == other.addr
44 }
45}
46impl Eq for ResponderMemoryEntry {}
47
48#[derive(Default)]
49pub(super) struct ResponderMemory(HashSet<ResponderMemoryEntry>);
50impl ResponderMemory {
51 #[inline(always)]
52 pub(super) fn get(&self, addr: &SocketAddr) -> Option<&ResponderMemoryEntry> {
53 self.0.get(addr)
54 }
55
56 #[inline(always)]
57 pub(super) fn replace(&mut self, entry: Arc<Responder>) {
58 self.0.replace(ResponderMemoryEntry {
59 inner: entry,
60 ignored_packets: Cell::new(0),
61 });
62 }
63
64 pub(super) fn sweep(&mut self, event_handler: &EventHandler, max_ignored_packets: u8) {
65 self.0.retain(|entry| {
66 let ignored_packets = entry.ignored_packets.get();
67 if ignored_packets < max_ignored_packets {
68 entry.ignored_packets.set(ignored_packets + 1);
69 true
70 } else {
71 let event_handler = event_handler.clone();
72 let responder = entry.inner.clone();
73 tokio::task::spawn_blocking(move || event_handler(DiscoveryEvent::ResponderLost(responder)));
74 false
75 }
76 });
77 }
78}