Class: DNSSD::Service
- Inherits:
-
Object
- Object
- DNSSD::Service
- Includes:
- Enumerable
- Defined in:
- lib/dnssd/service.rb,
ext/dnssd/service.c
Overview
A DNSSD::Service may be used for one DNS-SD call at a time. The service is automatically stopped after calling. A single service can not be reused multiple times.
DNSSD::Service provides the raw DNS-SD functions via the _
variants.
Direct Known Subclasses
Defined Under Namespace
Classes: Register
Constant Summary collapse
- IPv4 =
IPv4 protocol for #getaddrinfo
ULONG2NUM(kDNSServiceProtocol_IPv4)
- IPv6 =
IPv6 protocol for #getaddrinfo
ULONG2NUM(kDNSServiceProtocol_IPv6)
- MAX_DOMAIN_NAME =
Maximum length for a domain name
ULONG2NUM(kDNSServiceMaxDomainName)
- MAX_SERVICE_NAME =
Maximum length for a service name
ULONG2NUM(kDNSServiceMaxServiceName)
- DaemonVersion =
DaemonVersion property value
rb_str_new2(kDNSServiceProperty_DaemonVersion)
- TCP =
TCP protocol for creating NAT port mappings
ULONG2NUM(kDNSServiceProtocol_TCP)
- UDP =
UDP protocol for creating NAT port mappings
ULONG2NUM(kDNSServiceProtocol_UDP)
Class Method Summary collapse
-
.browse(type, domain = nil, flags = 0, interface = DNSSD::InterfaceAny) ⇒ Object
Browse for services.
-
.check_domain(domain) ⇒ Object
Raises an ArgumentError if
domain
is too long including NULL terminator and trailing ‘.’. -
.enumerate_domains(flags = DNSSD::Flags::BrowseDomains, interface = DNSSD::InterfaceAny, &block) ⇒ Object
Enumerate domains available for browsing and registration.
-
.DNSSD::Service.fullname(name, type, domain) ⇒ Object
Concatenate a three-part domain name like DNSSD::Reply#fullname into a properly-escaped full domain name.
-
.get_property(property) ⇒ Object
Binding for DNSServiceGetProperty.
-
.getaddrinfo(host, protocol = 0, flags = 0, interface = DNSSD::InterfaceAny, &block) ⇒ Object
Retrieve address information for
host
onprotocol
. -
.query_record(fullname, record_type, record_class = DNSSD::Record::IN, flags = 0, interface = DNSSD::InterfaceAny) ⇒ Object
Retrieves an arbitrary DNS record.
-
.register(name, type, domain, port, host = nil, text_record = nil, flags = 0, interface = DNSSD::InterfaceAny) ⇒ Object
Register a service.
-
.resolve(name, type = name.type, domain = name.domain, flags = 0, interface = DNSSD::InterfaceAny) ⇒ Object
Resolve a service discovered via #browse.
Instance Method Summary collapse
- #async_each(timeout = :never) ⇒ Object
- #each(timeout = :never) ⇒ Object
-
#initialize ⇒ Service
constructor
Creates a new DNSSD::Service.
- #push(record) ⇒ Object
-
#started? ⇒ Boolean
Returns true if the service has been started.
- #stop ⇒ Object
Constructor Details
#initialize ⇒ Service
Creates a new DNSSD::Service
23 24 25 26 27 28 |
# File 'lib/dnssd/service.rb', line 23 def initialize @replies = [] @continue = true @thread = nil @lock = Mutex.new end |
Class Method Details
.browse(type, domain = nil, flags = 0, interface = DNSSD::InterfaceAny) ⇒ Object
62 63 64 65 66 67 |
# File 'lib/dnssd/service.rb', line 62 def self.browse type, domain = nil, flags = 0, interface = DNSSD::InterfaceAny check_domain domain interface = DNSSD.interface_index interface unless Integer === interface _browse flags.to_i, interface, type, domain end |
.check_domain(domain) ⇒ Object
Raises an ArgumentError if domain
is too long including NULL terminator and trailing ‘.’
108 109 110 111 112 |
# File 'lib/dnssd/service.rb', line 108 def self.check_domain(domain) return unless domain raise ArgumentError, 'domain name string is too long' if domain.length >= MAX_DOMAIN_NAME - 1 end |
.enumerate_domains(flags = DNSSD::Flags::BrowseDomains, interface = DNSSD::InterfaceAny, &block) ⇒ Object
128 129 130 131 132 133 |
# File 'lib/dnssd/service.rb', line 128 def self.enumerate_domains(flags = DNSSD::Flags::BrowseDomains, interface = DNSSD::InterfaceAny, &block) interface = DNSSD.interface_index interface unless Integer === interface _enumerate_domains flags.to_i, interface end |
.DNSSD::Service.fullname(name, type, domain) ⇒ Object
Concatenate a three-part domain name like DNSSD::Reply#fullname into a properly-escaped full domain name.
Any dots or slashes in the name
must NOT be escaped.
name
may be nil
(to construct a PTR record name, e.g. “_ftp._tcp.apple.com”).
The type
is the service type followed by the protocol, separated by a dot (e.g. “_ftp._tcp”).
The domain
is the domain name, e.g. “apple.com”. Any literal dots or backslashes must be escaped.
Raises ArgumentError if the full service name cannot be constructed from the arguments.
106 107 108 109 110 111 112 113 114 115 |
# File 'ext/dnssd/service.c', line 106
static VALUE
dnssd_service_s_fullname(VALUE klass, VALUE _name, VALUE _type, VALUE _domain) {
char * name, * type, * domain;
dnssd_utf8_cstr(_name, name);
dnssd_utf8_cstr(_type, type);
dnssd_utf8_cstr(_domain, domain);
return create_fullname(name, type, domain);
}
|
.get_property(property) ⇒ Object
Binding for DNSServiceGetProperty. The only property currently supported in DNSSD is DaemonVersion
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'ext/dnssd/service.c', line 125
static VALUE
dnssd_service_s_get_property(VALUE klass, VALUE _property) {
char * property;
uint32_t result = 0;
uint32_t size = sizeof(result);
DNSServiceErrorType e;
dnssd_utf8_cstr(_property, property);
e = DNSServiceGetProperty(property, (void *)&result, &size);
dnssd_check_error_code(e);
/* as of this writing only a uint32_t will be returned */
return ULONG2NUM(result);
}
|
.getaddrinfo(host, protocol = 0, flags = 0, interface = DNSSD::InterfaceAny, &block) ⇒ Object
Retrieve address information for host
on protocol
addresses = []
service.getaddrinfo reply.target do |addrinfo|
addresses << addrinfo.address
break unless addrinfo.flags.more_coming?
end
When using DNSSD on top of the Avahi compatibilty shim you’ll need to setup your /etc/nsswitch.conf correctly. See avahi.org/wiki/AvahiAndUnicastDotLocal for details
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/dnssd/service.rb', line 148 def self.getaddrinfo(host, protocol = 0, flags = 0, interface = DNSSD::InterfaceAny, &block) interface = DNSSD.interface_index interface unless Integer === interface if respond_to? :_getaddrinfo, true then _getaddrinfo flags.to_i, interface, protocol, host else family = case protocol when IPv4 then Socket::AF_INET when IPv6 then Socket::AF_INET6 else protocol end addrinfo = Socket.getaddrinfo host, nil, family list = addrinfo.map do |_, _, a_host, ip, _| sockaddr = Socket.pack_sockaddr_in 0, ip DNSSD::Reply::AddrInfo.new(self, 0, 0, a_host, sockaddr, 0) end def list.stop; end list end end |
.query_record(fullname, record_type, record_class = DNSSD::Record::IN, flags = 0, interface = DNSSD::InterfaceAny) ⇒ Object
Retrieves an arbitrary DNS record
fullname
is the full name of the resource record. record_type
is the type of the resource record (see DNSSD::Resource).
flags
may be either DNSSD::Flags::ForceMulticast or DNSSD::Flags::LongLivedQuery
service.query_record "hostname._afpovertcp._tcp.local",
DNSService::Record::SRV do |record|
p record
end
186 187 188 189 190 191 |
# File 'lib/dnssd/service.rb', line 186 def self.query_record(fullname, record_type, record_class = DNSSD::Record::IN, flags = 0, interface = DNSSD::InterfaceAny) interface = DNSSD.interface_index interface unless Integer === interface _query_record flags.to_i, interface, fullname, record_type, record_class end |
.register(name, type, domain, port, host = nil, text_record = nil, flags = 0, interface = DNSSD::InterfaceAny) ⇒ Object
Register a service. A DNSSD::Reply object is passed to the optional block when the registration completes.
service.register "My Files", "_http._tcp", nil, 8080 do |r|
puts "successfully registered: #{r.inspect}"
end
201 202 203 204 205 206 207 208 |
# File 'lib/dnssd/service.rb', line 201 def self.register(name, type, domain, port, host = nil, text_record = nil, flags = 0, interface = DNSSD::InterfaceAny) check_domain domain interface = DNSSD.interface_index interface unless Integer === interface text_record = text_record.encode if text_record _register flags.to_i, interface, name, type, domain, host, port, text_record end |
.resolve(name, type = name.type, domain = name.domain, flags = 0, interface = DNSSD::InterfaceAny) ⇒ Object
Resolve a service discovered via #browse.
name
may be either the name of the service found or a DNSSD::Reply from DNSSD::Service#browse. When name
is a DNSSD::Reply, type
and domain
are automatically filled in, otherwise the service type and domain must be supplied.
The service is resolved to a target host name, port number, and text record, all contained in the DNSSD::Reply object passed to the required block.
service.resolve "foo bar", "_http._tcp", "local" do |r|
p r
end
226 227 228 229 230 231 232 233 |
# File 'lib/dnssd/service.rb', line 226 def self.resolve(name, type = name.type, domain = name.domain, flags = 0, interface = DNSSD::InterfaceAny) name = name.name if DNSSD::Reply === name check_domain domain interface = DNSSD.interface_index interface unless Integer === interface _resolve flags.to_i, interface, name, type, domain end |
Instance Method Details
#async_each(timeout = :never) ⇒ Object
93 94 95 96 97 98 |
# File 'lib/dnssd/service.rb', line 93 def async_each timeout = :never @lock.synchronize do raise DNSSD::Error, 'already stopped' unless @continue @thread = Thread.new { each(timeout) { |r| yield r } } end end |
#each(timeout = :never) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/dnssd/service.rb', line 69 def each timeout = :never raise DNSSD::Error, 'already stopped' unless @continue return enum_for __method__, timeout unless block_given? io = IO.new ref_sock_fd rd = [io] start_at = clock_time while @continue break unless timeout == :never || clock_time - start_at < timeout if IO.select rd, nil, nil, 1 begin process_result rescue DNSSD::UnknownError end @replies.each { |r| yield r } @replies.clear end end end |
#push(record) ⇒ Object
100 101 102 |
# File 'lib/dnssd/service.rb', line 100 def push record @replies << record end |
#started? ⇒ Boolean
Returns true if the service has been started.
238 239 240 |
# File 'lib/dnssd/service.rb', line 238 def started? @continue end |