zeroconf 1.1.0 → 1.3.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/.github/workflows/ci.yml +2 -2
- data/.github/workflows/release.yml +52 -0
- data/Gemfile +2 -0
- data/README.md +4 -2
- data/Rakefile +3 -0
- data/lib/zeroconf/service.rb +96 -5
- data/lib/zeroconf/utils.rb +6 -2
- data/lib/zeroconf/version.rb +1 -1
- data/test/helper.rb +9 -0
- data/test/service_test.rb +157 -0
- data/zeroconf.gemspec +1 -1
- metadata +8 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1b9ec7f1320fa0807e2cdb89addcc9b6796745c9248ac0463a72877d908b74f4
|
|
4
|
+
data.tar.gz: 3be32a8bdabfc923576ce8ed0b8c9dbf430141aae8be1eaf9bc7898b1f425109
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b3eedb494ee9507f0e4d541b05f2627fb94d9b63b90d1d1a27f303a901b02fa4c5640719857f35927fd922b511960e753b7e530dc40e30cccf106b0e2cc10168
|
|
7
|
+
data.tar.gz: ef7526948bbe2a34ae9a850c48ba0d12760ad4acb846c33f808338c277d184d9056e8681246e7bbb6154ce1cd31398feb9a4336c4dc6835bc36a63c489642c6a
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: Publish gem to rubygems.org
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
push:
|
|
13
|
+
if: github.repository == 'tenderlove/zeroconf'
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
|
|
16
|
+
environment:
|
|
17
|
+
name: rubygems.org
|
|
18
|
+
url: https://rubygems.org/gems/zeroconf
|
|
19
|
+
|
|
20
|
+
permissions:
|
|
21
|
+
contents: write
|
|
22
|
+
id-token: write
|
|
23
|
+
|
|
24
|
+
strategy:
|
|
25
|
+
matrix:
|
|
26
|
+
ruby: ["ruby"]
|
|
27
|
+
|
|
28
|
+
steps:
|
|
29
|
+
- name: Harden Runner
|
|
30
|
+
uses: step-security/harden-runner@v2
|
|
31
|
+
with:
|
|
32
|
+
egress-policy: audit
|
|
33
|
+
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
|
|
36
|
+
- name: Set up Ruby
|
|
37
|
+
uses: ruby/setup-ruby@v1
|
|
38
|
+
with:
|
|
39
|
+
ruby-version: ${{ matrix.ruby }}
|
|
40
|
+
|
|
41
|
+
- name: Install dependencies
|
|
42
|
+
run: bundle install --jobs 4 --retry 3
|
|
43
|
+
|
|
44
|
+
- name: Publish to RubyGems
|
|
45
|
+
uses: rubygems/release-gem@v1
|
|
46
|
+
|
|
47
|
+
- name: Create GitHub release
|
|
48
|
+
run: |
|
|
49
|
+
tag_name="$(git describe --tags --abbrev=0)"
|
|
50
|
+
gh release create "${tag_name}" --verify-tag --generate-notes
|
|
51
|
+
env:
|
|
52
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
data/Gemfile
CHANGED
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/Rakefile
CHANGED
data/lib/zeroconf/service.rb
CHANGED
|
@@ -7,18 +7,27 @@ module ZeroConf
|
|
|
7
7
|
include Utils
|
|
8
8
|
|
|
9
9
|
attr_reader :service, :service_port, :hostname, :service_interfaces,
|
|
10
|
-
:service_name, :qualified_host, :text, :abort_on_malformed_requests
|
|
10
|
+
:service_name, :qualified_host, :text, :abort_on_malformed_requests,
|
|
11
|
+
:subtypes
|
|
11
12
|
|
|
12
|
-
def initialize service, service_port, hostname = Socket.gethostname, service_interfaces: ZeroConf.service_interfaces, text: [""], abort_on_malformed_requests: false, started_callback: nil
|
|
13
|
+
def initialize service, service_port, hostname = Socket.gethostname, service_interfaces: ZeroConf.service_interfaces, instance_name: nil, text: [""], subtypes: [], abort_on_malformed_requests: false, started_callback: nil
|
|
13
14
|
@service = service
|
|
14
15
|
@service_port = service_port
|
|
15
|
-
|
|
16
|
+
|
|
17
|
+
@hostname = strip_dot_local(hostname) # We re-add .local anyway, later on
|
|
16
18
|
@service_interfaces = service_interfaces
|
|
17
19
|
@abort_on_malformed_requests = abort_on_malformed_requests
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
|
|
21
|
+
instance_name ||= @hostname
|
|
22
|
+
if instance_name.include?(".")
|
|
23
|
+
raise ArgumentError, "instance_name must not contain dots (is #{instance_name.inspect})"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
@service_name = "#{instance_name}.#{@service}"
|
|
27
|
+
@qualified_host = "#{@hostname}.local."
|
|
20
28
|
@started_callback = started_callback
|
|
21
29
|
@text = text
|
|
30
|
+
@subtypes = subtypes.map { |st| "#{st}._sub.#{@service}" }
|
|
22
31
|
@started = false
|
|
23
32
|
@rd, @wr = IO.pipe
|
|
24
33
|
end
|
|
@@ -54,6 +63,11 @@ module ZeroConf
|
|
|
54
63
|
60,
|
|
55
64
|
Resolv::DNS::Resource::IN::PTR.new(Resolv::DNS::Name.create(service_name))
|
|
56
65
|
|
|
66
|
+
subtypes.each do |st|
|
|
67
|
+
msg.add_answer st, 60,
|
|
68
|
+
Resolv::DNS::Resource::IN::PTR.new(Resolv::DNS::Name.create(service_name))
|
|
69
|
+
end
|
|
70
|
+
|
|
57
71
|
msg
|
|
58
72
|
end
|
|
59
73
|
|
|
@@ -86,6 +100,11 @@ module ZeroConf
|
|
|
86
100
|
0,
|
|
87
101
|
Resolv::DNS::Resource::IN::PTR.new(Resolv::DNS::Name.create(service_name))
|
|
88
102
|
|
|
103
|
+
subtypes.each do |st|
|
|
104
|
+
msg.add_answer st, 0,
|
|
105
|
+
Resolv::DNS::Resource::IN::PTR.new(Resolv::DNS::Name.create(service_name))
|
|
106
|
+
end
|
|
107
|
+
|
|
89
108
|
msg
|
|
90
109
|
end
|
|
91
110
|
|
|
@@ -167,6 +186,12 @@ module ZeroConf
|
|
|
167
186
|
else
|
|
168
187
|
name_answer_multicast
|
|
169
188
|
end
|
|
189
|
+
when *subtypes
|
|
190
|
+
if unicast
|
|
191
|
+
subtype_unicast_answer qn
|
|
192
|
+
else
|
|
193
|
+
subtype_multicast_answer qn
|
|
194
|
+
end
|
|
170
195
|
else
|
|
171
196
|
#p [:QUERY2, type, type::ClassValue, name]
|
|
172
197
|
end
|
|
@@ -306,6 +331,72 @@ module ZeroConf
|
|
|
306
331
|
msg
|
|
307
332
|
end
|
|
308
333
|
|
|
334
|
+
def subtype_multicast_answer subtype
|
|
335
|
+
msg = Resolv::DNS::Message.new(0)
|
|
336
|
+
msg.qr = 1
|
|
337
|
+
msg.aa = 1
|
|
338
|
+
|
|
339
|
+
msg.add_additional service_name, 60, Resolv::DNS::Resource::IN::SRV.new(0, 0, service_port, qualified_host)
|
|
340
|
+
|
|
341
|
+
service_interfaces.each do |iface|
|
|
342
|
+
if iface.addr.ipv4?
|
|
343
|
+
msg.add_additional qualified_host,
|
|
344
|
+
60,
|
|
345
|
+
Resolv::DNS::Resource::IN::A.new(iface.addr.ip_address)
|
|
346
|
+
else
|
|
347
|
+
msg.add_additional qualified_host,
|
|
348
|
+
60,
|
|
349
|
+
Resolv::DNS::Resource::IN::AAAA.new(iface.addr.ip_address)
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
if @text
|
|
354
|
+
msg.add_additional service_name,
|
|
355
|
+
60,
|
|
356
|
+
Resolv::DNS::Resource::IN::TXT.new(*@text)
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
msg.add_answer subtype,
|
|
360
|
+
60,
|
|
361
|
+
Resolv::DNS::Resource::IN::PTR.new(Resolv::DNS::Name.create(service_name))
|
|
362
|
+
|
|
363
|
+
msg
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
def subtype_unicast_answer subtype
|
|
367
|
+
msg = Resolv::DNS::Message.new(0)
|
|
368
|
+
msg.qr = 1
|
|
369
|
+
msg.aa = 1
|
|
370
|
+
|
|
371
|
+
msg.add_additional service_name, 10, Resolv::DNS::Resource::IN::SRV.new(0, 0, service_port, qualified_host)
|
|
372
|
+
|
|
373
|
+
service_interfaces.each do |iface|
|
|
374
|
+
if iface.addr.ipv4?
|
|
375
|
+
msg.add_additional qualified_host,
|
|
376
|
+
10,
|
|
377
|
+
Resolv::DNS::Resource::IN::A.new(iface.addr.ip_address)
|
|
378
|
+
else
|
|
379
|
+
msg.add_additional qualified_host,
|
|
380
|
+
10,
|
|
381
|
+
Resolv::DNS::Resource::IN::AAAA.new(iface.addr.ip_address)
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
if @text
|
|
386
|
+
msg.add_additional service_name,
|
|
387
|
+
10,
|
|
388
|
+
Resolv::DNS::Resource::IN::TXT.new(*@text)
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
msg.add_answer subtype,
|
|
392
|
+
10,
|
|
393
|
+
Resolv::DNS::Resource::IN::PTR.new(Resolv::DNS::Name.create(service_name))
|
|
394
|
+
|
|
395
|
+
msg.add_question subtype, PTR
|
|
396
|
+
|
|
397
|
+
msg
|
|
398
|
+
end
|
|
399
|
+
|
|
309
400
|
def service_instance_multicast_answer
|
|
310
401
|
msg = Resolv::DNS::Message.new(0)
|
|
311
402
|
msg.qr = 1
|
data/lib/zeroconf/utils.rb
CHANGED
|
@@ -69,8 +69,8 @@ module ZeroConf
|
|
|
69
69
|
sock
|
|
70
70
|
end
|
|
71
71
|
|
|
72
|
-
BROADCAST_V4 = Addrinfo.new
|
|
73
|
-
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
|
|
74
74
|
|
|
75
75
|
def multicast_send sock, query
|
|
76
76
|
dest = if sock.local_address.ipv4?
|
|
@@ -94,6 +94,10 @@ module ZeroConf
|
|
|
94
94
|
sock.send(data, 0, Addrinfo.new(to))
|
|
95
95
|
end
|
|
96
96
|
|
|
97
|
+
def strip_dot_local(from_string)
|
|
98
|
+
from_string.to_s.gsub(/\.local\.?$/, "")
|
|
99
|
+
end
|
|
100
|
+
|
|
97
101
|
def open_ipv6 saddr, port
|
|
98
102
|
sock = UDPSocket.new Socket::AF_INET6
|
|
99
103
|
sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
|
data/lib/zeroconf/version.rb
CHANGED
data/test/helper.rb
CHANGED
|
@@ -47,6 +47,15 @@ module ZeroConf
|
|
|
47
47
|
**opts
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
+
def make_subtype_server iface, host = HOST_NAME, **opts
|
|
51
|
+
Service.new SERVICE + ".",
|
|
52
|
+
42424,
|
|
53
|
+
host,
|
|
54
|
+
service_interfaces: [iface], text: ["test=1", "other=value"],
|
|
55
|
+
subtypes: ["_universal"],
|
|
56
|
+
**opts
|
|
57
|
+
end
|
|
58
|
+
|
|
50
59
|
def make_listener rd, q, started_callback: nil
|
|
51
60
|
Thread.new do
|
|
52
61
|
sock = open_ipv4 Addrinfo.new(Socket.sockaddr_in(Resolv::MDNS::Port, Socket::INADDR_ANY)), Resolv::MDNS::Port
|
data/test/service_test.rb
CHANGED
|
@@ -26,6 +26,37 @@ module ZeroConf
|
|
|
26
26
|
assert_equal [""], s.text
|
|
27
27
|
end
|
|
28
28
|
|
|
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
|
|
34
|
+
|
|
35
|
+
assert_raises ArgumentError do
|
|
36
|
+
Service.new "_test-mdns._tcp.local.", 42424,
|
|
37
|
+
"ruby-mdns", instance_name: "ruby.test"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
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
|
|
47
|
+
|
|
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
|
|
53
|
+
|
|
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
|
+
end
|
|
59
|
+
|
|
29
60
|
def test_unicast_service_instance_answer
|
|
30
61
|
latch = Queue.new
|
|
31
62
|
s = make_server iface, started_callback: -> { latch << :start }
|
|
@@ -409,6 +440,132 @@ module ZeroConf
|
|
|
409
440
|
assert_equal expected, res
|
|
410
441
|
end
|
|
411
442
|
|
|
443
|
+
def test_subtypes_expanded
|
|
444
|
+
s = Service.new "_ipp._tcp.local.", 631, "printer",
|
|
445
|
+
service_interfaces: [iface],
|
|
446
|
+
subtypes: ["_universal", "_print"]
|
|
447
|
+
|
|
448
|
+
assert_equal ["_universal._sub._ipp._tcp.local.", "_print._sub._ipp._tcp.local."], s.subtypes
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
def test_subtypes_default_empty
|
|
452
|
+
s = make_server iface
|
|
453
|
+
assert_equal [], s.subtypes
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
def test_announcement_includes_subtype_ptrs
|
|
457
|
+
s = Service.new "_test-mdns._tcp.local.", 42424,
|
|
458
|
+
"tc-lan-adapter",
|
|
459
|
+
service_interfaces: [iface],
|
|
460
|
+
subtypes: ["_universal"]
|
|
461
|
+
|
|
462
|
+
ann = s.announcement
|
|
463
|
+
subtype_ptrs = ann.answer.select { |name, ttl, data|
|
|
464
|
+
name.to_s == "_universal._sub._test-mdns._tcp.local"
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
assert_equal 1, subtype_ptrs.length
|
|
468
|
+
assert_equal s.service_name, subtype_ptrs.first.last.name.to_s + "."
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
def test_disconnect_includes_subtype_ptrs
|
|
472
|
+
s = Service.new "_test-mdns._tcp.local.", 42424,
|
|
473
|
+
"tc-lan-adapter",
|
|
474
|
+
service_interfaces: [iface],
|
|
475
|
+
subtypes: ["_universal"]
|
|
476
|
+
|
|
477
|
+
msg = s.disconnect_msg
|
|
478
|
+
subtype_ptrs = msg.answer.select { |name, ttl, data|
|
|
479
|
+
name.to_s == "_universal._sub._test-mdns._tcp.local"
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
assert_equal 1, subtype_ptrs.length
|
|
483
|
+
assert_equal 0, subtype_ptrs.first[1] # TTL 0 for disconnect
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
def test_subtype_unicast_answer
|
|
487
|
+
latch = Queue.new
|
|
488
|
+
s = make_subtype_server iface, started_callback: -> { latch << :start }
|
|
489
|
+
runner = Thread.new { s.start }
|
|
490
|
+
latch.pop
|
|
491
|
+
|
|
492
|
+
subtype = "_universal._sub._test-mdns._tcp.local."
|
|
493
|
+
query = Resolv::DNS::Message.new 0
|
|
494
|
+
query.add_question subtype, PTR
|
|
495
|
+
|
|
496
|
+
sock = open_ipv4 iface.addr, 0
|
|
497
|
+
multicast_send sock, query.encode
|
|
498
|
+
res = Resolv::DNS::Message.decode read_with_timeout(sock).first
|
|
499
|
+
s.stop
|
|
500
|
+
runner.join
|
|
501
|
+
|
|
502
|
+
expected = Resolv::DNS::Message.new(0)
|
|
503
|
+
expected.qr = 1
|
|
504
|
+
expected.aa = 1
|
|
505
|
+
|
|
506
|
+
expected.add_additional s.service_name, 10, Resolv::DNS::Resource::IN::SRV.new(0, 0, s.service_port, s.qualified_host)
|
|
507
|
+
|
|
508
|
+
expected.add_additional s.qualified_host,
|
|
509
|
+
10,
|
|
510
|
+
Resolv::DNS::Resource::IN::A.new(iface.addr.ip_address)
|
|
511
|
+
|
|
512
|
+
expected.add_additional s.service_name,
|
|
513
|
+
10,
|
|
514
|
+
Resolv::DNS::Resource::IN::TXT.new(*s.text)
|
|
515
|
+
|
|
516
|
+
expected.add_answer subtype,
|
|
517
|
+
10,
|
|
518
|
+
Resolv::DNS::Resource::IN::PTR.new(Resolv::DNS::Name.create(s.service_name))
|
|
519
|
+
|
|
520
|
+
expected.add_question subtype, PTR
|
|
521
|
+
|
|
522
|
+
assert_equal expected, res
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
def test_subtype_multicast_answer
|
|
526
|
+
q = Thread::Queue.new
|
|
527
|
+
rd, wr = IO.pipe
|
|
528
|
+
|
|
529
|
+
latch = Queue.new
|
|
530
|
+
listen = make_listener rd, q, started_callback: -> { latch << :start }
|
|
531
|
+
s = make_subtype_server iface, started_callback: -> { latch << :start }
|
|
532
|
+
server = Thread.new { s.start }
|
|
533
|
+
latch.pop
|
|
534
|
+
latch.pop
|
|
535
|
+
|
|
536
|
+
subtype = "_universal._sub._test-mdns._tcp.local."
|
|
537
|
+
query = Resolv::DNS::Message.new 0
|
|
538
|
+
query.add_question subtype, Resolv::DNS::Resource::IN::PTR
|
|
539
|
+
sock = open_ipv4 iface.addr, 0
|
|
540
|
+
multicast_send sock, query.encode
|
|
541
|
+
|
|
542
|
+
subtype_name = Resolv::DNS::Name.create subtype
|
|
543
|
+
service_name = Resolv::DNS::Name.create s.service_name
|
|
544
|
+
|
|
545
|
+
while res = q.pop
|
|
546
|
+
if res.answer.find { |name, ttl, data| name == subtype_name && data.name == service_name }
|
|
547
|
+
wr.write "x"
|
|
548
|
+
break
|
|
549
|
+
end
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
listen.join
|
|
553
|
+
s.stop
|
|
554
|
+
server.join
|
|
555
|
+
|
|
556
|
+
# Verify the response contains the subtype PTR
|
|
557
|
+
subtype_ptr = res.answer.find { |name, ttl, data|
|
|
558
|
+
name == subtype_name && data.name == service_name
|
|
559
|
+
}
|
|
560
|
+
assert subtype_ptr, "expected subtype PTR in answer"
|
|
561
|
+
|
|
562
|
+
# Verify it has SRV in additional
|
|
563
|
+
srv = res.additional.find { |_, _, data|
|
|
564
|
+
ZeroConf::MDNS::Announce::IN::SRV == data.class
|
|
565
|
+
}
|
|
566
|
+
assert srv, "expected SRV in additional"
|
|
567
|
+
end
|
|
568
|
+
|
|
412
569
|
def test_raise_on_malformed_requests
|
|
413
570
|
latch = Queue.new
|
|
414
571
|
s = make_server iface, abort_on_malformed_requests: true, started_callback: -> { latch << :start }
|
data/zeroconf.gemspec
CHANGED
|
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
|
|
|
12
12
|
s.homepage = "https://github.com/tenderlove/zeroconf"
|
|
13
13
|
s.license = "Apache-2.0"
|
|
14
14
|
|
|
15
|
-
s.add_dependency("resolv", "
|
|
15
|
+
s.add_dependency("resolv", ">= 0.7.1")
|
|
16
16
|
s.add_development_dependency("rake", "~> 13.0")
|
|
17
17
|
s.add_development_dependency("minitest", "~> 5.20")
|
|
18
18
|
end
|
metadata
CHANGED
|
@@ -1,29 +1,28 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: zeroconf
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.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
|
|
15
14
|
requirement: !ruby/object:Gem::Requirement
|
|
16
15
|
requirements:
|
|
17
|
-
- - "
|
|
16
|
+
- - ">="
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.
|
|
18
|
+
version: 0.7.1
|
|
20
19
|
type: :runtime
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
|
-
- - "
|
|
23
|
+
- - ">="
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.
|
|
25
|
+
version: 0.7.1
|
|
27
26
|
- !ruby/object:Gem::Dependency
|
|
28
27
|
name: rake
|
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -59,6 +58,7 @@ extensions: []
|
|
|
59
58
|
extra_rdoc_files: []
|
|
60
59
|
files:
|
|
61
60
|
- ".github/workflows/ci.yml"
|
|
61
|
+
- ".github/workflows/release.yml"
|
|
62
62
|
- CODE_OF_CONDUCT.md
|
|
63
63
|
- Gemfile
|
|
64
64
|
- LICENSE
|
|
@@ -80,7 +80,6 @@ homepage: https://github.com/tenderlove/zeroconf
|
|
|
80
80
|
licenses:
|
|
81
81
|
- Apache-2.0
|
|
82
82
|
metadata: {}
|
|
83
|
-
post_install_message:
|
|
84
83
|
rdoc_options: []
|
|
85
84
|
require_paths:
|
|
86
85
|
- lib
|
|
@@ -95,8 +94,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
95
94
|
- !ruby/object:Gem::Version
|
|
96
95
|
version: '0'
|
|
97
96
|
requirements: []
|
|
98
|
-
rubygems_version:
|
|
99
|
-
signing_key:
|
|
97
|
+
rubygems_version: 4.0.6
|
|
100
98
|
specification_version: 4
|
|
101
99
|
summary: Multicast DNS client and server
|
|
102
100
|
test_files:
|