diff --git a/zeroconf/Cargo.toml b/zeroconf/Cargo.toml index ab3065d..4c39543 100644 --- a/zeroconf/Cargo.toml +++ b/zeroconf/Cargo.toml @@ -18,6 +18,10 @@ categories = [ ] documentation = "https://docs.rs/zeroconf" +[features] +default = ["avahi"] +avahi = ["dep:avahi-sys"] + [dependencies] serde = { version = "1.0.188", features = ["derive"], optional = true } derive-getters = "0.3.0" @@ -34,7 +38,7 @@ serde_json = "1.0.107" clap = { version = "4.4.4", features = ["derive"] } [target.'cfg(unix)'.dependencies] -avahi-sys = "0.10.1" +avahi-sys = { version = "0.10.1", optional = true } [target.'cfg(target_vendor = "apple")'.dependencies] bonjour-sys = "0.3.0" diff --git a/zeroconf/src/avahi/browser.rs b/zeroconf/src/avahi/browser.rs index 6adab5e..50b12a0 100644 --- a/zeroconf/src/avahi/browser.rs +++ b/zeroconf/src/avahi/browser.rs @@ -37,6 +37,9 @@ pub struct AvahiMdnsBrowser { } impl TMdnsBrowser for AvahiMdnsBrowser { + type EventLoop = EventLoop; + type TxtRecord = TxtRecord; + fn new(service_type: ServiceType) -> Self { Self { client: None, diff --git a/zeroconf/src/avahi/service.rs b/zeroconf/src/avahi/service.rs index 5e068bc..4dd513c 100644 --- a/zeroconf/src/avahi/service.rs +++ b/zeroconf/src/avahi/service.rs @@ -33,6 +33,9 @@ pub struct AvahiMdnsService { } impl TMdnsService for AvahiMdnsService { + type EventLoop = EventLoop; + type TxtRecord = TxtRecord; + fn new(service_type: ServiceType, port: u16) -> Self { let kind = avahi_util::format_service_type(&service_type); diff --git a/zeroconf/src/bonjour/browser.rs b/zeroconf/src/bonjour/browser.rs index 20ea4b5..166fd5f 100644 --- a/zeroconf/src/bonjour/browser.rs +++ b/zeroconf/src/bonjour/browser.rs @@ -31,6 +31,9 @@ pub struct BonjourMdnsBrowser { } impl TMdnsBrowser for BonjourMdnsBrowser { + type EventLoop = EventLoop; + type TxtRecord = TxtRecord; + fn new(service_type: ServiceType) -> Self { Self { service: Arc::default(), diff --git a/zeroconf/src/bonjour/service.rs b/zeroconf/src/bonjour/service.rs index 014d6f7..e4c6591 100644 --- a/zeroconf/src/bonjour/service.rs +++ b/zeroconf/src/bonjour/service.rs @@ -29,6 +29,9 @@ pub struct BonjourMdnsService { } impl TMdnsService for BonjourMdnsService { + type EventLoop = EventLoop; + type TxtRecord = TxtRecord; + fn new(service_type: ServiceType, port: u16) -> Self { Self { service: Arc::default(), diff --git a/zeroconf/src/browser.rs b/zeroconf/src/browser.rs index 5817e7d..9728a72 100644 --- a/zeroconf/src/browser.rs +++ b/zeroconf/src/browser.rs @@ -1,6 +1,7 @@ //! Trait definition for cross-platform browser -use crate::{EventLoop, NetworkInterface, Result, ServiceType, TxtRecord}; +use crate::prelude::{TEventLoop, TTxtRecord}; +use crate::{NetworkInterface, Result, ServiceType}; use std::any::Any; use std::sync::Arc; @@ -8,13 +9,16 @@ use std::sync::Arc; /// /// [`MdnsBrowser`]: type.MdnsBrowser.html #[derive(Debug, Clone, PartialEq, Eq)] -pub enum BrowserEvent { - Add(ServiceDiscovery), +pub enum BrowserEvent { + Add(ServiceDiscovery), Remove(ServiceRemoval), } /// Interface for interacting with underlying mDNS implementation service browsing capabilities. pub trait TMdnsBrowser { + type EventLoop: TEventLoop; + type TxtRecord: TTxtRecord; + /// Creates a new `MdnsBrowser` that browses for the specified `kind` (e.g. `_http._tcp`) fn new(service_type: ServiceType) -> Self; @@ -31,7 +35,10 @@ pub trait TMdnsBrowser { /// resolved or removed a service. /// /// [`ServiceBrowserCallback`]: ../type.ServiceBrowserCallback.html - fn set_service_callback(&mut self, service_callback: Box); + fn set_service_callback( + &mut self, + service_callback: Box>, + ); /// Sets the optional user context to pass through to the callback. This is useful if you need /// to share state between pre and post-callback. The context type must implement `Any`. @@ -41,7 +48,7 @@ pub trait TMdnsBrowser { fn context(&self) -> Option<&dyn Any>; /// Starts the browser. Returns an `EventLoop` which can be called to keep the browser alive. - fn browse_services(&mut self) -> Result; + fn browse_services(&mut self) -> Result; } /// Callback invoked from [`MdnsBrowser`] once a service has been discovered and resolved or @@ -52,14 +59,16 @@ pub trait TMdnsBrowser { /// * `context` - The optional user context passed through /// /// [`MdnsBrowser`]: type.MdnsBrowser.html -pub type ServiceBrowserCallback = dyn Fn(Result, Option>); +pub type ServiceBrowserCallback = + dyn Fn(Result>, Option>); /// Represents a service that has been discovered by a [`MdnsBrowser`]. /// /// [`MdnsBrowser`]: type.MdnsBrowser.html #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[derive(Debug, Getters, Builder, BuilderDelegate, Clone, PartialEq, Eq)] -pub struct ServiceDiscovery { +// TODO: Restore derive(BuilderDelegate) +#[derive(Debug, Getters, Builder, Clone, PartialEq, Eq)] +pub struct ServiceDiscovery { name: String, service_type: ServiceType, domain: String, diff --git a/zeroconf/src/lib.rs b/zeroconf/src/lib.rs index 6263f21..fda794c 100644 --- a/zeroconf/src/lib.rs +++ b/zeroconf/src/lib.rs @@ -192,7 +192,7 @@ extern crate serde; extern crate derive_builder; #[macro_use] extern crate zeroconf_macros; -#[cfg(target_os = "linux")] +#[cfg(all(target_os = "linux", feature = "avahi"))] extern crate avahi_sys; #[cfg(any(target_vendor = "apple", target_vendor = "pc"))] extern crate bonjour_sys; @@ -223,7 +223,7 @@ pub mod prelude; pub mod service; pub mod txt_record; -#[cfg(target_os = "linux")] +#[cfg(all(target_os = "linux", feature = "avahi"))] pub mod avahi; #[cfg(any(target_vendor = "apple", target_vendor = "pc"))] pub mod bonjour; @@ -234,21 +234,21 @@ pub use service::{ServiceRegisteredCallback, ServiceRegistration}; pub use service_type::*; /// Type alias for the platform-specific mDNS browser implementation -#[cfg(target_os = "linux")] +#[cfg(all(target_os = "linux", feature = "avahi"))] pub type MdnsBrowser = avahi::browser::AvahiMdnsBrowser; /// Type alias for the platform-specific mDNS browser implementation #[cfg(any(target_vendor = "apple", target_vendor = "pc"))] pub type MdnsBrowser = bonjour::browser::BonjourMdnsBrowser; /// Type alias for the platform-specific mDNS service implementation -#[cfg(target_os = "linux")] +#[cfg(all(target_os = "linux", feature = "avahi"))] pub type MdnsService = avahi::service::AvahiMdnsService; /// Type alias for the platform-specific mDNS service implementation #[cfg(any(target_vendor = "apple", target_vendor = "pc"))] pub type MdnsService = bonjour::service::BonjourMdnsService; /// Type alias for the platform-specific structure responsible for polling the mDNS event loop -#[cfg(target_os = "linux")] +#[cfg(all(target_os = "linux", feature = "avahi"))] pub type EventLoop = avahi::event_loop::AvahiEventLoop; /// Type alias for the platform-specific structure responsible for polling the mDNS event loop #[cfg(any(target_vendor = "apple", target_vendor = "pc"))] @@ -256,7 +256,7 @@ pub type EventLoop = bonjour::event_loop::BonjourEventLoop; /// Type alias for the platform-specific structure responsible for storing and accessing TXT /// record data -#[cfg(target_os = "linux")] +#[cfg(all(target_os = "linux", feature = "avahi"))] pub type TxtRecord = avahi::txt_record::AvahiTxtRecord; /// Type alias for the platform-specific structure responsible for storing and accessing TXT /// record data diff --git a/zeroconf/src/service.rs b/zeroconf/src/service.rs index e6e7360..e9478b6 100644 --- a/zeroconf/src/service.rs +++ b/zeroconf/src/service.rs @@ -1,12 +1,16 @@ //! Trait definition for cross-platform service. -use crate::{EventLoop, NetworkInterface, Result, ServiceType, TxtRecord}; +use crate::prelude::{TEventLoop, TTxtRecord}; +use crate::{NetworkInterface, Result, ServiceType}; use std::any::Any; use std::sync::Arc; /// Interface for interacting with underlying mDNS service implementation registration /// capabilities. pub trait TMdnsService { + type EventLoop: TEventLoop; + type TxtRecord: TTxtRecord; + /// Creates a new `MdnsService` with the specified `ServiceType` (e.g. `_http._tcp`) and `port`. fn new(service_type: ServiceType, port: u16) -> Self; @@ -45,10 +49,10 @@ pub trait TMdnsService { fn host(&self) -> Option<&str>; /// Sets the optional `TxtRecord` to register this service with. - fn set_txt_record(&mut self, txt_record: TxtRecord); + fn set_txt_record(&mut self, txt_record: Self::TxtRecord); /// Returns the optional `TxtRecord` to register this service with. - fn txt_record(&self) -> Option<&TxtRecord>; + fn txt_record(&self) -> Option<&Self::TxtRecord>; /// Sets the [`ServiceRegisteredCallback`] that is invoked when the service has been /// registered. @@ -65,7 +69,7 @@ pub trait TMdnsService { /// Registers and start's the service. Returns an `EventLoop` which can be called to keep /// the service alive. - fn register(&mut self) -> Result; + fn register(&mut self) -> Result; } /// Callback invoked from [`MdnsService`] once it has successfully registered. diff --git a/zeroconf/src/txt_record.rs b/zeroconf/src/txt_record.rs index d2706ac..90e2277 100644 --- a/zeroconf/src/txt_record.rs +++ b/zeroconf/src/txt_record.rs @@ -149,7 +149,13 @@ impl Debug for TxtRecord { } } -#[cfg(test)] +#[cfg(all( + test, + any( + all(target_os = "linux", feature = "avahi"), + all(target_vendor = "apple", target_vendor = "pc"), + ) +))] mod tests { use super::*; use crate::TxtRecord;