rubydns 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +60 -7
- data/lib/rubydns.rb +1 -3
- data/lib/rubydns/extensions/{resolv-1.8.rb → resolv.rb} +0 -25
- data/lib/rubydns/handler.rb +13 -4
- data/lib/rubydns/message.rb +2 -0
- data/lib/rubydns/server.rb +78 -56
- data/lib/rubydns/transaction.rb +33 -9
- data/lib/rubydns/version.rb +1 -1
- data/test/examples/GeoLiteCountry.dat +0 -0
- data/test/{daemon1.rb → examples/dropping-dns.rb} +10 -10
- data/test/{fortune-dns.rb → examples/fortune-dns.rb} +0 -2
- data/test/examples/geoip-dns.rb +86 -0
- data/test/examples/log/DroppingDaemon.log +107 -0
- data/test/examples/log/FortuneDNS.log +5 -0
- data/test/examples/log/GeoIPDNSDaemon.log +0 -0
- data/test/examples/log/TestDaemon.log +340 -0
- data/test/examples/run/DroppingDaemon.pid +1 -0
- data/test/examples/run/GeoIPDNSDaemon.pid +1 -0
- data/test/{soa_example1.rb → examples/soa-dns.rb} +5 -3
- data/test/{example1.rb → examples/test-dns-1.rb} +4 -3
- data/test/{daemon2.rb → examples/test-dns-2.rb} +4 -4
- data/test/log/BasicTestServer.log +64 -1453
- data/test/log/SlowServer.log +48 -0
- data/test/log/TestPassthroughServer.log +24 -790
- data/test/log/TruncatedServer.log +52 -959
- data/test/test_daemon.rb +5 -3
- data/test/test_passthrough.rb +4 -2
- data/test/test_rules.rb +53 -0
- data/test/test_slow_server.rb +77 -0
- data/test/test_truncation.rb +4 -2
- metadata +39 -31
- data/lib/rubydns/extensions/resolv-1.9.rb +0 -111
- data/test/TruncatedServer/log/daemon.log +0 -445
- data/test/log/FortuneDNS.log +0 -265
data/test/test_daemon.rb
CHANGED
@@ -9,11 +9,13 @@ require 'rexec'
|
|
9
9
|
require 'rexec/daemon'
|
10
10
|
|
11
11
|
class BasicTestServer < RExec::Daemon::Base
|
12
|
+
SERVER_PORTS = [[:udp, '127.0.0.1', 5350], [:tcp, '127.0.0.1', 5350]]
|
13
|
+
|
12
14
|
@@base_directory = File.dirname(__FILE__)
|
13
15
|
|
14
16
|
def self.run
|
15
17
|
# Start the RubyDNS server
|
16
|
-
RubyDNS::run_server(:listen =>
|
18
|
+
RubyDNS::run_server(:listen => SERVER_PORTS) do
|
17
19
|
match("test.local", IN::A) do |transaction|
|
18
20
|
transaction.respond!("192.168.1.1")
|
19
21
|
end
|
@@ -45,7 +47,7 @@ class DaemonTest < Test::Unit::TestCase
|
|
45
47
|
assert_equal :running, RExec::Daemon::ProcessFile.status(BasicTestServer)
|
46
48
|
|
47
49
|
EventMachine.run do
|
48
|
-
resolver = resolver = RubyDNS::Resolver.new(
|
50
|
+
resolver = resolver = RubyDNS::Resolver.new(BasicTestServer::SERVER_PORTS)
|
49
51
|
|
50
52
|
resolver.query("test.local") do |response|
|
51
53
|
answer = response.answer.first
|
@@ -62,7 +64,7 @@ class DaemonTest < Test::Unit::TestCase
|
|
62
64
|
assert_equal :running, RExec::Daemon::ProcessFile.status(BasicTestServer)
|
63
65
|
|
64
66
|
EventMachine.run do
|
65
|
-
resolver = resolver = RubyDNS::Resolver.new(
|
67
|
+
resolver = resolver = RubyDNS::Resolver.new(BasicTestServer::SERVER_PORTS)
|
66
68
|
|
67
69
|
resolver.query("foobar") do |response|
|
68
70
|
answer = response.answer.first
|
data/test/test_passthrough.rb
CHANGED
@@ -9,13 +9,15 @@ require 'rexec'
|
|
9
9
|
require 'rexec/daemon'
|
10
10
|
|
11
11
|
class TestPassthroughServer < RExec::Daemon::Base
|
12
|
+
SERVER_PORTS = [[:udp, '127.0.0.1', 5340], [:tcp, '127.0.0.1', 5340]]
|
13
|
+
|
12
14
|
@@base_directory = File.dirname(__FILE__)
|
13
15
|
|
14
16
|
def self.run
|
15
17
|
resolver = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
|
16
18
|
|
17
19
|
# Start the RubyDNS server
|
18
|
-
RubyDNS::run_server(:listen =>
|
20
|
+
RubyDNS::run_server(:listen => SERVER_PORTS) do
|
19
21
|
match(/.*\.com/, IN::A) do |match, transaction|
|
20
22
|
transaction.passthrough!(resolver)
|
21
23
|
end
|
@@ -43,7 +45,7 @@ class PassthroughTest < Test::Unit::TestCase
|
|
43
45
|
assert_equal :running, RExec::Daemon::ProcessFile.status(TestPassthroughServer)
|
44
46
|
|
45
47
|
EventMachine.run do
|
46
|
-
resolver = RubyDNS::Resolver.new(
|
48
|
+
resolver = RubyDNS::Resolver.new(TestPassthroughServer::SERVER_PORTS)
|
47
49
|
|
48
50
|
resolver.query("google.com") do |response|
|
49
51
|
answer = response.answer.first
|
data/test/test_rules.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
|
2
|
+
require 'helper'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
require 'rubydns'
|
6
|
+
require 'rubydns/resolver'
|
7
|
+
require 'rubydns/extensions/string'
|
8
|
+
|
9
|
+
class RulesTest < Test::Unit::TestCase
|
10
|
+
IN = Resolv::DNS::Resource::IN
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@server = RubyDNS::Server.new
|
14
|
+
@true_callback = Proc.new { true }
|
15
|
+
end
|
16
|
+
|
17
|
+
def teardown
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_string_pattern
|
21
|
+
rule = RubyDNS::Server::Rule.new(["foobar", IN::A], @true_callback)
|
22
|
+
|
23
|
+
assert rule.call(@server, "foobar", IN::A)
|
24
|
+
assert !rule.call(@server, "barfoo", IN::A)
|
25
|
+
assert !rule.call(@server, "foobar", IN::TXT)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_regexp_pattern
|
29
|
+
rule = RubyDNS::Server::Rule.new([/foo/, IN::A], @true_callback)
|
30
|
+
|
31
|
+
assert rule.call(@server, "foobar", IN::A)
|
32
|
+
assert !rule.call(@server, "barbaz", IN::A)
|
33
|
+
assert !rule.call(@server, "foobar", IN::TXT)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_callback_pattern
|
37
|
+
calls = 0
|
38
|
+
|
39
|
+
callback = Proc.new do |name, resource_class|
|
40
|
+
# A counter used to check the number of times this block was invoked.
|
41
|
+
calls += 1
|
42
|
+
|
43
|
+
name.size == 6
|
44
|
+
end
|
45
|
+
|
46
|
+
rule = RubyDNS::Server::Rule.new([callback], @true_callback)
|
47
|
+
|
48
|
+
assert rule.call(@server, "foobar", IN::A)
|
49
|
+
assert !rule.call(@server, "foobarbaz", IN::A)
|
50
|
+
|
51
|
+
assert_equal 2, calls
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
|
2
|
+
require 'helper'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
require 'rubydns'
|
6
|
+
require 'rubydns/resolver'
|
7
|
+
require 'rubydns/extensions/string'
|
8
|
+
|
9
|
+
class SlowServer < RExec::Daemon::Base
|
10
|
+
SERVER_PORTS = [[:udp, '127.0.0.1', 5330], [:tcp, '127.0.0.1', 5330]]
|
11
|
+
|
12
|
+
@@base_directory = File.dirname(__FILE__)
|
13
|
+
|
14
|
+
Name = Resolv::DNS::Name
|
15
|
+
IN = Resolv::DNS::Resource::IN
|
16
|
+
|
17
|
+
def self.run
|
18
|
+
RubyDNS::run_server(:listen => SERVER_PORTS) do
|
19
|
+
match(/\.*.com/, IN::A) do |match, transaction|
|
20
|
+
transaction.defer!
|
21
|
+
|
22
|
+
# No domain exists, after 5 seconds:
|
23
|
+
EventMachine::Timer.new(2) do
|
24
|
+
transaction.failure!(:NXDomain)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
otherwise do |transaction|
|
29
|
+
transaction.failure!(:NXDomain)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class SlowServerTest < Test::Unit::TestCase
|
36
|
+
def setup
|
37
|
+
SlowServer.start
|
38
|
+
end
|
39
|
+
|
40
|
+
def teardown
|
41
|
+
SlowServer.stop
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_slow_request
|
45
|
+
start_time = Time.now
|
46
|
+
end_time = nil
|
47
|
+
|
48
|
+
resolver = RubyDNS::Resolver.new(SlowServer::SERVER_PORTS, :timeout => 10)
|
49
|
+
|
50
|
+
EventMachine::run do
|
51
|
+
resolver.query("apple.com", IN::A) do |response|
|
52
|
+
end_time = Time.now
|
53
|
+
|
54
|
+
EventMachine::stop
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
assert (end_time - start_time) > 2.0
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_normal_request
|
62
|
+
start_time = Time.now
|
63
|
+
end_time = nil
|
64
|
+
|
65
|
+
resolver = RubyDNS::Resolver.new(SlowServer::SERVER_PORTS, :timeout => 10)
|
66
|
+
|
67
|
+
EventMachine::run do
|
68
|
+
resolver.query("oriontransfer.org", IN::A) do |response|
|
69
|
+
end_time = Time.now
|
70
|
+
|
71
|
+
EventMachine::stop
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
assert (end_time - start_time) < 2.0
|
76
|
+
end
|
77
|
+
end
|
data/test/test_truncation.rb
CHANGED
@@ -7,6 +7,8 @@ require 'rubydns/resolver'
|
|
7
7
|
require 'rubydns/extensions/string'
|
8
8
|
|
9
9
|
class TruncatedServer < RExec::Daemon::Base
|
10
|
+
SERVER_PORTS = [[:udp, '127.0.0.1', 5320], [:tcp, '127.0.0.1', 5320]]
|
11
|
+
|
10
12
|
@@base_directory = File.dirname(__FILE__)
|
11
13
|
|
12
14
|
Name = Resolv::DNS::Name
|
@@ -14,7 +16,7 @@ class TruncatedServer < RExec::Daemon::Base
|
|
14
16
|
|
15
17
|
def self.run
|
16
18
|
# Start the RubyDNS server
|
17
|
-
RubyDNS::run_server(:listen =>
|
19
|
+
RubyDNS::run_server(:listen => SERVER_PORTS) do
|
18
20
|
match("truncation", IN::TXT) do |transaction|
|
19
21
|
text = "Hello World! " * 100
|
20
22
|
transaction.respond!(*text.chunked)
|
@@ -38,7 +40,7 @@ class TruncationTest < Test::Unit::TestCase
|
|
38
40
|
end
|
39
41
|
|
40
42
|
def test_tcp_failover
|
41
|
-
resolver = RubyDNS::Resolver.new(
|
43
|
+
resolver = RubyDNS::Resolver.new(TruncatedServer::SERVER_PORTS)
|
42
44
|
|
43
45
|
EventMachine::run do
|
44
46
|
resolver.query("truncation", IN::TXT) do |response|
|
metadata
CHANGED
@@ -1,48 +1,48 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubydns
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.1
|
4
5
|
prerelease:
|
5
|
-
version: 0.5.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Samuel Williams
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-10-
|
12
|
+
date: 2012-10-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
|
16
|
-
|
15
|
+
name: rexec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: 1.5.1
|
22
|
-
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
25
|
none: false
|
24
26
|
requirements:
|
25
27
|
- - ~>
|
26
28
|
- !ruby/object:Gem::Version
|
27
29
|
version: 1.5.1
|
28
|
-
type: :runtime
|
29
|
-
name: rexec
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
|
-
|
32
|
-
|
31
|
+
name: eventmachine
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
33
|
none: false
|
34
34
|
requirements:
|
35
35
|
- - ~>
|
36
36
|
- !ruby/object:Gem::Version
|
37
37
|
version: 1.0.0
|
38
|
-
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
41
|
none: false
|
40
42
|
requirements:
|
41
43
|
- - ~>
|
42
44
|
- !ruby/object:Gem::Version
|
43
45
|
version: 1.0.0
|
44
|
-
type: :runtime
|
45
|
-
name: eventmachine
|
46
46
|
description:
|
47
47
|
email: samuel@oriontransfer.org
|
48
48
|
executables:
|
@@ -53,8 +53,13 @@ extra_rdoc_files: []
|
|
53
53
|
files:
|
54
54
|
- bin/rd-dns-check
|
55
55
|
- bin/rd-resolve-test
|
56
|
-
- lib/rubydns.rb
|
57
56
|
- lib/rubydns/chunked.rb
|
57
|
+
- lib/rubydns/extensions/hexdump.rb
|
58
|
+
- lib/rubydns/extensions/resolv.rb
|
59
|
+
- lib/rubydns/extensions/string-1.8.rb
|
60
|
+
- lib/rubydns/extensions/string-1.9.2.rb
|
61
|
+
- lib/rubydns/extensions/string-1.9.3.rb
|
62
|
+
- lib/rubydns/extensions/string.rb
|
58
63
|
- lib/rubydns/handler.rb
|
59
64
|
- lib/rubydns/message.rb
|
60
65
|
- lib/rubydns/resolver.rb
|
@@ -62,31 +67,34 @@ files:
|
|
62
67
|
- lib/rubydns/system.rb
|
63
68
|
- lib/rubydns/transaction.rb
|
64
69
|
- lib/rubydns/version.rb
|
65
|
-
- lib/rubydns
|
66
|
-
-
|
67
|
-
-
|
68
|
-
-
|
69
|
-
-
|
70
|
-
-
|
71
|
-
-
|
72
|
-
- test/
|
73
|
-
- test/
|
74
|
-
- test/
|
75
|
-
- test/
|
70
|
+
- lib/rubydns.rb
|
71
|
+
- test/examples/GeoLiteCountry.dat
|
72
|
+
- test/examples/dropping-dns.rb
|
73
|
+
- test/examples/fortune-dns.rb
|
74
|
+
- test/examples/geoip-dns.rb
|
75
|
+
- test/examples/log/DroppingDaemon.log
|
76
|
+
- test/examples/log/FortuneDNS.log
|
77
|
+
- test/examples/log/GeoIPDNSDaemon.log
|
78
|
+
- test/examples/log/TestDaemon.log
|
79
|
+
- test/examples/run/DroppingDaemon.pid
|
80
|
+
- test/examples/run/GeoIPDNSDaemon.pid
|
81
|
+
- test/examples/soa-dns.rb
|
82
|
+
- test/examples/test-dns-1.rb
|
83
|
+
- test/examples/test-dns-2.rb
|
76
84
|
- test/helper.rb
|
77
85
|
- test/hosts.txt
|
78
|
-
- test/
|
86
|
+
- test/log/BasicTestServer.log
|
87
|
+
- test/log/SlowServer.log
|
88
|
+
- test/log/TestPassthroughServer.log
|
89
|
+
- test/log/TruncatedServer.log
|
79
90
|
- test/test_daemon.rb
|
80
91
|
- test/test_domains.txt
|
81
92
|
- test/test_passthrough.rb
|
82
93
|
- test/test_resolver.rb
|
94
|
+
- test/test_rules.rb
|
95
|
+
- test/test_slow_server.rb
|
83
96
|
- test/test_system.rb
|
84
97
|
- test/test_truncation.rb
|
85
|
-
- test/log/BasicTestServer.log
|
86
|
-
- test/log/FortuneDNS.log
|
87
|
-
- test/log/TestPassthroughServer.log
|
88
|
-
- test/log/TruncatedServer.log
|
89
|
-
- test/TruncatedServer/log/daemon.log
|
90
98
|
- rakefile.rb
|
91
99
|
- Gemfile
|
92
100
|
- README.md
|
@@ -101,10 +109,10 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
101
109
|
requirements:
|
102
110
|
- - ! '>='
|
103
111
|
- !ruby/object:Gem::Version
|
104
|
-
hash: 2002549777813010636
|
105
112
|
version: '0'
|
106
113
|
segments:
|
107
114
|
- 0
|
115
|
+
hash: 1826136753171810618
|
108
116
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
117
|
none: false
|
110
118
|
requirements:
|
@@ -1,111 +0,0 @@
|
|
1
|
-
# Copyright (c) 2009, 2011 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
|
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 'resolv'
|
22
|
-
|
23
|
-
class Resolv
|
24
|
-
class DNS
|
25
|
-
# This issue was not fixed in 1.9.3 but the proposed patch works as expected:
|
26
|
-
# https://bugs.ruby-lang.org/issues/4788
|
27
|
-
def fetch_resource(name, typeclass)
|
28
|
-
lazy_initialize
|
29
|
-
requester = make_udp_requester
|
30
|
-
senders = {}
|
31
|
-
begin
|
32
|
-
@config.resolv(name) {|candidate, tout, nameserver, port|
|
33
|
-
msg = Message.new
|
34
|
-
msg.rd = 1
|
35
|
-
msg.add_question(candidate, typeclass)
|
36
|
-
unless sender = senders[[candidate, nameserver, port]]
|
37
|
-
sender = senders[[candidate, nameserver, port]] =
|
38
|
-
requester.sender(msg, candidate, nameserver, port)
|
39
|
-
end
|
40
|
-
reply, reply_name = requester.request(sender, tout)
|
41
|
-
case reply.rcode
|
42
|
-
when RCode::NoError
|
43
|
-
if reply.tc == 1 and not Requester::TCP === requester
|
44
|
-
requester.close
|
45
|
-
# Retry via TCP:
|
46
|
-
requester = make_tcp_requester(nameserver, port)
|
47
|
-
senders = {}
|
48
|
-
# This will use TCP for all remaining candidates (assuming the
|
49
|
-
# current candidate does not already respond successfully via
|
50
|
-
# TCP). This makes sense because we already know the full
|
51
|
-
# response will not fit in an untruncated UDP packet.
|
52
|
-
redo
|
53
|
-
else
|
54
|
-
yield(reply, reply_name)
|
55
|
-
end
|
56
|
-
return
|
57
|
-
when RCode::NXDomain
|
58
|
-
raise Config::NXDomain.new(reply_name.to_s)
|
59
|
-
else
|
60
|
-
raise Config::OtherResolvError.new(reply_name.to_s)
|
61
|
-
end
|
62
|
-
}
|
63
|
-
ensure
|
64
|
-
requester.close
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def each_resource(name, typeclass, &proc)
|
69
|
-
fetch_resource(name, typeclass) do |reply, reply_name|
|
70
|
-
extract_resources(reply, reply_name, typeclass, &proc)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
# Queries the given DNS server and returns its response in its entirety.
|
75
|
-
# This allows such responses to be passed upstream with little or no
|
76
|
-
# modification/reinterpretation.
|
77
|
-
def query(name, typeclass)
|
78
|
-
fetch_resource(name, typeclass) do |reply, reply_name|
|
79
|
-
return reply, reply_name
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
class Message
|
84
|
-
# Merge the given message with this message. A number of heuristics are
|
85
|
-
# applied in order to ensure that the result makes sense. For example,
|
86
|
-
# If the current message is not recursive but is being merged with a
|
87
|
-
# message that was recursive, this bit is maintained. If either message
|
88
|
-
# is authoritive, then the result is also authoritive.
|
89
|
-
#
|
90
|
-
# Modifies the current message in place.
|
91
|
-
def merge! (other)
|
92
|
-
# Authoritive Answer
|
93
|
-
@aa = @aa && other.aa
|
94
|
-
|
95
|
-
@question += other.question
|
96
|
-
@answer += other.answer
|
97
|
-
@authority += other.authority
|
98
|
-
@additional += other.additional
|
99
|
-
|
100
|
-
# Recursion Available
|
101
|
-
@ra = @ra || other.ra
|
102
|
-
|
103
|
-
# Result Code (Error Code)
|
104
|
-
@rcode = other.rcode unless other.rcode == 0
|
105
|
-
|
106
|
-
# Recursion Desired
|
107
|
-
@rd = @rd || other.rd
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|