net-dns 0.5.3 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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