music_player_discovery/
lib.rs

1#[cfg(test)]
2mod tests;
3
4use async_stream::stream;
5use futures_util::Stream;
6use mdns_sd::{ServiceDaemon, ServiceEvent, ServiceInfo};
7use std::thread;
8
9use music_player_settings::{read_settings, Settings};
10
11pub const SERVICE_NAME: &'static str = "_music-player._tcp.local.";
12pub const XBMC_SERVICE_NAME: &'static str = "_xbmc-jsonrpc-h._tcp.local.";
13
14pub struct MdnsResponder {
15    responder: libmdns::Responder,
16    svc: Vec<libmdns::Service>,
17}
18
19impl MdnsResponder {
20    pub fn new() -> Self {
21        let responder = libmdns::Responder::new().unwrap();
22        Self {
23            responder,
24            svc: vec![],
25        }
26    }
27
28    pub fn register_service(&mut self, name: &str, port: u16) {
29        let config = read_settings().unwrap();
30        let settings = config.try_deserialize::<Settings>().unwrap();
31        let device_name = format!("device_name={}", settings.device_name);
32
33        self.svc.push(self.responder.register(
34            "_music-player._tcp".to_owned(),
35            name.to_owned(),
36            port,
37            &["path=/", device_name.as_str()],
38        ));
39    }
40}
41
42pub fn register_services() {
43    let config = read_settings().unwrap();
44    let settings = config.try_deserialize::<Settings>().unwrap();
45    let http_service = format!("http-{}", settings.device_id);
46    let ws_service = format!("websocket-{}", settings.device_id);
47    let grpc_service = format!("grpc-{}", settings.device_id);
48
49    thread::spawn(move || {
50        let mut responder = MdnsResponder::new();
51        responder.register_service(&http_service, settings.http_port);
52        responder.register_service(&ws_service, settings.ws_port);
53        responder.register_service(&grpc_service, settings.port);
54        loop {
55            ::std::thread::sleep(::std::time::Duration::from_secs(10));
56        }
57    });
58}
59
60pub fn register(name: &str, port: u16) {
61    /*
62    let mut builder = env_logger::Builder::new();
63    builder.parse_filters("libmdns=debug");
64    builder.init();
65    */
66
67    let config = read_settings().unwrap();
68    let settings = config.try_deserialize::<Settings>().unwrap();
69    let device_name = format!("device_name={}", settings.device_name);
70
71    let responder = libmdns::Responder::new().unwrap();
72    let _svc = responder.register(
73        "_music-player._tcp".to_owned(),
74        name.to_owned(),
75        port,
76        &["path=/", device_name.as_str()],
77    );
78
79    loop {
80        ::std::thread::sleep(::std::time::Duration::from_secs(10));
81    }
82}
83
84pub fn discover(service_name: &str) -> impl Stream<Item = ServiceInfo> {
85    let mdns = ServiceDaemon::new().unwrap();
86    let receiver = mdns.browse(&service_name).expect("Failed to browse");
87
88    stream! {
89        while let Ok(event) = receiver.recv() {
90            match event {
91                ServiceEvent::ServiceResolved(info) => {
92                    yield info;
93                }
94                _ => {}
95            }
96        }
97    }
98}