Linux & MacOS mDNS services now implement the Mdns trait

This commit is contained in:
ivmarkov 2023-04-24 07:21:35 +00:00
parent b4b549bb10
commit bd87ac4ab3
3 changed files with 183 additions and 62 deletions

View file

@ -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;

View file

@ -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<Mutex<Responder>> = 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<SysMdnsService, Error> {
info!("mDNS Registration Type {}", regtype);
info!("mDNS properties {:?}", txt_kvs);
}
pub struct LinuxMdns {
responder: Responder,
services: HashMap<ServiceId, Service>,
}
impl LinuxMdns {
pub fn new() -> Result<Self, Error> {
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]));
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);
let service =
self.responder
.register(service_type.to_owned(), name.to_owned(), port, &properties);
Ok(SysMdnsService { service })
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)
}
}

View file

@ -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<SysMdnsService, Error> {
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<RegisteredDnsService, RegisteredDnsService>,
}
impl MacOsMdns {
pub fn new() -> Result<Self, Error> {
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)
}
}