sparkles_parser/
discovery_wrapper.rs1use std::collections::{BTreeMap, HashSet};
2use std::net::{IpAddr, Ipv4Addr, SocketAddr};
3use std::thread;
4use std::time::Duration;
5use log::info;
6use multicast_discovery_socket::config::MulticastDiscoveryConfig;
7use multicast_discovery_socket::MulticastDiscoverySocket;
8
9
10const DEFAULT_MULTICAST_GROUP: Ipv4Addr = Ipv4Addr::new(239, 38, 38, 38);
11pub fn default_config() -> MulticastDiscoveryConfig {
12 MulticastDiscoveryConfig::new(DEFAULT_MULTICAST_GROUP, "sparkles".into())
13 .with_multicast_port(38338)
14 .with_backup_ports(45_337..45_339)
15 .with_disabled_announce()
16}
17
18pub struct DiscoveryWrapper {
19 socket: MulticastDiscoverySocket<()>,
20}
21
22impl DiscoveryWrapper {
23 pub fn new() -> Self {
24 let cfg = default_config();
25 let mut socket = MulticastDiscoverySocket::new_discover_only(&cfg)
26 .expect("Failed to create discovery socket");
27
28 socket.set_discover_replies_en(false);
29 Self { socket }
30 }
31
32 pub fn discover(&mut self) -> std::io::Result<BTreeMap<u32, Vec<SocketAddr>>> {
33
34 self.socket.discover();
35 thread::sleep(Duration::from_millis(50));
36 self.socket.discover();
37
38 let mut clients: BTreeMap<u32, HashSet<SocketAddr>> = BTreeMap::new();
39 for _ in 0..10 {
40 self.socket.poll(|res| {
41 match res {
42 multicast_discovery_socket::PollResult::DiscoveredClient { addr, discover_id, .. } => {
43 clients.entry(discover_id).or_default().insert(addr.into());
44 }
45 multicast_discovery_socket::PollResult::DisconnectedClient { addr, discover_id } => {
46 info!("Client disconnected: {addr} - {discover_id:x}");
47 }
48 }
49 });
50 thread::sleep(Duration::from_millis(50));
51 }
52
53 Ok(clients.iter_mut().map(|(id, addrs)| {
55 let mut addrs: Vec<_> = addrs.iter().cloned().collect();
56 addrs.sort_by_key(|a1| {
57 if a1.is_ipv4() {
58 match a1.ip() {
59 IpAddr::V4(a) => {
60 match a.octets() {
61 [127, _, _, _] => 0,
62 [192, 168, _, _] => 10,
63 [172, b, _, _] if (16..=31).contains(&b) => 20,
64 [10, _, _, _] => 30,
65 _ => 90
66 }
67 }
68 _ => 100
69 }
70 } else if a1.ip().is_loopback() {
71 80
72 } else {
73 100
74 }
75 });
76 (*id, addrs)
77 }).collect())
78 }
79}