Skip to content

Commit

Permalink
Migration to async-dns - work in progress.
Browse files Browse the repository at this point in the history
  • Loading branch information
ioquatix committed Apr 7, 2017
1 parent 244ab10 commit b4df27f
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 65 deletions.
4 changes: 3 additions & 1 deletion .rspec
@@ -1,2 +1,4 @@
--color
--format documentation
--format documentation
--warnings
--require spec_helper
4 changes: 4 additions & 0 deletions Gemfile
Expand Up @@ -2,6 +2,10 @@ source 'https://rubygems.org'

gemspec

group :development do
gem "process-daemon"
end

group :test do
gem 'simplecov'
gem 'coveralls', require: false
Expand Down
33 changes: 13 additions & 20 deletions lib/rubydns.rb
Expand Up @@ -18,35 +18,28 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

require 'celluloid/dns'
require 'async/dns'

require_relative 'rubydns/version'
require_relative 'rubydns/rule_based_server'

module RubyDNS
# Backwards compatibility:
Resolver = Celluloid::DNS::Resolver
Resolver = Async::DNS::Resolver

# Run a server with the given rules.
def self.run_server (options = {}, &block)
server_class = options[:server_class] || RuleBasedServer

actor = server_class.new(options, &block)

actor.run

if options[:asynchronous]
return actor
def self.run_server (server_class: RuleBasedServer, asynchronous: false, **options, &block)
# Should fix this... allow nested reactors.
if asynchronous
Async::Task.current.reactor.async do
server = server_class.new(**options, &block)
server.run
end
else
read, write = IO.pipe

trap(:INT) {
write.puts
}

IO.select([read])

actor.terminate
Async::Reactor.run do
server = server_class.new(**options, &block)
server.run
end
end
end
end
7 changes: 2 additions & 5 deletions lib/rubydns/rule_based_server.rb
Expand Up @@ -18,11 +18,11 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

require 'celluloid/dns/server'
require 'async/dns/server'

module RubyDNS
# 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.
class RuleBasedServer < Celluloid::DNS::Server
class RuleBasedServer < Async::DNS::Server
# Represents a single rule in the server.
class Rule
def initialize(pattern, callback)
Expand Down Expand Up @@ -92,9 +92,6 @@ def to_s
end
end

# Don't wrap the block going into initialize.
execute_block_on_receiver :initialize

# Instantiate a server with a block
#
# server = Server.new do
Expand Down
7 changes: 3 additions & 4 deletions rubydns.gemspec
Expand Up @@ -28,12 +28,11 @@ Gem::Specification.new do |spec|
spec.require_paths = ["lib"]
spec.has_rdoc = "yard"

spec.required_ruby_version = '>= 2.0.0'
spec.required_ruby_version = '>= 2.2.6'

spec.add_dependency("celluloid-dns", "~> 0.17.3")
spec.add_dependency("async-dns", "~> 0.9")

spec.add_development_dependency "bundler", "~> 1.3"
spec.add_development_dependency "process-daemon", "~> 1.0.0"
spec.add_development_dependency "rspec", "~> 3.4.0"
spec.add_development_dependency "rspec", "~> 3.4"
spec.add_development_dependency "rake"
end
46 changes: 23 additions & 23 deletions spec/rubydns/daemon_spec.rb
Expand Up @@ -32,44 +32,44 @@ def working_directory
File.expand_path("../tmp", __FILE__)
end

def reactor
Async::Reactor.new
end

def startup
Celluloid.boot

# Start the RubyDNS server
@actor = RubyDNS::run_server(listen: SERVER_PORTS, asynchronous: true) do
match("test.local", IN::A) do |transaction|
transaction.respond!("192.168.1.1")
end
reactor.run do
RubyDNS::run_server(listen: SERVER_PORTS, asynchronous: true) do
match("test.local", IN::A) do |transaction|
transaction.respond!("192.168.1.1")
end

match(/foo.*/, IN::A) do |transaction|
transaction.respond!("192.168.1.2")
end
match(/foo.*/, IN::A) do |transaction|
transaction.respond!("192.168.1.2")
end

match(/peername/, IN::A) do |transaction|
transaction.respond!(transaction[:peer])
end
match(/peername/, IN::A) do |transaction|
transaction.respond!(transaction[:peer])
end

# Default DNS handler
otherwise do |transaction|
transaction.fail!(:NXDomain)
# Default DNS handler
otherwise do |transaction|
transaction.fail!(:NXDomain)
end
end
end
end

def shutdown
@actor.terminate
@reactor.stop
end
end

describe "RubyDNS Daemonized Server" do
include_context "reactor"

before(:all) do
Celluloid.shutdown

# Trying to fork with Celluloid running is a recipe for disaster.
# BasicTestServer.controller output: $stderr
BasicTestServer.start

Celluloid.boot
end

after(:all) do
Expand All @@ -79,7 +79,7 @@ def shutdown
it "should resolve local domain correctly" do
expect(BasicTestServer.status).to be == :running

resolver = RubyDNS::Resolver.new(BasicTestServer::SERVER_PORTS, search_domain: '')
resolver = RubyDNS::Resolver.new(BasicTestServer::SERVER_PORTS)

response = resolver.query("test.local")

Expand Down
15 changes: 9 additions & 6 deletions spec/rubydns/injected_supervisor_spec.rb
Expand Up @@ -21,7 +21,7 @@
# THE SOFTWARE.

require 'rubydns'
require 'celluloid/dns/extensions/string'
require 'async/dns/extensions/string'

module RubyDNS::InjectedSupervisorSpec
class TestServer < RubyDNS::RuleBasedServer
Expand All @@ -33,11 +33,10 @@ def test_message
SERVER_PORTS = [[:udp, '127.0.0.1', 5520]]
IN = Resolv::DNS::Resource::IN

describe "RubyDNS Injected Supervisor" do
before(:all) do
Celluloid.shutdown
Celluloid.boot

describe "RubyDNS::run_server(server_class: ...)" do
include_context "reactor"

let(:server) do
# Start the RubyDNS server
RubyDNS::run_server(listen: SERVER_PORTS, server_class: TestServer, asynchronous: true) do
match("test_message", IN::TXT) do |transaction|
Expand All @@ -52,10 +51,14 @@ def test_message
end

it "should use the injected class" do
server

resolver = RubyDNS::Resolver.new(SERVER_PORTS)
response = resolver.query("test_message", IN::TXT)
text = response.answer.first
expect(text[2].strings.join).to be == 'Testing...'

server.stop!
end
end
end
18 changes: 12 additions & 6 deletions spec/rubydns/passthrough_spec.rb
Expand Up @@ -28,12 +28,10 @@ module RubyDNS::PassthroughSpec
IN = Resolv::DNS::Resource::IN

describe "RubyDNS Passthrough Server" do
before(:all) do
Celluloid.shutdown
Celluloid.boot
include_context "reactor"

# Start the RubyDNS server
@server = RubyDNS::run_server(:listen => SERVER_PORTS, asynchronous: true) do
let(:server) do
RubyDNS::run_server(:listen => SERVER_PORTS, asynchronous: true) do
resolver = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])

match(/.*\.com/, IN::A) do |transaction|
Expand All @@ -50,8 +48,10 @@ module RubyDNS::PassthroughSpec
end
end
end

it "should resolve domain correctly" do
server

resolver = RubyDNS::Resolver.new(SERVER_PORTS)

response = resolver.query("google.com")
Expand All @@ -63,16 +63,22 @@ module RubyDNS::PassthroughSpec

addresses = answer.select {|record| record.kind_of? Resolv::DNS::Resource::IN::A}
expect(addresses.size).to be > 0

server.stop!
end

it "should resolve prefixed domain correctly" do
server

resolver = RubyDNS::Resolver.new(SERVER_PORTS)

response = resolver.query("a-slashdot.org")
answer = response.answer.first

expect(answer).not_to be == nil
expect(answer.count).to be > 0

server.stop!
end
end
end
41 changes: 41 additions & 0 deletions spec/spec_helper.rb
@@ -0,0 +1,41 @@

if ENV['COVERAGE'] || ENV['TRAVIS']
begin
require 'simplecov'

SimpleCov.start do
add_filter "/spec/"
end

if ENV['TRAVIS']
require 'coveralls'
Coveralls.wear!
end
rescue LoadError
warn "Could not load simplecov: #{$!}"
end
end

require "bundler/setup"
require "async"
require "async/tcp_socket"
require "async/udp_socket"

RSpec.shared_context "reactor" do
let(:reactor) {Async::Reactor.new}

around(:each) do |example|
reactor.run do
example.run
end
end
end

RSpec.configure do |config|
# Enable flags like --only-failures and --next-failure
config.example_status_persistence_file_path = ".rspec_status"

config.expect_with :rspec do |c|
c.syntax = :expect
end
end

0 comments on commit b4df27f

Please sign in to comment.