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.
@@ -13,7 +13,7 @@ module DNSSD
13
13
  ##
14
14
  # The version of DNSSD you're using.
15
15
 
16
- VERSION = '2.0.1'
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 ||= DNSSD.getservbyport port
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(type, domain = nil, flags = 0,
69
- interface = DNSSD::InterfaceAny, &block)
70
- service = DNSSD::Service.new
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!(type, domain = nil, flags = 0,
83
- interface = DNSSD::InterfaceAny, &block)
84
- service = DNSSD::Service.new
85
-
86
- run(service, :browse, type, domain, flags, interface, &block)
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(flags = DNSSD::Flags::BrowseDomains,
93
- interface = DNSSD::InterfaceAny, &block)
94
- service = DNSSD::Service.new
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.new
109
-
110
- run(service, :enumerate_domains, flags, interface, &block)
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, &block)
118
- service = DNSSD::Service.new
119
-
120
- if block_given? then
121
- Thread.start do
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.new
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, &block)
155
- service = DNSSD::Service.new
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, &block)
168
- service = DNSSD::Service.new
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 unless service.stopped?
147
+ service.stop if service
183
148
  end
184
-
185
149
  end
186
150
 
187
151
  require 'socket'
@@ -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! self do |reply|
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
-
@@ -178,6 +178,4 @@ class DNSSD::Reply::QueryRecord < DNSSD::Reply
178
178
  fullname, ttl, record_class_name, record_type_name, record_data
179
179
  ]
180
180
  end
181
-
182
181
  end
183
-
@@ -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
@@ -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.new
66
+ service = DNSSD::Service.getaddrinfo target, addrinfo_protocol,
67
+ addrinfo_flags, @interface
67
68
 
68
- service.getaddrinfo target, addrinfo_protocol, addrinfo_flags,
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?
@@ -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 = nil
24
- @type = nil
26
+ @thread = nil
27
+ @lock = Mutex.new
25
28
  end
26
29
 
27
- ##
28
- # Adds an extra DNS record of +type+ containing +data+. +ttl+ is in
29
- # seconds, use 0 for the default value. +flags+ are currently ignored.
30
- #
31
- # Must be called on a service only after #register.
32
- #
33
- # Returns the added DNSSD::Record
30
+ class Register < ::DNSSD::Service
31
+ def initialize
32
+ super
33
+ @records = []
34
+ end
34
35
 
35
- def add_record(type, data, ttl = 0, flags = 0)
36
- raise TypeError, 'must be called after register' unless @type == :register
37
- @records ||= []
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
- _add_record flags.to_i, type, data, ttl
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(type, domain = nil, flags = 0, interface = DNSSD::InterfaceAny,
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
- raise DNSSD::Error, 'service in progress' if started?
66
+ _browse flags.to_i, interface, type, domain
67
+ end
61
68
 
62
- @type = :browse
69
+ def each timeout = :never
70
+ raise DNSSD::Error, 'already stopped' unless @continue
63
71
 
64
- _browse flags.to_i, interface, type, domain
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
- process(&block)
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
- # available_domains = []
86
- #
87
- # service.enumerate_domains! do |r|
88
- # available_domains << r.domain
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.each do |_, _, a_host, ip, _|
163
+ list = addrinfo.map do |_, _, a_host, ip, _|
142
164
  sockaddr = Socket.pack_sockaddr_in 0, ip
143
- @replies << DNSSD::Reply::AddrInfo.new(self, 0, 0, a_host, sockaddr, 0)
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, &block)
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, &block)
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
- raise DNSSD::Error, 'service in progress' if started?
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, &block)
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
- not stopped?
239
+ @continue
265
240
  end
266
241
 
267
- end
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