dnssd 1.2 → 1.3
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.
- data.tar.gz.sig +0 -0
- data/.autotest +14 -0
- data/History.txt +22 -3
- data/Manifest.txt +15 -0
- data/README.txt +27 -3
- data/Rakefile +5 -4
- data/ext/dnssd/dnssd.c +4 -0
- data/ext/dnssd/dnssd.h +13 -18
- data/ext/dnssd/errors.c +9 -3
- data/ext/dnssd/extconf.rb +51 -44
- data/ext/dnssd/flags.c +68 -14
- data/ext/dnssd/record.c +218 -0
- data/ext/dnssd/service.c +341 -121
- data/lib/dnssd.rb +46 -11
- data/lib/dnssd/record.rb +97 -0
- data/lib/dnssd/reply.rb +39 -92
- data/lib/dnssd/reply/addr_info.rb +47 -0
- data/lib/dnssd/reply/browse.rb +52 -0
- data/lib/dnssd/reply/domain.rb +22 -0
- data/lib/dnssd/reply/query_record.rb +183 -0
- data/lib/dnssd/reply/register.rb +37 -0
- data/lib/dnssd/reply/resolve.rb +105 -0
- data/lib/dnssd/service.rb +123 -16
- data/lib/dnssd/text_record.rb +28 -19
- data/sample/browse.rb +24 -6
- data/sample/enumerate_domains.rb +7 -1
- data/sample/getaddrinfo.rb +28 -0
- data/sample/growl.rb +2 -0
- data/sample/query_record.rb +15 -0
- data/sample/register.rb +19 -20
- data/sample/resolve.rb +31 -7
- data/sample/resolve_ichat.rb +5 -6
- data/sample/server.rb +2 -0
- data/sample/socket.rb +4 -0
- data/test/test_dnssd.rb +6 -4
- data/test/test_dnssd_flags.rb +1 -15
- data/test/test_dnssd_record.rb +92 -0
- data/test/test_dnssd_reply.rb +13 -79
- data/test/test_dnssd_reply_browse.rb +28 -0
- data/test/test_dnssd_reply_query_record.rb +92 -0
- data/test/test_dnssd_reply_resolve.rb +47 -0
- data/test/test_dnssd_service.rb +12 -0
- data/test/test_dnssd_text_record.rb +3 -3
- metadata +32 -11
- metadata.gz.sig +0 -0
data/lib/dnssd/text_record.rb
CHANGED
@@ -1,17 +1,36 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
1
3
|
##
|
2
|
-
# DNSSD::TextRecord is a Hash
|
4
|
+
# DNSSD::TextRecord is a Hash delegate that can encode its contents for DNSSD.
|
3
5
|
|
4
|
-
class DNSSD::TextRecord
|
6
|
+
class DNSSD::TextRecord < DelegateClass(Hash)
|
5
7
|
|
6
8
|
##
|
7
|
-
# Creates a new TextRecord
|
9
|
+
# Creates a new TextRecord decoding an encoded +text_record+ if given or
|
10
|
+
# from a given Hash.
|
11
|
+
#
|
12
|
+
# DNSSD::TextRecord.new "\003k=v"
|
13
|
+
#
|
14
|
+
# or
|
15
|
+
#
|
16
|
+
# DNSSD::TextRecord.new 'k' => 'v'
|
8
17
|
|
9
18
|
def initialize(text_record = nil)
|
10
|
-
|
19
|
+
super case text_record
|
20
|
+
when Hash then
|
21
|
+
text_record.dup
|
22
|
+
when String then
|
23
|
+
decode(text_record.dup)
|
24
|
+
else
|
25
|
+
Hash.new
|
26
|
+
end
|
27
|
+
end
|
11
28
|
|
12
|
-
|
29
|
+
##
|
30
|
+
# Decodes +text_record+ and returns a Hash
|
13
31
|
|
14
|
-
|
32
|
+
def decode(text_record)
|
33
|
+
record = {}
|
15
34
|
|
16
35
|
until text_record.empty? do
|
17
36
|
size = text_record.slice! 0
|
@@ -28,16 +47,10 @@ class DNSSD::TextRecord
|
|
28
47
|
|
29
48
|
next unless key
|
30
49
|
|
31
|
-
|
50
|
+
record[key] = value
|
32
51
|
end
|
33
|
-
end
|
34
52
|
|
35
|
-
|
36
|
-
@records[key]
|
37
|
-
end
|
38
|
-
|
39
|
-
def []=(key, value)
|
40
|
-
@records[key] = value
|
53
|
+
record
|
41
54
|
end
|
42
55
|
|
43
56
|
##
|
@@ -46,7 +59,7 @@ class DNSSD::TextRecord
|
|
46
59
|
# clients.
|
47
60
|
|
48
61
|
def encode
|
49
|
-
|
62
|
+
sort.map do |key, value|
|
50
63
|
key = key.to_s
|
51
64
|
|
52
65
|
raise DNSSD::Error, "empty key" if key.empty?
|
@@ -61,9 +74,5 @@ class DNSSD::TextRecord
|
|
61
74
|
end.join ''
|
62
75
|
end
|
63
76
|
|
64
|
-
def to_hash
|
65
|
-
@records.dup
|
66
|
-
end
|
67
|
-
|
68
77
|
end
|
69
78
|
|
data/sample/browse.rb
CHANGED
@@ -1,11 +1,29 @@
|
|
1
1
|
require 'dnssd'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
end
|
3
|
+
Thread.abort_on_exception = true
|
4
|
+
trap 'INT' do exit end
|
5
|
+
trap 'TERM' do exit end
|
6
|
+
|
7
|
+
browser = DNSSD::Service.new
|
8
|
+
services = {}
|
9
|
+
|
10
|
+
puts "Browsing for TCP blackjack service"
|
11
|
+
puts "(run sample/register.rb)"
|
12
|
+
puts
|
6
13
|
|
7
|
-
|
8
|
-
|
14
|
+
browser.browse '_blackjack._tcp' do |reply|
|
15
|
+
services[reply.fullname] = reply
|
16
|
+
next if reply.flags.more_coming?
|
9
17
|
|
10
|
-
|
18
|
+
services.sort_by do |_, service|
|
19
|
+
[(service.flags.add? ? 0 : 1), service.fullname]
|
20
|
+
end.each do |_, service|
|
21
|
+
add = service.flags.add? ? 'Add' : 'Remove'
|
22
|
+
puts "#{add} #{service.name} on #{service.domain}"
|
23
|
+
end
|
24
|
+
|
25
|
+
services.clear
|
26
|
+
|
27
|
+
puts
|
28
|
+
end
|
11
29
|
|
data/sample/enumerate_domains.rb
CHANGED
@@ -2,8 +2,14 @@ require 'dnssd'
|
|
2
2
|
|
3
3
|
Thread.abort_on_exception = true
|
4
4
|
|
5
|
+
domains = []
|
6
|
+
|
5
7
|
enumerator = DNSSD.enumerate_domains do |reply|
|
6
|
-
|
8
|
+
domains << reply.domain
|
9
|
+
next if reply.flags.more_coming?
|
10
|
+
|
11
|
+
puts "Found domains:\n#{domains.join "\n"}"
|
12
|
+
exit
|
7
13
|
end
|
8
14
|
|
9
15
|
trap 'INT' do enumerator.stop; exit end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'dnssd'
|
2
|
+
|
3
|
+
Thread.abort_on_exception = true
|
4
|
+
|
5
|
+
abort "#{$0} \"http service name\"" if ARGV.empty?
|
6
|
+
|
7
|
+
resolver = DNSSD.resolve ARGV.shift, '_http._tcp', 'local' do |reply|
|
8
|
+
addresses = []
|
9
|
+
|
10
|
+
service = DNSSD::Service.new
|
11
|
+
begin
|
12
|
+
service.getaddrinfo reply.target do |addrinfo|
|
13
|
+
addresses << addrinfo.address
|
14
|
+
break unless addrinfo.flags.more_coming?
|
15
|
+
end
|
16
|
+
ensure
|
17
|
+
service.stop
|
18
|
+
end
|
19
|
+
|
20
|
+
puts "Addresses for #{reply.target}:\n#{addresses.join "\n"}"
|
21
|
+
exit
|
22
|
+
end
|
23
|
+
|
24
|
+
trap 'INT' do resolver.stop; exit end
|
25
|
+
trap 'TERM' do resolver.stop; exit end
|
26
|
+
|
27
|
+
sleep
|
28
|
+
|
data/sample/growl.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'dnssd'
|
2
|
+
|
3
|
+
Thread.abort_on_exception = true
|
4
|
+
trap 'INT' do exit end
|
5
|
+
trap 'TERM' do exit end
|
6
|
+
|
7
|
+
query = DNSSD::Service.new
|
8
|
+
|
9
|
+
abort "#{$0} fullname" if ARGV.empty?
|
10
|
+
fullname = ARGV.shift
|
11
|
+
|
12
|
+
query.query_record fullname, DNSSD::Record::SRV do |record|
|
13
|
+
puts record
|
14
|
+
end
|
15
|
+
|
data/sample/register.rb
CHANGED
@@ -1,30 +1,29 @@
|
|
1
1
|
require 'dnssd'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
p :registered => reply.fullname
|
7
|
-
end
|
8
|
-
|
9
|
-
sleep 1
|
3
|
+
Thread.abort_on_exception = true
|
4
|
+
trap 'INT' do exit end
|
5
|
+
trap 'TERM' do exit end
|
10
6
|
|
7
|
+
puts "Registering some blackjack services"
|
8
|
+
puts "(run sample/browse.rb or sample/resolve.rb)"
|
11
9
|
puts
|
12
10
|
|
13
|
-
|
11
|
+
DNSSD.register 'blockless', '_blackjack._tcp', nil, 1025
|
12
|
+
puts "registered blockless (no callback)"
|
14
13
|
|
15
|
-
|
16
|
-
if
|
17
|
-
found[reply.name] = true
|
18
|
-
else
|
19
|
-
puts "found:\n#{found.keys.join "\n"}"
|
20
|
-
puts
|
21
|
-
|
22
|
-
found.clear
|
23
|
-
end
|
14
|
+
DNSSD.register 'block', '_blackjack._tcp', nil, 1026 do |r|
|
15
|
+
puts "registered #{r.fullname}" if r.flags.add?
|
24
16
|
end
|
25
17
|
|
26
|
-
|
18
|
+
registrar = DNSSD::Service.new
|
19
|
+
|
20
|
+
service = nil
|
27
21
|
|
28
|
-
|
29
|
-
|
22
|
+
tr = DNSSD::TextRecord.new
|
23
|
+
tr['foo'] = 'bar'
|
24
|
+
registrar.register 'add_record', '_blackjack._tcp', nil, 1027, nil, tr do |r|
|
25
|
+
puts "registered #{r.fullname}" if r.flags.add?
|
26
|
+
record = registrar.add_record DNSSD::Record::RP, 'nobody.local. .'
|
27
|
+
puts "added RP record"
|
28
|
+
end
|
30
29
|
|
data/sample/resolve.rb
CHANGED
@@ -1,13 +1,37 @@
|
|
1
1
|
require 'dnssd'
|
2
2
|
|
3
|
-
|
3
|
+
Thread.abort_on_exception = true
|
4
|
+
trap 'INT' do exit end
|
5
|
+
trap 'TERM' do exit end
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
7
|
+
puts "Resolving TCP blackjack services"
|
8
|
+
puts "(run sample/register.rb)"
|
9
|
+
puts
|
10
|
+
|
11
|
+
browser = DNSSD::Service.new
|
12
|
+
services = {}
|
13
|
+
|
14
|
+
browser.browse '_blackjack._tcp' do |reply|
|
15
|
+
services[reply.fullname] = reply
|
16
|
+
next if reply.flags.more_coming?
|
17
|
+
|
18
|
+
services.sort_by do |_, service|
|
19
|
+
[(service.flags.add? ? 0 : 1), service.fullname]
|
20
|
+
end.each do |_, service|
|
21
|
+
next unless service.flags.add?
|
8
22
|
|
9
|
-
|
10
|
-
|
23
|
+
resolver = DNSSD::Service.new
|
24
|
+
resolver.resolve service do |r|
|
25
|
+
puts "#{r.name} on #{r.target}:#{r.port}"
|
26
|
+
puts "\t#{r.text_record.inspect}" unless r.text_record.empty?
|
27
|
+
break unless r.flags.more_coming?
|
28
|
+
end
|
11
29
|
|
12
|
-
|
30
|
+
resolver.stop
|
31
|
+
end
|
32
|
+
|
33
|
+
services.clear
|
34
|
+
|
35
|
+
puts
|
36
|
+
end
|
13
37
|
|
data/sample/resolve_ichat.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
require 'dnssd'
|
2
|
-
|
2
|
+
|
3
|
+
Thread.abort_on_exception = true
|
4
|
+
trap 'INT' do exit end
|
5
|
+
trap 'TERM' do exit end
|
3
6
|
|
4
7
|
class ChatNameResolver
|
5
8
|
def self.resolve_add(reply)
|
6
9
|
Thread.new reply do |reply|
|
7
10
|
DNSSD.resolve reply.name, reply.type, reply.domain do |resolve_reply|
|
8
11
|
puts "Adding: #{resolve_reply.inspect}"
|
9
|
-
pp resolve_reply.text_record
|
10
12
|
resolve_reply.service.stop
|
11
13
|
end
|
12
14
|
end
|
@@ -21,7 +23,7 @@ class ChatNameResolver
|
|
21
23
|
end
|
22
24
|
end
|
23
25
|
|
24
|
-
|
26
|
+
DNSSD.browse '_presence._tcp' do |reply|
|
25
27
|
if reply.flags.add? then
|
26
28
|
ChatNameResolver.resolve_add reply
|
27
29
|
else
|
@@ -29,8 +31,5 @@ browser = DNSSD.browse '_presence._tcp' do |reply|
|
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
32
|
-
trap 'INT' do browser.stop; exit end
|
33
|
-
trap 'TERM' do browser.stop; exit end
|
34
|
-
|
35
34
|
sleep
|
36
35
|
|
data/sample/server.rb
CHANGED
data/sample/socket.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
require 'dnssd'
|
2
2
|
|
3
|
+
Thread.abort_on_exception = true
|
3
4
|
trap 'INT' do exit end
|
4
5
|
trap 'TERM' do exit end
|
5
6
|
|
7
|
+
puts 'run sample/server.rb'
|
8
|
+
|
6
9
|
service = nil
|
7
10
|
|
8
11
|
DNSSD.browse! '_blackjack._tcp', 'local.' do |reply|
|
@@ -15,4 +18,5 @@ puts "found service #{service.name}"
|
|
15
18
|
socket = service.connect
|
16
19
|
|
17
20
|
puts "Connected to %s:%d" % socket.peeraddr.values_at(2, 1)
|
21
|
+
puts " from %s:%d" % socket.addr.values_at(2, 1)
|
18
22
|
|
data/test/test_dnssd.rb
CHANGED
@@ -61,14 +61,16 @@ class TestDNSSD < MiniTest::Unit::TestCase
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def test_class_interface_index
|
64
|
-
index = DNSSD.interface_index
|
65
|
-
|
64
|
+
index = DNSSD.interface_index 'lo0'
|
65
|
+
index = DNSSD.interface_index 'lo' if index.zero?
|
66
|
+
refute_equal 0, index, 'what? no lo0? no lo?'
|
66
67
|
end
|
67
68
|
|
68
69
|
def test_class_interface_name
|
69
|
-
index = DNSSD.interface_index
|
70
|
+
index = DNSSD.interface_index 'lo0'
|
71
|
+
index = DNSSD.interface_index 'lo' if index.zero?
|
70
72
|
|
71
|
-
|
73
|
+
assert_match %r%^lo0?$%, DNSSD.interface_name(index)
|
72
74
|
end
|
73
75
|
|
74
76
|
end
|
data/test/test_dnssd_flags.rb
CHANGED
@@ -65,21 +65,7 @@ class TestDNSSDFlags < MiniTest::Unit::TestCase
|
|
65
65
|
def test_complement
|
66
66
|
new_flags = ~@flags
|
67
67
|
|
68
|
-
|
69
|
-
DNSSD::Flags::AllowRemoteQuery,
|
70
|
-
DNSSD::Flags::BrowseDomains,
|
71
|
-
DNSSD::Flags::Default,
|
72
|
-
DNSSD::Flags::Force,
|
73
|
-
DNSSD::Flags::ForceMulticast,
|
74
|
-
DNSSD::Flags::LongLivedQuery,
|
75
|
-
DNSSD::Flags::MoreComing,
|
76
|
-
DNSSD::Flags::NoAutoRename,
|
77
|
-
DNSSD::Flags::RegistrationDomains,
|
78
|
-
DNSSD::Flags::ReturnIntermediates,
|
79
|
-
DNSSD::Flags::Shared,
|
80
|
-
DNSSD::Flags::Unique)
|
81
|
-
|
82
|
-
assert_equal expected, new_flags
|
68
|
+
assert_equal DNSSD::Flags.new(*DNSSD::Flags::ALL_FLAGS), new_flags
|
83
69
|
end
|
84
70
|
|
85
71
|
def test_equals
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'dnssd'
|
3
|
+
|
4
|
+
class TestDNSSDRecord < MiniTest::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@fullname = 'blackjack._blackjack._tcp.test.'
|
8
|
+
@IN = DNSSD::Record::IN
|
9
|
+
@ipv4 = "\300\000\002\001"
|
10
|
+
@ipv6 = " \001\r\270\000\000\000\000\000\000\000\000\000\000\000\001"
|
11
|
+
@nowhere = "\007nowhere\007example\000"
|
12
|
+
|
13
|
+
@R = DNSSD::Record
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_class_to_data_invalid
|
17
|
+
assert_raises ArgumentError do
|
18
|
+
@R.to_data(-1)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_class_to_data_A
|
23
|
+
assert_equal @ipv4, @R.to_data(DNSSD::Record::A, '192.0.2.1')
|
24
|
+
assert_equal @ipv4, @R.to_data(DNSSD::Record::A, IPAddr.new('192.0.2.1'))
|
25
|
+
|
26
|
+
assert_raises ArgumentError do
|
27
|
+
@R.to_data DNSSD::Record::A, '2001:db8::1'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_class_to_data_AAAA
|
32
|
+
assert_equal @ipv6, @R.to_data(DNSSD::Record::AAAA, '2001:db8::1')
|
33
|
+
assert_equal @ipv6,
|
34
|
+
@R.to_data(DNSSD::Record::AAAA, IPAddr.new('2001:db8::1'))
|
35
|
+
|
36
|
+
assert_raises ArgumentError do
|
37
|
+
@R.to_data DNSSD::Record::AAAA, '192.0.2.1'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_class_to_data_CNAME
|
42
|
+
assert_equal @nowhere, @R.to_data(DNSSD::Record::CNAME, 'nowhere.example.')
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_class_to_data_MX
|
46
|
+
assert_equal "\000\010#{@nowhere}",
|
47
|
+
@R.to_data(DNSSD::Record::MX, 8, 'nowhere.example.')
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_class_to_data_NS
|
51
|
+
assert_equal @nowhere, @R.to_data(DNSSD::Record::NS, 'nowhere.example.')
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_class_to_data_PTR
|
55
|
+
assert_equal @nowhere, @R.to_data(DNSSD::Record::PTR, 'nowhere.example.')
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_class_to_data_SOA
|
59
|
+
serial = 1
|
60
|
+
refresh = 86400
|
61
|
+
rtry = 3600
|
62
|
+
expire = 86400 * 2
|
63
|
+
minimum = 3600 * 12
|
64
|
+
|
65
|
+
expected = "#{@nowhere}\002me#{@nowhere}#{[serial, refresh, rtry, expire, minimum].pack 'NNNNN'}"
|
66
|
+
|
67
|
+
data = @R.to_data(DNSSD::Record::SOA, 'nowhere.example.',
|
68
|
+
'me.nowhere.example.', serial, refresh, rtry, expire,
|
69
|
+
minimum)
|
70
|
+
|
71
|
+
assert_equal expected, data
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_class_to_data_SRV
|
75
|
+
priority = 1
|
76
|
+
weight = 5
|
77
|
+
port = 1025
|
78
|
+
|
79
|
+
expected = "#{[priority, weight, port].pack 'nnn'}#{@nowhere}"
|
80
|
+
|
81
|
+
assert_equal expected,
|
82
|
+
@R.to_data(DNSSD::Record::SRV, priority, weight, port,
|
83
|
+
'nowhere.example.')
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_class_to_data_TXT
|
87
|
+
assert_equal "\005Hello\006World!",
|
88
|
+
@R.to_data(DNSSD::Record::TXT, 'Hello', 'World!')
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|