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 CHANGED
@@ -1 +1 @@
1
- 0.1.14
1
+ 0.1.15
@@ -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
- def post_init
36
- # Sequence numbers do not have to be cryptographically secure, but having
37
- # a healthy amount of randomness is a good thing.
38
- @sequence = (rand(SEQUENCE_LIMIT) ^ (object_id ^ (Time.now.to_f * SEQUENCE_LIMIT).to_i)) % SEQUENCE_LIMIT
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
- def receive_data(data)
74
- message = ReDNS::Message.new(ReDNS::Buffer.new(data))
75
-
76
- if (callback = @callback.delete(message.id))
77
- answers = message.answers
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
- message.serialize.to_s,
98
- random_nameserver,
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
- :callback => callback,
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
- if (params and params[:at] < timeout_at)
126
- params[:callback].call(nil)
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.14"
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 = ["tadman"]
12
- s.date = %q{2011-08-02}
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 = ["lib"]
54
- s.rubygems_version = %q{1.5.3}
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.32.10') do |result|
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[ www.example.com. ], reverse.collect { |a| a.rdata.to_s }
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
- description: ReDNS is a pure Ruby DNS library with drivers for reactor-model engines such as EventMachine
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: "0"
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: "0"
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
79
72
  requirements: []
80
-
81
73
  rubyforge_project:
82
- rubygems_version: 1.5.3
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: []