dnssd 1.2 → 1.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|