dnssd 1.2 → 1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.autotest +14 -0
  3. data/History.txt +22 -3
  4. data/Manifest.txt +15 -0
  5. data/README.txt +27 -3
  6. data/Rakefile +5 -4
  7. data/ext/dnssd/dnssd.c +4 -0
  8. data/ext/dnssd/dnssd.h +13 -18
  9. data/ext/dnssd/errors.c +9 -3
  10. data/ext/dnssd/extconf.rb +51 -44
  11. data/ext/dnssd/flags.c +68 -14
  12. data/ext/dnssd/record.c +218 -0
  13. data/ext/dnssd/service.c +341 -121
  14. data/lib/dnssd.rb +46 -11
  15. data/lib/dnssd/record.rb +97 -0
  16. data/lib/dnssd/reply.rb +39 -92
  17. data/lib/dnssd/reply/addr_info.rb +47 -0
  18. data/lib/dnssd/reply/browse.rb +52 -0
  19. data/lib/dnssd/reply/domain.rb +22 -0
  20. data/lib/dnssd/reply/query_record.rb +183 -0
  21. data/lib/dnssd/reply/register.rb +37 -0
  22. data/lib/dnssd/reply/resolve.rb +105 -0
  23. data/lib/dnssd/service.rb +123 -16
  24. data/lib/dnssd/text_record.rb +28 -19
  25. data/sample/browse.rb +24 -6
  26. data/sample/enumerate_domains.rb +7 -1
  27. data/sample/getaddrinfo.rb +28 -0
  28. data/sample/growl.rb +2 -0
  29. data/sample/query_record.rb +15 -0
  30. data/sample/register.rb +19 -20
  31. data/sample/resolve.rb +31 -7
  32. data/sample/resolve_ichat.rb +5 -6
  33. data/sample/server.rb +2 -0
  34. data/sample/socket.rb +4 -0
  35. data/test/test_dnssd.rb +6 -4
  36. data/test/test_dnssd_flags.rb +1 -15
  37. data/test/test_dnssd_record.rb +92 -0
  38. data/test/test_dnssd_reply.rb +13 -79
  39. data/test/test_dnssd_reply_browse.rb +28 -0
  40. data/test/test_dnssd_reply_query_record.rb +92 -0
  41. data/test/test_dnssd_reply_resolve.rb +47 -0
  42. data/test/test_dnssd_service.rb +12 -0
  43. data/test/test_dnssd_text_record.rb +3 -3
  44. metadata +32 -11
  45. metadata.gz.sig +0 -0
@@ -1,17 +1,36 @@
1
+ require 'delegate'
2
+
1
3
  ##
2
- # DNSSD::TextRecord is a Hash wrapper that can encode its contents for DNSSD.
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, decoding an encoded +text_record+ if given.
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
- @records = {}
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
- return unless text_record
29
+ ##
30
+ # Decodes +text_record+ and returns a Hash
13
31
 
14
- text_record = text_record.dup
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
- @records[key] = value
50
+ record[key] = value
32
51
  end
33
- end
34
52
 
35
- def [](key)
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
- @records.sort.map do |key, value|
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
 
@@ -1,11 +1,29 @@
1
1
  require 'dnssd'
2
2
 
3
- browser = DNSSD.browse '_presence._tcp' do |reply|
4
- p reply
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
- trap 'INT' do browser.stop; exit end
8
- trap 'TERM' do browser.stop; exit end
14
+ browser.browse '_blackjack._tcp' do |reply|
15
+ services[reply.fullname] = reply
16
+ next if reply.flags.more_coming?
9
17
 
10
- sleep
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
 
@@ -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
- p reply.domain
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
+
@@ -1,5 +1,7 @@
1
1
  require 'dnssd'
2
2
 
3
+ Thread.abort_on_exception = true
4
+
3
5
  browser = DNSSD.browse '_growl._tcp' do |b|
4
6
  DNSSD.resolve b.name, b.type, b.domain do |r|
5
7
  puts "#{b.name} of #{b.type} in #{b.domain} => #{r.target}:#{r.port} on #{b.interface} txt #{r.text_record.inspect}"
@@ -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
+
@@ -1,30 +1,29 @@
1
1
  require 'dnssd'
2
2
 
3
- DNSSD.register "hey ruby", "_http._tcp", nil, 8081
4
-
5
- registrar = DNSSD.register "chad ruby", "_http._tcp", nil, 8080 do |reply|
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
- found = {}
11
+ DNSSD.register 'blockless', '_blackjack._tcp', nil, 1025
12
+ puts "registered blockless (no callback)"
14
13
 
15
- browser = DNSSD.browse '_http._tcp' do |reply|
16
- if reply.flags.more_coming? then
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
- sleep 0.1
18
+ registrar = DNSSD::Service.new
19
+
20
+ service = nil
27
21
 
28
- browser.stop
29
- registrar.stop
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
 
@@ -1,13 +1,37 @@
1
1
  require 'dnssd'
2
2
 
3
- abort "#{$0} \"http service name\"" if ARGV.empty?
3
+ Thread.abort_on_exception = true
4
+ trap 'INT' do exit end
5
+ trap 'TERM' do exit end
4
6
 
5
- resolver = DNSSD.resolve ARGV.shift, '_http._tcp', 'local' do |reply|
6
- p reply
7
- end
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
- trap 'INT' do resolver.stop; exit end
10
- trap 'TERM' do resolver.stop; exit end
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
- sleep
30
+ resolver.stop
31
+ end
32
+
33
+ services.clear
34
+
35
+ puts
36
+ end
13
37
 
@@ -1,12 +1,14 @@
1
1
  require 'dnssd'
2
- require 'pp'
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
- browser = DNSSD.browse '_presence._tcp' do |reply|
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
 
@@ -1,5 +1,7 @@
1
1
  require 'dnssd'
2
2
 
3
+ Thread.abort_on_exception = true
4
+
3
5
  port = Socket.getservbyname 'blackjack'
4
6
  blackjack = TCPServer.new nil, port
5
7
 
@@ -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
 
@@ -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('lo0')
65
- refute_equal 0, index, 'what? no lo0?'
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('lo0')
70
+ index = DNSSD.interface_index 'lo0'
71
+ index = DNSSD.interface_index 'lo' if index.zero?
70
72
 
71
- assert_equal 'lo0', DNSSD.interface_name(index)
73
+ assert_match %r%^lo0?$%, DNSSD.interface_name(index)
72
74
  end
73
75
 
74
76
  end
@@ -65,21 +65,7 @@ class TestDNSSDFlags < MiniTest::Unit::TestCase
65
65
  def test_complement
66
66
  new_flags = ~@flags
67
67
 
68
- expected = DNSSD::Flags.new(DNSSD::Flags::Add,
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
+