redns 0.1.14 → 0.1.15
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.
- 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: []
|