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.
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
+