diff --git a/examples/register.rs b/examples/register.rs index 51c2be0c..cc1281f1 100644 --- a/examples/register.rs +++ b/examples/register.rs @@ -10,8 +10,9 @@ //! //! Options: //! "--unregister": automatically unregister after 2 seconds. +//! "--disable-ipv6": not to use IPv6 interfaces. -use mdns_sd::{DaemonEvent, ServiceDaemon, ServiceInfo}; +use mdns_sd::{DaemonEvent, IfKind, ServiceDaemon, ServiceInfo}; use std::{env, thread, time::Duration}; fn main() { @@ -20,14 +21,23 @@ fn main() { // Simple command line options. let args: Vec = env::args().collect(); let mut should_unreg = false; + let mut disable_ipv6 = false; + for arg in args.iter() { if arg.as_str() == "--unregister" { should_unreg = true + } else if arg.as_str() == "--disable-ipv6" { + disable_ipv6 = true } } // Create a new mDNS daemon. let mdns = ServiceDaemon::new().expect("Could not create service daemon"); + + if disable_ipv6 { + mdns.disable_interface(IfKind::IPv6).unwrap(); + } + let service_type = match args.get(1) { Some(arg) => format!("{}.local.", arg), None => { diff --git a/src/service_daemon.rs b/src/service_daemon.rs index 9efadcce..dc6fae8a 100644 --- a/src/service_daemon.rs +++ b/src/service_daemon.rs @@ -285,16 +285,10 @@ impl ServiceDaemon { /// /// To re-announce a service with an updated `service_info`, just call /// this `register` function again. No need to call `unregister` first. - pub fn register(&self, mut service_info: ServiceInfo) -> Result<()> { + pub fn register(&self, service_info: ServiceInfo) -> Result<()> { check_service_name(service_info.get_fullname())?; check_hostname(service_info.get_hostname())?; - if service_info.is_addr_auto() { - for iface in my_ip_interfaces() { - service_info.insert_ipaddr(iface.ip()); - } - } - self.send_cmd(Command::Register(service_info)) } @@ -624,7 +618,6 @@ impl ServiceDaemon { } Command::Register(service_info) => { - debug!("register service {:?}", &service_info); zc.register_service(service_info); zc.increase_counter(Counter::Register, 1); } @@ -1081,6 +1074,31 @@ impl Zeroconf { self.timers.pop().map(|Reverse(v)| v) } + /// Apply all selections to `interfaces` and return the selected addresses. + fn selected_addrs(&self, interfaces: Vec) -> HashSet { + let intf_count = interfaces.len(); + let mut intf_selections = vec![true; intf_count]; + + // apply if_selections + for selection in self.if_selections.iter() { + // Mark the interfaces for this selection. + for i in 0..intf_count { + if selection.if_kind.matches(&interfaces[i]) { + intf_selections[i] = selection.selected; + } + } + } + + let mut selected_addrs = HashSet::new(); + for i in 0..intf_count { + if intf_selections[i] { + selected_addrs.insert(interfaces[i].addr.ip()); + } + } + + selected_addrs + } + /// Apply all selections to `interfaces`. /// /// For any interface, add it if selected but not bound yet, @@ -1192,7 +1210,7 @@ impl Zeroconf { /// Section, all of its newly registered resource records /// /// Zeroconf will then respond to requests for information about this service. - fn register_service(&mut self, info: ServiceInfo) { + fn register_service(&mut self, mut info: ServiceInfo) { // Check the service name length. if let Err(e) = check_service_name_length(info.get_type(), self.service_name_len_max) { error!("check_service_name_length: {}", &e); @@ -1200,6 +1218,15 @@ impl Zeroconf { return; } + if info.is_addr_auto() { + let selected_addrs = self.selected_addrs(my_ip_interfaces()); + for addr in selected_addrs { + info.insert_ipaddr(addr); + } + } + + debug!("register service {:?}", &info); + let outgoing_addrs = self.send_unsolicited_response(&info); if !outgoing_addrs.is_empty() { self.notify_monitors(DaemonEvent::Announce( @@ -2483,7 +2510,7 @@ fn check_service_name(fullname: &str) -> Result<()> { /// Validate a hostname. fn check_hostname(hostname: &str) -> Result<()> { if !hostname.ends_with(".local.") { - return Err(e_fmt!("Hostname must end with '.local.'")); + return Err(e_fmt!("Hostname must end with '.local.': {hostname}")); } if hostname == ".local." {