sparkles_parser/
discovery_wrapper.rs

1use 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        // Heuristic sorting of addresses by priority
54        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}