celluloid-dns 0.0.1 → 0.17.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +0 -2
  3. data/.simplecov +15 -0
  4. data/.travis.yml +13 -7
  5. data/Gemfile +5 -6
  6. data/README.md +118 -41
  7. data/Rakefile +8 -3
  8. data/celluloid-dns.gemspec +29 -18
  9. data/lib/celluloid/dns.rb +30 -7
  10. data/lib/celluloid/dns/chunked.rb +34 -0
  11. data/lib/celluloid/dns/extensions/resolv.rb +136 -0
  12. data/lib/celluloid/dns/extensions/string.rb +28 -0
  13. data/lib/celluloid/dns/handler.rb +198 -0
  14. data/lib/celluloid/dns/logger.rb +31 -0
  15. data/lib/celluloid/dns/message.rb +76 -0
  16. data/lib/celluloid/dns/replace.rb +54 -0
  17. data/lib/celluloid/dns/resolver.rb +288 -0
  18. data/lib/celluloid/dns/server.rb +151 -27
  19. data/lib/celluloid/dns/system.rb +146 -0
  20. data/lib/celluloid/dns/transaction.rb +202 -0
  21. data/lib/celluloid/dns/transport.rb +75 -0
  22. data/lib/celluloid/dns/version.rb +23 -3
  23. data/spec/celluloid/dns/celluloid_bug_spec.rb +92 -0
  24. data/spec/celluloid/dns/hosts.txt +2 -0
  25. data/spec/celluloid/dns/ipv6_spec.rb +70 -0
  26. data/spec/celluloid/dns/message_spec.rb +56 -0
  27. data/spec/celluloid/dns/origin_spec.rb +106 -0
  28. data/spec/celluloid/dns/replace_spec.rb +42 -0
  29. data/spec/celluloid/dns/resolver_performance_spec.rb +110 -0
  30. data/spec/celluloid/dns/resolver_spec.rb +152 -0
  31. data/spec/celluloid/dns/server/bind9/generate-local.rb +25 -0
  32. data/spec/celluloid/dns/server/bind9/local.zone +5014 -0
  33. data/spec/celluloid/dns/server/bind9/named.conf +14 -0
  34. data/spec/celluloid/dns/server/bind9/named.run +0 -0
  35. data/spec/celluloid/dns/server/million.rb +85 -0
  36. data/spec/celluloid/dns/server_performance_spec.rb +139 -0
  37. data/spec/celluloid/dns/slow_server_spec.rb +91 -0
  38. data/spec/celluloid/dns/socket_spec.rb +71 -0
  39. data/spec/celluloid/dns/system_spec.rb +60 -0
  40. data/spec/celluloid/dns/transaction_spec.rb +138 -0
  41. data/spec/celluloid/dns/truncation_spec.rb +62 -0
  42. metadata +124 -56
  43. data/.coveralls.yml +0 -1
  44. data/.gitignore +0 -17
  45. data/CHANGES.md +0 -3
  46. data/LICENSE.txt +0 -22
  47. data/lib/celluloid/dns/request.rb +0 -46
  48. data/spec/celluloid/dns/server_spec.rb +0 -26
  49. data/spec/spec_helper.rb +0 -5
  50. data/tasks/rspec.task +0 -7
@@ -0,0 +1,14 @@
1
+
2
+ options {
3
+ directory "./";
4
+
5
+ listen-on-v6 { none; };
6
+ listen-on { 127.0.0.1; };
7
+
8
+ pid-file "./named.pid";
9
+ };
10
+
11
+ zone "local" {
12
+ type master;
13
+ file "./local.zone";
14
+ };
@@ -0,0 +1,85 @@
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 'celluloid/dns'
24
+ require 'benchmark'
25
+
26
+ require 'stackprof'
27
+
28
+ Name = Resolv::DNS::Name
29
+ IN = Resolv::DNS::Resource::IN
30
+
31
+ # Generate a million A record "domains":
32
+
33
+ million = {}
34
+
35
+ Benchmark.bm do |x|
36
+ x.report("Generate names") do
37
+ (1..1_000_000).each do |i|
38
+ domain = "domain#{i}.local"
39
+
40
+ million[domain] = "#{69}.#{(i >> 16)%256}.#{(i >> 8)%256}.#{i%256}"
41
+ end
42
+ end
43
+ end
44
+
45
+ # Run the server:
46
+
47
+ StackProf.run(mode: :cpu, out: 'celluloid/dns.stackprof') do
48
+ Celluloid::DNS::run_server(:listen => [[:udp, '0.0.0.0', 5300]]) do
49
+ @logger.level = Logger::WARN
50
+
51
+ match(//, IN::A) do |transaction|
52
+ transaction.respond!(million[transaction.name])
53
+ end
54
+
55
+ # Default DNS handler
56
+ otherwise do |transaction|
57
+ logger.info "Passing DNS request upstream..."
58
+ transaction.fail!(:NXDomain)
59
+ end
60
+ end
61
+ end
62
+
63
+ # Expected output:
64
+ #
65
+ # > dig @localhost -p 5300 domain1000000
66
+ #
67
+ # ; <<>> DiG 9.8.3-P1 <<>> @localhost -p 5300 domain1000000
68
+ # ; (3 servers found)
69
+ # ;; global options: +cmd
70
+ # ;; Got answer:
71
+ # ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50336
72
+ # ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
73
+ # ;; WARNING: recursion requested but not available
74
+ #
75
+ # ;; QUESTION SECTION:
76
+ # ;domain1000000. IN A
77
+ #
78
+ # ;; ANSWER SECTION:
79
+ # domain1000000. 86400 IN A 69.15.66.64
80
+ #
81
+ # ;; Query time: 1 msec
82
+ # ;; SERVER: 127.0.0.1#5300(127.0.0.1)
83
+ # ;; WHEN: Fri May 16 19:17:48 2014
84
+ # ;; MSG SIZE rcvd: 47
85
+ #
@@ -0,0 +1,139 @@
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 'celluloid/dns'
24
+ require 'benchmark'
25
+ require 'process/daemon'
26
+
27
+ module Celluloid::DNS::ServerPerformanceSpec
28
+ describe Celluloid::DNS::Server do
29
+ context 'benchmark' do
30
+ class MillionServer < Celluloid::DNS::Server
31
+ def initialize(*)
32
+ super
33
+
34
+ @million = {}
35
+
36
+ (1..5_000).each do |i|
37
+ domain = "domain#{i}.local"
38
+
39
+ @million[domain] = "#{69}.#{(i >> 16)%256}.#{(i >> 8)%256}.#{i%256}"
40
+ end
41
+ end
42
+
43
+ def process(name, resource_class, transaction)
44
+ transaction.respond!(@million[name])
45
+ end
46
+ end
47
+
48
+ class CelluloidServerDaemon < Process::Daemon
49
+ IN = Resolv::DNS::Resource::IN
50
+
51
+ def working_directory
52
+ File.expand_path("../tmp", __FILE__)
53
+ end
54
+
55
+ def startup
56
+ puts "Booting celluloid..."
57
+ Celluloid.boot
58
+
59
+ puts "Starting DNS server..."
60
+ @server = MillionServer.new(listen: [[:udp, '0.0.0.0', 5300]])
61
+
62
+ @server.async.run
63
+ end
64
+
65
+ def shutdown
66
+ @server.terminate
67
+ end
68
+ end
69
+
70
+ class Bind9ServerDaemon < Process::Daemon
71
+ def working_directory
72
+ File.expand_path("../server/bind9", __FILE__)
73
+ end
74
+
75
+ def run
76
+ exec(self.class.named_executable, "-c", "named.conf", "-f", "-p", "5400", "-g")
77
+ end
78
+
79
+ def self.named_executable
80
+ # Check if named executable is available:
81
+ @named ||= `which named`.chomp
82
+ end
83
+ end
84
+
85
+ before(:all) do
86
+ Celluloid.shutdown
87
+
88
+ @servers = []
89
+ @servers << ["Celluloid::DNS::Server", 5300]
90
+
91
+ @domains = (1..1000).collect do |i|
92
+ "domain#{i}.local"
93
+ end
94
+
95
+ CelluloidServerDaemon.start
96
+
97
+ unless Bind9ServerDaemon.named_executable.empty?
98
+ Bind9ServerDaemon.start
99
+ @servers << ["Bind9", 5400]
100
+ end
101
+
102
+ sleep 2
103
+
104
+ Celluloid.boot
105
+ end
106
+
107
+ after(:all) do
108
+ CelluloidServerDaemon.stop
109
+
110
+ unless Bind9ServerDaemon.named_executable.empty?
111
+ Bind9ServerDaemon.stop
112
+ end
113
+ end
114
+
115
+ it 'takes time' do
116
+ # Celluloid.logger.level = Logger::ERROR
117
+
118
+ Benchmark.bm(30) do |x|
119
+ @servers.each do |name, port|
120
+ resolver = Celluloid::DNS::Resolver.new([[:udp, '127.0.0.1', port]])
121
+
122
+ x.report(name) do
123
+ # Number of requests remaining since this is an asynchronous event loop:
124
+ 5.times do
125
+ pending = @domains.size
126
+
127
+ futures = @domains.collect{|domain| resolver.future.addresses_for(domain)}
128
+
129
+ futures.collect do |future|
130
+ expect(future.value).to_not be nil
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,91 @@
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 'celluloid/dns'
24
+
25
+ module Celluloid::DNS::SlowServerSpec
26
+ SERVER_PORTS = [[:udp, '127.0.0.1', 5330], [:tcp, '127.0.0.1', 5330]]
27
+ IN = Resolv::DNS::Resource::IN
28
+
29
+ class TestServer < Celluloid::DNS::Server
30
+ def process(name, resource_class, transaction)
31
+ @resolver ||= Celluloid::DNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
32
+
33
+ sleep(2) if name.end_with?('.com')
34
+
35
+ transaction.fail!(:NXDomain)
36
+ end
37
+ end
38
+
39
+ describe "Celluloid::DNS Slow Server" do
40
+ before(:all) do
41
+ @server = TestServer.new(listen: SERVER_PORTS)
42
+ @server.run
43
+ end
44
+
45
+ after(:all) do
46
+ @server.terminate
47
+ end
48
+
49
+ it "get no answer after 2 seconds" do
50
+ start_time = Time.now
51
+
52
+ resolver = Celluloid::DNS::Resolver.new(SERVER_PORTS, :timeout => 10)
53
+
54
+ response = resolver.query("apple.com", IN::A)
55
+
56
+ expect(response.answer.length).to be == 0
57
+
58
+ end_time = Time.now
59
+
60
+ expect(end_time - start_time).to be_within(0.1).of(2.0)
61
+ end
62
+
63
+ it "times out after 1 second" do
64
+ start_time = Time.now
65
+
66
+ resolver = Celluloid::DNS::Resolver.new(SERVER_PORTS, :timeout => 0.5)
67
+
68
+ response = resolver.query("apple.com", IN::A)
69
+
70
+ expect(response).to be nil
71
+
72
+ end_time = Time.now
73
+
74
+ expect(end_time - start_time).to be_within(0.1).of(1.0)
75
+ end
76
+
77
+ it "gets no answer immediately" do
78
+ start_time = Time.now
79
+
80
+ resolver = Celluloid::DNS::Resolver.new(SERVER_PORTS, :timeout => 0.5)
81
+
82
+ response = resolver.query("oriontransfer.org", IN::A)
83
+
84
+ expect(response.answer.length).to be 0
85
+
86
+ end_time = Time.now
87
+
88
+ expect(end_time - start_time).to be_within(0.1).of(0.0)
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright, 2014, 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 'celluloid/dns'
24
+ require 'celluloid/dns/system'
25
+
26
+ module Celluloid::DNS::SocketSpec
27
+ IN = Resolv::DNS::Resource::IN
28
+
29
+ class TestServer < Celluloid::DNS::Server
30
+ def process(name, resource_class, transaction)
31
+ @resolver ||= Celluloid::DNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
32
+
33
+ transaction.passthrough!(@resolver)
34
+ end
35
+ end
36
+
37
+ describe Celluloid::DNS::TCPSocketHandler do
38
+ after(:each) do
39
+ @server.terminate
40
+ end
41
+
42
+ it "should create server with existing TCP socket" do
43
+ socket = TCPServer.new('127.0.0.1', 2002)
44
+
45
+ @server = TestServer.new(listen: [socket])
46
+ @server.run
47
+
48
+ resolver = Celluloid::DNS::Resolver.new([[:tcp, '127.0.0.1', 2002]])
49
+ response = resolver.query('google.com')
50
+ expect(response.class).to be == Celluloid::DNS::Message
51
+ end
52
+ end
53
+
54
+ describe Celluloid::DNS::UDPSocketHandler do
55
+ after(:each) do
56
+ @server.terminate
57
+ end
58
+
59
+ it "should create server with existing UDP socket" do
60
+ socket = UDPSocket.new
61
+ socket.bind('127.0.0.1', 2002)
62
+
63
+ @server = TestServer.new(listen: [socket])
64
+ @server.run
65
+
66
+ resolver = Celluloid::DNS::Resolver.new([[:udp, '127.0.0.1', 2002]])
67
+ response = resolver.query('google.com')
68
+ expect(response.class).to be == Celluloid::DNS::Message
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,60 @@
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 'celluloid/dns'
24
+ require 'celluloid/dns/system'
25
+
26
+ module Celluloid::DNS::SystemSpec
27
+ describe Celluloid::DNS::System do
28
+ before(:all) do
29
+ Celluloid.shutdown
30
+ Celluloid.boot
31
+ end
32
+
33
+ it "should have at least one namesever" do
34
+ expect(Celluloid::DNS::System::nameservers.length).to be > 0
35
+ end
36
+
37
+ it "should respond to query for google.com" do
38
+ resolver = Celluloid::DNS::Resolver.new(Celluloid::DNS::System::nameservers)
39
+
40
+ response = resolver.query('google.com')
41
+
42
+ expect(response.class).to be == Celluloid::DNS::Message
43
+ expect(response.rcode).to be == Resolv::DNS::RCode::NoError
44
+ end
45
+ end
46
+
47
+ describe Celluloid::DNS::System::Hosts do
48
+ it "should parse the hosts file" do
49
+ hosts = Celluloid::DNS::System::Hosts.new
50
+
51
+ # Load the test hosts data:
52
+ File.open(File.expand_path("../hosts.txt", __FILE__)) do |file|
53
+ hosts.parse_hosts(file)
54
+ end
55
+
56
+ expect(hosts.call('testing')).to be == true
57
+ expect(hosts['testing']).to be == '1.2.3.4'
58
+ end
59
+ end
60
+ end