dnssd 0.7.1 → 1.0
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/History.txt +5 -0
- data/Manifest.txt +12 -0
- data/README.txt +48 -0
- data/Rakefile +34 -0
- data/ext/{dns_sd.h → dnssd/dns_sd.h} +0 -0
- data/ext/dnssd/dnssd.c +141 -0
- data/ext/dnssd/dnssd.h +60 -0
- data/ext/dnssd/dnssd_service.c +698 -0
- data/ext/dnssd/dnssd_structs.c +397 -0
- data/ext/dnssd/dnssd_tr.c +248 -0
- data/ext/dnssd/extconf.rb +51 -0
- data/lib/dnssd.rb +38 -25
- data/test/test_dnssd_flags.rb +152 -0
- metadata +107 -29
- metadata.gz.sig +0 -0
- data/ext/MANIFEST +0 -0
- data/ext/extconf.rb +0 -58
- data/ext/rdnssd.c +0 -150
- data/ext/rdnssd.h +0 -63
- data/ext/rdnssd_service.c +0 -712
- data/ext/rdnssd_structs.c +0 -710
- data/ext/rdnssd_tr.c +0 -257
- data/ext/run_rdoc +0 -4
@@ -0,0 +1,51 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# :nodoc: all
|
3
|
+
#
|
4
|
+
# Extension configuration script for DNS_SD C Extension.
|
5
|
+
|
6
|
+
def check_for_funcs(*funcs)
|
7
|
+
funcs.flatten!
|
8
|
+
funcs.each do |f|
|
9
|
+
abort("need function #{f}") unless have_func(f)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
require "mkmf"
|
14
|
+
|
15
|
+
$CFLAGS << " -Wall"
|
16
|
+
$CFLAGS << " -DDEBUG" if $DEBUG
|
17
|
+
|
18
|
+
unless RUBY_PLATFORM.include? "darwin"
|
19
|
+
have_library( "mdns", "DNSServiceRefSockFD" ) or
|
20
|
+
have_library( "dns_sd", "DNSServiceRefSockFD" ) or
|
21
|
+
abort( "can't find rendezvous library" )
|
22
|
+
end
|
23
|
+
|
24
|
+
#have_library( "dns-sd", "DNSServiceRefSockFD" ) or
|
25
|
+
# abort( "Can't find rendezvous client library" )
|
26
|
+
|
27
|
+
have_header("dns_sd.h") or abort("can't find the rendezvous client headers")
|
28
|
+
|
29
|
+
have_header "unistd.h"
|
30
|
+
have_header "sys/types.h"
|
31
|
+
have_header "sys/socket.h"
|
32
|
+
have_header "sys/param.h"
|
33
|
+
have_header "sys/if.h"
|
34
|
+
have_header "net/if.h"
|
35
|
+
have_header "arpa/inet.h"
|
36
|
+
|
37
|
+
abort "need function #{f}" unless have_macro("htons") || have_func("htons")
|
38
|
+
abort "need function #{f}" unless have_macro("ntohs") || have_func("ntohs")
|
39
|
+
|
40
|
+
check_for_funcs "if_indextoname", "if_nametoindex"
|
41
|
+
have_func "gethostname"
|
42
|
+
|
43
|
+
s1 = check_sizeof "void*"
|
44
|
+
s2 = check_sizeof("DNSServiceFlags", "dns_sd.h") or
|
45
|
+
abort("can't determine sizeof(DNSServiceFlags)")
|
46
|
+
|
47
|
+
# need to make sure storing unsigned integer in void * is OK.
|
48
|
+
s1 >= s2 or abort("sizeof(void*) < sizeof(DNSServiceFlags) please contact the authors!")
|
49
|
+
|
50
|
+
create_makefile "dnssd"
|
51
|
+
|
data/lib/dnssd.rb
CHANGED
@@ -1,17 +1,29 @@
|
|
1
|
-
require '
|
1
|
+
require 'dnssd/dnssd'
|
2
|
+
|
3
|
+
##
|
4
|
+
# DNSSD is a wrapper for Apple's DNS Service Discovery library. The methods
|
5
|
+
# DNSSD.enumerate_domains, DNSSD.browse(), DNSSD.register(), and
|
6
|
+
# DNSSD.resolve() provide the basic API for making your applications DNS
|
7
|
+
# Service Discovery aware.
|
8
|
+
|
9
|
+
module DNSSD
|
10
|
+
VERSION = '1.0'
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'dnssd/flags'
|
2
14
|
|
3
15
|
=begin
|
4
16
|
|
5
17
|
module DNSSD
|
6
|
-
class
|
7
|
-
class
|
8
|
-
|
18
|
+
class MalformedDomain < Error; end
|
19
|
+
class MalformedPort < Error; end
|
20
|
+
|
9
21
|
def self.new_text_record(hash={})
|
10
22
|
TextRecord.new(hash)
|
11
23
|
end
|
12
24
|
|
13
25
|
class ServiceDescription
|
14
|
-
|
26
|
+
|
15
27
|
class Location
|
16
28
|
attr_accessor :name, :port, :iface
|
17
29
|
def initialize(port, name=nil, iface=0)
|
@@ -27,8 +39,8 @@ module DNSSD
|
|
27
39
|
@domain = validate_domain(domain)
|
28
40
|
@location = validate_location(location)
|
29
41
|
end
|
30
|
-
|
31
|
-
def self.for_browse_notification(name, domain,
|
42
|
+
|
43
|
+
def self.for_browse_notification(name, domain,
|
32
44
|
|
33
45
|
def stop
|
34
46
|
@registrar.stop
|
@@ -36,14 +48,14 @@ module DNSSD
|
|
36
48
|
|
37
49
|
def validate_location(location)
|
38
50
|
unless(location.port.respond_to?(:to_int))
|
39
|
-
raise
|
51
|
+
raise MalformedPort.new("#{location.port} is not a valid port number")
|
40
52
|
end
|
41
53
|
location
|
42
54
|
end
|
43
55
|
|
44
56
|
def validate_domain(domain)
|
45
57
|
unless(domain.empty? || domain =~ /^[a-z_]+$/)
|
46
|
-
raise
|
58
|
+
raise MalformedDomain.new("#{domain} is not a valid domain name")
|
47
59
|
end
|
48
60
|
domain
|
49
61
|
end
|
@@ -62,64 +74,65 @@ module DNSSD
|
|
62
74
|
def self.advertise_http(name, port=80, domain="", iface=0, &block)
|
63
75
|
self.advertise("_http._tcp", name, port, domain, iface, &block)
|
64
76
|
end
|
65
|
-
|
77
|
+
|
66
78
|
##
|
67
|
-
# iface: Numerical interface (0 = all interfaces, This should be used for
|
68
|
-
#
|
79
|
+
# iface: Numerical interface (0 = all interfaces, This should be used for
|
80
|
+
# most applications)
|
81
|
+
|
69
82
|
def self.advertise(type, name, port, domain="", iface=0, &block)
|
70
83
|
service_description = ServiceDescription.new(type, name, domain, Location.new(port,nil,iface))
|
71
|
-
service_description.advertise_and_confirm
|
84
|
+
service_description.advertise_and_confirm
|
72
85
|
yield service_description if block_given?
|
73
86
|
service_description
|
74
87
|
end
|
75
88
|
end
|
76
89
|
|
77
90
|
class Browser
|
78
|
-
|
91
|
+
|
79
92
|
Context = Struct.new(:service, :name, :type, :domain, :operation, :interface)
|
80
|
-
|
93
|
+
|
81
94
|
class Context
|
82
95
|
def ==(other)
|
83
96
|
self.to_s == other.to_s
|
84
97
|
end
|
85
|
-
|
98
|
+
|
86
99
|
def to_s
|
87
100
|
"#{name}.#{type}.#{domain}"
|
88
101
|
end
|
89
|
-
|
102
|
+
|
90
103
|
def eql?(other)
|
91
104
|
self == other
|
92
105
|
end
|
93
|
-
|
106
|
+
|
94
107
|
def hash
|
95
108
|
to_s.hash
|
96
109
|
end
|
97
110
|
end
|
98
|
-
|
111
|
+
|
99
112
|
def on_change(&block)
|
100
113
|
@change_listener ||= []
|
101
114
|
@change_listeners << block
|
102
115
|
end
|
103
|
-
|
116
|
+
|
104
117
|
def on_add(&block)
|
105
118
|
@add_listeners || = []
|
106
119
|
@add_listeners << block
|
107
120
|
end
|
108
|
-
|
121
|
+
|
109
122
|
def on_remove(&block)
|
110
123
|
@remove_listeners || = []
|
111
124
|
@remove_listeners << block
|
112
125
|
end
|
113
|
-
|
126
|
+
|
114
127
|
def initialize(type, domain="")
|
115
128
|
@list = []
|
116
|
-
@browse_service = DNSSD::Protocol.browse(type, domain) do
|
129
|
+
@browse_service = DNSSD::Protocol.browse(type, domain) do
|
117
130
|
|service, name, type, domain, operation, interface|
|
118
131
|
context = Context.new(service, name, type, domain, operation, interface)
|
119
132
|
puts "Name: #{name} Type: #{type} Domain: #{domain} Operation: #{operation} Interface: #{interface}"
|
120
133
|
end
|
121
134
|
end
|
122
|
-
|
135
|
+
|
123
136
|
def service_descriptions
|
124
137
|
@list.clone
|
125
138
|
end
|
@@ -134,4 +147,4 @@ module DNSSD
|
|
134
147
|
end
|
135
148
|
end
|
136
149
|
|
137
|
-
=end
|
150
|
+
=end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'dnssd'
|
3
|
+
|
4
|
+
class TestDNSSDFlags < MiniTest::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@flags = DNSSD::Flags.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_accessors
|
11
|
+
DNSSD::Flags.constants.each do |name|
|
12
|
+
next unless name =~ /[a-z]/
|
13
|
+
attr = name.to_s.gsub(/([a-z])([A-Z])/, '\1_\2').downcase
|
14
|
+
|
15
|
+
assert_respond_to @flags, "#{attr}="
|
16
|
+
assert_respond_to @flags, "#{attr}?"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_add_eh
|
21
|
+
refute @flags.add?
|
22
|
+
|
23
|
+
@flags.add = true
|
24
|
+
|
25
|
+
assert @flags.add?
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_add_equals
|
29
|
+
@flags.add = true
|
30
|
+
|
31
|
+
assert_equal DNSSD::Flags::Add, @flags
|
32
|
+
|
33
|
+
@flags.add = false
|
34
|
+
|
35
|
+
assert_equal 0, @flags
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_default_eh
|
39
|
+
refute @flags.default?
|
40
|
+
|
41
|
+
@flags.default = true
|
42
|
+
|
43
|
+
assert @flags.default?
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_default_equals
|
47
|
+
@flags.default = true
|
48
|
+
|
49
|
+
assert_equal DNSSD::Flags::Default, @flags
|
50
|
+
|
51
|
+
@flags.default = false
|
52
|
+
|
53
|
+
assert_equal 0, @flags
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_clear_flag
|
57
|
+
@flags.set_flag DNSSD::Flags::Add
|
58
|
+
@flags.set_flag DNSSD::Flags::Default
|
59
|
+
|
60
|
+
@flags.clear_flag DNSSD::Flags::Add
|
61
|
+
|
62
|
+
assert_equal DNSSD::Flags::Default, @flags
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_complement
|
66
|
+
new_flags = ~@flags
|
67
|
+
|
68
|
+
expected = DNSSD::Flags.new(DNSSD::Flags::Add,
|
69
|
+
DNSSD::Flags::BrowseDomains,
|
70
|
+
DNSSD::Flags::Default,
|
71
|
+
DNSSD::Flags::LongLivedQuery,
|
72
|
+
DNSSD::Flags::MoreComing,
|
73
|
+
DNSSD::Flags::NoAutoRename,
|
74
|
+
DNSSD::Flags::RegistrationDomains,
|
75
|
+
DNSSD::Flags::Shared, DNSSD::Flags::Unique)
|
76
|
+
|
77
|
+
assert_equal expected, new_flags
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_equals
|
81
|
+
assert_equal @flags, DNSSD::Flags.new
|
82
|
+
refute_equal @flags, DNSSD::Flags.new(DNSSD::Flags::Add)
|
83
|
+
|
84
|
+
@flags.add = true
|
85
|
+
@flags.default = true
|
86
|
+
|
87
|
+
assert_equal @flags, (DNSSD::Flags::Add | DNSSD::Flags::Default)
|
88
|
+
assert_equal @flags, (DNSSD::Flags::Add | DNSSD::Flags::Default)
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_inspect
|
92
|
+
assert_equal '#<DNSSD::Flags>', @flags.inspect
|
93
|
+
|
94
|
+
@flags.add = true
|
95
|
+
@flags.default = true
|
96
|
+
|
97
|
+
assert_equal '#<DNSSD::Flags add, default>', @flags.inspect
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_intersection
|
101
|
+
new_flags = @flags & DNSSD::Flags::Add
|
102
|
+
|
103
|
+
assert_equal @flags, new_flags
|
104
|
+
|
105
|
+
@flags.default = true
|
106
|
+
|
107
|
+
new_flags = @flags & DNSSD::Flags::Default
|
108
|
+
|
109
|
+
assert_equal @flags, new_flags
|
110
|
+
|
111
|
+
assert_equal new_flags, (new_flags & new_flags)
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_set_flag
|
115
|
+
@flags.set_flag DNSSD::Flags::Add
|
116
|
+
|
117
|
+
assert_equal DNSSD::Flags::Add, @flags
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_to_a
|
121
|
+
assert_equal [], @flags.to_a
|
122
|
+
|
123
|
+
@flags.add = true
|
124
|
+
@flags.default = true
|
125
|
+
|
126
|
+
assert_equal %w[add default], @flags.to_a.sort
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_to_i
|
130
|
+
assert_equal 0, @flags.to_i
|
131
|
+
|
132
|
+
@flags.add = true
|
133
|
+
@flags.default = true
|
134
|
+
|
135
|
+
assert_equal 6, @flags.to_i
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_union
|
139
|
+
new_flags = @flags | DNSSD::Flags::Add
|
140
|
+
|
141
|
+
assert_equal DNSSD::Flags.new(DNSSD::Flags::Add), new_flags
|
142
|
+
|
143
|
+
new_flags = new_flags | DNSSD::Flags::Default
|
144
|
+
|
145
|
+
assert_equal DNSSD::Flags.new(DNSSD::Flags::Add, DNSSD::Flags::Default),
|
146
|
+
new_flags
|
147
|
+
|
148
|
+
assert_equal new_flags, (new_flags | new_flags)
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
metadata
CHANGED
@@ -1,44 +1,122 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dnssd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0
|
4
|
+
version: "1.0"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
8
|
-
|
7
|
+
- Chad Fowler
|
8
|
+
- Charles Mills
|
9
|
+
- Rich Kilmer
|
10
|
+
- Phil Hagelberg
|
11
|
+
- Aaron Patterson
|
12
|
+
- Eric Hodel
|
13
|
+
autorequire:
|
9
14
|
bindir: bin
|
10
|
-
cert_chain:
|
15
|
+
cert_chain:
|
16
|
+
- |
|
17
|
+
-----BEGIN CERTIFICATE-----
|
18
|
+
MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMRAwDgYDVQQDDAdkcmJy
|
19
|
+
YWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZFgNu
|
20
|
+
ZXQwHhcNMDcxMjIxMDIwNDE0WhcNMDgxMjIwMDIwNDE0WjBBMRAwDgYDVQQDDAdk
|
21
|
+
cmJyYWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZ
|
22
|
+
FgNuZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbbgLrGLGIDE76
|
23
|
+
LV/cvxdEzCuYuS3oG9PrSZnuDweySUfdp/so0cDq+j8bqy6OzZSw07gdjwFMSd6J
|
24
|
+
U5ddZCVywn5nnAQ+Ui7jMW54CYt5/H6f2US6U0hQOjJR6cpfiymgxGdfyTiVcvTm
|
25
|
+
Gj/okWrQl0NjYOYBpDi+9PPmaH2RmLJu0dB/NylsDnW5j6yN1BEI8MfJRR+HRKZY
|
26
|
+
mUtgzBwF1V4KIZQ8EuL6I/nHVu07i6IkrpAgxpXUfdJQJi0oZAqXurAV3yTxkFwd
|
27
|
+
g62YrrW26mDe+pZBzR6bpLE+PmXCzz7UxUq3AE0gPHbiMXie3EFE0oxnsU3lIduh
|
28
|
+
sCANiQ8BAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
|
29
|
+
BBS5k4Z75VSpdM0AclG2UvzFA/VW5DANBgkqhkiG9w0BAQUFAAOCAQEAHagT4lfX
|
30
|
+
kP/hDaiwGct7XPuVGbrOsKRVD59FF5kETBxEc9UQ1clKWngf8JoVuEoKD774dW19
|
31
|
+
bU0GOVWO+J6FMmT/Cp7nuFJ79egMf/gy4gfUfQMuvfcr6DvZUPIs9P/TlK59iMYF
|
32
|
+
DIOQ3DxdF3rMzztNUCizN4taVscEsjCcgW6WkUJnGdqlu3OHWpQxZBJkBTjPCoc6
|
33
|
+
UW6on70SFPmAy/5Cq0OJNGEWBfgD9q7rrs/X8GGwUWqXb85RXnUVi/P8Up75E0ag
|
34
|
+
14jEc90kN+C7oI/AGCBN0j6JnEtYIEJZibjjDJTSMWlUKKkj30kq7hlUC2CepJ4v
|
35
|
+
x52qPcexcYZR7w==
|
36
|
+
-----END CERTIFICATE-----
|
11
37
|
|
12
|
-
date: 2009-
|
38
|
+
date: 2009-08-05 00:00:00 -07:00
|
13
39
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
16
|
-
|
17
|
-
|
40
|
+
dependencies:
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: hoe-seattlerb
|
43
|
+
type: :development
|
44
|
+
version_requirement:
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ~>
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: "1.2"
|
50
|
+
version:
|
51
|
+
- !ruby/object:Gem::Dependency
|
52
|
+
name: minitest
|
53
|
+
type: :development
|
54
|
+
version_requirement:
|
55
|
+
version_requirements: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ~>
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: "1.4"
|
60
|
+
version:
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: rake-complier
|
63
|
+
type: :development
|
64
|
+
version_requirement:
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: "0.6"
|
70
|
+
version:
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: hoe
|
73
|
+
type: :development
|
74
|
+
version_requirement:
|
75
|
+
version_requirements: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: 2.3.2
|
80
|
+
version:
|
81
|
+
description: |-
|
82
|
+
DNS Service Discovery (aka Bonjour, MDNS) API for Ruby. Implements browsing,
|
83
|
+
resolving, registration and domain enumeration.
|
84
|
+
email:
|
85
|
+
- chad@chadfowler.com
|
86
|
+
- ""
|
87
|
+
- ""
|
88
|
+
- phil@hagelb.org
|
89
|
+
- aaronp@rubyforge.org
|
90
|
+
- drbrain@segment.net
|
18
91
|
executables: []
|
19
92
|
|
20
93
|
extensions:
|
21
|
-
- ext/extconf.rb
|
22
|
-
extra_rdoc_files:
|
23
|
-
|
94
|
+
- ext/dnssd/extconf.rb
|
95
|
+
extra_rdoc_files:
|
96
|
+
- History.txt
|
97
|
+
- Manifest.txt
|
98
|
+
- README.txt
|
24
99
|
files:
|
100
|
+
- History.txt
|
101
|
+
- Manifest.txt
|
102
|
+
- README.txt
|
103
|
+
- Rakefile
|
104
|
+
- ext/dnssd/dns_sd.h
|
105
|
+
- ext/dnssd/dnssd.c
|
106
|
+
- ext/dnssd/dnssd.h
|
107
|
+
- ext/dnssd/dnssd_service.c
|
108
|
+
- ext/dnssd/dnssd_structs.c
|
109
|
+
- ext/dnssd/dnssd_tr.c
|
110
|
+
- ext/dnssd/extconf.rb
|
25
111
|
- lib/dnssd.rb
|
26
|
-
|
27
|
-
- ext/dns_sd.h
|
28
|
-
- ext/rdnssd.c
|
29
|
-
- ext/rdnssd_tr.c
|
30
|
-
- ext/rdnssd_structs.c
|
31
|
-
- ext/run_rdoc
|
32
|
-
- ext/rdnssd_service.c
|
33
|
-
- ext/MANIFEST
|
34
|
-
- ext/rdnssd.h
|
35
|
-
has_rdoc: false
|
112
|
+
has_rdoc: true
|
36
113
|
homepage: http://rubyforge.org/projects/dnssd
|
37
114
|
licenses: []
|
38
115
|
|
39
116
|
post_install_message:
|
40
|
-
rdoc_options:
|
41
|
-
|
117
|
+
rdoc_options:
|
118
|
+
- --main
|
119
|
+
- README.txt
|
42
120
|
require_paths:
|
43
121
|
- lib
|
44
122
|
- ext
|
@@ -56,10 +134,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
56
134
|
version:
|
57
135
|
requirements: []
|
58
136
|
|
59
|
-
rubyforge_project:
|
60
|
-
rubygems_version: 1.3.
|
137
|
+
rubyforge_project: dnssd
|
138
|
+
rubygems_version: 1.3.5
|
61
139
|
signing_key:
|
62
140
|
specification_version: 3
|
63
|
-
summary: DNS Service Discovery (aka Bonjour) API for Ruby
|
64
|
-
test_files:
|
65
|
-
|
141
|
+
summary: DNS Service Discovery (aka Bonjour, MDNS) API for Ruby
|
142
|
+
test_files:
|
143
|
+
- test/test_dnssd_flags.rb
|