rubydns 2.0.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,121 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: utf-8
3
-
4
- # Copyright, 2009, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
5
- #
6
- # Permission is hereby granted, free of charge, to any person obtaining a copy
7
- # of this software and associated documentation files (the "Software"), to deal
8
- # in the Software without restriction, including without limitation the rights
9
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- # copies of the Software, and to permit persons to whom the Software is
11
- # furnished to do so, subject to the following conditions:
12
- #
13
- # The above copyright notice and this permission notice shall be included in
14
- # all copies or substantial portions of the Software.
15
- #
16
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
- # THE SOFTWARE.
23
-
24
- require 'rubydns'
25
-
26
- require 'cgi'
27
- require 'json'
28
-
29
- require 'digest/md5'
30
-
31
- require 'async/logger'
32
- require 'async/http/client'
33
- require 'async/dns/extensions/string'
34
- require 'async/http/url_endpoint'
35
-
36
- # Encapsulates the logic for fetching information from Wikipedia.
37
- module Wikipedia
38
- ENDPOINT = Async::HTTP::URLEndpoint.parse("https://en.wikipedia.org")
39
-
40
- def self.lookup(title, logger: nil)
41
- client = Async::HTTP::Client.new([ENDPOINT])
42
- url = self.summary_url(title)
43
-
44
- logger&.info "Making request to #{ENDPOINT} for #{url}."
45
- response = client.get(url, {'Host' => ENDPOINT.hostname})
46
- logger&.info "Got response #{response.inspect}."
47
-
48
- if response.status == 301
49
- return lookup(response.headers['HTTP_LOCATION'])
50
- else
51
- return self.extract_summary(response.body).force_encoding('ASCII-8BIT')
52
- end
53
- end
54
-
55
- def self.summary_url(title)
56
- "/api/rest_v1/page/summary/#{CGI.escape title}"
57
- end
58
-
59
- def self.extract_summary(json_text)
60
- document = JSON.parse(json_text)
61
-
62
- return document['extract']
63
- rescue
64
- return 'Invalid Article.'
65
- end
66
- end
67
-
68
- # A DNS server that queries Wikipedia and returns summaries for
69
- # specifically crafted queries.
70
- class WikipediaDNS
71
- Name = Resolv::DNS::Name
72
- IN = Resolv::DNS::Resource::IN
73
-
74
- INTERFACES = [
75
- [:udp, '::', 5300],
76
- [:tcp, '::', 5300],
77
- ]
78
-
79
- def startup
80
- # Don't buffer output (for debug purposes)
81
- $stderr.sync = true
82
-
83
- stats = { requested: 0 }
84
-
85
- # Start the RubyDNS server
86
- RubyDNS.run_server(INTERFACES) do
87
- on(:start) do
88
- # Process::Daemon::Privileges.change_user(RUN_AS)
89
-
90
- if ARGV.include?('--debug')
91
- @logger.level = Logger::DEBUG
92
- else
93
- @logger.level = Logger::WARN
94
- end
95
-
96
- @logger.info "Starting Wikipedia DNS..."
97
- end
98
-
99
- match(/stats\.wikipedia/, IN::TXT) do |transaction|
100
- transaction.respond!(*stats.inspect.chunked)
101
- end
102
-
103
- match(/(.+)\.wikipedia/, IN::TXT) do |transaction, match_data|
104
- title = match_data[1]
105
- stats[:requested] += 1
106
-
107
- summary = Wikipedia.lookup(title, logger: @logger)
108
-
109
- transaction.respond!(*summary.chunked)
110
- end
111
-
112
- # Default DNS handler
113
- otherwise do |transaction|
114
- transaction.fail!(:NXDomain)
115
- end
116
- end
117
- end
118
- end
119
-
120
- wikipedia_dns = WikipediaDNS.new
121
- wikipedia_dns.startup
@@ -1,180 +0,0 @@
1
- # Copyright, 2009, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require 'async/dns/server'
22
-
23
- module RubyDNS
24
- # Provides the core of the RubyDNS domain-specific language (DSL). It contains a list of rules which are used to match against incoming DNS questions. These rules are used to generate responses which are either DNS resource records or failures.
25
- class RuleBasedServer < Async::DNS::Server
26
- # Represents a single rule in the server.
27
- class Rule
28
- def initialize(pattern, callback)
29
- @pattern = pattern
30
- @callback = callback
31
- end
32
-
33
- # Returns true if the name and resource_class are sufficient:
34
- def match(name, resource_class)
35
- # If the pattern doesn't specify any resource classes, we implicitly pass this test:
36
- return true if @pattern.size < 2
37
-
38
- # Otherwise, we try to match against some specific resource classes:
39
- if Class === @pattern[1]
40
- @pattern[1] == resource_class
41
- else
42
- @pattern[1].include?(resource_class) rescue false
43
- end
44
- end
45
-
46
- # Invoke the rule, if it matches the incoming request, it is evaluated and returns `true`, otherwise returns `false`.
47
- def call(server, name, resource_class, transaction)
48
- unless match(name, resource_class)
49
- server.logger.debug "<#{transaction.query.id}> Resource class #{resource_class} failed to match #{@pattern[1].inspect}!"
50
-
51
- return false
52
- end
53
-
54
- # Does this rule match against the supplied name?
55
- case @pattern[0]
56
- when Regexp
57
- match_data = @pattern[0].match(name)
58
-
59
- if match_data
60
- server.logger.debug "<#{transaction.query.id}> Regexp pattern matched with #{match_data.inspect}."
61
-
62
- @callback[transaction, match_data]
63
-
64
- return true
65
- end
66
- when String
67
- if @pattern[0] == name
68
- server.logger.debug "<#{transaction.query.id}> String pattern matched."
69
-
70
- @callback[transaction]
71
-
72
- return true
73
- end
74
- else
75
- if (@pattern[0].call(name, resource_class) rescue false)
76
- server.logger.debug "<#{transaction.query.id}> Callable pattern matched."
77
-
78
- @callback[transaction]
79
-
80
- return true
81
- end
82
- end
83
-
84
- server.logger.debug "<#{transaction.query.id}> No pattern matched."
85
-
86
- # We failed to match the pattern.
87
- return false
88
- end
89
-
90
- def to_s
91
- @pattern.inspect
92
- end
93
- end
94
-
95
- # Instantiate a server with a block
96
- #
97
- # server = Server.new do
98
- # match(/server.mydomain.com/, IN::A) do |transaction|
99
- # transaction.respond!("1.2.3.4")
100
- # end
101
- # end
102
- #
103
- def initialize(*args, &block)
104
- super(*args)
105
-
106
- @events = {}
107
- @rules = []
108
- @otherwise = nil
109
-
110
- if block_given?
111
- instance_eval(&block)
112
- end
113
- end
114
-
115
- attr_accessor :logger
116
-
117
- # This function connects a pattern with a block. A pattern is either a String or a Regex instance. Optionally, a second argument can be provided which is either a String, Symbol or Array of resource record types which the rule matches against.
118
- #
119
- # match("www.google.com")
120
- # match("gmail.com", IN::MX)
121
- # match(/g?mail.(com|org|net)/, [IN::MX, IN::A])
122
- #
123
- def match(*pattern, &block)
124
- @rules << Rule.new(pattern, block)
125
- end
126
-
127
- # Register a named event which may be invoked later using #fire
128
- #
129
- # on(:start) do |server|
130
- # Process::Daemon::Permissions.change_user(RUN_AS)
131
- # end
132
- def on(event_name, &block)
133
- @events[event_name] = block
134
- end
135
-
136
- # Fire the named event, which must have been registered using on.
137
- def fire(event_name)
138
- callback = @events[event_name]
139
-
140
- if callback
141
- callback.call(self)
142
- end
143
- end
144
-
145
- # Specify a default block to execute if all other rules fail to match. This block is typially used to pass the request on to another server (i.e. recursive request).
146
- #
147
- # otherwise do |transaction|
148
- # transaction.passthrough!($R)
149
- # end
150
- #
151
- def otherwise(&block)
152
- @otherwise = block
153
- end
154
-
155
- # If you match a rule, but decide within the rule that it isn't the correct one to use, you can call `next!` to evaluate the next rule - in other words, to continue falling down through the list of rules.
156
- def next!
157
- throw :next
158
- end
159
-
160
- # Give a name and a record type, try to match a rule and use it for processing the given arguments.
161
- def process(name, resource_class, transaction)
162
- @logger.debug {"<#{transaction.query.id}> Searching for #{name} #{resource_class.name}"}
163
-
164
- @rules.each do |rule|
165
- @logger.debug {"<#{transaction.query.id}> Checking rule #{rule}..."}
166
-
167
- catch (:next) do
168
- # If the rule returns true, we assume that it was successful and no further rules need to be evaluated.
169
- return if rule.call(self, name, resource_class, transaction)
170
- end
171
- end
172
-
173
- if @otherwise
174
- @otherwise.call(transaction)
175
- else
176
- @logger.warn "<#{transaction.query.id}> Failed to handle #{name} #{resource_class.name}!"
177
- end
178
- end
179
- end
180
- end
data/rubydns.gemspec DELETED
@@ -1,28 +0,0 @@
1
-
2
- require_relative 'lib/rubydns/version'
3
-
4
- Gem::Specification.new do |spec|
5
- spec.name = "rubydns"
6
- spec.version = RubyDNS::VERSION
7
- spec.authors = ["Samuel Williams"]
8
- spec.email = ["samuel.williams@oriontransfer.co.nz"]
9
- spec.description = <<-EOF
10
- RubyDNS provides a rule-based DSL for implementing DNS servers, built on top of `Async::DNS`.
11
- EOF
12
- spec.summary = "An easy to use DNS server and resolver for Ruby."
13
- spec.homepage = "https://github.com/socketry/rubydns"
14
- spec.license = "MIT"
15
-
16
- spec.files = `git ls-files`.split($/)
17
- spec.executables = spec.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
20
- spec.has_rdoc = "yard"
21
-
22
- spec.add_dependency("async-dns", "~> 1.0")
23
- spec.add_development_dependency("async-rspec", "~> 1.0")
24
-
25
- spec.add_development_dependency "bundler", "~> 1.3"
26
- spec.add_development_dependency "rspec", "~> 3.4"
27
- spec.add_development_dependency "rake"
28
- end
@@ -1,114 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- # THE SOFTWARE.
22
-
23
- require 'rubydns'
24
- require 'process/daemon'
25
-
26
- class BasicTestServer < Process::Daemon
27
- SERVER_PORTS = [[:udp, '127.0.0.1', 5350], [:tcp, '127.0.0.1', 5350]]
28
-
29
- IN = Resolv::DNS::Resource::IN
30
-
31
- def working_directory
32
- File.expand_path("../tmp", __FILE__)
33
- end
34
-
35
- def reactor
36
- Async::Reactor.new
37
- end
38
-
39
- def startup
40
- reactor.run do
41
- RubyDNS::run_server(SERVER_PORTS) do
42
- match("test.local", IN::A) do |transaction|
43
- transaction.respond!("192.168.1.1")
44
- end
45
-
46
- match(/foo.*/, IN::A) do |transaction|
47
- transaction.respond!("192.168.1.2")
48
- end
49
-
50
- match(/peername/, IN::A) do |transaction|
51
- transaction.respond!(transaction[:remote_address].ip_address)
52
- end
53
-
54
- # Default DNS handler
55
- otherwise do |transaction|
56
- transaction.fail!(:NXDomain)
57
- end
58
- end
59
- end
60
- end
61
-
62
- def shutdown
63
- @reactor.stop
64
- end
65
- end
66
-
67
- describe "RubyDNS Daemonized Server" do
68
- include_context Async::RSpec::Reactor
69
-
70
- before(:all) do
71
- # BasicTestServer.controller output: $stderr
72
- BasicTestServer.start
73
- end
74
-
75
- after(:all) do
76
- BasicTestServer.stop
77
- end
78
-
79
- it "should resolve local domain correctly" do
80
- expect(BasicTestServer.status).to be == :running
81
-
82
- resolver = RubyDNS::Resolver.new(BasicTestServer::SERVER_PORTS)
83
-
84
- response = resolver.query("test.local")
85
-
86
- answer = response.answer.first
87
-
88
- expect(answer[0].to_s).to be == "test.local."
89
- expect(answer[2].address.to_s).to be == "192.168.1.1"
90
- end
91
-
92
- it "should pattern match correctly" do
93
- expect(BasicTestServer.status).to be == :running
94
-
95
- resolver = RubyDNS::Resolver.new(BasicTestServer::SERVER_PORTS)
96
-
97
- response = resolver.query("foobar")
98
- answer = response.answer.first
99
-
100
- expect(answer[0]).to be == resolver.fully_qualified_name("foobar")
101
- expect(answer[2].address.to_s).to be == "192.168.1.2"
102
- end
103
-
104
- it "should give peer ip address" do
105
- expect(BasicTestServer.status).to be == :running
106
-
107
- resolver = RubyDNS::Resolver.new(BasicTestServer::SERVER_PORTS)
108
-
109
- response = resolver.query("peername")
110
- answer = response.answer.first
111
-
112
- expect(answer[2].address.to_s).to be == "127.0.0.1"
113
- end
114
- end
@@ -1,2 +0,0 @@
1
- # A testing host:
2
- 1.2.3.4 testing apples
@@ -1,64 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- # THE SOFTWARE.
22
-
23
- require 'rubydns'
24
- require 'async/dns/extensions/string'
25
-
26
- module RubyDNS::InjectedSupervisorSpec
27
- class TestServer < RubyDNS::RuleBasedServer
28
- def test_message
29
- 'Testing...'
30
- end
31
- end
32
-
33
- SERVER_PORTS = [[:udp, '127.0.0.1', 5520]]
34
- IN = Resolv::DNS::Resource::IN
35
-
36
- describe "RubyDNS::run_server(server_class: ...)" do
37
- include_context Async::RSpec::Reactor
38
-
39
- let(:server) do
40
- # Start the RubyDNS server
41
- RubyDNS::run_server(SERVER_PORTS, server_class: TestServer) do
42
- match("test_message", IN::TXT) do |transaction|
43
- transaction.respond!(*test_message.chunked)
44
- end
45
-
46
- # Default DNS handler
47
- otherwise do |transaction|
48
- transaction.fail!(:NXDomain)
49
- end
50
- end
51
- end
52
-
53
- it "should use the injected class" do
54
- task = server
55
-
56
- resolver = RubyDNS::Resolver.new(SERVER_PORTS)
57
- response = resolver.query("test_message", IN::TXT)
58
- text = response.answer.first
59
- expect(text[2].strings.join).to be == 'Testing...'
60
-
61
- task.stop
62
- end
63
- end
64
- end
@@ -1,85 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- # THE SOFTWARE.
22
-
23
- require 'rubydns'
24
-
25
- module RubyDNS::PassthroughSpec
26
- SERVER_PORTS = [[:udp, '127.0.0.1', 5340], [:tcp, '127.0.0.1', 5340]]
27
- Name = Resolv::DNS::Name
28
- IN = Resolv::DNS::Resource::IN
29
-
30
- describe "RubyDNS Passthrough Server" do
31
- include_context Async::RSpec::Reactor
32
-
33
- def run_server
34
- task = RubyDNS::run_server(listen: SERVER_PORTS) do
35
- resolver = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
36
-
37
- match(/.*\.com/, IN::A) do |transaction|
38
- transaction.passthrough!(resolver)
39
- end
40
-
41
- match(/a-(.*\.org)/) do |transaction, match_data|
42
- transaction.passthrough!(resolver, :name => match_data[1])
43
- end
44
-
45
- # Default DNS handler
46
- otherwise do |transaction|
47
- transaction.fail!(:NXDomain)
48
- end
49
- end
50
-
51
- yield
52
-
53
- ensure
54
- task.stop
55
- end
56
-
57
- it "should resolve domain correctly" do
58
- run_server do
59
- resolver = RubyDNS::Resolver.new(SERVER_PORTS, timeout: 1)
60
-
61
- response = resolver.query("google.com")
62
- expect(response.ra).to be == 1
63
-
64
- answer = response.answer.first
65
- expect(answer).not_to be == nil
66
- expect(answer.count).to be > 0
67
-
68
- addresses = answer.select {|record| record.kind_of? Resolv::DNS::Resource::IN::A}
69
- expect(addresses.size).to be > 0
70
- end
71
- end
72
-
73
- it "should resolve prefixed domain correctly" do
74
- run_server do
75
- resolver = RubyDNS::Resolver.new(SERVER_PORTS)
76
-
77
- response = resolver.query("a-slashdot.org")
78
- answer = response.answer.first
79
-
80
- expect(answer).not_to be == nil
81
- expect(answer.count).to be > 0
82
- end
83
- end
84
- end
85
- end
@@ -1,74 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- # THE SOFTWARE.
22
-
23
- require 'rubydns'
24
-
25
- module RubyDNS::RulesSpec
26
- describe RubyDNS::RuleBasedServer do
27
- IN = Resolv::DNS::Resource::IN
28
-
29
- true_callback = Proc.new { true }
30
-
31
- it "should match string patterns correctly" do
32
- server = double(:logger => Logger.new("/dev/null"))
33
- transaction = double(:query => Resolv::DNS::Message.new(0))
34
-
35
- rule = RubyDNS::RuleBasedServer::Rule.new(["foobar", IN::A], true_callback)
36
-
37
- expect(rule.call(server, "foobar", IN::A, transaction)).to be == true
38
- expect(rule.call(server, "barfoo", IN::A, transaction)).to be == false
39
- expect(rule.call(server, "foobar", IN::TXT, transaction)).to be == false
40
- end
41
-
42
- it "should match regular expression patterns correctly" do
43
- server = double(:logger => Logger.new("/dev/null"))
44
- transaction = double(:query => Resolv::DNS::Message.new(0))
45
-
46
- rule = RubyDNS::RuleBasedServer::Rule.new([/foo/, IN::A], true_callback)
47
-
48
- expect(rule.call(server, "foobar", IN::A, transaction)).to be == true
49
- expect(rule.call(server, "barbaz", IN::A, transaction)).to be == false
50
- expect(rule.call(server, "foobar", IN::TXT, transaction)).to be == false
51
- end
52
-
53
- it "should match callback patterns correctly" do
54
- server = double(:logger => Logger.new("/dev/null"))
55
- transaction = double(:query => Resolv::DNS::Message.new(0))
56
-
57
- calls = 0
58
-
59
- callback = Proc.new do |name, resource_class|
60
- # A counter used to check the number of times this block was invoked.
61
- calls += 1
62
-
63
- name.size == 6
64
- end
65
-
66
- rule = RubyDNS::RuleBasedServer::Rule.new([callback], true_callback)
67
-
68
- expect(rule.call(server, "foobar", IN::A, transaction)).to be == true
69
- expect(rule.call(server, "foobarbaz", IN::A, transaction)).to be == false
70
-
71
- expect(calls).to be == 2
72
- end
73
- end
74
- end