mDNS Service Discovery

The st.mdns module provides an interface for performing service discovery on the local network for LAN Edge Drivers. It leverages the mDNS Protocol and DNS Service Discovery, which are systems that build on top of the concepts and data structures from traditional DNS and adapts them to run over UDP Multicast as well as advertising “services” in addition to just hostname resolution. This removes the need to have an authoritative central name server, making it very suitable for individual devices to advertise service discovery information on their own.

For more information about DNS, DNS Service Discovery, and mDNS, consult their RFCs:

The entry point most likely to be useful is mdns.discover which takes a Service Type string and a Domain string, then attempts to find and resolves all hosts that provide that service on the local network.

Note: any mDNS services not on the local network will not be included in the response.

A good example of a LAN integration that uses mDNS for service discovery is Philips Hue. A simple example of what browsing for Hue bridges would look like:

-- scan for Hue bridges on the local network
local discover_responses = mdns.discover("_hue._tcp", "local") or {}

for idx, found in ipairs(discover_responses.found) do
  -- sanity check that the answer contains a response to the correct service type,
  -- and we only want to process ipv4
  if found ~= nil and found.service_info.name == "_hue._tcp"
      and not net_utils.validate_ipv4_string(found.host_info.address) then
    -- process response
  end
end

mDNS Module Documentation

st.mdns.discover(service_type, domain)

Perform mdns/DNS-SD discovery for service types on the given domain.

Service types in a search query are often prefixed with underscores by convention to avoid collisions with existing hostnames.

For network services, they are often composed of two parts: The unique service name, followed by a dot, and then the underlying transport protocol being used. For example, the Philips Hue bridge advertises itself as the “hue” service, and because it’s a REST API it goes over TCP. As such, to search for Hue bridges on the local domain, you should use _hue._tcp as the service name, and local as the domain. Another example would be Apple’s AirPlay service, which is also TCP-backed and advertises itself as “airplay”, meaning the search term would use _airplay._tcp on the local domain (again noting the underscores).

Replies to the query should be a deduplicated list of responses; however, if a service supports IPv4 and IPv6 you may receive multiple responses for the same host name, one for each interface. So if, for example, you only need to process IPv4 responses, you can use something like the validation tools in net_utils to ignore responses that are IPv6.

Parameters
  • service_type (str) – the service type to search for hosts on

  • domain (str) – the domain to search for hosts on

Returns

the response to the query, or nil if there was an error.

Return type

ServiceDiscoveryResponse or nil

Returns

error message if any

Return type

nil or str

st.mdns.resolve(host, service_type, domain)

Resolve the IP address needed to interact with a service given the host name, service type,

and domain. Note that “resolve” in the context of DNS Service Discovery over mDNS can refer to resolving a PTR record to an SRV record, or refer to resolving an SRV record to an A/AAAA record. What this API does is:

> Given a hostname and a service type, find all of the A/AAAA records that resolve the host > argument by performing a browse for the given service type and following the PTR and SRV > records to find all of the relevant hostnames.

If you don’t know the specific host name of the host providing the service, the discover API will instead perform browse for the given service type and return all of the SRV,PTR,TXT, and A/AAAA record information for all responders for that service on the given domain.

Parameters
  • host (str) – the hostname to resolve

  • service_type (str) – the service type to search for hosts on

  • domain (str) – the domain to search for hosts on

Returns

the response to the query, or nil if there was an error.

Return type

list[HostInfo] or nil

Returns

error message if any

Return type

nil or str

class st.mdns.ServiceInfo
name: str

the informational name of the service record

service_type: str

the service type, which should match the one passed in during the query

domain: str

the domain on which the service is located, which should match the one passed in during the query

class st.mdns.HostInfo
name: str

The hostname on the domain.

address: str

The IP address as a string at which the host can be reached.

port: integer

The port number as an integer for the service on the host

class st.mdns.RawTxtRecord
text: list[str]

an array of raw byte strings. Each element in the array represents a record in its entirety as a single byte string; this means that for key-value type records, the string has the entire <key=value> contents as a single item.

class st.mdns.ServiceDiscoveryEvent
service_info: ServiceInfo
host_info: HostInfo
txt: RawTxtRecord
class st.mdns.ServiceDiscoveryResponse

All responses to a service discovery request.

found: list[ServiceDiscoveryEvent]

Information about found hosts for the given service type