zeroconf 1.0.1 → 1.2.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.md +4 -2
- data/lib/zeroconf/client.rb +1 -1
- data/lib/zeroconf/service.rb +41 -26
- data/lib/zeroconf/utils.rb +8 -5
- data/lib/zeroconf/version.rb +1 -1
- data/lib/zeroconf.rb +2 -2
- data/test/client_test.rb +18 -12
- data/test/helper.rb +5 -3
- data/test/service_test.rb +89 -163
- metadata +3 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f58175fb721fb08fa2a5abb36b0b2165d9b38592bb7ff66bd3a3f4c303ed2f9
|
4
|
+
data.tar.gz: afd32fb72b31c90e84aaea02db2f81e603b872f8f81c1f6f147d15c13ce3713e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2e4faed4b18775a5fec2faf0b4064556356699b049c6ca1d6d2d4c03b685cd8702e3ba8591d098799d3ec6ee54efdb9aee1f0e5ea68578b92c1df7ea8fbbba7b
|
7
|
+
data.tar.gz: 210e338f7d21bbe98df962e4785e0716e2364e538fb44c1029217465fca0fe6ea2f414986d4bb7ce0f3588efd5bfbbd8caeb140ef5f1028b5e75b58648de57e6
|
data/README.md
CHANGED
@@ -108,12 +108,14 @@ to run an HTTP server and simultaneously advertise the server:
|
|
108
108
|
|
109
109
|
```ruby
|
110
110
|
require "zeroconf"
|
111
|
-
require
|
111
|
+
require "webrick"
|
112
112
|
|
113
113
|
port = 8080
|
114
114
|
host = "test-hostname"
|
115
115
|
|
116
|
-
|
116
|
+
Ractor.new(port, host) { |port, host|
|
117
|
+
ZeroConf.service "_http._tcp.local.", port, host
|
118
|
+
}
|
117
119
|
|
118
120
|
server = WEBrick::HTTPServer.new(:Port => port,
|
119
121
|
:SSLEnable => false,
|
data/lib/zeroconf/client.rb
CHANGED
@@ -14,7 +14,7 @@ module ZeroConf
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def run timeout: 3
|
17
|
-
sockets = open_interfaces interfaces.map(&:addr),
|
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) }
|
data/lib/zeroconf/service.rb
CHANGED
@@ -7,15 +7,24 @@ 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, instance_name: nil, text: [""], abort_on_malformed_requests: false, started_callback: nil
|
13
13
|
@service = service
|
14
14
|
@service_port = service_port
|
15
|
-
|
15
|
+
|
16
|
+
@hostname = strip_dot_local(hostname) # We re-add .local anyway, later on
|
16
17
|
@service_interfaces = service_interfaces
|
17
|
-
@
|
18
|
-
|
18
|
+
@abort_on_malformed_requests = abort_on_malformed_requests
|
19
|
+
|
20
|
+
instance_name ||= @hostname
|
21
|
+
if instance_name.include?(".")
|
22
|
+
raise ArgumentError, "instance_name must not contain dots (is #{instance_name.inspect})"
|
23
|
+
end
|
24
|
+
|
25
|
+
@service_name = "#{instance_name}.#{@service}"
|
26
|
+
@qualified_host = "#{@hostname}.local."
|
27
|
+
@started_callback = started_callback
|
19
28
|
@text = text
|
20
29
|
@started = false
|
21
30
|
@rd, @wr = IO.pipe
|
@@ -88,6 +97,7 @@ module ZeroConf
|
|
88
97
|
end
|
89
98
|
|
90
99
|
def stop
|
100
|
+
return unless @started
|
91
101
|
@wr.write "x"
|
92
102
|
@wr.close
|
93
103
|
@started = false
|
@@ -104,16 +114,27 @@ module ZeroConf
|
|
104
114
|
multicast_send(sock, msg.encode)
|
105
115
|
|
106
116
|
@started = true
|
117
|
+
@started_callback&.call
|
107
118
|
|
108
119
|
loop do
|
109
120
|
readers, = IO.select(sockets, [], [])
|
110
121
|
next unless readers
|
111
122
|
|
112
123
|
readers.each do |reader|
|
113
|
-
|
124
|
+
if reader == @rd
|
125
|
+
@rd.close
|
126
|
+
return
|
127
|
+
end
|
114
128
|
|
115
129
|
buf, from = reader.recvfrom 2048
|
116
|
-
msg =
|
130
|
+
msg = begin
|
131
|
+
Resolv::DNS::Message.decode(buf)
|
132
|
+
rescue Resolv::DNS::DecodeError
|
133
|
+
next unless abort_on_malformed_requests
|
134
|
+
@rd.close
|
135
|
+
stop
|
136
|
+
raise
|
137
|
+
end
|
117
138
|
|
118
139
|
has_flags = (buf.getbyte(3) << 8 | buf.getbyte(2)) != 0
|
119
140
|
|
@@ -122,9 +143,7 @@ module ZeroConf
|
|
122
143
|
|
123
144
|
break unless class_type == 1 || class_type == 255
|
124
145
|
|
125
|
-
|
126
|
-
unicast = legacy || type::ClassValue & PTR::MDNS_UNICAST_RESPONSE > 0
|
127
|
-
reply_id = legacy ? msg.id : 0
|
146
|
+
unicast = type::ClassValue & PTR::MDNS_UNICAST_RESPONSE > 0
|
128
147
|
|
129
148
|
qn = name.to_s + "."
|
130
149
|
|
@@ -133,25 +152,25 @@ module ZeroConf
|
|
133
152
|
break if has_flags
|
134
153
|
|
135
154
|
if unicast
|
136
|
-
dnssd_unicast_answer
|
155
|
+
dnssd_unicast_answer
|
137
156
|
else
|
138
157
|
dnssd_multicast_answer
|
139
158
|
end
|
140
159
|
when service
|
141
160
|
if unicast
|
142
|
-
service_unicast_answer
|
161
|
+
service_unicast_answer
|
143
162
|
else
|
144
163
|
service_multicast_answer
|
145
164
|
end
|
146
165
|
when service_name
|
147
166
|
if unicast
|
148
|
-
service_instance_unicast_answer
|
167
|
+
service_instance_unicast_answer
|
149
168
|
else
|
150
169
|
service_instance_multicast_answer
|
151
170
|
end
|
152
171
|
when qualified_host
|
153
172
|
if unicast
|
154
|
-
name_answer_unicast
|
173
|
+
name_answer_unicast
|
155
174
|
else
|
156
175
|
name_answer_multicast
|
157
176
|
end
|
@@ -178,11 +197,10 @@ module ZeroConf
|
|
178
197
|
|
179
198
|
private
|
180
199
|
|
181
|
-
def service_instance_unicast_answer
|
200
|
+
def service_instance_unicast_answer
|
182
201
|
msg = Resolv::DNS::Message.new(0)
|
183
202
|
msg.qr = 1
|
184
203
|
msg.aa = 1
|
185
|
-
msg.id = id
|
186
204
|
|
187
205
|
service_interfaces.each do |iface|
|
188
206
|
if iface.addr.ipv4?
|
@@ -202,16 +220,15 @@ module ZeroConf
|
|
202
220
|
Resolv::DNS::Resource::IN::TXT.new(*@text)
|
203
221
|
end
|
204
222
|
msg.add_answer service_name, 10, Resolv::DNS::Resource::IN::SRV.new(0, 0, service_port, qualified_host)
|
205
|
-
msg.add_question service_name,
|
223
|
+
msg.add_question service_name, MDNS::Announce::IN::SRV
|
206
224
|
|
207
225
|
msg
|
208
226
|
end
|
209
227
|
|
210
|
-
def service_unicast_answer
|
228
|
+
def service_unicast_answer
|
211
229
|
msg = Resolv::DNS::Message.new(0)
|
212
230
|
msg.qr = 1
|
213
231
|
msg.aa = 1
|
214
|
-
msg.id = id
|
215
232
|
|
216
233
|
msg.add_additional service_name, 10, Resolv::DNS::Resource::IN::SRV.new(0, 0, service_port, qualified_host)
|
217
234
|
|
@@ -237,21 +254,20 @@ module ZeroConf
|
|
237
254
|
10,
|
238
255
|
Resolv::DNS::Resource::IN::PTR.new(Resolv::DNS::Name.create(service_name))
|
239
256
|
|
240
|
-
msg.add_question service,
|
257
|
+
msg.add_question service, PTR
|
241
258
|
|
242
259
|
msg
|
243
260
|
end
|
244
261
|
|
245
|
-
def dnssd_unicast_answer
|
262
|
+
def dnssd_unicast_answer
|
246
263
|
msg = Resolv::DNS::Message.new(0)
|
247
264
|
msg.qr = 1
|
248
265
|
msg.aa = 1
|
249
|
-
msg.id = id
|
250
266
|
|
251
267
|
msg.add_answer DISCOVERY_NAME, 10,
|
252
268
|
Resolv::DNS::Resource::IN::PTR.new(Resolv::DNS::Name.create(service))
|
253
269
|
|
254
|
-
msg.add_question DISCOVERY_NAME,
|
270
|
+
msg.add_question DISCOVERY_NAME, PTR
|
255
271
|
msg
|
256
272
|
end
|
257
273
|
|
@@ -325,11 +341,10 @@ module ZeroConf
|
|
325
341
|
msg
|
326
342
|
end
|
327
343
|
|
328
|
-
def name_answer_unicast
|
344
|
+
def name_answer_unicast
|
329
345
|
msg = Resolv::DNS::Message.new(0)
|
330
346
|
msg.qr = 1
|
331
347
|
msg.aa = 1
|
332
|
-
msg.id = id
|
333
348
|
|
334
349
|
first = true
|
335
350
|
|
@@ -358,7 +373,7 @@ module ZeroConf
|
|
358
373
|
end
|
359
374
|
end
|
360
375
|
|
361
|
-
msg.add_question qualified_host,
|
376
|
+
msg.add_question qualified_host, MDNS::Announce::IN::A
|
362
377
|
|
363
378
|
if @text
|
364
379
|
msg.add_additional service_name,
|
data/lib/zeroconf/utils.rb
CHANGED
@@ -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)
|
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,
|
@@ -70,8 +69,8 @@ module ZeroConf
|
|
70
69
|
sock
|
71
70
|
end
|
72
71
|
|
73
|
-
BROADCAST_V4 = Addrinfo.new
|
74
|
-
BROADCAST_V6 = Addrinfo.new
|
72
|
+
BROADCAST_V4 = Addrinfo.new(Socket.sockaddr_in(Resolv::MDNS::Port, Resolv::MDNS::AddressV4)).freeze
|
73
|
+
BROADCAST_V6 = Addrinfo.new(Socket.sockaddr_in(Resolv::MDNS::Port, Resolv::MDNS::AddressV6)).freeze
|
75
74
|
|
76
75
|
def multicast_send sock, query
|
77
76
|
dest = if sock.local_address.ipv4?
|
@@ -95,10 +94,14 @@ module ZeroConf
|
|
95
94
|
sock.send(data, 0, Addrinfo.new(to))
|
96
95
|
end
|
97
96
|
|
97
|
+
def strip_dot_local(from_string)
|
98
|
+
from_string.to_s.gsub(/\.local\.?$/, "")
|
99
|
+
end
|
100
|
+
|
98
101
|
def open_ipv6 saddr, port
|
99
102
|
sock = UDPSocket.new Socket::AF_INET6
|
100
103
|
sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
|
101
|
-
sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEPORT, true)
|
104
|
+
sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEPORT, true)
|
102
105
|
sock.setsockopt(Socket::IPPROTO_IPV6, Socket::IPV6_MULTICAST_HOPS, true)
|
103
106
|
sock.setsockopt(Socket::IPPROTO_IPV6, Socket::IPV6_MULTICAST_LOOP, true)
|
104
107
|
|
data/lib/zeroconf/version.rb
CHANGED
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
|
71
|
-
s = Service.new(
|
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
|
-
|
13
|
+
latch = Queue.new
|
14
|
+
s = make_server iface, "coolhostname", started_callback: -> { latch << :start }
|
14
15
|
runner = Thread.new { s.start }
|
15
|
-
|
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
|
-
|
37
|
+
latch = Queue.new
|
38
|
+
s = make_server iface, "coolhostname", started_callback: -> { latch << :start }
|
37
39
|
runner = Thread.new { s.start }
|
38
|
-
|
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
|
-
|
62
|
+
latch = Queue.new
|
63
|
+
s = make_server iface, started_callback: -> { latch << :start }
|
61
64
|
runner = Thread.new { s.start }
|
62
|
-
|
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
|
-
|
84
|
+
latch = Queue.new
|
85
|
+
s = make_server iface, started_callback: -> { latch << :start }
|
82
86
|
runner = Thread.new { s.start }
|
83
|
-
|
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
|
-
|
106
|
+
latch = Queue.new
|
107
|
+
s = make_server iface, started_callback: -> { latch << :start }
|
103
108
|
runner = Thread.new { s.start }
|
104
|
-
|
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
|
-
|
129
|
+
latch = Queue.new
|
130
|
+
s = make_server iface, started_callback: -> { latch << :start }
|
125
131
|
runner = Thread.new { s.start }
|
126
|
-
|
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
@@ -26,44 +26,45 @@ module ZeroConf
|
|
26
26
|
assert_equal [""], s.text
|
27
27
|
end
|
28
28
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
query = Resolv::DNS::Message.new 10
|
35
|
-
query.add_question "tc-lan-adapter._test-mdns._tcp.local.", SRV
|
36
|
-
|
37
|
-
sock = open_ipv4 iface.addr, Resolv::MDNS::Port
|
38
|
-
multicast_send sock, query.encode
|
39
|
-
res = Resolv::DNS::Message.decode read_with_timeout(sock).first
|
40
|
-
s.stop
|
41
|
-
runner.join
|
29
|
+
def test_raises_when_creating_a_service_with_dot_in_the_name
|
30
|
+
assert_raises ArgumentError do
|
31
|
+
Service.new "_test-mdns._tcp.local.", 42424,
|
32
|
+
"some.subdomain.workstation"
|
33
|
+
end
|
42
34
|
|
43
|
-
|
44
|
-
|
45
|
-
|
35
|
+
assert_raises ArgumentError do
|
36
|
+
Service.new "_test-mdns._tcp.local.", 42424,
|
37
|
+
"ruby-mdns", instance_name: "ruby.test"
|
38
|
+
end
|
39
|
+
end
|
46
40
|
|
47
|
-
|
48
|
-
|
49
|
-
|
41
|
+
def test_sets_correct_service_name_from_instance_name
|
42
|
+
s = Service.new "_test-mdns._tcp.local.", 42424,
|
43
|
+
"my-rb-service", instance_name: "My RB service"
|
44
|
+
assert_equal "my-rb-service.local.", s.qualified_host
|
45
|
+
assert_equal "My RB service._test-mdns._tcp.local.", s.service_name
|
46
|
+
end
|
50
47
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
48
|
+
def test_removes_dot_local_tld_from_passed_hostname
|
49
|
+
s = Service.new "_test-mdns._tcp.local.", 42424,
|
50
|
+
"ThisMac.local"
|
51
|
+
assert_equal "ThisMac.local.", s.qualified_host
|
52
|
+
assert_equal "ThisMac._test-mdns._tcp.local.", s.service_name
|
56
53
|
|
57
|
-
|
54
|
+
s = Service.new "_test-mdns._tcp.local.", 42424,
|
55
|
+
"ThisMac.local."
|
56
|
+
assert_equal "ThisMac.local.", s.qualified_host
|
57
|
+
assert_equal "ThisMac._test-mdns._tcp.local.", s.service_name
|
58
58
|
end
|
59
59
|
|
60
|
-
def
|
61
|
-
|
60
|
+
def test_unicast_service_instance_answer
|
61
|
+
latch = Queue.new
|
62
|
+
s = make_server iface, started_callback: -> { latch << :start }
|
62
63
|
runner = Thread.new { s.start }
|
63
|
-
|
64
|
+
latch.pop
|
64
65
|
|
65
|
-
query = Resolv::DNS::Message.new
|
66
|
-
query.add_question "tc-lan-adapter._test-mdns._tcp.local.",
|
66
|
+
query = Resolv::DNS::Message.new 0
|
67
|
+
query.add_question "tc-lan-adapter._test-mdns._tcp.local.", SRV
|
67
68
|
|
68
69
|
sock = open_ipv4 iface.addr, 0
|
69
70
|
multicast_send sock, query.encode
|
@@ -71,7 +72,7 @@ module ZeroConf
|
|
71
72
|
s.stop
|
72
73
|
runner.join
|
73
74
|
|
74
|
-
expected = Resolv::DNS::Message.new(
|
75
|
+
expected = Resolv::DNS::Message.new(0)
|
75
76
|
expected.qr = 1
|
76
77
|
expected.aa = 1
|
77
78
|
|
@@ -83,7 +84,7 @@ module ZeroConf
|
|
83
84
|
10,
|
84
85
|
Resolv::DNS::Resource::IN::TXT.new(*s.text)
|
85
86
|
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,
|
87
|
+
expected.add_question s.service_name, MDNS::Announce::IN::SRV
|
87
88
|
|
88
89
|
assert_equal expected, res
|
89
90
|
end
|
@@ -93,13 +94,14 @@ module ZeroConf
|
|
93
94
|
rd, wr = IO.pipe
|
94
95
|
|
95
96
|
listen = make_listener rd, q
|
96
|
-
|
97
|
+
latch = Queue.new
|
98
|
+
s = make_server iface, started_callback: -> { latch << :start }
|
97
99
|
server = Thread.new { s.start }
|
98
|
-
|
100
|
+
latch.pop
|
99
101
|
|
100
|
-
query = Resolv::DNS::Message.new
|
102
|
+
query = Resolv::DNS::Message.new 0
|
101
103
|
query.add_question "_services._dns-sd._udp.local.", Resolv::DNS::Resource::IN::PTR
|
102
|
-
sock = open_ipv4 iface.addr,
|
104
|
+
sock = open_ipv4 iface.addr, 0
|
103
105
|
multicast_send sock, query.encode
|
104
106
|
|
105
107
|
while res = q.pop
|
@@ -196,14 +198,15 @@ module ZeroConf
|
|
196
198
|
end
|
197
199
|
|
198
200
|
def test_dnssd_unicast_answer
|
199
|
-
|
201
|
+
latch = Queue.new
|
202
|
+
s = make_server iface, started_callback: -> { latch << :start }
|
200
203
|
runner = Thread.new { s.start }
|
201
|
-
|
204
|
+
latch.pop
|
202
205
|
|
203
|
-
query = Resolv::DNS::Message.new
|
206
|
+
query = Resolv::DNS::Message.new 0
|
204
207
|
query.add_question "_services._dns-sd._udp.local.", PTR
|
205
208
|
|
206
|
-
sock = open_ipv4 iface.addr,
|
209
|
+
sock = open_ipv4 iface.addr, 0
|
207
210
|
multicast_send sock, query.encode
|
208
211
|
|
209
212
|
res = nil
|
@@ -230,53 +233,20 @@ module ZeroConf
|
|
230
233
|
assert_equal expected, res
|
231
234
|
end
|
232
235
|
|
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
236
|
def test_service_multicast_answer
|
269
237
|
q = Thread::Queue.new
|
270
238
|
rd, wr = IO.pipe
|
271
239
|
|
272
|
-
|
273
|
-
|
240
|
+
latch = Queue.new
|
241
|
+
listen = make_listener rd, q, started_callback: -> { latch << :start }
|
242
|
+
s = make_server iface, started_callback: -> { latch << :start }
|
274
243
|
server = Thread.new { s.start }
|
275
|
-
|
244
|
+
latch.pop
|
245
|
+
latch.pop
|
276
246
|
|
277
|
-
query = Resolv::DNS::Message.new
|
247
|
+
query = Resolv::DNS::Message.new 0
|
278
248
|
query.add_question "_test-mdns._tcp.local.", Resolv::DNS::Resource::IN::PTR
|
279
|
-
sock = open_ipv4 iface.addr,
|
249
|
+
sock = open_ipv4 iface.addr, 0
|
280
250
|
multicast_send sock, query.encode
|
281
251
|
|
282
252
|
service = Resolv::DNS::Name.create s.service
|
@@ -316,14 +286,15 @@ module ZeroConf
|
|
316
286
|
end
|
317
287
|
|
318
288
|
def test_service_unicast_answer
|
319
|
-
|
289
|
+
latch = Queue.new
|
290
|
+
s = make_server iface, started_callback: -> { latch << :start }
|
320
291
|
runner = Thread.new { s.start }
|
321
|
-
|
292
|
+
latch.pop
|
322
293
|
|
323
|
-
query = Resolv::DNS::Message.new
|
294
|
+
query = Resolv::DNS::Message.new 0
|
324
295
|
query.add_question "_test-mdns._tcp.local.", PTR
|
325
296
|
|
326
|
-
sock = open_ipv4 iface.addr,
|
297
|
+
sock = open_ipv4 iface.addr, 0
|
327
298
|
multicast_send sock, query.encode
|
328
299
|
res = Resolv::DNS::Message.decode read_with_timeout(sock).first
|
329
300
|
s.stop
|
@@ -349,53 +320,20 @@ module ZeroConf
|
|
349
320
|
assert_equal expected, res
|
350
321
|
end
|
351
322
|
|
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
323
|
def test_multicast_service_instance_answer
|
388
324
|
q = Queue.new
|
389
325
|
rd, wr = IO.pipe
|
390
326
|
|
391
|
-
|
392
|
-
|
327
|
+
latch = Queue.new
|
328
|
+
listen = make_listener rd, q, started_callback: -> { latch << :start }
|
329
|
+
s = make_server iface, started_callback: -> { latch << :start }
|
393
330
|
server = Thread.new { s.start }
|
394
|
-
|
331
|
+
latch.pop
|
332
|
+
latch.pop
|
395
333
|
|
396
|
-
query = Resolv::DNS::Message.new
|
334
|
+
query = Resolv::DNS::Message.new 0
|
397
335
|
query.add_question "tc-lan-adapter._test-mdns._tcp.local.", Resolv::DNS::Resource::IN::PTR
|
398
|
-
sock = open_ipv4 iface.addr,
|
336
|
+
sock = open_ipv4 iface.addr, 0
|
399
337
|
multicast_send sock, query.encode
|
400
338
|
|
401
339
|
service_name = Resolv::DNS::Name.create s.service_name
|
@@ -430,14 +368,15 @@ module ZeroConf
|
|
430
368
|
end
|
431
369
|
|
432
370
|
def test_unicast_name_lookup
|
433
|
-
|
371
|
+
latch = Queue.new
|
372
|
+
s = make_server iface, started_callback: -> { latch << :start }
|
434
373
|
runner = Thread.new { s.start }
|
435
|
-
|
374
|
+
latch.pop
|
436
375
|
|
437
|
-
query = Resolv::DNS::Message.new
|
376
|
+
query = Resolv::DNS::Message.new 0
|
438
377
|
query.add_question "tc-lan-adapter.local.", A
|
439
378
|
|
440
|
-
sock = open_ipv4 iface.addr,
|
379
|
+
sock = open_ipv4 iface.addr, 0
|
441
380
|
multicast_send sock, query.encode
|
442
381
|
res = Resolv::DNS::Message.decode read_with_timeout(sock).first
|
443
382
|
s.stop
|
@@ -459,48 +398,20 @@ module ZeroConf
|
|
459
398
|
assert_equal expected, res
|
460
399
|
end
|
461
400
|
|
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
401
|
def test_multicast_name
|
493
402
|
q = Queue.new
|
494
403
|
rd, wr = IO.pipe
|
495
404
|
|
496
|
-
|
497
|
-
|
405
|
+
latch = Queue.new
|
406
|
+
listen = make_listener rd, q, started_callback: -> { latch << :start }
|
407
|
+
s = make_server iface, started_callback: -> { latch << :start }
|
498
408
|
server = Thread.new { s.start }
|
499
|
-
|
409
|
+
latch.pop
|
410
|
+
latch.pop
|
500
411
|
|
501
|
-
query = Resolv::DNS::Message.new
|
412
|
+
query = Resolv::DNS::Message.new 0
|
502
413
|
query.add_question "tc-lan-adapter.local.", Resolv::DNS::Resource::IN::A
|
503
|
-
sock = open_ipv4 iface.addr,
|
414
|
+
sock = open_ipv4 iface.addr, 0
|
504
415
|
multicast_send sock, query.encode
|
505
416
|
|
506
417
|
host = Resolv::DNS::Name.create s.qualified_host
|
@@ -529,6 +440,21 @@ module ZeroConf
|
|
529
440
|
assert_equal expected, res
|
530
441
|
end
|
531
442
|
|
443
|
+
def test_raise_on_malformed_requests
|
444
|
+
latch = Queue.new
|
445
|
+
s = make_server iface, abort_on_malformed_requests: true, started_callback: -> { latch << :start }
|
446
|
+
runner = Thread.new {
|
447
|
+
assert_raises do
|
448
|
+
s.start
|
449
|
+
end
|
450
|
+
}
|
451
|
+
latch.pop
|
452
|
+
|
453
|
+
sock = open_ipv4 iface.addr, Resolv::MDNS::Port
|
454
|
+
multicast_send sock, "not a valid DNS message"
|
455
|
+
runner.join
|
456
|
+
end
|
457
|
+
|
532
458
|
def read_with_timeout sock
|
533
459
|
return unless sock.wait_readable(3)
|
534
460
|
sock.recvfrom(2048)
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zeroconf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Patterson
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: resolv
|
@@ -80,7 +79,6 @@ homepage: https://github.com/tenderlove/zeroconf
|
|
80
79
|
licenses:
|
81
80
|
- Apache-2.0
|
82
81
|
metadata: {}
|
83
|
-
post_install_message:
|
84
82
|
rdoc_options: []
|
85
83
|
require_paths:
|
86
84
|
- lib
|
@@ -95,8 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
95
93
|
- !ruby/object:Gem::Version
|
96
94
|
version: '0'
|
97
95
|
requirements: []
|
98
|
-
rubygems_version: 3.
|
99
|
-
signing_key:
|
96
|
+
rubygems_version: 3.7.0.dev
|
100
97
|
specification_version: 4
|
101
98
|
summary: Multicast DNS client and server
|
102
99
|
test_files:
|