dnssd 2.0.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.txt +2 -2
- data/Rakefile +6 -1
- data/ext/dnssd/dnssd.c +0 -33
- data/ext/dnssd/dnssd.h +0 -6
- data/ext/dnssd/extconf.rb +0 -8
- data/ext/dnssd/service.c +103 -136
- data/lib/dnssd.rb +35 -71
- data/lib/dnssd/reply/browse.rb +6 -3
- data/lib/dnssd/reply/query_record.rb +0 -2
- data/lib/dnssd/reply/register.rb +5 -0
- data/lib/dnssd/reply/resolve.rb +4 -3
- data/lib/dnssd/service.rb +95 -102
- data/lib/dnssd/text_record.rb +26 -23
- data/test/test_dnssd.rb +65 -26
- data/test/test_dnssd_flags.rb +2 -3
- data/test/test_dnssd_record.rb +10 -6
- data/test/test_dnssd_reply.rb +2 -3
- data/test/test_dnssd_reply_browse.rb +15 -9
- data/test/test_dnssd_reply_query_record.rb +2 -3
- data/test/test_dnssd_reply_resolve.rb +6 -4
- data/test/test_dnssd_service.rb +175 -7
- data/test/test_dnssd_text_record.rb +2 -3
- metadata +8 -8
data/lib/dnssd.rb
CHANGED
@@ -13,7 +13,7 @@ module DNSSD
|
|
13
13
|
##
|
14
14
|
# The version of DNSSD you're using.
|
15
15
|
|
16
|
-
VERSION = '
|
16
|
+
VERSION = '3.0.0'
|
17
17
|
|
18
18
|
##
|
19
19
|
# Registers +socket+ with DNSSD as +name+. If +service+ is omitted it is
|
@@ -32,7 +32,7 @@ module DNSSD
|
|
32
32
|
|
33
33
|
raise ArgumentError, 'socket not bound' if port == 0
|
34
34
|
|
35
|
-
service ||=
|
35
|
+
service ||= Socket.getservbyport port
|
36
36
|
|
37
37
|
proto = case socket
|
38
38
|
when TCPSocket then 'tcp'
|
@@ -65,38 +65,29 @@ module DNSSD
|
|
65
65
|
##
|
66
66
|
# Asynchronous version of DNSSD::Service#browse
|
67
67
|
|
68
|
-
def self.browse
|
69
|
-
|
70
|
-
service
|
71
|
-
|
72
|
-
Thread.start do
|
73
|
-
run(service, :browse, type, domain, flags, interface, &block)
|
74
|
-
end
|
75
|
-
|
68
|
+
def self.browse type, domain = nil, flags = 0, interface = DNSSD::InterfaceAny
|
69
|
+
service = DNSSD::Service.browse type, domain, flags, interface
|
70
|
+
service.async_each { |r| yield r }
|
76
71
|
service
|
77
72
|
end
|
78
73
|
|
79
74
|
##
|
80
75
|
# Synchronous version of DNSSD::Service#browse
|
81
76
|
|
82
|
-
def self.browse!
|
83
|
-
|
84
|
-
service
|
85
|
-
|
86
|
-
|
77
|
+
def self.browse! type, domain = nil, flags = 0, interface = DNSSD::InterfaceAny
|
78
|
+
service = DNSSD::Service.browse type, domain, flags, interface
|
79
|
+
service.each { |r| yield r }
|
80
|
+
ensure
|
81
|
+
service.stop
|
87
82
|
end
|
88
83
|
|
89
84
|
##
|
90
85
|
# Asynchronous version of DNSSD::Service#enumerate_domains
|
91
86
|
|
92
|
-
def self.enumerate_domains
|
93
|
-
interface = DNSSD::InterfaceAny
|
94
|
-
service = DNSSD::Service.
|
95
|
-
|
96
|
-
Thread.start do
|
97
|
-
run(service, :enumerate_domains, flags, interface, &block)
|
98
|
-
end
|
99
|
-
|
87
|
+
def self.enumerate_domains flags = DNSSD::Flags::BrowseDomains,
|
88
|
+
interface = DNSSD::InterfaceAny
|
89
|
+
service = DNSSD::Service.enumerate_domains flags, interface
|
90
|
+
service.async_each { |r| yield r }
|
100
91
|
service
|
101
92
|
end
|
102
93
|
|
@@ -105,27 +96,21 @@ module DNSSD
|
|
105
96
|
|
106
97
|
def self.enumerate_domains!(flags = DNSSD::Flags::BrowseDomains,
|
107
98
|
interface = DNSSD::InterfaceAny, &block)
|
108
|
-
service = DNSSD::Service.
|
109
|
-
|
110
|
-
|
99
|
+
service = DNSSD::Service.enumerate_domains flags, interface
|
100
|
+
service.each { |r| yield r }
|
101
|
+
ensure
|
102
|
+
service.stop
|
111
103
|
end
|
112
104
|
|
113
105
|
##
|
114
106
|
# Asynchronous version of DNSSD::Service#register
|
115
107
|
|
116
108
|
def self.register(name, type, domain, port, text_record = nil, flags = 0,
|
117
|
-
interface = DNSSD::InterfaceAny
|
118
|
-
service = DNSSD::Service.
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
run(service, :register, name, type, domain, port, nil, text_record,
|
123
|
-
flags, interface, &block)
|
124
|
-
end
|
125
|
-
else
|
126
|
-
service.register name, type, domain, port, nil, text_record, flags,
|
127
|
-
interface
|
128
|
-
end
|
109
|
+
interface = DNSSD::InterfaceAny)
|
110
|
+
service = DNSSD::Service.register name, type, domain, port, nil,
|
111
|
+
text_record, flags, interface
|
112
|
+
|
113
|
+
service.async_each { |r| yield r } if block_given?
|
129
114
|
|
130
115
|
service
|
131
116
|
end
|
@@ -135,53 +120,32 @@ module DNSSD
|
|
135
120
|
|
136
121
|
def self.register!(name, type, domain, port, text_record = nil, flags = 0,
|
137
122
|
interface = DNSSD::InterfaceAny, &block)
|
138
|
-
service = DNSSD::Service.
|
139
|
-
|
140
|
-
if block_given? then
|
141
|
-
run(service, :register, name, type, domain, port, nil, text_record, flags,
|
142
|
-
interface, &block)
|
143
|
-
else
|
144
|
-
service.register name, type, domain, port, nil, text_record, flags,
|
145
|
-
interface
|
146
|
-
end
|
123
|
+
service = DNSSD::Service.register name, type, domain, port, nil,
|
124
|
+
text_record, flags, interface
|
147
125
|
|
148
|
-
service
|
126
|
+
service.each { |r| yield r } if block_given?
|
127
|
+
ensure
|
128
|
+
service.stop
|
149
129
|
end
|
150
130
|
|
151
131
|
##
|
152
132
|
# Asynchronous version of DNSSD::Service#resolve
|
153
133
|
|
154
|
-
def self.resolve(*args
|
155
|
-
service = DNSSD::Service.
|
156
|
-
|
157
|
-
Thread.start do
|
158
|
-
run(service, :resolve, *args, &block)
|
159
|
-
end
|
160
|
-
|
134
|
+
def self.resolve(*args)
|
135
|
+
service = DNSSD::Service.resolve(*args)
|
136
|
+
service.async_each { |r| yield r }
|
161
137
|
service
|
162
138
|
end
|
163
139
|
|
164
140
|
##
|
165
141
|
# Synchronous version of DNSSD::Service#resolve
|
166
142
|
|
167
|
-
def self.resolve!(*args
|
168
|
-
service = DNSSD::Service.
|
169
|
-
|
170
|
-
run(service, :resolve, *args, &block)
|
171
|
-
end
|
172
|
-
|
173
|
-
##
|
174
|
-
# Dispatches +args+ and +block+ to +method+ on +service+ and ensures
|
175
|
-
# +service+ is shut down after use.
|
176
|
-
|
177
|
-
def self.run(service, method, *args, &block)
|
178
|
-
service.send(method, *args, &block)
|
179
|
-
|
180
|
-
service
|
143
|
+
def self.resolve!(*args)
|
144
|
+
service = DNSSD::Service.resolve(*args)
|
145
|
+
service.each { |r| yield r }
|
181
146
|
ensure
|
182
|
-
service.stop
|
147
|
+
service.stop if service
|
183
148
|
end
|
184
|
-
|
185
149
|
end
|
186
150
|
|
187
151
|
require 'socket'
|
data/lib/dnssd/reply/browse.rb
CHANGED
@@ -34,7 +34,7 @@ class DNSSD::Reply::Browse < DNSSD::Reply
|
|
34
34
|
def connect(family = Socket::AF_UNSPEC, addrinfo_flags = 0)
|
35
35
|
value = nil
|
36
36
|
|
37
|
-
DNSSD.resolve!
|
37
|
+
DNSSD.resolve! name, type, domain do |reply|
|
38
38
|
value = reply
|
39
39
|
break
|
40
40
|
end
|
@@ -42,11 +42,14 @@ class DNSSD::Reply::Browse < DNSSD::Reply
|
|
42
42
|
value.connect family, addrinfo_flags
|
43
43
|
end
|
44
44
|
|
45
|
+
def resolve
|
46
|
+
service = DNSSD::Service.resolve name, type, domain
|
47
|
+
service.first
|
48
|
+
end
|
49
|
+
|
45
50
|
def inspect # :nodoc:
|
46
51
|
"#<%s:0x%x %p interface: %s flags: %p>" % [
|
47
52
|
self.class, object_id, fullname, interface_name, @flags
|
48
53
|
]
|
49
54
|
end
|
50
|
-
|
51
55
|
end
|
52
|
-
|
data/lib/dnssd/reply/register.rb
CHANGED
@@ -27,6 +27,11 @@ class DNSSD::Reply::Register < DNSSD::Reply
|
|
27
27
|
set_names name, type, domain
|
28
28
|
end
|
29
29
|
|
30
|
+
def resolve
|
31
|
+
service = DNSSD::Service.resolve name, type, domain
|
32
|
+
service.first
|
33
|
+
end
|
34
|
+
|
30
35
|
def inspect # :nodoc:
|
31
36
|
"#<%s:0x%x %p flags: %p>" % [
|
32
37
|
self.class, object_id, fullname, @flags
|
data/lib/dnssd/reply/resolve.rb
CHANGED
@@ -63,10 +63,10 @@ class DNSSD::Reply::Resolve < DNSSD::Reply
|
|
63
63
|
else raise ArgumentError, "invalid family #{family}"
|
64
64
|
end
|
65
65
|
|
66
|
-
service = DNSSD::Service.
|
66
|
+
service = DNSSD::Service.getaddrinfo target, addrinfo_protocol,
|
67
|
+
addrinfo_flags, @interface
|
67
68
|
|
68
|
-
service.
|
69
|
-
@interface do |addrinfo|
|
69
|
+
service.each do |addrinfo|
|
70
70
|
address = addrinfo.address
|
71
71
|
|
72
72
|
begin
|
@@ -80,6 +80,7 @@ class DNSSD::Reply::Resolve < DNSSD::Reply
|
|
80
80
|
socket.connect address, port
|
81
81
|
end
|
82
82
|
|
83
|
+
service.stop
|
83
84
|
return socket
|
84
85
|
rescue
|
85
86
|
next if addrinfo.flags.more_coming?
|
data/lib/dnssd/service.rb
CHANGED
@@ -8,35 +8,42 @@ require 'thread'
|
|
8
8
|
# DNSSD::Service provides the raw DNS-SD functions via the +_+ variants.
|
9
9
|
|
10
10
|
class DNSSD::Service
|
11
|
+
include Enumerable
|
11
12
|
|
12
13
|
# :stopdoc:
|
13
14
|
IPv4 = 1 unless const_defined? :IPv4
|
14
15
|
IPv6 = 2 unless const_defined? :IPv6
|
15
16
|
# :startdoc:
|
16
17
|
|
18
|
+
class << self; private :new; end
|
19
|
+
|
17
20
|
##
|
18
21
|
# Creates a new DNSSD::Service
|
19
22
|
|
20
23
|
def initialize
|
21
|
-
@replies
|
24
|
+
@replies = []
|
22
25
|
@continue = true
|
23
|
-
@thread
|
24
|
-
@
|
26
|
+
@thread = nil
|
27
|
+
@lock = Mutex.new
|
25
28
|
end
|
26
29
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
#
|
33
|
-
# Returns the added DNSSD::Record
|
30
|
+
class Register < ::DNSSD::Service
|
31
|
+
def initialize
|
32
|
+
super
|
33
|
+
@records = []
|
34
|
+
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
##
|
37
|
+
# Adds an extra DNS record of +type+ containing +data+. +ttl+ is in
|
38
|
+
# seconds, use 0 for the default value. +flags+ are currently ignored.
|
39
|
+
#
|
40
|
+
# Must be called on a service only after #register.
|
41
|
+
#
|
42
|
+
# Returns the added DNSSD::Record
|
38
43
|
|
39
|
-
|
44
|
+
def add_record type, data, ttl = 0, flags = 0
|
45
|
+
@records << _add_record(flags.to_i, type, data, ttl)
|
46
|
+
end
|
40
47
|
end
|
41
48
|
|
42
49
|
##
|
@@ -52,56 +59,77 @@ class DNSSD::Service
|
|
52
59
|
# rescue Timeout::Error
|
53
60
|
# end
|
54
61
|
|
55
|
-
def browse
|
56
|
-
&block)
|
62
|
+
def self.browse type, domain = nil, flags = 0, interface = DNSSD::InterfaceAny
|
57
63
|
check_domain domain
|
58
64
|
interface = DNSSD.interface_index interface unless Integer === interface
|
59
65
|
|
60
|
-
|
66
|
+
_browse flags.to_i, interface, type, domain
|
67
|
+
end
|
61
68
|
|
62
|
-
|
69
|
+
def each timeout = :never
|
70
|
+
raise DNSSD::Error, 'already stopped' unless @continue
|
63
71
|
|
64
|
-
|
72
|
+
return enum_for __method__, timeout unless block_given?
|
73
|
+
|
74
|
+
io = IO.new ref_sock_fd
|
75
|
+
rd = [io]
|
76
|
+
|
77
|
+
start_at = clock_time
|
78
|
+
|
79
|
+
while @continue
|
80
|
+
break unless timeout == :never || clock_time - start_at < timeout
|
65
81
|
|
66
|
-
|
82
|
+
if IO.select rd, nil, nil, 1
|
83
|
+
begin
|
84
|
+
process_result
|
85
|
+
rescue DNSSD::UnknownError
|
86
|
+
end
|
87
|
+
@replies.each { |r| yield r }
|
88
|
+
@replies.clear
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def async_each timeout = :never
|
94
|
+
@lock.synchronize do
|
95
|
+
raise DNSSD::Error, 'already stopped' unless @continue
|
96
|
+
@thread = Thread.new { each(timeout) { |r| yield r } }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def push record
|
101
|
+
@replies << record
|
67
102
|
end
|
68
103
|
|
69
104
|
##
|
70
105
|
# Raises an ArgumentError if +domain+ is too long including NULL terminator
|
71
106
|
# and trailing '.'
|
72
107
|
|
73
|
-
def check_domain(domain)
|
108
|
+
def self.check_domain(domain)
|
74
109
|
return unless domain
|
75
110
|
raise ArgumentError, 'domain name string is too long' if
|
76
111
|
domain.length >= MAX_DOMAIN_NAME - 1
|
77
112
|
end
|
78
113
|
|
114
|
+
|
79
115
|
##
|
80
116
|
# Enumerate domains available for browsing and registration.
|
81
117
|
#
|
82
118
|
# For each domain found a DNSSD::Reply object is passed to block with
|
83
119
|
# #domain set to the enumerated domain.
|
84
120
|
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
# service.
|
88
|
-
#
|
121
|
+
# service = DNSSD::Service.enumerate_domains
|
122
|
+
#
|
123
|
+
# service.each do |r|
|
124
|
+
# p r.domain
|
89
125
|
# break unless r.flags.more_coming?
|
90
126
|
# end
|
91
|
-
#
|
92
|
-
# p available_domains
|
93
127
|
|
94
|
-
def enumerate_domains(flags = DNSSD::Flags::BrowseDomains,
|
128
|
+
def self.enumerate_domains(flags = DNSSD::Flags::BrowseDomains,
|
95
129
|
interface = DNSSD::InterfaceAny, &block)
|
96
130
|
interface = DNSSD.interface_index interface unless Integer === interface
|
97
131
|
|
98
|
-
raise DNSSD::Error, 'service in progress' if started?
|
99
|
-
|
100
132
|
_enumerate_domains flags.to_i, interface
|
101
|
-
|
102
|
-
@type = :enumerate_domains
|
103
|
-
|
104
|
-
process(&block)
|
105
133
|
end
|
106
134
|
|
107
135
|
##
|
@@ -117,18 +145,12 @@ class DNSSD::Service
|
|
117
145
|
# setup your /etc/nsswitch.conf correctly. See
|
118
146
|
# http://avahi.org/wiki/AvahiAndUnicastDotLocal for details
|
119
147
|
|
120
|
-
def getaddrinfo(host, protocol = 0, flags = 0,
|
148
|
+
def self.getaddrinfo(host, protocol = 0, flags = 0,
|
121
149
|
interface = DNSSD::InterfaceAny, &block)
|
122
150
|
interface = DNSSD.interface_index interface unless Integer === interface
|
123
151
|
|
124
|
-
if respond_to? :_getaddrinfo then
|
125
|
-
raise DNSSD::Error, 'service in progress' if started?
|
126
|
-
|
152
|
+
if respond_to? :_getaddrinfo, true then
|
127
153
|
_getaddrinfo flags.to_i, interface, protocol, host
|
128
|
-
|
129
|
-
@type = :getaddrinfo
|
130
|
-
|
131
|
-
process(&block)
|
132
154
|
else
|
133
155
|
family = case protocol
|
134
156
|
when IPv4 then Socket::AF_INET
|
@@ -138,43 +160,15 @@ class DNSSD::Service
|
|
138
160
|
|
139
161
|
addrinfo = Socket.getaddrinfo host, nil, family
|
140
162
|
|
141
|
-
addrinfo.
|
163
|
+
list = addrinfo.map do |_, _, a_host, ip, _|
|
142
164
|
sockaddr = Socket.pack_sockaddr_in 0, ip
|
143
|
-
|
165
|
+
DNSSD::Reply::AddrInfo.new(self, 0, 0, a_host, sockaddr, 0)
|
144
166
|
end
|
167
|
+
def list.stop; end
|
168
|
+
list
|
145
169
|
end
|
146
170
|
end
|
147
171
|
|
148
|
-
def inspect # :nodoc:
|
149
|
-
stopped = stopped? ? 'stopped' : 'running'
|
150
|
-
"#<%s:0x%x %s>" % [self.class, object_id, stopped]
|
151
|
-
end
|
152
|
-
|
153
|
-
##
|
154
|
-
# Yields results from the mDNS daemon, blocking until data is available.
|
155
|
-
# Use break or return when you wish to stop receiving results.
|
156
|
-
#
|
157
|
-
# The service is automatically stopped after calling this method.
|
158
|
-
|
159
|
-
def process # :yields: DNSSD::Result
|
160
|
-
@thread = Thread.current
|
161
|
-
|
162
|
-
while @continue do
|
163
|
-
_process if @replies.empty?
|
164
|
-
yield @replies.shift until @replies.empty?
|
165
|
-
end
|
166
|
-
|
167
|
-
@thread = nil
|
168
|
-
|
169
|
-
self
|
170
|
-
rescue DNSSD::ServiceNotRunningError
|
171
|
-
# raised when we jump out of DNSServiceProcess() while it's waiting for a
|
172
|
-
# response
|
173
|
-
self
|
174
|
-
ensure
|
175
|
-
stop unless stopped?
|
176
|
-
end
|
177
|
-
|
178
172
|
##
|
179
173
|
# Retrieves an arbitrary DNS record
|
180
174
|
#
|
@@ -189,17 +183,11 @@ class DNSSD::Service
|
|
189
183
|
# p record
|
190
184
|
# end
|
191
185
|
|
192
|
-
def query_record(fullname, record_type, record_class = DNSSD::Record::IN,
|
193
|
-
flags = 0, interface = DNSSD::InterfaceAny
|
186
|
+
def self.query_record(fullname, record_type, record_class = DNSSD::Record::IN,
|
187
|
+
flags = 0, interface = DNSSD::InterfaceAny)
|
194
188
|
interface = DNSSD.interface_index interface unless Integer === interface
|
195
189
|
|
196
|
-
raise DNSSD::Error, 'service in progress' if started?
|
197
|
-
|
198
190
|
_query_record flags.to_i, interface, fullname, record_type, record_class
|
199
|
-
|
200
|
-
@type = :query_record
|
201
|
-
|
202
|
-
process(&block)
|
203
191
|
end
|
204
192
|
|
205
193
|
##
|
@@ -210,20 +198,13 @@ class DNSSD::Service
|
|
210
198
|
# puts "successfully registered: #{r.inspect}"
|
211
199
|
# end
|
212
200
|
|
213
|
-
def register(name, type, domain, port, host = nil, text_record = nil,
|
214
|
-
flags = 0, interface = DNSSD::InterfaceAny
|
201
|
+
def self.register(name, type, domain, port, host = nil, text_record = nil,
|
202
|
+
flags = 0, interface = DNSSD::InterfaceAny)
|
215
203
|
check_domain domain
|
216
204
|
interface = DNSSD.interface_index interface unless Integer === interface
|
217
205
|
text_record = text_record.encode if text_record
|
218
206
|
|
219
|
-
|
220
|
-
|
221
|
-
_register flags.to_i, interface, name, type, domain, host, port,
|
222
|
-
text_record, &block
|
223
|
-
|
224
|
-
@type = :register
|
225
|
-
|
226
|
-
process(&block) if block
|
207
|
+
_register flags.to_i, interface, name, type, domain, host, port, text_record
|
227
208
|
end
|
228
209
|
|
229
210
|
##
|
@@ -242,27 +223,39 @@ class DNSSD::Service
|
|
242
223
|
# p r
|
243
224
|
# end
|
244
225
|
|
245
|
-
def resolve(name, type = name.type, domain = name.domain, flags = 0,
|
246
|
-
interface = DNSSD::InterfaceAny
|
226
|
+
def self.resolve(name, type = name.type, domain = name.domain, flags = 0,
|
227
|
+
interface = DNSSD::InterfaceAny)
|
247
228
|
name = name.name if DNSSD::Reply === name
|
248
229
|
check_domain domain
|
249
230
|
interface = DNSSD.interface_index interface unless Integer === interface
|
250
231
|
|
251
|
-
raise DNSSD::Error, 'service in progress' if started?
|
252
|
-
|
253
232
|
_resolve flags.to_i, interface, name, type, domain
|
254
|
-
|
255
|
-
@type = :resolve
|
256
|
-
|
257
|
-
process(&block)
|
258
233
|
end
|
259
234
|
|
260
235
|
##
|
261
236
|
# Returns true if the service has been started.
|
262
237
|
|
263
238
|
def started?
|
264
|
-
|
239
|
+
@continue
|
265
240
|
end
|
266
241
|
|
267
|
-
|
242
|
+
def stop
|
243
|
+
raise DNSSD::Error, 'service is already stopped' unless started?
|
244
|
+
@continue = false
|
245
|
+
@thread.join if @thread
|
246
|
+
_stop
|
247
|
+
self
|
248
|
+
end
|
268
249
|
|
250
|
+
private
|
251
|
+
|
252
|
+
if defined? Process::CLOCK_MONOTONIC
|
253
|
+
def clock_time
|
254
|
+
Process.clock_gettime Process::CLOCK_MONOTONIC
|
255
|
+
end
|
256
|
+
else
|
257
|
+
def clock_time
|
258
|
+
Time.now
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|