zeroconf 1.0.1 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 39d1c369a77bb16908b77e600e166c264662ec1fc624de8aee2f62fc752e3aae
4
- data.tar.gz: 6f58a84ef9926d9e900182390249b6b029312332a7376cc1f1229b182812bb59
3
+ metadata.gz: 0a6933171abe1ab052bf99d2bdb6efa5bd0378f536859e0cf812f2dd68b23461
4
+ data.tar.gz: 9c016607692b33ed3a516a872aa80117a119f3ac138a997a19a845684914890c
5
5
  SHA512:
6
- metadata.gz: 5a515ce4490d93f37439bec362b84a6bb99c4d42098892f8250d9059537984c9ac6f0c90e9cbf005374f0fdb9abd0a78cb4fd2f7b54e87e05f8acce6eee892cb
7
- data.tar.gz: be3a38c8bfab29934aca1d2d1100fa4fdda4aa7bfc8c31fe095a461337cffc67b44ac1d982c2faf8f6131891c9eee1a9d444932fa5899b353b0f12e9b8968210
6
+ metadata.gz: bdc315b09c4ada48b56f6f102c24b5c0a51740c6163ccb3b9a96e67c7f262a35e95126c950bb1efd394b4cbea06ec0b29e1ae3e55bd02bbd63b42b4159faa06f
7
+ data.tar.gz: 663cc13801926e626a61aea7aebe75d51e92e07ab5133723c53be48259dc19bec30c42cbe10348c3a6881028fac9124afb8c50a697203736f8e394060b479b99
@@ -14,7 +14,7 @@ module ZeroConf
14
14
  end
15
15
 
16
16
  def run timeout: 3
17
- sockets = open_interfaces interfaces.map(&:addr), Resolv::MDNS::Port
17
+ sockets = open_interfaces interfaces.map(&:addr), 0
18
18
 
19
19
  query = get_query
20
20
  sockets.each { |socket| multicast_send(socket, query.encode) }
@@ -7,15 +7,17 @@ module ZeroConf
7
7
  include Utils
8
8
 
9
9
  attr_reader :service, :service_port, :hostname, :service_interfaces,
10
- :service_name, :qualified_host, :text
10
+ :service_name, :qualified_host, :text, :abort_on_malformed_requests
11
11
 
12
- def initialize service, service_port, hostname = Socket.gethostname, service_interfaces: ZeroConf.service_interfaces, text: [""]
12
+ def initialize service, service_port, hostname = Socket.gethostname, service_interfaces: ZeroConf.service_interfaces, text: [""], abort_on_malformed_requests: false, started_callback: nil
13
13
  @service = service
14
14
  @service_port = service_port
15
15
  @hostname = hostname
16
16
  @service_interfaces = service_interfaces
17
+ @abort_on_malformed_requests = abort_on_malformed_requests
17
18
  @service_name = "#{hostname}.#{service}"
18
19
  @qualified_host = "#{hostname}.local."
20
+ @started_callback = started_callback
19
21
  @text = text
20
22
  @started = false
21
23
  @rd, @wr = IO.pipe
@@ -88,6 +90,7 @@ module ZeroConf
88
90
  end
89
91
 
90
92
  def stop
93
+ return unless @started
91
94
  @wr.write "x"
92
95
  @wr.close
93
96
  @started = false
@@ -104,16 +107,27 @@ module ZeroConf
104
107
  multicast_send(sock, msg.encode)
105
108
 
106
109
  @started = true
110
+ @started_callback&.call
107
111
 
108
112
  loop do
109
113
  readers, = IO.select(sockets, [], [])
110
114
  next unless readers
111
115
 
112
116
  readers.each do |reader|
113
- return if reader == @rd
117
+ if reader == @rd
118
+ @rd.close
119
+ return
120
+ end
114
121
 
115
122
  buf, from = reader.recvfrom 2048
116
- msg = Resolv::DNS::Message.decode(buf)
123
+ msg = begin
124
+ Resolv::DNS::Message.decode(buf)
125
+ rescue Resolv::DNS::DecodeError
126
+ next unless abort_on_malformed_requests
127
+ @rd.close
128
+ stop
129
+ raise
130
+ end
117
131
 
118
132
  has_flags = (buf.getbyte(3) << 8 | buf.getbyte(2)) != 0
119
133
 
@@ -122,9 +136,7 @@ module ZeroConf
122
136
 
123
137
  break unless class_type == 1 || class_type == 255
124
138
 
125
- legacy = from[1] != Resolv::MDNS::Port
126
- unicast = legacy || type::ClassValue & PTR::MDNS_UNICAST_RESPONSE > 0
127
- reply_id = legacy ? msg.id : 0
139
+ unicast = type::ClassValue & PTR::MDNS_UNICAST_RESPONSE > 0
128
140
 
129
141
  qn = name.to_s + "."
130
142
 
@@ -133,25 +145,25 @@ module ZeroConf
133
145
  break if has_flags
134
146
 
135
147
  if unicast
136
- dnssd_unicast_answer(id: reply_id, legacy: legacy)
148
+ dnssd_unicast_answer
137
149
  else
138
150
  dnssd_multicast_answer
139
151
  end
140
152
  when service
141
153
  if unicast
142
- service_unicast_answer(id: reply_id, legacy: legacy)
154
+ service_unicast_answer
143
155
  else
144
156
  service_multicast_answer
145
157
  end
146
158
  when service_name
147
159
  if unicast
148
- service_instance_unicast_answer(id: reply_id, legacy: legacy)
160
+ service_instance_unicast_answer
149
161
  else
150
162
  service_instance_multicast_answer
151
163
  end
152
164
  when qualified_host
153
165
  if unicast
154
- name_answer_unicast(id: reply_id, legacy: legacy)
166
+ name_answer_unicast
155
167
  else
156
168
  name_answer_multicast
157
169
  end
@@ -178,11 +190,10 @@ module ZeroConf
178
190
 
179
191
  private
180
192
 
181
- def service_instance_unicast_answer(id:, legacy:)
193
+ def service_instance_unicast_answer
182
194
  msg = Resolv::DNS::Message.new(0)
183
195
  msg.qr = 1
184
196
  msg.aa = 1
185
- msg.id = id
186
197
 
187
198
  service_interfaces.each do |iface|
188
199
  if iface.addr.ipv4?
@@ -202,16 +213,15 @@ module ZeroConf
202
213
  Resolv::DNS::Resource::IN::TXT.new(*@text)
203
214
  end
204
215
  msg.add_answer service_name, 10, Resolv::DNS::Resource::IN::SRV.new(0, 0, service_port, qualified_host)
205
- msg.add_question service_name, legacy ? Resolv::DNS::Resource::IN::SRV : MDNS::Announce::IN::SRV
216
+ msg.add_question service_name, MDNS::Announce::IN::SRV
206
217
 
207
218
  msg
208
219
  end
209
220
 
210
- def service_unicast_answer(id:, legacy:)
221
+ def service_unicast_answer
211
222
  msg = Resolv::DNS::Message.new(0)
212
223
  msg.qr = 1
213
224
  msg.aa = 1
214
- msg.id = id
215
225
 
216
226
  msg.add_additional service_name, 10, Resolv::DNS::Resource::IN::SRV.new(0, 0, service_port, qualified_host)
217
227
 
@@ -237,21 +247,20 @@ module ZeroConf
237
247
  10,
238
248
  Resolv::DNS::Resource::IN::PTR.new(Resolv::DNS::Name.create(service_name))
239
249
 
240
- msg.add_question service, legacy ? Resolv::DNS::Resource::IN::PTR : PTR
250
+ msg.add_question service, PTR
241
251
 
242
252
  msg
243
253
  end
244
254
 
245
- def dnssd_unicast_answer(id:, legacy:)
255
+ def dnssd_unicast_answer
246
256
  msg = Resolv::DNS::Message.new(0)
247
257
  msg.qr = 1
248
258
  msg.aa = 1
249
- msg.id = id
250
259
 
251
260
  msg.add_answer DISCOVERY_NAME, 10,
252
261
  Resolv::DNS::Resource::IN::PTR.new(Resolv::DNS::Name.create(service))
253
262
 
254
- msg.add_question DISCOVERY_NAME, legacy ? Resolv::DNS::Resource::IN::PTR : PTR
263
+ msg.add_question DISCOVERY_NAME, PTR
255
264
  msg
256
265
  end
257
266
 
@@ -325,11 +334,10 @@ module ZeroConf
325
334
  msg
326
335
  end
327
336
 
328
- def name_answer_unicast(id:, legacy:)
337
+ def name_answer_unicast
329
338
  msg = Resolv::DNS::Message.new(0)
330
339
  msg.qr = 1
331
340
  msg.aa = 1
332
- msg.id = id
333
341
 
334
342
  first = true
335
343
 
@@ -358,7 +366,7 @@ module ZeroConf
358
366
  end
359
367
  end
360
368
 
361
- msg.add_question qualified_host, legacy ? Resolv::DNS::Resource::IN::A : MDNS::Announce::IN::A
369
+ msg.add_question qualified_host, MDNS::Announce::IN::A
362
370
 
363
371
  if @text
364
372
  msg.add_additional service_name,
@@ -4,7 +4,6 @@ require "socket"
4
4
  require "ipaddr"
5
5
  require "fcntl"
6
6
  require "resolv"
7
- require "rbconfig"
8
7
 
9
8
  module ZeroConf
10
9
  MDNS_CACHE_FLUSH = 0x8000
@@ -58,7 +57,7 @@ module ZeroConf
58
57
  def open_ipv4 saddr, port
59
58
  sock = UDPSocket.new Socket::AF_INET
60
59
  sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
61
- sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEPORT, true) unless RbConfig::CONFIG["host_os"].include?("linux")
60
+ sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEPORT, true)
62
61
  sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_MULTICAST_TTL, true)
63
62
  sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_MULTICAST_LOOP, true)
64
63
  sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP,
@@ -98,7 +97,7 @@ module ZeroConf
98
97
  def open_ipv6 saddr, port
99
98
  sock = UDPSocket.new Socket::AF_INET6
100
99
  sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
101
- sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEPORT, true) unless RbConfig::CONFIG["host_os"].include?("linux")
100
+ sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEPORT, true)
102
101
  sock.setsockopt(Socket::IPPROTO_IPV6, Socket::IPV6_MULTICAST_HOPS, true)
103
102
  sock.setsockopt(Socket::IPPROTO_IPV6, Socket::IPV6_MULTICAST_LOOP, true)
104
103
 
@@ -1,3 +1,3 @@
1
1
  module ZeroConf
2
- VERSION = "1.0.1"
2
+ VERSION = "1.1.0"
3
3
  end
data/lib/zeroconf.rb CHANGED
@@ -67,8 +67,8 @@ module ZeroConf
67
67
  resolver.run(timeout:, &blk)
68
68
  end
69
69
 
70
- def self.service service, service_port, hostname = Socket.gethostname, service_interfaces: self.service_interfaces, text: [""]
71
- s = Service.new(service, service_port, hostname, service_interfaces:, text:)
70
+ def self.service ...
71
+ s = Service.new(...)
72
72
  s.start
73
73
  end
74
74
 
data/test/client_test.rb CHANGED
@@ -10,9 +10,10 @@ module ZeroConf
10
10
  end
11
11
 
12
12
  def test_resolve
13
- s = make_server iface, "coolhostname"
13
+ latch = Queue.new
14
+ s = make_server iface, "coolhostname", started_callback: -> { latch << :start }
14
15
  runner = Thread.new { s.start }
15
- Thread.pass until s.started?
16
+ latch.pop
16
17
  found = nil
17
18
 
18
19
  name = "coolhostname.local"
@@ -33,9 +34,10 @@ module ZeroConf
33
34
  end
34
35
 
35
36
  def test_resolve_returns_early
36
- s = make_server iface, "coolhostname"
37
+ latch = Queue.new
38
+ s = make_server iface, "coolhostname", started_callback: -> { latch << :start }
37
39
  runner = Thread.new { s.start }
38
- Thread.pass until s.started?
40
+ latch.pop
39
41
  found = nil
40
42
 
41
43
  name = "coolhostname.local"
@@ -57,9 +59,10 @@ module ZeroConf
57
59
  end
58
60
 
59
61
  def test_discover_works
60
- s = make_server iface
62
+ latch = Queue.new
63
+ s = make_server iface, started_callback: -> { latch << :start }
61
64
  runner = Thread.new { s.start }
62
- Thread.pass until s.started?
65
+ latch.pop
63
66
  found = nil
64
67
 
65
68
  took = time_it do
@@ -78,9 +81,10 @@ module ZeroConf
78
81
  end
79
82
 
80
83
  def test_discover_return_early
81
- s = make_server iface
84
+ latch = Queue.new
85
+ s = make_server iface, started_callback: -> { latch << :start }
82
86
  runner = Thread.new { s.start }
83
- Thread.pass until s.started?
87
+ latch.pop
84
88
  found = nil
85
89
 
86
90
  took = time_it do
@@ -99,9 +103,10 @@ module ZeroConf
99
103
  end
100
104
 
101
105
  def test_browse
102
- s = make_server iface
106
+ latch = Queue.new
107
+ s = make_server iface, started_callback: -> { latch << :start }
103
108
  runner = Thread.new { s.start }
104
- Thread.pass until s.started?
109
+ latch.pop
105
110
  found = nil
106
111
 
107
112
  took = time_it do
@@ -121,9 +126,10 @@ module ZeroConf
121
126
  end
122
127
 
123
128
  def test_browse_returns_early
124
- s = make_server iface
129
+ latch = Queue.new
130
+ s = make_server iface, started_callback: -> { latch << :start }
125
131
  runner = Thread.new { s.start }
126
- Thread.pass until s.started?
132
+ latch.pop
127
133
  found = nil
128
134
 
129
135
  took = time_it do
data/test/helper.rb CHANGED
@@ -39,16 +39,18 @@ module ZeroConf
39
39
  Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
40
40
  end
41
41
 
42
- def make_server iface, host = HOST_NAME
42
+ def make_server iface, host = HOST_NAME, **opts
43
43
  Service.new SERVICE + ".",
44
44
  42424,
45
45
  host,
46
- service_interfaces: [iface], text: ["test=1", "other=value"]
46
+ service_interfaces: [iface], text: ["test=1", "other=value"],
47
+ **opts
47
48
  end
48
49
 
49
- def make_listener rd, q
50
+ def make_listener rd, q, started_callback: nil
50
51
  Thread.new do
51
52
  sock = open_ipv4 Addrinfo.new(Socket.sockaddr_in(Resolv::MDNS::Port, Socket::INADDR_ANY)), Resolv::MDNS::Port
53
+ started_callback&.call
52
54
  Thread.current[:started] = true
53
55
  loop do
54
56
  readers, = IO.select([sock, rd])
data/test/service_test.rb CHANGED
@@ -27,14 +27,15 @@ module ZeroConf
27
27
  end
28
28
 
29
29
  def test_unicast_service_instance_answer
30
- s = make_server iface
30
+ latch = Queue.new
31
+ s = make_server iface, started_callback: -> { latch << :start }
31
32
  runner = Thread.new { s.start }
32
- Thread.pass until s.started?
33
+ latch.pop
33
34
 
34
- query = Resolv::DNS::Message.new 10
35
+ query = Resolv::DNS::Message.new 0
35
36
  query.add_question "tc-lan-adapter._test-mdns._tcp.local.", SRV
36
37
 
37
- sock = open_ipv4 iface.addr, Resolv::MDNS::Port
38
+ sock = open_ipv4 iface.addr, 0
38
39
  multicast_send sock, query.encode
39
40
  res = Resolv::DNS::Message.decode read_with_timeout(sock).first
40
41
  s.stop
@@ -57,49 +58,19 @@ module ZeroConf
57
58
  assert_equal expected, res
58
59
  end
59
60
 
60
- def test_legacy_unicast_service_instance_answer
61
- s = make_server iface
62
- runner = Thread.new { s.start }
63
- Thread.pass until s.started?
64
-
65
- query = Resolv::DNS::Message.new 10
66
- query.add_question "tc-lan-adapter._test-mdns._tcp.local.", Resolv::DNS::Resource::IN::SRV
67
-
68
- sock = open_ipv4 iface.addr, 0
69
- multicast_send sock, query.encode
70
- res = Resolv::DNS::Message.decode read_with_timeout(sock).first
71
- s.stop
72
- runner.join
73
-
74
- expected = Resolv::DNS::Message.new(10)
75
- expected.qr = 1
76
- expected.aa = 1
77
-
78
- expected.add_additional s.qualified_host,
79
- 10,
80
- Resolv::DNS::Resource::IN::A.new(iface.addr.ip_address)
81
-
82
- expected.add_additional s.service_name,
83
- 10,
84
- Resolv::DNS::Resource::IN::TXT.new(*s.text)
85
- expected.add_answer s.service_name, 10, Resolv::DNS::Resource::IN::SRV.new(0, 0, s.service_port, s.qualified_host)
86
- expected.add_question s.service_name, Resolv::DNS::Resource::IN::SRV
87
-
88
- assert_equal expected, res
89
- end
90
-
91
61
  def test_multicast_discover
92
62
  q = Queue.new
93
63
  rd, wr = IO.pipe
94
64
 
95
65
  listen = make_listener rd, q
96
- s = make_server iface
66
+ latch = Queue.new
67
+ s = make_server iface, started_callback: -> { latch << :start }
97
68
  server = Thread.new { s.start }
98
- Thread.pass until s.started?
69
+ latch.pop
99
70
 
100
- query = Resolv::DNS::Message.new 10
71
+ query = Resolv::DNS::Message.new 0
101
72
  query.add_question "_services._dns-sd._udp.local.", Resolv::DNS::Resource::IN::PTR
102
- sock = open_ipv4 iface.addr, Resolv::MDNS::Port
73
+ sock = open_ipv4 iface.addr, 0
103
74
  multicast_send sock, query.encode
104
75
 
105
76
  while res = q.pop
@@ -196,14 +167,15 @@ module ZeroConf
196
167
  end
197
168
 
198
169
  def test_dnssd_unicast_answer
199
- s = make_server iface
170
+ latch = Queue.new
171
+ s = make_server iface, started_callback: -> { latch << :start }
200
172
  runner = Thread.new { s.start }
201
- Thread.pass until s.started?
173
+ latch.pop
202
174
 
203
- query = Resolv::DNS::Message.new 10
175
+ query = Resolv::DNS::Message.new 0
204
176
  query.add_question "_services._dns-sd._udp.local.", PTR
205
177
 
206
- sock = open_ipv4 iface.addr, Resolv::MDNS::Port
178
+ sock = open_ipv4 iface.addr, 0
207
179
  multicast_send sock, query.encode
208
180
 
209
181
  res = nil
@@ -230,53 +202,20 @@ module ZeroConf
230
202
  assert_equal expected, res
231
203
  end
232
204
 
233
- def test_dnssd_legacy_unicast_answer
234
- s = make_server iface
235
- runner = Thread.new { s.start }
236
- Thread.pass until s.started?
237
-
238
- query = Resolv::DNS::Message.new 10
239
- query.add_question "_services._dns-sd._udp.local.", Resolv::DNS::Resource::IN::PTR
240
-
241
- sock = open_ipv4 iface.addr, 0
242
- multicast_send sock, query.encode
243
-
244
- res = nil
245
- loop do
246
- buf, from = read_with_timeout sock
247
- res = Resolv::DNS::Message.decode buf
248
- if from.last == iface.addr.ip_address
249
- break if res.answer.find { |name, ttl, data| data.name.to_s == SERVICE }
250
- end
251
- end
252
-
253
- s.stop
254
- runner.join
255
-
256
- expected = Resolv::DNS::Message.new(10)
257
- expected.qr = 1
258
- expected.aa = 1
259
-
260
- expected.add_answer DISCOVERY_NAME, 10,
261
- Resolv::DNS::Resource::IN::PTR.new(Resolv::DNS::Name.create(s.service))
262
-
263
- expected.add_question DISCOVERY_NAME, Resolv::DNS::Resource::IN::PTR
264
-
265
- assert_equal expected, res
266
- end
267
-
268
205
  def test_service_multicast_answer
269
206
  q = Thread::Queue.new
270
207
  rd, wr = IO.pipe
271
208
 
272
- listen = make_listener rd, q
273
- s = make_server iface
209
+ latch = Queue.new
210
+ listen = make_listener rd, q, started_callback: -> { latch << :start }
211
+ s = make_server iface, started_callback: -> { latch << :start }
274
212
  server = Thread.new { s.start }
275
- Thread.pass until s.started? && listen[:started]
213
+ latch.pop
214
+ latch.pop
276
215
 
277
- query = Resolv::DNS::Message.new 10
216
+ query = Resolv::DNS::Message.new 0
278
217
  query.add_question "_test-mdns._tcp.local.", Resolv::DNS::Resource::IN::PTR
279
- sock = open_ipv4 iface.addr, Resolv::MDNS::Port
218
+ sock = open_ipv4 iface.addr, 0
280
219
  multicast_send sock, query.encode
281
220
 
282
221
  service = Resolv::DNS::Name.create s.service
@@ -316,14 +255,15 @@ module ZeroConf
316
255
  end
317
256
 
318
257
  def test_service_unicast_answer
319
- s = make_server iface
258
+ latch = Queue.new
259
+ s = make_server iface, started_callback: -> { latch << :start }
320
260
  runner = Thread.new { s.start }
321
- Thread.pass until s.started?
261
+ latch.pop
322
262
 
323
- query = Resolv::DNS::Message.new 10
263
+ query = Resolv::DNS::Message.new 0
324
264
  query.add_question "_test-mdns._tcp.local.", PTR
325
265
 
326
- sock = open_ipv4 iface.addr, Resolv::MDNS::Port
266
+ sock = open_ipv4 iface.addr, 0
327
267
  multicast_send sock, query.encode
328
268
  res = Resolv::DNS::Message.decode read_with_timeout(sock).first
329
269
  s.stop
@@ -349,53 +289,20 @@ module ZeroConf
349
289
  assert_equal expected, res
350
290
  end
351
291
 
352
- def test_service_legacy_unicast_answer
353
- s = make_server iface
354
- runner = Thread.new { s.start }
355
- Thread.pass until s.started?
356
-
357
- query = Resolv::DNS::Message.new 10
358
- query.add_question "_test-mdns._tcp.local.", PTR
359
-
360
- sock = open_ipv4 iface.addr, 0
361
- multicast_send sock, query.encode
362
- res = Resolv::DNS::Message.decode read_with_timeout(sock).first
363
- s.stop
364
- runner.join
365
-
366
- expected = Resolv::DNS::Message.new(10)
367
- expected.qr = 1
368
- expected.aa = 1
369
-
370
- expected.add_additional s.service_name, 10, Resolv::DNS::Resource::IN::SRV.new(0, 0, s.service_port, s.qualified_host)
371
- expected.add_additional s.qualified_host,
372
- 10,
373
- Resolv::DNS::Resource::IN::A.new(iface.addr.ip_address)
374
-
375
- expected.add_additional s.service_name,
376
- 10,
377
- Resolv::DNS::Resource::IN::TXT.new(*s.text)
378
- expected.add_answer s.service,
379
- 10,
380
- Resolv::DNS::Resource::IN::PTR.new(Resolv::DNS::Name.create(s.service_name))
381
- expected.add_question s.service, Resolv::DNS::Resource::IN::PTR
382
-
383
- assert_equal expected, res
384
- end
385
-
386
-
387
292
  def test_multicast_service_instance_answer
388
293
  q = Queue.new
389
294
  rd, wr = IO.pipe
390
295
 
391
- listen = make_listener rd, q
392
- s = make_server iface
296
+ latch = Queue.new
297
+ listen = make_listener rd, q, started_callback: -> { latch << :start }
298
+ s = make_server iface, started_callback: -> { latch << :start }
393
299
  server = Thread.new { s.start }
394
- Thread.pass until s.started?
300
+ latch.pop
301
+ latch.pop
395
302
 
396
- query = Resolv::DNS::Message.new 10
303
+ query = Resolv::DNS::Message.new 0
397
304
  query.add_question "tc-lan-adapter._test-mdns._tcp.local.", Resolv::DNS::Resource::IN::PTR
398
- sock = open_ipv4 iface.addr, Resolv::MDNS::Port
305
+ sock = open_ipv4 iface.addr, 0
399
306
  multicast_send sock, query.encode
400
307
 
401
308
  service_name = Resolv::DNS::Name.create s.service_name
@@ -430,14 +337,15 @@ module ZeroConf
430
337
  end
431
338
 
432
339
  def test_unicast_name_lookup
433
- s = make_server iface
340
+ latch = Queue.new
341
+ s = make_server iface, started_callback: -> { latch << :start }
434
342
  runner = Thread.new { s.start }
435
- Thread.pass until s.started?
343
+ latch.pop
436
344
 
437
- query = Resolv::DNS::Message.new 10
345
+ query = Resolv::DNS::Message.new 0
438
346
  query.add_question "tc-lan-adapter.local.", A
439
347
 
440
- sock = open_ipv4 iface.addr, Resolv::MDNS::Port
348
+ sock = open_ipv4 iface.addr, 0
441
349
  multicast_send sock, query.encode
442
350
  res = Resolv::DNS::Message.decode read_with_timeout(sock).first
443
351
  s.stop
@@ -459,48 +367,20 @@ module ZeroConf
459
367
  assert_equal expected, res
460
368
  end
461
369
 
462
- def test_legacy_unicast_name_lookup
463
- s = make_server iface
464
- runner = Thread.new { s.start }
465
- Thread.pass until s.started?
466
-
467
- query = Resolv::DNS::Message.new 10
468
- query.add_question "tc-lan-adapter.local.", Resolv::DNS::Resource::IN::A
469
-
470
- sock = open_ipv4 iface.addr, 0
471
- multicast_send sock, query.encode
472
- res = Resolv::DNS::Message.decode read_with_timeout(sock).first
473
- s.stop
474
- runner.join
475
-
476
- expected = Resolv::DNS::Message.new(10)
477
- expected.qr = 1
478
- expected.aa = 1
479
-
480
- expected.add_answer s.qualified_host, 10, Resolv::DNS::Resource::IN::A.new(iface.addr.ip_address)
481
-
482
- expected.add_additional s.service_name,
483
- 10,
484
- Resolv::DNS::Resource::IN::TXT.new(*s.text)
485
-
486
- expected.add_question s.qualified_host,
487
- Resolv::DNS::Resource::IN::A
488
-
489
- assert_equal expected, res
490
- end
491
-
492
370
  def test_multicast_name
493
371
  q = Queue.new
494
372
  rd, wr = IO.pipe
495
373
 
496
- listen = make_listener rd, q
497
- s = make_server iface
374
+ latch = Queue.new
375
+ listen = make_listener rd, q, started_callback: -> { latch << :start }
376
+ s = make_server iface, started_callback: -> { latch << :start }
498
377
  server = Thread.new { s.start }
499
- Thread.pass until s.started?
378
+ latch.pop
379
+ latch.pop
500
380
 
501
- query = Resolv::DNS::Message.new 10
381
+ query = Resolv::DNS::Message.new 0
502
382
  query.add_question "tc-lan-adapter.local.", Resolv::DNS::Resource::IN::A
503
- sock = open_ipv4 iface.addr, Resolv::MDNS::Port
383
+ sock = open_ipv4 iface.addr, 0
504
384
  multicast_send sock, query.encode
505
385
 
506
386
  host = Resolv::DNS::Name.create s.qualified_host
@@ -529,6 +409,21 @@ module ZeroConf
529
409
  assert_equal expected, res
530
410
  end
531
411
 
412
+ def test_raise_on_malformed_requests
413
+ latch = Queue.new
414
+ s = make_server iface, abort_on_malformed_requests: true, started_callback: -> { latch << :start }
415
+ runner = Thread.new {
416
+ assert_raises do
417
+ s.start
418
+ end
419
+ }
420
+ latch.pop
421
+
422
+ sock = open_ipv4 iface.addr, Resolv::MDNS::Port
423
+ multicast_send sock, "not a valid DNS message"
424
+ runner.join
425
+ end
426
+
532
427
  def read_with_timeout sock
533
428
  return unless sock.wait_readable(3)
534
429
  sock.recvfrom(2048)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zeroconf
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Patterson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-15 00:00:00.000000000 Z
11
+ date: 2024-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: resolv