diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | lib/resolv.rb | 31 | ||||
-rw-r--r-- | test/resolv/test_dns.rb | 24 |
3 files changed, 59 insertions, 1 deletions
@@ -1,3 +1,8 @@ +Sat Oct 22 17:43:33 2011 Tanaka Akira <akr@fsij.org> + + * lib/resolv.rb: make timeout configurable for DNS query. + patch by Eric Wong. [ruby-core:38533] [Feature #5100] + Sat Oct 22 02:07:48 2011 Naohisa Goto <ngotogenome@gmail.com> * numeric.c (rb_infinity, rb_nan): use union to prevent bus error diff --git a/lib/resolv.rb b/lib/resolv.rb index 1e1889370a..89094a0ebf 100644 --- a/lib/resolv.rb +++ b/lib/resolv.rb @@ -336,6 +336,21 @@ class Resolv @initialized = nil end + # Sets the resolver timeouts. This may be a single positive number + # or an array of positive numbers representing timeouts in seconds. + # If an array is specified, a DNS request will retry and wait for + # each successive interval in the array until a successful response + # is received. Specifying +nil+ reverts to the default timeouts: + # [ 5, second = 5 * 2 / nameserver_count, 2 * second, 4 * second ] + # + # Example: + # + # dns.timeouts = 3 + # + def timeouts=(values) + @config.timeouts = values + end + def lazy_initialize # :nodoc: @mutex.synchronize { unless @initialized @@ -851,6 +866,20 @@ class Resolv @mutex = Mutex.new @config_info = config_info @initialized = nil + @timeouts = nil + end + + def timeouts=(values) + if values + values = Array(values) + values.each do |t| + Numeric === t or raise ArgumentError, "#{t.inspect} is not numeric" + t > 0.0 or raise Argument, "timeout=#{t} must be postive" + end + @timeouts = values + else + @timeouts = nil + end end def Config.parse_resolv_conf(filename) @@ -1013,7 +1042,7 @@ class Resolv def resolv(name) candidates = generate_candidates(name) - timeouts = generate_timeouts + timeouts = @timeouts || generate_timeouts begin candidates.each {|candidate| begin diff --git a/test/resolv/test_dns.rb b/test/resolv/test_dns.rb index 9a9c33ea84..3fce206c6b 100644 --- a/test/resolv/test_dns.rb +++ b/test/resolv/test_dns.rb @@ -105,6 +105,30 @@ class TestResolvDNS < Test::Unit::TestCase } end + def test_query_ipv4_address_timeout + with_udp('127.0.0.1', 0) {|u| + _, port , _, host = u.addr + start = nil + rv = Resolv::DNS.open(:nameserver_port => [[host, port]]) {|dns| + dns.timeouts = 0.1 + start = Time.now + dns.getresources("foo.example.org", Resolv::DNS::Resource::IN::A) + } + diff = Time.now - start + assert rv.empty?, "unexpected: #{rv.inspect} (expected empty)" + assert_in_delta 0.1, diff, 0.05 + + rv = Resolv::DNS.open(:nameserver_port => [[host, port]]) {|dns| + dns.timeouts = [ 0.1, 0.2 ] + start = Time.now + dns.getresources("foo.example.org", Resolv::DNS::Resource::IN::A) + } + diff = Time.now - start + assert rv.empty?, "unexpected: #{rv.inspect} (expected empty)" + assert_in_delta 0.3, diff, 0.05 + } + end + def test_no_server u = UDPSocket.new u.bind("127.0.0.1", 0) |