rubydns 1.0.3 → 2.0.0.pre.rc1
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.
- checksums.yaml +4 -4
- data/.rspec +4 -0
- data/.travis.yml +9 -12
- data/Gemfile +4 -1
- data/README.md +49 -151
- data/Rakefile +2 -7
- data/examples/basic-dns.rb +24 -0
- data/examples/cname.rb +25 -0
- data/examples/flakey-dns.rb +2 -2
- data/examples/simple.rb +25 -0
- data/examples/soa-dns.rb +82 -0
- data/examples/test-dns-1.rb +83 -0
- data/examples/test-dns-2.rb +83 -0
- data/examples/wikipedia-dns.rb +4 -18
- data/lib/rubydns.rb +9 -23
- data/lib/rubydns/{server.rb → rule_based_server.rb} +2 -160
- data/lib/rubydns/version.rb +1 -1
- data/rubydns.gemspec +3 -6
- data/spec/rubydns/daemon_spec.rb +26 -22
- data/spec/rubydns/injected_supervisor_spec.rb +10 -7
- data/spec/rubydns/passthrough_spec.rb +31 -24
- data/spec/spec_helper.rb +43 -0
- metadata +21 -100
- data/lib/rubydns/chunked.rb +0 -34
- data/lib/rubydns/extensions/resolv.rb +0 -85
- data/lib/rubydns/extensions/string.rb +0 -28
- data/lib/rubydns/handler.rb +0 -188
- data/lib/rubydns/logger.rb +0 -31
- data/lib/rubydns/message.rb +0 -76
- data/lib/rubydns/resolver.rb +0 -294
- data/lib/rubydns/system.rb +0 -146
- data/lib/rubydns/transaction.rb +0 -204
- data/lib/rubydns/transport.rb +0 -75
- data/spec/rubydns/celluloid_bug_spec.rb +0 -92
- data/spec/rubydns/ipv6_spec.rb +0 -70
- data/spec/rubydns/message_spec.rb +0 -56
- data/spec/rubydns/origin_spec.rb +0 -106
- data/spec/rubydns/resolver_performance_spec.rb +0 -110
- data/spec/rubydns/resolver_spec.rb +0 -152
- data/spec/rubydns/server/bind9/generate-local.rb +0 -25
- data/spec/rubydns/server/bind9/local.zone +0 -5014
- data/spec/rubydns/server/bind9/named.conf +0 -14
- data/spec/rubydns/server/bind9/named.run +0 -0
- data/spec/rubydns/server/million.rb +0 -85
- data/spec/rubydns/server/rubydns.stackprof +0 -0
- data/spec/rubydns/server_performance_spec.rb +0 -136
- data/spec/rubydns/slow_server_spec.rb +0 -89
- data/spec/rubydns/socket_spec.rb +0 -77
- data/spec/rubydns/system_spec.rb +0 -60
- data/spec/rubydns/transaction_spec.rb +0 -138
- data/spec/rubydns/truncation_spec.rb +0 -59
@@ -0,0 +1,83 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Copyright, 2009, 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 'rubygems'
|
24
|
+
require 'rubydns'
|
25
|
+
require 'rubydns/system'
|
26
|
+
|
27
|
+
# You can specify other DNS servers easily
|
28
|
+
# $R = Resolv::DNS.new(:nameserver => ["xx.xx.1.1", "xx.xx.2.2"])
|
29
|
+
|
30
|
+
R = RubyDNS::Resolver.new(RubyDNS::System.nameservers)
|
31
|
+
Name = Resolv::DNS::Name
|
32
|
+
IN = Resolv::DNS::Resource::IN
|
33
|
+
INTERFACES = [
|
34
|
+
[:udp, '0.0.0.0', 5300],
|
35
|
+
[:tcp, '0.0.0.0', 5300],
|
36
|
+
# [:udp, '::0', 5300],
|
37
|
+
# [:tcp, '::0', 5300],
|
38
|
+
]
|
39
|
+
|
40
|
+
RubyDNS.run_server(listen: INTERFACES) do
|
41
|
+
# % dig +nocmd +noall +answer @localhost ANY dev.mydomain.org
|
42
|
+
# dev.mydomain.org. 16000 IN A 10.0.0.80
|
43
|
+
# dev.mydomain.org. 16000 IN MX 10 mail.mydomain.org.
|
44
|
+
match(/dev.mydomain.org/, IN::ANY) do |transaction|
|
45
|
+
transaction.append_question!
|
46
|
+
|
47
|
+
[IN::A, IN::CNAME, IN::MX].each do |resource_class|
|
48
|
+
logger.debug "Appending query for #{resource_class}..."
|
49
|
+
transaction.append!(transaction.name, resource_class)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# For this exact address record, return an IP address
|
54
|
+
match('dev.mydomain.org', IN::A) do |transaction|
|
55
|
+
transaction.respond!('10.0.0.80')
|
56
|
+
end
|
57
|
+
|
58
|
+
match('80.0.0.10.in-addr.arpa', IN::PTR) do |transaction|
|
59
|
+
transaction.respond!(Name.create('dev.mydomain.org.'))
|
60
|
+
end
|
61
|
+
|
62
|
+
match('dev.mydomain.org', IN::MX) do |transaction|
|
63
|
+
transaction.respond!(10, Name.create('mail.mydomain.org.'))
|
64
|
+
end
|
65
|
+
|
66
|
+
match(/^test([0-9]+).mydomain.org$/, IN::A) do |transaction, match_data|
|
67
|
+
offset = match_data[1].to_i
|
68
|
+
|
69
|
+
if offset > 0 && offset < 10
|
70
|
+
logger.info "Responding with address #{'10.0.0.' + (90 + offset).to_s}..."
|
71
|
+
transaction.respond!('10.0.0.' + (90 + offset).to_s)
|
72
|
+
else
|
73
|
+
logger.info "Address out of range: #{offset}!"
|
74
|
+
false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Default DNS handler
|
79
|
+
otherwise do |transaction|
|
80
|
+
logger.info 'Passing DNS request upstream...'
|
81
|
+
transaction.passthrough!(R)
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Copyright, 2009, 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
|
+
# To run this command, use the standard daemon syntax as root
|
27
|
+
# ./daemon2.rb start
|
28
|
+
|
29
|
+
# You should be able to see that the server has dropped priviledges
|
30
|
+
# # ps aux | grep daemon2.rb
|
31
|
+
# daemon 16555 0.4 0.0 81392 2024 ?? S 3:35am 0:00.28 ruby ../test/daemon2.rb start
|
32
|
+
|
33
|
+
# Test using the following command
|
34
|
+
# dig @localhost test.mydomain.org
|
35
|
+
# dig +tcp @localhost test.mydomain.org
|
36
|
+
|
37
|
+
# You might need to change the user name "daemon". This can be a user name or a user id.
|
38
|
+
RUN_AS = 'daemon'
|
39
|
+
|
40
|
+
INTERFACES = [
|
41
|
+
[:udp, '0.0.0.0', 53],
|
42
|
+
[:tcp, '0.0.0.0', 53]
|
43
|
+
]
|
44
|
+
|
45
|
+
# We need to be root in order to bind to privileged port
|
46
|
+
if RExec.current_user != 'root'
|
47
|
+
$stderr.puts 'Sorry, this command needs to be run as root!'
|
48
|
+
exit 1
|
49
|
+
end
|
50
|
+
|
51
|
+
# The Daemon itself
|
52
|
+
class Server < Process::Daemon
|
53
|
+
Name = Resolv::DNS::Name
|
54
|
+
IN = Resolv::DNS::Resource::IN
|
55
|
+
|
56
|
+
# Use upstream DNS for name resolution.
|
57
|
+
UPSTREAM = RubyDNS::Resolver.new([[:udp, '8.8.8.8', 53], [:tcp, '8.8.8.8', 53]])
|
58
|
+
|
59
|
+
def startup
|
60
|
+
# Don't buffer output (for debug purposes)
|
61
|
+
$stderr.sync = true
|
62
|
+
|
63
|
+
# Start the RubyDNS server
|
64
|
+
RubyDNS.run_server(listen: INTERFACES) do
|
65
|
+
on(:start) do
|
66
|
+
RExec.change_user(RUN_AS)
|
67
|
+
end
|
68
|
+
|
69
|
+
match('test.mydomain.org', IN::A) do |transaction|
|
70
|
+
transaction.respond!('10.0.0.80')
|
71
|
+
end
|
72
|
+
|
73
|
+
# Default DNS handler
|
74
|
+
otherwise do |transaction|
|
75
|
+
logger.info "Passthrough: #{transaction}"
|
76
|
+
transaction.passthrough!(UPSTREAM)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# RExec daemon runner
|
83
|
+
Server.daemonize
|
data/examples/wikipedia-dns.rb
CHANGED
@@ -22,7 +22,6 @@
|
|
22
22
|
# THE SOFTWARE.
|
23
23
|
|
24
24
|
require 'rubydns'
|
25
|
-
require 'rubydns/extensions/string'
|
26
25
|
|
27
26
|
require 'process/daemon'
|
28
27
|
require 'process/daemon/privileges'
|
@@ -33,6 +32,8 @@ require 'json'
|
|
33
32
|
|
34
33
|
require 'digest/md5'
|
35
34
|
|
35
|
+
require 'http'
|
36
|
+
|
36
37
|
# You might need to change the user name "daemon". This can be a user name
|
37
38
|
# or a user id.
|
38
39
|
RUN_AS = 'daemon'
|
@@ -42,19 +43,6 @@ if Process::Daemon::Privileges.current_user != 'root'
|
|
42
43
|
exit 1
|
43
44
|
end
|
44
45
|
|
45
|
-
require 'http'
|
46
|
-
|
47
|
-
# Celluloid::IO fetcher to retrieve URLs.
|
48
|
-
class HttpFetcher
|
49
|
-
include Celluloid::IO
|
50
|
-
|
51
|
-
def get(url)
|
52
|
-
# Note: For SSL support specify:
|
53
|
-
# ssl_socket_class: Celluloid::IO::SSLSocket
|
54
|
-
HTTP.get(url, socket_class: Celluloid::IO::TCPSocket)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
46
|
# Encapsulates the logic for fetching information from Wikipedia.
|
59
47
|
module Wikipedia
|
60
48
|
def self.summary_url(title)
|
@@ -81,9 +69,6 @@ class WikipediaDNS < Process::Daemon
|
|
81
69
|
|
82
70
|
stats = { requested: 0 }
|
83
71
|
|
84
|
-
# Use a Celluloid supervisor so the system recovers if the actor dies
|
85
|
-
fetcher = HttpFetcher.supervise
|
86
|
-
|
87
72
|
# Start the RubyDNS server
|
88
73
|
RubyDNS.run_server do
|
89
74
|
on(:start) do
|
@@ -103,7 +88,8 @@ class WikipediaDNS < Process::Daemon
|
|
103
88
|
title = match_data[1]
|
104
89
|
stats[:requested] += 1
|
105
90
|
|
106
|
-
|
91
|
+
url = Wikipedia.summary_url(title)
|
92
|
+
response = HTTP.get(url) # socket_class: ... is not yet supported.
|
107
93
|
|
108
94
|
summary =
|
109
95
|
Wikipedia.extract_summary(response).force_encoding('ASCII-8BIT')
|
data/lib/rubydns.rb
CHANGED
@@ -18,33 +18,19 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
|
-
|
21
|
+
require 'async/dns'
|
22
22
|
|
23
|
-
require_relative 'rubydns/
|
24
|
-
require_relative 'rubydns/
|
25
|
-
require_relative 'rubydns/resolver'
|
26
|
-
require_relative 'rubydns/handler'
|
27
|
-
require_relative 'rubydns/logger'
|
23
|
+
require_relative 'rubydns/version'
|
24
|
+
require_relative 'rubydns/rule_based_server'
|
28
25
|
|
29
26
|
module RubyDNS
|
27
|
+
# Backwards compatibility:
|
28
|
+
Resolver = Async::DNS::Resolver
|
29
|
+
|
30
30
|
# Run a server with the given rules.
|
31
|
-
def self.run_server (
|
32
|
-
|
33
|
-
|
34
|
-
supervisor = server_class.supervise(options, &block)
|
31
|
+
def self.run_server (server_class: RuleBasedServer, **options, &block)
|
32
|
+
server = server_class.new(**options, &block)
|
35
33
|
|
36
|
-
|
37
|
-
if options[:asynchronous]
|
38
|
-
return supervisor
|
39
|
-
else
|
40
|
-
read, write = IO.pipe
|
41
|
-
|
42
|
-
trap(:INT) {
|
43
|
-
write.puts
|
44
|
-
}
|
45
|
-
|
46
|
-
IO.select([read])
|
47
|
-
supervisor.terminate
|
48
|
-
end
|
34
|
+
server.run
|
49
35
|
end
|
50
36
|
end
|
@@ -18,166 +18,11 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
|
-
require '
|
22
|
-
|
23
|
-
require_relative 'transaction'
|
24
|
-
require_relative 'logger'
|
21
|
+
require 'async/dns/server'
|
25
22
|
|
26
23
|
module RubyDNS
|
27
|
-
class UDPSocketWrapper < Celluloid::IO::UDPSocket
|
28
|
-
def initialize(socket)
|
29
|
-
@socket = socket
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
class TCPServerWrapper < Celluloid::IO::TCPServer
|
34
|
-
def initialize(server)
|
35
|
-
@server = server
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
class Server
|
40
|
-
include Celluloid::IO
|
41
|
-
|
42
|
-
finalizer :shutdown
|
43
|
-
|
44
|
-
# The default server interfaces
|
45
|
-
DEFAULT_INTERFACES = [[:udp, "0.0.0.0", 53], [:tcp, "0.0.0.0", 53]]
|
46
|
-
|
47
|
-
# Instantiate a server with a block
|
48
|
-
#
|
49
|
-
# server = Server.new do
|
50
|
-
# match(/server.mydomain.com/, IN::A) do |transaction|
|
51
|
-
# transaction.respond!("1.2.3.4")
|
52
|
-
# end
|
53
|
-
# end
|
54
|
-
#
|
55
|
-
def initialize(options = {})
|
56
|
-
@handlers = []
|
57
|
-
|
58
|
-
@logger = options[:logger] || Celluloid.logger
|
59
|
-
@interfaces = options[:listen] || DEFAULT_INTERFACES
|
60
|
-
|
61
|
-
@origin = options[:origin] || '.'
|
62
|
-
end
|
63
|
-
|
64
|
-
# Records are relative to this origin:
|
65
|
-
attr_accessor :origin
|
66
|
-
|
67
|
-
attr_accessor :logger
|
68
|
-
|
69
|
-
# Fire the named event as part of running the server.
|
70
|
-
def fire(event_name)
|
71
|
-
end
|
72
|
-
|
73
|
-
def shutdown
|
74
|
-
fire(:stop)
|
75
|
-
end
|
76
|
-
|
77
|
-
# Give a name and a record type, try to match a rule and use it for processing the given arguments.
|
78
|
-
def process(name, resource_class, transaction)
|
79
|
-
raise NotImplementedError.new
|
80
|
-
end
|
81
|
-
|
82
|
-
# Process an incoming DNS message. Returns a serialized message to be sent back to the client.
|
83
|
-
def process_query(query, options = {}, &block)
|
84
|
-
start_time = Time.now
|
85
|
-
|
86
|
-
# Setup response
|
87
|
-
response = Resolv::DNS::Message::new(query.id)
|
88
|
-
response.qr = 1 # 0 = Query, 1 = Response
|
89
|
-
response.opcode = query.opcode # Type of Query; copy from query
|
90
|
-
response.aa = 1 # Is this an authoritative response: 0 = No, 1 = Yes
|
91
|
-
response.rd = query.rd # Is Recursion Desired, copied from query
|
92
|
-
response.ra = 0 # Does name server support recursion: 0 = No, 1 = Yes
|
93
|
-
response.rcode = 0 # Response code: 0 = No errors
|
94
|
-
|
95
|
-
transaction = nil
|
96
|
-
|
97
|
-
begin
|
98
|
-
query.question.each do |question, resource_class|
|
99
|
-
begin
|
100
|
-
question = question.without_origin(@origin)
|
101
|
-
|
102
|
-
@logger.debug {"<#{query.id}> Processing question #{question} #{resource_class}..."}
|
103
|
-
|
104
|
-
transaction = Transaction.new(self, query, question, resource_class, response, options)
|
105
|
-
|
106
|
-
transaction.process
|
107
|
-
rescue Resolv::DNS::OriginError
|
108
|
-
# This is triggered if the question is not part of the specified @origin:
|
109
|
-
@logger.debug {"<#{query.id}> Skipping question #{question} #{resource_class} because #{$!}"}
|
110
|
-
end
|
111
|
-
end
|
112
|
-
rescue Celluloid::ResumableError
|
113
|
-
raise
|
114
|
-
rescue StandardError => error
|
115
|
-
@logger.error "<#{query.id}> Exception thrown while processing #{transaction}!"
|
116
|
-
RubyDNS.log_exception(@logger, error)
|
117
|
-
|
118
|
-
response.rcode = Resolv::DNS::RCode::ServFail
|
119
|
-
end
|
120
|
-
|
121
|
-
end_time = Time.now
|
122
|
-
@logger.debug {"<#{query.id}> Time to process request: #{end_time - start_time}s"}
|
123
|
-
|
124
|
-
return response
|
125
|
-
end
|
126
|
-
|
127
|
-
#
|
128
|
-
# By default the server runs on port 53, both TCP and UDP, which is usually a priviledged port and requires root access to bind. You can change this by specifying `options[:listen]` which should contain an array of `[protocol, interface address, port]` specifications.
|
129
|
-
#
|
130
|
-
# INTERFACES = [[:udp, "0.0.0.0", 5300]]
|
131
|
-
# RubyDNS::run_server(:listen => INTERFACES) do
|
132
|
-
# ...
|
133
|
-
# end
|
134
|
-
#
|
135
|
-
# You can specify already connected sockets if need be:
|
136
|
-
#
|
137
|
-
# socket = UDPSocket.new; socket.bind("0.0.0.0", 53)
|
138
|
-
# Process::Sys.setuid(server_uid)
|
139
|
-
# INTERFACES = [socket]
|
140
|
-
#
|
141
|
-
def run
|
142
|
-
@logger.info "Starting RubyDNS server (v#{RubyDNS::VERSION})..."
|
143
|
-
|
144
|
-
fire(:setup)
|
145
|
-
|
146
|
-
# Setup server sockets
|
147
|
-
@interfaces.each do |spec|
|
148
|
-
if spec.is_a?(BasicSocket)
|
149
|
-
spec.do_not_reverse_lookup
|
150
|
-
protocol = spec.getsockopt(Socket::SOL_SOCKET, Socket::SO_TYPE).unpack("i")[0]
|
151
|
-
ip = spec.local_address.ip_address
|
152
|
-
port = spec.local_address.ip_port
|
153
|
-
|
154
|
-
case protocol
|
155
|
-
when Socket::SOCK_DGRAM
|
156
|
-
@logger.info "<> Attaching to pre-existing UDP socket #{ip}:#{port}"
|
157
|
-
link UDPSocketHandler.new(self, UDPSocketWrapper.new(spec))
|
158
|
-
when Socket::SOCK_STREAM
|
159
|
-
@logger.info "<> Attaching to pre-existing TCP socket #{ip}:#{port}"
|
160
|
-
link TCPSocketHandler.new(self, TCPServerWrapper.new(spec))
|
161
|
-
else
|
162
|
-
raise ArgumentError.new("Unknown socket protocol: #{protocol}")
|
163
|
-
end
|
164
|
-
elsif spec[0] == :udp
|
165
|
-
@logger.info "<> Listening on #{spec.join(':')}"
|
166
|
-
link UDPHandler.new(self, spec[1], spec[2])
|
167
|
-
elsif spec[0] == :tcp
|
168
|
-
@logger.info "<> Listening on #{spec.join(':')}"
|
169
|
-
link TCPHandler.new(self, spec[1], spec[2])
|
170
|
-
else
|
171
|
-
raise ArgumentError.new("Invalid connection specification: #{spec.inspect}")
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
fire(:start)
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
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.
|
180
|
-
class RuleBasedServer < Server
|
25
|
+
class RuleBasedServer < Async::DNS::Server
|
181
26
|
# Represents a single rule in the server.
|
182
27
|
class Rule
|
183
28
|
def initialize(pattern, callback)
|
@@ -247,9 +92,6 @@ module RubyDNS
|
|
247
92
|
end
|
248
93
|
end
|
249
94
|
|
250
|
-
# Don't wrap the block going into initialize.
|
251
|
-
execute_block_on_receiver :initialize
|
252
|
-
|
253
95
|
# Instantiate a server with a block
|
254
96
|
#
|
255
97
|
# server = Server.new do
|
data/lib/rubydns/version.rb
CHANGED