music_player_discovery/
lib.rs1#[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 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}