From bd87ac4ab390e5f3b76196c387411912b8145759 Mon Sep 17 00:00:00 2001 From: ivmarkov Date: Mon, 24 Apr 2023 07:21:35 +0000 Subject: [PATCH] Linux & MacOS mDNS services now implement the Mdns trait --- matter/src/sys/mod.rs | 8 +-- matter/src/sys/sys_linux.rs | 126 ++++++++++++++++++++++++++---------- matter/src/sys/sys_macos.rs | 111 ++++++++++++++++++++++++------- 3 files changed, 183 insertions(+), 62 deletions(-) diff --git a/matter/src/sys/mod.rs b/matter/src/sys/mod.rs index 9b5219e..0ce65e7 100644 --- a/matter/src/sys/mod.rs +++ b/matter/src/sys/mod.rs @@ -15,14 +15,14 @@ * limitations under the License. */ -#[cfg(target_os = "macos")] +#[cfg(all(feature = "std", target_os = "macos"))] mod sys_macos; -#[cfg(target_os = "macos")] +#[cfg(all(feature = "std", target_os = "macos"))] pub use self::sys_macos::*; -#[cfg(target_os = "linux")] +#[cfg(all(feature = "std", target_os = "linux"))] mod sys_linux; -#[cfg(target_os = "linux")] +#[cfg(all(feature = "std", target_os = "linux"))] pub use self::sys_linux::*; pub const SPAKE2_ITERATION_COUNT: u32 = 2000; diff --git a/matter/src/sys/sys_linux.rs b/matter/src/sys/sys_linux.rs index 881764d..0d3f0dc 100644 --- a/matter/src/sys/sys_linux.rs +++ b/matter/src/sys/sys_linux.rs @@ -16,43 +16,101 @@ */ use crate::error::Error; -use lazy_static::lazy_static; +use crate::mdns::Mdns; use libmdns::{Responder, Service}; use log::info; -use std::sync::{Arc, Mutex}; +use std::collections::HashMap; use std::vec::Vec; -#[allow(dead_code)] -pub struct SysMdnsService { - service: Service, -} - -lazy_static! { - static ref RESPONDER: Arc> = Arc::new(Mutex::new(Responder::new().unwrap())); -} - -/// Publish a mDNS service -/// name - can be a service name (comma separate subtypes may follow) -/// regtype - registration type (e.g. _matter_.tcp etc) -/// port - the port -pub fn sys_publish_service( - name: &str, - regtype: &str, +#[derive(Debug, Clone, Eq, PartialEq, Hash)] +pub struct ServiceId { + name: String, + service_type: String, port: u16, - txt_kvs: &[[&str; 2]], -) -> Result { - info!("mDNS Registration Type {}", regtype); - info!("mDNS properties {:?}", txt_kvs); - - let mut properties = Vec::new(); - for kvs in txt_kvs { - info!("mDNS TXT key {} val {}", kvs[0], kvs[1]); - properties.push(format!("{}={}", kvs[0], kvs[1])); - } - let properties: Vec<&str> = properties.iter().map(|entry| entry.as_str()).collect(); - - let responder = RESPONDER.lock().map_err(|_| Error::MdnsError)?; - let service = responder.register(regtype.to_owned(), name.to_owned(), port, &properties); - - Ok(SysMdnsService { service }) +} + +pub struct LinuxMdns { + responder: Responder, + services: HashMap, +} + +impl LinuxMdns { + pub fn new() -> Result { + let responder = Responder::new()?; + + Ok(Self { + responder, + services: HashMap::new(), + }) + } + + pub fn add( + &mut self, + name: &str, + service_type: &str, + port: u16, + txt_kvs: &[(&str, &str)], + ) -> Result<(), Error> { + info!( + "Registering mDNS service {}/{}/{}", + name, service_type, port + ); + + let _ = self.remove(name, service_type, port); + + let mut properties = Vec::new(); + for kvs in txt_kvs { + info!("mDNS TXT key {} val {}", kvs.0, kvs.1); + properties.push(format!("{}={}", kvs.0, kvs.1)); + } + let properties: Vec<&str> = properties.iter().map(|entry| entry.as_str()).collect(); + + let service = + self.responder + .register(service_type.to_owned(), name.to_owned(), port, &properties); + + self.services.insert( + ServiceId { + name: name.into(), + service_type: service_type.into(), + port, + }, + service, + ); + + Ok(()) + } + + pub fn remove(&mut self, name: &str, service_type: &str, port: u16) -> Result<(), Error> { + let id = ServiceId { + name: name.into(), + service_type: service_type.into(), + port, + }; + + if self.services.remove(&id).is_some() { + info!( + "Deregistering mDNS service {}/{}/{}", + name, service_type, port + ); + } + + Ok(()) + } +} + +impl Mdns for LinuxMdns { + fn add( + &mut self, + name: &str, + service_type: &str, + port: u16, + txt_kvs: &[(&str, &str)], + ) -> Result<(), Error> { + LinuxMdns::add(self, name, service_type, port, txt_kvs) + } + + fn remove(&mut self, name: &str, service_type: &str, port: u16) -> Result<(), Error> { + LinuxMdns::remove(self, name, service_type, port) + } } diff --git a/matter/src/sys/sys_macos.rs b/matter/src/sys/sys_macos.rs index ba2ce22..d8ffe3a 100644 --- a/matter/src/sys/sys_macos.rs +++ b/matter/src/sys/sys_macos.rs @@ -15,32 +15,95 @@ * limitations under the License. */ -use crate::error::Error; +use std::collections::HashMap; + +use crate::{error::Error, mdns::Mdns}; use astro_dnssd::{DNSServiceBuilder, RegisteredDnsService}; use log::info; -#[allow(dead_code)] -pub struct SysMdnsService { - s: RegisteredDnsService, -} - -/// Publish a mDNS service -/// name - can be a service name (comma separate subtypes may follow) -/// regtype - registration type (e.g. _matter_.tcp etc) -/// port - the port -pub fn sys_publish_service( - name: &str, - regtype: &str, +#[derive(Debug, Clone, Eq, PartialEq, Hash)] +pub struct ServiceId { + name: String, + service_type: String, port: u16, - txt_kvs: &[[&str; 2]], -) -> Result { - let mut builder = DNSServiceBuilder::new(regtype, port).with_name(name); - - info!("mDNS Registration Type {}", regtype); - for kvs in txt_kvs { - info!("mDNS TXT key {} val {}", kvs[0], kvs[1]); - builder = builder.with_key_value(kvs[0].to_string(), kvs[1].to_string()); - } - let s = builder.register().map_err(|_| Error::MdnsError)?; - Ok(SysMdnsService { s }) +} + +pub struct MacOsMdns { + services: HashMap, +} + +impl MacOsMdns { + pub fn new() -> Result { + Ok(Self { + services: HashMap::new(), + }) + } + + pub fn add( + &mut self, + name: &str, + service_type: &str, + port: u16, + txt_kvs: &[(&str, &str)], + ) -> Result<(), Error> { + info!( + "Registering mDNS service {}/{}/{}", + name, service_type, port + ); + + let _ = self.remove(name, service_type, port); + + let mut builder = DNSServiceBuilder::new(service_type, port).with_name(name); + + for kvs in txt_kvs { + info!("mDNS TXT key {} val {}", kvs.0, kvs.1); + builder = builder.with_key_value(kvs.0.to_string(), kvs.1.to_string()); + } + + let service = builder.register().map_err(|_| Error::MdnsError)?; + + self.services.insert( + ServiceId { + name: name.into(), + service_type: service_type.into(), + port, + }, + service, + ); + + Ok(()) + } + + pub fn remove(&mut self, name: &str, service_type: &str, port: u16) -> Result<(), Error> { + let id = ServiceId { + name: name.into(), + service_type: service_type.into(), + port, + }; + + if self.services.remove(&id).is_some() { + info!( + "Deregistering mDNS service {}/{}/{}", + name, service_type, port + ); + } + + Ok(()) + } +} + +impl Mdns for MacOsMdns { + fn add( + &mut self, + name: &str, + service_type: &str, + port: u16, + txt_kvs: &[(&str, &str)], + ) -> Result<(), Error> { + MacOsMdns::add(self, name, service_type, port, txt_kvs) + } + + fn remove(&mut self, name: &str, service_type: &str, port: u16) -> Result<(), Error> { + MacOsMdns::remove(self, name, service_type, port) + } }