dnssd 2.0.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|