searchlight/discovery/
presence.rs

1use 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)]
6/// A responder is a device that responds to our queries.
7pub struct Responder {
8	/// The socket address they responded from.
9	pub addr: SocketAddr,
10
11	/// The last response we received from them, as a raw DNS message.
12	pub last_response: DnsResponse,
13
14	/// The last time we received a response from them.
15	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}