redns 0.1.14 → 0.1.15
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/redns/connection.rb +98 -46
- data/redns.gemspec +5 -19
- data/test/test_redns_connection.rb +23 -3
- metadata +22 -42
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.15
|
data/lib/redns/connection.rb
CHANGED
@@ -4,11 +4,12 @@ class ReDNS::Connection < EventMachine::Connection
|
|
4
4
|
# == Constants ============================================================
|
5
5
|
|
6
6
|
DEFAULT_TIMEOUT = 5
|
7
|
+
DEFAULT_ATTEMPTS = 2
|
7
8
|
SEQUENCE_LIMIT = 0x10000
|
8
9
|
|
9
10
|
# == Properties ===========================================================
|
10
11
|
|
11
|
-
attr_accessor :timeout
|
12
|
+
attr_accessor :timeout, :attempts
|
12
13
|
|
13
14
|
# == Extensions ===========================================================
|
14
15
|
|
@@ -32,19 +33,20 @@ class ReDNS::Connection < EventMachine::Connection
|
|
32
33
|
|
33
34
|
# == Instance Methods =====================================================
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
@
|
39
|
-
|
40
|
-
# Callback tracking is done by matching response IDs in a lookup table
|
41
|
-
@callback = { }
|
42
|
-
|
43
|
-
EventMachine.add_periodic_timer(1) do
|
44
|
-
check_for_timeouts!
|
45
|
-
end
|
36
|
+
# Sets the current timeout parameter to the supplied value (in seconds).
|
37
|
+
# If the supplied value is zero or nil, will revert to the default.
|
38
|
+
def timeout=(value)
|
39
|
+
@timeout = value.to_i
|
40
|
+
@timeout = DEFAULT_TIMEOUT if (@timeout == 0)
|
46
41
|
end
|
47
|
-
|
42
|
+
|
43
|
+
# Sets the current retry attempts parameter to the supplied value.
|
44
|
+
# If the supplied value is zero or nil, will revert to the default.
|
45
|
+
def attempts=(value)
|
46
|
+
@attempts = value.to_i
|
47
|
+
@attempts = DEFAULT_ATTEMPTS if (@attempts == 0)
|
48
|
+
end
|
49
|
+
|
48
50
|
# Returns the configured list of nameservers as an Array. If not configured
|
49
51
|
# specifically, will look in the resolver configuration file, typically
|
50
52
|
# /etc/resolv.conf for which servers to use.
|
@@ -70,39 +72,33 @@ class ReDNS::Connection < EventMachine::Connection
|
|
70
72
|
Socket.unpack_sockaddr_in(get_sockname)[0]
|
71
73
|
end
|
72
74
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
# If the request was made for a specific type of record...
|
80
|
-
if (type = callback[:type])
|
81
|
-
if (type != :any)
|
82
|
-
# ...only include that type of answer in the result set.
|
83
|
-
answers = answers.select { |a| a.rtype == type }
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
callback[:callback].call(answers)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
def resolve(query, type = nil, &callback)
|
75
|
+
# Resolves a given query and optional type asynchronously, yielding to the
|
76
|
+
# callback function with either the answers or nil if a timeout or error
|
77
|
+
# occurred. The filter option will restrict responses ot those matching
|
78
|
+
# the requested type if true, or return all responses if false. The default
|
79
|
+
# is to filter responses.
|
80
|
+
def resolve(query, type = nil, filter = true, &callback)
|
92
81
|
message = ReDNS::Message.question(query, type) do |m|
|
93
82
|
m.id = @sequence
|
94
83
|
end
|
84
|
+
|
85
|
+
serialized_message = message.serialize.to_s
|
86
|
+
target_nameserver = random_nameserver
|
95
87
|
|
96
88
|
result = send_datagram(
|
97
|
-
|
98
|
-
|
89
|
+
serialized_message,
|
90
|
+
target_nameserver,
|
99
91
|
ReDNS::Support.dns_port
|
100
92
|
)
|
101
93
|
|
102
94
|
if (result > 0)
|
103
95
|
@callback[@sequence] = {
|
104
|
-
:
|
96
|
+
:serialized_message => serialized_message,
|
105
97
|
:type => type,
|
98
|
+
:filter_by_type => (type == :any || !filter) ? false : type,
|
99
|
+
:nameserver => target_nameserver,
|
100
|
+
:attempts => self.attempts - 1,
|
101
|
+
:callback => callback,
|
106
102
|
:at => Time.now
|
107
103
|
}
|
108
104
|
else
|
@@ -112,25 +108,81 @@ class ReDNS::Connection < EventMachine::Connection
|
|
112
108
|
@sequence += 1
|
113
109
|
@sequence %= SEQUENCE_LIMIT
|
114
110
|
end
|
111
|
+
|
112
|
+
# EventMachine: Called after the connection is initialized.
|
113
|
+
def post_init
|
114
|
+
# Sequence numbers do not have to be cryptographically secure, but having
|
115
|
+
# a healthy amount of randomness is a good thing.
|
116
|
+
@sequence = (rand(SEQUENCE_LIMIT) ^ (object_id ^ (Time.now.to_f * SEQUENCE_LIMIT).to_i)) % SEQUENCE_LIMIT
|
117
|
+
|
118
|
+
# Callback tracking is done by matching response IDs in a lookup table
|
119
|
+
@callback = { }
|
120
|
+
|
121
|
+
@timeout ||= DEFAULT_TIMEOUT
|
122
|
+
@attempts ||= DEFAULT_ATTEMPTS
|
123
|
+
|
124
|
+
EventMachine.add_periodic_timer(1) do
|
125
|
+
check_for_timeouts!
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# EventMachine: Called when data is received on the active socket.
|
130
|
+
def receive_data(data)
|
131
|
+
message = ReDNS::Message.new(ReDNS::Buffer.new(data))
|
132
|
+
|
133
|
+
if (callback = @callback.delete(message.id))
|
134
|
+
answers = message.answers
|
135
|
+
|
136
|
+
if (type = callback[:filter_by_type])
|
137
|
+
answers = answers.select { |a| a.rtype == type }
|
138
|
+
end
|
139
|
+
|
140
|
+
callback[:callback].call(answers)
|
141
|
+
end
|
142
|
+
end
|
115
143
|
|
144
|
+
# EventMachine: Called when the connection is closed.
|
116
145
|
def unbind
|
117
146
|
end
|
118
|
-
|
147
|
+
|
148
|
+
protected
|
149
|
+
# Returns the next nameserver in the list for a given entry, wrapping around
|
150
|
+
# to the beginning if required.
|
151
|
+
def nameserver_after(nameserver)
|
152
|
+
self.nameservers[(self.nameservers.index(nameserver).to_i + 1) % self.nameservers.length]
|
153
|
+
end
|
154
|
+
|
155
|
+
# Checks all pending queries for timeouts and triggers callbacks or retries
|
156
|
+
# if necessary.
|
119
157
|
def check_for_timeouts!
|
120
158
|
timeout_at = Time.now - (@timeout || DEFAULT_TIMEOUT)
|
121
|
-
|
159
|
+
|
122
160
|
@callback.keys.each do |k|
|
123
|
-
params = @callback[k]
|
124
|
-
|
125
|
-
|
126
|
-
|
161
|
+
if (params = @callback[k])
|
162
|
+
if (params[:at] < timeout_at)
|
163
|
+
if (params[:attempts] > 0)
|
164
|
+
# If this request can be retried, find a different nameserver.
|
165
|
+
target_nameserver = nameserver_after(params[:target_nameserver])
|
166
|
+
|
167
|
+
# Send exactly the same request to it so that the request ID will
|
168
|
+
# match to the same callback.
|
169
|
+
send_datagram(
|
170
|
+
params[:serialized_message],
|
171
|
+
target_nameserver,
|
172
|
+
ReDNS::Support.dns_port
|
173
|
+
)
|
174
|
+
|
175
|
+
params[:target_nameserver] = target_nameserver
|
176
|
+
params[:attempts] -= 1
|
177
|
+
else
|
178
|
+
params[:callback].call(nil)
|
179
|
+
@callback.delete(k)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
else
|
183
|
+
# Was missing params so should be deleted if not already removed.
|
127
184
|
@callback.delete(k)
|
128
185
|
end
|
129
186
|
end
|
130
187
|
end
|
131
|
-
|
132
|
-
def timeout=(value)
|
133
|
-
@timeout = value.to_i
|
134
|
-
@timeout = DEFAULT_TIMEOUT if (@timeout == 0)
|
135
|
-
end
|
136
188
|
end
|
data/redns.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{redns}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.15"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors = [
|
12
|
-
s.date = %q{2011-08-
|
11
|
+
s.authors = [%q{tadman}]
|
12
|
+
s.date = %q{2011-08-10}
|
13
13
|
s.description = %q{ReDNS is a pure Ruby DNS library with drivers for reactor-model engines such as EventMachine}
|
14
14
|
s.email = %q{github@tadman.ca}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -50,23 +50,9 @@ Gem::Specification.new do |s|
|
|
50
50
|
"test/test_redns_support.rb"
|
51
51
|
]
|
52
52
|
s.homepage = %q{http://github.com/tadman/redns}
|
53
|
-
s.require_paths = [
|
54
|
-
s.rubygems_version = %q{1.
|
53
|
+
s.require_paths = [%q{lib}]
|
54
|
+
s.rubygems_version = %q{1.8.7}
|
55
55
|
s.summary = %q{Ruby Reactor-Ready DNS Library}
|
56
|
-
s.test_files = [
|
57
|
-
"test/helper.rb",
|
58
|
-
"test/test_redns.rb",
|
59
|
-
"test/test_redns_address.rb",
|
60
|
-
"test/test_redns_buffer.rb",
|
61
|
-
"test/test_redns_connection.rb",
|
62
|
-
"test/test_redns_fragment.rb",
|
63
|
-
"test/test_redns_message.rb",
|
64
|
-
"test/test_redns_name.rb",
|
65
|
-
"test/test_redns_question.rb",
|
66
|
-
"test/test_redns_resolver.rb",
|
67
|
-
"test/test_redns_resource.rb",
|
68
|
-
"test/test_redns_support.rb"
|
69
|
-
]
|
70
56
|
|
71
57
|
if s.respond_to? :specification_version then
|
72
58
|
s.specification_version = 3
|
@@ -33,7 +33,7 @@ class TestReDNSConnection < Test::Unit::TestCase
|
|
33
33
|
end
|
34
34
|
|
35
35
|
# Simple reverse lookup, one PTR record
|
36
|
-
dns.resolve('192.0.
|
36
|
+
dns.resolve('192.0.43.10') do |result|
|
37
37
|
reverse = result
|
38
38
|
|
39
39
|
EventMachine.stop_event_loop if (address and reverse and nameservers and cname)
|
@@ -59,10 +59,9 @@ class TestReDNSConnection < Test::Unit::TestCase
|
|
59
59
|
end
|
60
60
|
|
61
61
|
assert_equal %w[ 192.0.43.10 ], address.collect { |a| a.rdata.to_s }
|
62
|
-
assert_equal %w[
|
62
|
+
assert_equal %w[ 43-10.any.icann.org. ], reverse.collect { |a| a.rdata.to_s }
|
63
63
|
assert_equal %w[ a.iana-servers.net. b.iana-servers.net. ], nameservers.collect { |a| a.rdata.to_s }.sort
|
64
64
|
assert_equal %w[ 74.207.228.18 ], cname.collect { |a| a.rdata.to_s }
|
65
|
-
|
66
65
|
end
|
67
66
|
|
68
67
|
def test_simple_timeout
|
@@ -95,4 +94,25 @@ class TestReDNSConnection < Test::Unit::TestCase
|
|
95
94
|
EventMachine.stop_event_loop
|
96
95
|
end
|
97
96
|
end
|
97
|
+
|
98
|
+
def test_simple_attempts
|
99
|
+
address = :fail
|
100
|
+
|
101
|
+
EventMachine.run do
|
102
|
+
dns = ReDNS::Connection.instance do |c|
|
103
|
+
c.nameservers += %w[ 127.0.0.2 127.0.0.3 127.0.0.4 127.0.0.5 127.0.0.6 127.0.0.7 127.0.0.8 127.0.0.9 ]
|
104
|
+
c.timeout = 1
|
105
|
+
c.attempts = 10
|
106
|
+
end
|
107
|
+
|
108
|
+
dns.resolve('example.com') do |result|
|
109
|
+
address = result
|
110
|
+
|
111
|
+
EventMachine.stop_event_loop
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
assert address
|
116
|
+
assert_equal '192.0.43.10', address.first.rdata.to_s
|
117
|
+
end
|
98
118
|
end
|
metadata
CHANGED
@@ -1,28 +1,24 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: redns
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.15
|
4
5
|
prerelease:
|
5
|
-
version: 0.1.14
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- tadman
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
date: 2011-08-02 00:00:00 -04:00
|
14
|
-
default_executable:
|
12
|
+
date: 2011-08-10 00:00:00.000000000Z
|
15
13
|
dependencies: []
|
16
|
-
|
17
|
-
|
14
|
+
description: ReDNS is a pure Ruby DNS library with drivers for reactor-model engines
|
15
|
+
such as EventMachine
|
18
16
|
email: github@tadman.ca
|
19
17
|
executables: []
|
20
|
-
|
21
18
|
extensions: []
|
22
|
-
|
23
|
-
extra_rdoc_files:
|
19
|
+
extra_rdoc_files:
|
24
20
|
- README.rdoc
|
25
|
-
files:
|
21
|
+
files:
|
26
22
|
- .document
|
27
23
|
- README.rdoc
|
28
24
|
- Rakefile
|
@@ -55,44 +51,28 @@ files:
|
|
55
51
|
- test/test_redns_resolver.rb
|
56
52
|
- test/test_redns_resource.rb
|
57
53
|
- test/test_redns_support.rb
|
58
|
-
has_rdoc: true
|
59
54
|
homepage: http://github.com/tadman/redns
|
60
55
|
licenses: []
|
61
|
-
|
62
56
|
post_install_message:
|
63
57
|
rdoc_options: []
|
64
|
-
|
65
|
-
require_paths:
|
58
|
+
require_paths:
|
66
59
|
- lib
|
67
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
61
|
none: false
|
69
|
-
requirements:
|
70
|
-
- -
|
71
|
-
- !ruby/object:Gem::Version
|
72
|
-
version:
|
73
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
67
|
none: false
|
75
|
-
requirements:
|
76
|
-
- -
|
77
|
-
- !ruby/object:Gem::Version
|
78
|
-
version:
|
68
|
+
requirements:
|
69
|
+
- - ! '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
79
72
|
requirements: []
|
80
|
-
|
81
73
|
rubyforge_project:
|
82
|
-
rubygems_version: 1.
|
74
|
+
rubygems_version: 1.8.7
|
83
75
|
signing_key:
|
84
76
|
specification_version: 3
|
85
77
|
summary: Ruby Reactor-Ready DNS Library
|
86
|
-
test_files:
|
87
|
-
- test/helper.rb
|
88
|
-
- test/test_redns.rb
|
89
|
-
- test/test_redns_address.rb
|
90
|
-
- test/test_redns_buffer.rb
|
91
|
-
- test/test_redns_connection.rb
|
92
|
-
- test/test_redns_fragment.rb
|
93
|
-
- test/test_redns_message.rb
|
94
|
-
- test/test_redns_name.rb
|
95
|
-
- test/test_redns_question.rb
|
96
|
-
- test/test_redns_resolver.rb
|
97
|
-
- test/test_redns_resource.rb
|
98
|
-
- test/test_redns_support.rb
|
78
|
+
test_files: []
|