Project

dns-sd

0.0
No commit activity in last 3 years
No release in over 3 years
If you need to retrieve and work with DNS-SD records, this is the library you've been waiting for.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies
 Project Readme

DNS-SD is a method of laying out standard DNS records in such a way that permits service discovery and enumeration, high availability, load balancing, and failover of arbitrary services. Whilst it is often used in concert with Multicast DNS (mDNS), it works just as well with regular DNS services, and that is what this package is focused on. If you're interested in mDNS-based DNS-SD interaction, the similarly-named dnssd gem might be more to your liking.

Installation

It's a gem:

gem install dns-sd

There's also the wonders of the Gemfile:

gem 'dns-sd'

If you're the sturdy type that likes to run from git:

rake install

Or, if you've eschewed the convenience of Rubygems entirely, then you presumably know what to do already.

Usage

The basic class, DNSSD, is the usual entrypoint for everything:

require 'dns-sd'

dnssd = DNSSD.new("example.com")

From there, you can connect directly to a service instance, get a service type so you can ask it for all available instances, or even ask for all services in the domain.

The sub-sections below show some common usage patterns. If your specific use case isn't covered, the per-class documentation may be more enlightening.

Connecting to a service instance

If you know what service and instance you're interested in, you can go straight there:

my_printer = dnssd.service_instance("My Printer", "ipp", :TCP)

Then get the connection targets and even try connecting to them:

targets = my_printer.targets

sock = begin
  break nil if targets.empty?
  t = targets.shift
  TCPSocket.new(t.hostname, t.port)
rescue SystemCallError
  # Automatically go on to the next server
  retry
end

if sock.nil?
  $stderr.puts "Failed to connect to My Printer"
else
  # Work with `sock` as required
end

If there's more than one target registered for a given service instance (common in high-availability and load-balanced systems), every time you call DNSSD::ServiceInstance#targets, you'll get the server list in a different order, respecting the priorities and weights of the constituent SRV records.

The SRV record lookups (like all DNS records) are cached, so if you wish to connect to a service instance repeatedly, you should call #targets on your service instance object each time you want to make a connection, rather than re-using the result of a single call to #target. As long as you're operating against the same DNSSD::ServiceInstance object and the record TTLs haven't expired, successive calls to #target should be very efficient.

Enumerating all instances of a service

If you know you want a printer, but aren't sure which one, you can ask for the IPP service, and then enumerate all the service instances:

dnssd.service("ipp", :TCP).each do |name, instance|
  puts "I found a printer named #{name}"
  puts "Its targets are #{instance.targets.map { |t| "#{t.hostname}:#{t.port}" }.join(", ")}"
end

Enumerating all services

If you're just curious about what might be on a domain, you can try the "Service Type Enumeration" endpoint:

dnssd.services.each do |name, svc|
  puts "I found a service named #{name}"
  puts "It has instances of #{svc.instances.map { |i| i.name }.join(", ")}"
end

Contributing

Bug reports should be sent to the Github issue tracker. Patches can be sent as a Github pull request.

Licence

Unless otherwise stated, everything in this repo is covered by the following copyright notice:

Copyright (C) 2017, 2019 Civilized Discourse Construction Kit, Inc.

This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License version 3, as
published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.