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 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: []