Crate mdns_sd

source · []
Expand description

A small and safe library for Multicast DNS-SD (Service Discovery).

This library creates one new thread to run a mDNS daemon, and exposes its API that interacts with the daemon via a crossbeam-channel.

For example, a client querying (browsing) a service behaves like this:

  Client       <channel>       mDNS daemon thread
    |                             | starts its run-loop.
    |       --- Browse -->        |
    |                             | detects services
    |                             | finds service instance A
    |       <-- Found A --        |
    |           ...               | resolves service A
    |       <-- Resolved A --     |
    |           ...               |

All commands in the public API are sent to the daemon using the unblocking try_send() so that the caller can use it with both sync and async code, with no dependency on any particular async runtimes.

Usage

The user starts with creating a daemon by calling ServiceDaemon::new(). Then as a mDNS querier, the user would call browse to search for services, and/or as a mDNS responder, call register to publish (i.e. announce) its own service. And, the daemon type can be cloned and passed around between threads.

Example: a client querying for a service type.

use mdns_sd::{ServiceDaemon, ServiceEvent};

// Create a daemon
let mdns = ServiceDaemon::new().expect("Failed to create daemon");

// Browse for a service type.
let service_type = "_mdns-sd-my-test._udp.local.";
let receiver = mdns.browse(service_type).expect("Failed to browse");

// Receive the browse events in sync or async. Here is
// an example of using a thread. Users can call `receiver.try_recv()`
// if running in async environment.
std::thread::spawn(move || {
    while let Ok(event) = receiver.recv() {
        match (event) {
            ServiceEvent::ServiceResolved(info) => {
                println!("Resolved a new service: {}", info.get_fullname());
            }
            other_event => {
                println!("Received other event: {:?}", &other_event);
            }
        }
    }
});

Example: a server publishs a service and responds to queries.

use mdns_sd::{ServiceDaemon, ServiceInfo};
use std::collections::HashMap;

// Create a daemon
let mdns = ServiceDaemon::new().expect("Failed to create daemon");

// Create a service info.
let service_type = "_mdns-sd-my-test._udp.local.";
let instance_name = "my_instance";
let host_ipv4 = "192.168.1.12";
let host_name = "192.168.1.12.local.";
let port = 5200;
let mut properties = HashMap::new();
properties.insert("property_1".to_string(), "test".to_string());
properties.insert("property_2".to_string(), "1234".to_string());

let my_service = ServiceInfo::new(
    service_type,
    instance_name,
    host_name,
    host_ipv4,
    port,
    Some(properties),
);

// Register with the daemon, which publishs the service.
mdns.register(my_service).expect("Failed to register our service");

Limitations

This implementation is based on the following RFCs:

We focus on the common use cases at first, and currently have the following limitations:

  • Only support IPv4, not IPv6.
  • Only support multicast, not unicast send/recv.
  • Only tested on Linux and MacOS, not on Windows or other OSes.

Structs

A daemon thread for mDNS

Complete info about a Service Instance.

Enums

A basic error type from this library.

All possible events sent to the client from the daemon.

Response status code for the service unregister call.

Type Definitions

The metrics is a HashMap of (name_key, i64_value). The main purpose is to help monitoring the mDNS packet traffic.

One and only Result type from this library crate.