Skip to content

Conversation

@lorenzleutgeb
Copy link

@lorenzleutgeb lorenzleutgeb commented Oct 15, 2025

Progress towards #82. As of 2025-10-16, this is only a draft, to get early feedback.

Please read the commit messages. I realized that the two implementations are actually leaked through the respective traits. This prevents cleanly providing a third implementation. Before I go any further, I'd like your feedback. Because honestly if we don't figure this out and agree, it would not make much sense to continue.

In preparation to contribute other implementations on Linux, such as one
based on `systemd-resolved`, add a feature to this crate to enable
`avahi`.

To maximise backwards compatibility, the newly introduced feature flag
is enabled by default. Dependents that deliberately disabled default
features will see breakage, but can easily recover by enabling the new
feature.
The layout of the crate promises extensibility, but the traits depend on
`crate::{TxtRecord,EventLoop}` which actually are particular
implementations. This makes it impossible to e.g. provide additional
implementations for the traits on Linux, which are not directly tied to
the already existing Avahi implementation.

To resolve this, use associated types.
@windy1
Copy link
Owner

windy1 commented Oct 18, 2025

There seems to be a little confusion, so maybe I can help clear this up before I provide a more granular review. The purpose of this library is to provide a cross-platform interface for platform-specific mDNS implementations, i.e. Avahi and Bonjour. Therefore, there is no need to add a feature flag for the individual libraries because Bonjour is the de facto standard for macOS/Windows, as Avahi is for Linux. If we were to add additional implementations per-platform, then a feature would be appropriate, but as it stands now, you must have at least one of these.

To implement your requested feature, my recommendation would be to allow registration of some kind of side effect handler/callback that can be invoked in the implementations. What you've previously described is something core to how mDNS works, so both Avahi and Bonjour should be implemented on the common traits. That said, I am not inherently against providing implementation specific interfaces should there be a specific behavior that is present in one implementation, but not another that we wish to expose, but that does not seem to be the case here.

Hope this helps you get a better understanding of the motive of this library, and I am happy to answer any questions you may have!

@lorenzleutgeb
Copy link
Author

lorenzleutgeb commented Oct 18, 2025

The purpose of this library is to provide a cross-platform interface for platform-specific mDNS implementations, i.e. Avahi and Bonjour. Therefore, there is no need to add a feature flag for the individual libraries because Bonjour is the de facto standard for macOS/Windows, as Avahi is for Linux.

I understand that Avahi is quite common and might be regarded as the de facto standard. However, I do not use Avahi, and would still like to use this library.

If we were to add additional implementations per-platform, then a feature would be appropriate, but as it stands now, you must have at least one of these.

I am trying to change this, so that Linux users do not have to have Avahi installed to use this library, but they may also use systemd-resolved. So, I argue a feature would be appropriate, and this is the reason why you can see one being added in the (draft) changes pushed.

For more details on systemd-resolved, please refer to:

To state it very clearly: This is an alternative to Avahi.

To implement your requested feature, my recommendation would be to allow registration of some kind of side effect handler/callback that can be invoked in the implementations.

Sorry, here I just fail to understand what you mean. I do not understand what "kind of side effect handler/callback" you would want to have "invoked in the implementations". Maybe you can give more concrete examples so that I have an easier time following? Thanks.

What you've previously described is something core to how mDNS works, so both Avahi and Bonjour should be implemented on the common traits.

I also have trouble following here, probably in part due to failure to understand the preceding sentence, as I do not see what you are referring to as "previously described". Maybe you could be more specific? Thanks.

@windy1
Copy link
Owner

windy1 commented Oct 18, 2025

To state it very clearly: This is an alternative to Avahi.

Ah! Thank you for the clarification, I misunderstood your original request. I was under the impression that you wanted to expose the internal resolution handlers. Your direction seems reasonable to me then, and I am not against adding implementation alternatives.

edit: One caveat, I would like these changes to be opt-in. I can see you have already made avahi the default, but thought it would be worth mentioning.

@lorenzleutgeb
Copy link
Author

lorenzleutgeb commented Oct 18, 2025

One caveat, I would like these changes to be opt-in. I can see you have already made avahi the default, but thought it would be worth mentioning.

Feature Flag for Avahi

I have added the feature flag "avahi" for supporting Avahi, but at the same time also added it to the list of default features. This means that all dependents that did not explicitly select default-features = false, will not notice a change. Those dependents that have selected default-features = false in their Cargo.toml (which is relatively rare), will have to make a very simple change, like so:

 [dependencies]
 zeroconf = {
   version = "...",
   default-features = false,
   features = [
+    "avahi",
     "serde"
   ]
 }

(The "serde" feature here is just an example. Their list of enabled features might be empty.)

Feature Flag for systemd

All changes (to Rust code in this crate, and to the declaration of its dependencies in Cargo.toml) that relate to systemd-resolved would be guarded by a feature flag "systemd".

Additivity of Features

To be compatible with Cargo feature unification all features must be additive. That means, the crate must compile if dependents decide to enable both "avahi" and "systemd". Combine this with the desire for backwards compatibility, and this means that the types zeroconf::{MdnsBrowser,MdnsService} must always map to the Avahi implementations.

Submodule for systemd

Just like the module zeroconf::avahi would be guarded by the feature flag "avahi", the module zeroconf::systemd I am suggesting to introduce would be guarded by the feature flag "systemd".

To help dependents choose at runtime which of the two implementations they might want to use, I suggest to implement a fn zeroconf::detect_implementation() -> zeroconf::Implementation or similar, where

enum Implementation {
  #[cfg(all(feature = "avahi", target_os = "linux")]
  Avahi,
  #[cfg(any(target_vendor = "apple", target_vendor = "pc"))]
  Bonjour,
  #[cfg(all(feature = "systemd", target_os = "linux")]
  Systemd,
}

Note at this point, that this is all optional, and no dependent would be forced to call detect_implementation just by the fact that systemd-resolved would be supported. The exported types would still remain where they are, and dependents that want to use systemd would opt-in as you asked.

Leaky Abstraction

However to get there, some types must be associated to the trait, and not leaked to an exported name of the crate and used in the trait definitions. The leak must have happened because the authors did not expect another implementation to pop up. See f1c21f6

@windy1
Copy link
Owner

windy1 commented Oct 18, 2025

Makes sense, thank you for your overview. You are right in thinking that I did not anticipate multiple implementations for a single platform when I started out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants