net-dns 0.5.3 → 0.6.0

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.
Files changed (53) hide show
  1. data/.gitignore +6 -0
  2. data/AUTHORS.rdoc +7 -0
  3. data/CHANGELOG.rdoc +34 -0
  4. data/README.rdoc +26 -14
  5. data/Rakefile +23 -30
  6. data/{THANKS → THANKS.rdoc} +0 -0
  7. data/VERSION.yml +3 -2
  8. data/demo/check_soa.rb +6 -11
  9. data/lib/net/{dns/dns.rb → dns.rb} +5 -12
  10. data/lib/net/dns/core_ext.rb +52 -0
  11. data/lib/net/dns/header.rb +55 -49
  12. data/lib/net/dns/names/names.rb +20 -10
  13. data/lib/net/dns/packet.rb +33 -26
  14. data/lib/net/dns/question.rb +60 -27
  15. data/lib/net/dns/resolver.rb +101 -156
  16. data/lib/net/dns/resolver/timeouts.rb +71 -65
  17. data/lib/net/dns/rr.rb +131 -166
  18. data/lib/net/dns/rr/a.rb +20 -26
  19. data/lib/net/dns/rr/aaaa.rb +15 -20
  20. data/lib/net/dns/rr/classes.rb +1 -1
  21. data/lib/net/dns/rr/cname.rb +8 -14
  22. data/lib/net/dns/rr/hinfo.rb +8 -14
  23. data/lib/net/dns/rr/mr.rb +8 -14
  24. data/lib/net/dns/rr/mx.rb +11 -18
  25. data/lib/net/dns/rr/ns.rb +8 -14
  26. data/lib/net/dns/rr/null.rb +7 -14
  27. data/lib/net/dns/rr/ptr.rb +9 -15
  28. data/lib/net/dns/rr/soa.rb +9 -15
  29. data/lib/net/dns/rr/srv.rb +10 -19
  30. data/lib/net/dns/rr/txt.rb +9 -20
  31. data/lib/net/dns/rr/types.rb +51 -58
  32. data/lib/net/dns/version.rb +22 -0
  33. data/test/{net/dns/test_header.rb → header_test.rb} +20 -20
  34. data/test/{net/dns/test_packet.rb → packet_test.rb} +2 -2
  35. data/test/question_test.rb +84 -0
  36. data/test/resolver/timeouts_test.rb +109 -0
  37. data/test/{net/dns/test_resolver.rb → resolver_test.rb} +6 -6
  38. data/test/rr/a_test.rb +66 -0
  39. data/test/{net/dns/rr/test_classes.rb → rr/classes_test.rb} +5 -5
  40. data/test/rr/ns_test.rb +64 -0
  41. data/test/rr/types_test.rb +69 -0
  42. data/test/{net/dns/test_rr.rb → rr_test.rb} +10 -12
  43. data/test/test_helper.rb +4 -0
  44. metadata +50 -35
  45. data/AUTHORS +0 -10
  46. data/CHANGELOG +0 -7
  47. data/INSTALL +0 -8
  48. data/net-dns.gemspec +0 -92
  49. data/test/net/dns/resolver/test_timeouts.rb +0 -59
  50. data/test/net/dns/rr/test_a.rb +0 -72
  51. data/test/net/dns/rr/test_ns.rb +0 -66
  52. data/test/net/dns/rr/test_types.rb +0 -124
  53. data/test/net/dns/test_question.rb +0 -54
@@ -1,73 +1,79 @@
1
1
  require 'timeout'
2
2
 
3
- module SecondsHandle #:nodoc: all
4
- def transform(secs)
5
- case secs
6
- when 0
7
- to_s
8
- when 1..59
9
- "#{secs} seconds"
10
- when 60..3559
11
- "#{secs/60} minutes and #{secs%60} seconds"
12
- else
13
- hours = secs/3600
14
- secs -= (hours*3600)
15
- "#{hours} hours, #{secs/60} minutes and #{secs%60} seconds"
16
- end
17
- end
18
- end
3
+ module Net # :nodoc:
4
+ module DNS
5
+ class Resolver
19
6
 
20
- class DnsTimeout # :nodoc: all
7
+ class DnsTimeout
8
+
9
+ attr_reader :seconds
10
+
11
+
12
+ def initialize(seconds)
13
+ if seconds.is_a? Numeric and seconds >= 0
14
+ @seconds = seconds
15
+ else
16
+ raise ::ArgumentError, "Invalid value for tcp timeout"
17
+ end
18
+ end
19
+
20
+ # Returns a string representation of the timeout corresponding
21
+ # to the number of <tt>@seconds</tt>.
22
+ def to_s
23
+ if @seconds == 0
24
+ @output.to_s
25
+ else
26
+ @seconds.to_s
27
+ end
28
+ end
29
+
30
+ def pretty_to_s
31
+ transform(@seconds)
32
+ end
33
+
34
+ # Executes the method's block. If the block execution terminates before +sec+
35
+ # seconds has passed, it returns true. If not, it terminates the execution
36
+ # and raises Timeout::Error.
37
+ # If @seconds is 0 or nil, no timeout is set.
38
+ def timeout(&block)
39
+ raise LocalJumpError, "no block given" unless block_given?
40
+ Timeout.timeout(@seconds, &block)
41
+ end
42
+
43
+
44
+ private
45
+
46
+ def transform(secs)
47
+ case secs
48
+ when 0
49
+ to_s
50
+ when 1..59
51
+ "#{secs} seconds"
52
+ when 60..3559
53
+ "#{secs / 60} minutes and #{secs % 60} seconds"
54
+ else
55
+ hours = secs / 3600
56
+ secs -= (hours * 3600)
57
+ "#{hours} hours, #{secs / 60} minutes and #{secs % 60} seconds"
58
+ end
59
+ end
21
60
 
22
- include SecondsHandle
23
-
24
- def initialize(seconds)
25
- if seconds.is_a? Numeric and seconds >= 0
26
- @timeout = seconds
27
- else
28
- raise DnsTimeoutArgumentError, "Invalid value for tcp timeout"
29
- end
30
- end
31
-
32
- def to_s
33
- if @timeout == 0
34
- @output
35
- else
36
- @timeout.to_s
37
- end
38
- end
39
-
40
- def pretty_to_s
41
- transform(@timeout)
42
- end
43
-
44
- def timeout
45
- unless block_given?
46
- raise DnsTimeoutArgumentError, "Block required but missing"
47
- end
48
- if @timeout == 0
49
- yield
50
- else
51
- return Timeout.timeout(@timeout) do
52
- yield
53
61
  end
54
- end
55
- end
56
- end
57
62
 
58
- class TcpTimeout < DnsTimeout # :nodoc: all
59
- def initialize(seconds)
60
- @output = "infinite"
61
- super(seconds)
62
- end
63
- end
63
+ class TcpTimeout < DnsTimeout
64
+ def initialize(seconds)
65
+ @output = "infinite"
66
+ super
67
+ end
68
+ end
64
69
 
65
- class UdpTimeout < DnsTimeout # :nodoc: all
66
- def initialize(seconds)
67
- @output = "not defined"
68
- super(seconds)
69
- end
70
- end
70
+ class UdpTimeout < DnsTimeout
71
+ def initialize(seconds)
72
+ @output = "not defined"
73
+ super
74
+ end
75
+ end
71
76
 
72
- class DnsTimeoutArgumentError < ArgumentError # :nodoc: all
73
- end
77
+ end
78
+ end
79
+ end
@@ -1,7 +1,3 @@
1
- #
2
- # $Id: RR.rb,v 1.19 2006/07/28 07:33:36 bluemonk Exp $
3
- #
4
-
5
1
  require 'net/dns/names/names'
6
2
  require 'net/dns/rr/types'
7
3
  require 'net/dns/rr/classes'
@@ -14,16 +10,9 @@ end
14
10
  module Net # :nodoc:
15
11
  module DNS
16
12
 
17
- # =Name
18
- #
19
- # Net::DNS::RR - DNS Resource Record class
20
13
  #
21
- # =Synopsis
22
- #
23
- # require 'net/dns/rr'
14
+ # = Net::DNS::RR - DNS Resource Record class
24
15
  #
25
- # =Description
26
- #
27
16
  # The Net::DNS::RR is the base class for DNS Resource
28
17
  # Record (RR) objects. A RR is a pack of data that represents
29
18
  # resources for a DNS zone. The form in which this data is
@@ -50,30 +39,36 @@ module Net # :nodoc:
50
39
  # such the ones above, or specifying each field as the pair
51
40
  # of an hash. See the Net::DNS::RR.new method for details.
52
41
  #
53
- # =Error classes
42
+ # == Error classes
54
43
  #
55
44
  # Some error classes has been defined for the Net::DNS::RR class,
56
45
  # which are listed here to keep a light and browsable main documentation.
57
46
  # We have:
58
47
  #
59
- # * RRArgumentError: Generic argument error for class Net::DNS::RR
60
- # * RRDataError: Error in parsing binary data, maybe from a malformed packet
61
- #
62
- # =Copyright
63
- #
64
- # Copyright (c) 2006 Marco Ceresa
65
- #
66
- # All rights reserved. This program is free software; you may redistribute
67
- # it and/or modify it under the same terms as Ruby itself.
48
+ # ArgumentError:: Generic argument error for class Net::DNS::RR
49
+ # DataError:: Error in parsing binary data, maybe from a malformed packet.
68
50
  #
69
51
  class RR
70
52
  include Net::DNS::Names
71
53
 
54
+ # Argument Error for class Net::DNS::RR.
55
+ class ArgumentError < ArgumentError
56
+ end
57
+
58
+ # Base error class.
59
+ class Error < StandardError
60
+ end
61
+
62
+ # Error in parsing binary data, maybe from a malformed packet.
63
+ class DataError < Error
64
+ end
65
+
66
+
72
67
  # Regexp matching an RR string
73
68
  RR_REGEXP = Regexp.new("^\\s*(\\S+)\\s*(\\d+)?\\s+(" +
74
69
  Net::DNS::RR::Classes.regexp +
75
70
  "|CLASS\\d+)?\\s*(" +
76
- Net::DNS::RR::Types.regexp +
71
+ Net::DNS::RR::Types.regexp +
77
72
  "|TYPE\\d+)?\\s*(.*)$", Regexp::IGNORECASE)
78
73
 
79
74
  # Dimension of the sum of class, type, TTL and rdlength fields in a
@@ -131,13 +126,13 @@ module Net # :nodoc:
131
126
  # for the resource in each subclass.
132
127
  #
133
128
  def initialize(arg)
134
- case arg
135
- when String
136
- instance = new_from_string(arg)
137
- when Hash
138
- instance = new_from_hash(arg)
139
- else
140
- raise RRArgumentError, "Invalid argument, must be a RR string or an hash of values"
129
+ instance = case arg
130
+ when String
131
+ new_from_string(arg)
132
+ when Hash
133
+ new_from_hash(arg)
134
+ else
135
+ raise ArgumentError, "Invalid argument, must be a RR string or an hash of values"
141
136
  end
142
137
 
143
138
  if @type.to_s == "ANY"
@@ -205,17 +200,16 @@ module Net # :nodoc:
205
200
  return str + [type,cls,@ttl,@rdlength].pack("n2 N n") + get_data
206
201
  end
207
202
 
208
- # Canonical inspect method
203
+ # Canonical inspect method.
209
204
  #
210
205
  # mx = Net::DNS::RR.new("example.com. 7200 MX 10 mailhost.example.com.")
211
- # #=> example.com. 7200 IN MX 10 mailhost.example.com.
206
+ # #=> example.com. 7200 IN MX 10 mailhost.example.com.
212
207
  #
213
208
  def inspect
214
209
  data = get_inspect
215
210
  # Returns the preformatted string
216
211
  if @name.size < 24
217
- [@name, @ttl.to_s, @cls.to_s, @type.to_s,
218
- data].pack("A24 A8 A8 A8 A*")
212
+ [@name, @ttl.to_s, @cls.to_s, @type.to_s, data].pack("A24 A8 A8 A8 A*")
219
213
  else
220
214
  to_a.join(" ")
221
215
  end
@@ -225,20 +219,20 @@ module Net # :nodoc:
225
219
  #
226
220
  # mx = Net::DNS::RR.new("example.com. 7200 MX 10 mailhost.example.com.")
227
221
  # mx.to_s
228
- # #=> "example.com. 7200 IN MX 10 mailhost.example.com."
222
+ # #=> "example.com. 7200 IN MX 10 mailhost.example.com."
229
223
  #
230
224
  def to_s
231
- "#{self.inspect}"
225
+ inspect.to_s
232
226
  end
233
227
 
234
228
  # Returns an array with all the fields for the RR record.
235
229
  #
236
230
  # mx = Net::DNS::RR.new("example.com. 7200 MX 10 mailhost.example.com.")
237
231
  # mx.to_a
238
- # #=> ["example.com.",7200,"IN","MX","10 mailhost.example.com."]
232
+ # #=> ["example.com.",7200,"IN","MX","10 mailhost.example.com."]
239
233
  #
240
234
  def to_a
241
- [@name,@ttl,@cls.to_s,@type.to_s,get_inspect]
235
+ [@name, @ttl, @cls.to_s, @type.to_s, get_inspect]
242
236
  end
243
237
 
244
238
  # Type accessor
@@ -252,111 +246,113 @@ module Net # :nodoc:
252
246
  end
253
247
 
254
248
  private
255
-
256
- #---
257
- # New RR with argument in string form
258
- #---
259
- def new_from_string(rrstring)
260
249
 
261
- unless rrstring =~ RR_REGEXP
262
- raise RRArgumentError,
263
- "Format error for RR string (maybe CLASS and TYPE not valid?)"
264
- end
250
+ #---
251
+ # New RR with argument in string form
252
+ #---
253
+ def new_from_string(rrstring)
265
254
 
266
- # Name of RR - mandatory
267
- begin
268
- @name = $1.downcase
269
- rescue NoMethodError
270
- raise RRArgumentError, "Missing name field in RR string #{rrstring}"
271
- end
272
-
273
- # Time to live for RR, default 3 hours
274
- @ttl = $2 ? $2.to_i : 10800
275
-
276
- # RR class, default to IN
277
- @cls = Net::DNS::RR::Classes.new $3
278
-
279
- # RR type, default to A
280
- @type = Net::DNS::RR::Types.new $4
281
-
282
- # All the rest is data
283
- @rdata = $5 ? $5.strip : ""
284
-
285
- if self.class == Net::DNS::RR
286
- (eval "Net::DNS::RR::#@type").new(rrstring)
287
- else
288
- subclass_new_from_string(@rdata)
289
- self.class
290
- end
291
- end
292
-
293
- def new_from_hash(args)
294
-
295
- # Name field is mandatory
296
- unless args.has_key? :name
297
- raise RRArgumentError, "RR argument error: need at least RR name"
255
+ unless rrstring =~ RR_REGEXP
256
+ raise ArgumentError,
257
+ "Format error for RR string (maybe CLASS and TYPE not valid?)"
258
+ end
259
+
260
+ # Name of RR - mandatory
261
+ begin
262
+ @name = $1.downcase
263
+ rescue NoMethodError
264
+ raise ArgumentError, "Missing name field in RR string #{rrstring}"
265
+ end
266
+
267
+ # Time to live for RR, default 3 hours
268
+ @ttl = $2 ? $2.to_i : 10800
269
+
270
+ # RR class, default to IN
271
+ @cls = Net::DNS::RR::Classes.new $3
272
+
273
+ # RR type, default to A
274
+ @type = Net::DNS::RR::Types.new $4
275
+
276
+ # All the rest is data
277
+ @rdata = $5 ? $5.strip : ""
278
+
279
+ if self.class == Net::DNS::RR
280
+ (eval "Net::DNS::RR::#@type").new(rrstring)
281
+ else
282
+ subclass_new_from_string(@rdata)
283
+ self.class
284
+ end
298
285
  end
299
286
 
300
- @name = args[:name].downcase
301
- @ttl = args[:ttl] ? args[:ttl].to_i : 10800 # Default 3 hours
302
- @type = Net::DNS::RR::Types.new args[:type]
303
- @cls = Net::DNS::RR::Classes.new args[:cls]
304
-
305
- @rdata = args[:rdata] ? args[:rdata].strip : ""
306
- @rdlength = args[:rdlength] || @rdata.size
287
+ def new_from_hash(args)
288
+ # Name field is mandatory
289
+ unless args.has_key? :name
290
+ raise ArgumentError, "RR argument error: need at least RR name"
291
+ end
307
292
 
308
- if self.class == Net::DNS::RR
309
- (eval "Net::DNS::RR::#@type").new(args)
310
- else
311
- hash = args - [:name,:ttl,:type,:cls]
312
- if hash.has_key? :rdata
313
- subclass_new_from_string(hash[:rdata])
293
+ @name = args[:name].downcase
294
+ @ttl = args[:ttl] ? args[:ttl].to_i : 10800 # Default 3 hours
295
+ @type = Net::DNS::RR::Types.new args[:type]
296
+ @cls = Net::DNS::RR::Classes.new args[:cls]
297
+
298
+ @rdata = args[:rdata] ? args[:rdata].strip : ""
299
+ @rdlength = args[:rdlength] || @rdata.size
300
+
301
+ if self.class == Net::DNS::RR
302
+ (eval "Net::DNS::RR::#@type").new(args)
303
+ else
304
+ hash = args - [:name,:ttl,:type,:cls]
305
+ if hash.has_key? :rdata
306
+ subclass_new_from_string(hash[:rdata])
307
+ else
308
+ subclass_new_from_hash(hash)
309
+ end
310
+ self.class
311
+ end
312
+ end # new_from_hash
313
+
314
+ def new_from_binary(data,offset)
315
+ if self.class == Net::DNS::RR
316
+ temp = dn_expand(data,offset)[1]
317
+ type = Net::DNS::RR::Types.new data.unpack("@#{temp} n")[0]
318
+ (eval "Net::DNS::RR::#{type}").parse_packet(data,offset)
314
319
  else
315
- subclass_new_from_hash(hash)
320
+ @name,offset = dn_expand(data,offset)
321
+ rrtype,cls,@ttl,@rdlength = data.unpack("@#{offset} n2 N n")
322
+ @type = Net::DNS::RR::Types.new rrtype
323
+ @cls = Net::DNS::RR::Classes.new cls
324
+ offset += RRFIXEDSZ
325
+ offset = subclass_new_from_binary(data,offset)
326
+ build_pack
327
+ set_type
328
+ return [self,offset]
316
329
  end
317
- self.class
318
330
  end
319
- end # new_from_hash
320
331
 
321
- def new_from_binary(data,offset)
322
- if self.class == Net::DNS::RR
323
- temp = dn_expand(data,offset)[1]
324
- type = Net::DNS::RR::Types.new data.unpack("@#{temp} n")[0]
325
- (eval "Net::DNS::RR::#{type}").parse_packet(data,offset)
326
- else
327
- @name,offset = dn_expand(data,offset)
328
- rrtype,cls,@ttl,@rdlength = data.unpack("@#{offset} n2 N n")
329
- @type = Net::DNS::RR::Types.new rrtype
330
- @cls = Net::DNS::RR::Classes.new cls
331
- offset += RRFIXEDSZ
332
- offset = subclass_new_from_binary(data,offset)
333
- build_pack
334
- set_type
335
- return [self,offset]
332
+ # Methods to be overridden by subclasses
333
+ def subclass_new_from_array(arr)
334
+ end
335
+ def subclass_new_from_string(str)
336
+ end
337
+ def subclass_new_from_hash(hash)
338
+ end
339
+ def subclass_new_from_binary(data,offset)
340
+ end
341
+ def build_pack
342
+ end
343
+ def get_inspect
344
+ @rdata
345
+ end
346
+ def get_data
347
+ @rdata
336
348
  end
337
- # rescue StandardError => err
338
- # raise RRDataError, "Caught exception, maybe packet malformed: #{err}"
339
- end
340
-
341
- # Methods to be overridden by subclasses
342
- def subclass_new_from_array(arr)
343
- end
344
- def subclass_new_from_string(str)
345
- end
346
- def subclass_new_from_hash(hash)
347
- end
348
- def subclass_new_from_binary(data,offset)
349
- end
350
- def build_pack
351
- end
352
- def set_type
353
- end
354
- def get_inspect
355
- @rdata
356
- end
357
- def get_data
358
- @rdata
359
- end
349
+
350
+ def set_type
351
+ # TODO: Here we should probably
352
+ # raise NotImplementedError
353
+ # if we want the method to be implemented in any subclass.
354
+ end
355
+
360
356
 
361
357
  # NEW new method :)
362
358
  def self.new(*args)
@@ -369,38 +365,7 @@ module Net # :nodoc:
369
365
  end
370
366
  end
371
367
 
372
- end # class RR
373
-
374
- end # module DNS
375
- end # module Net
376
-
377
- class RRArgumentError < ArgumentError # :nodoc:
378
- end
379
- class RRDataError < StandardError # :nodoc:
380
- end
381
-
382
- module ExtendHash # :nodoc:
383
-
384
- # Performs a sort of group difference
385
- # operation on hashes or arrays
386
- #
387
- # a = {:a=>1,:b=>2,:c=>3}
388
- # b = {:a=>1,:b=>2}
389
- # c = [:a,:c]
390
- # a-b #=> {:c=>3}
391
- # a-c #=> {:b=>2}
392
- #
393
- def -(oth)
394
- case oth
395
- when Hash
396
- delete_if {|k,v| oth.has_key? k}
397
- when Array
398
- delete_if {|k,v| oth.include? k}
399
368
  end
369
+
400
370
  end
401
- end
402
-
403
- class Hash # :nodoc:
404
- include ExtendHash
405
- end
406
-
371
+ end