Index: lib/resolv.rb =================================================================== --- lib/resolv.rb (revision 40339) +++ lib/resolv.rb (working copy) @@ -513,29 +513,26 @@ def fetch_resource(name, typeclass) lazy_initialize - requester = make_udp_requester + protocols = {} + requesters = {} senders = {} - begin @config.resolv(name) {|candidate, tout, nameserver, port| msg = Message.new msg.rd = 1 msg.add_question(candidate, typeclass) - unless sender = senders[[candidate, nameserver, port]] - sender = senders[[candidate, nameserver, port]] = + protocol = protocols[candidate| ||= :udp + requester = requesters[[protocol, nameserver]] ||= case protocol + when :udp then make_udp_requester + when :tcp then make_tcp_requester(nameserver, port) + end + sender = senders[[candidate, requester, nameserver, port]] ||= requester.sender(msg, candidate, nameserver, port) - end reply, reply_name = requester.request(sender, tout) case reply.rcode when RCode::NoError - if reply.tc == 1 and not Requester::TCP === requester - requester.close + if protocol == :udp and reply.tc == 1 # Retry via TCP: - requester = make_tcp_requester(nameserver, port) - senders = {} - # This will use TCP for all remaining candidates (assuming the - # current candidate does not already respond successfully via - # TCP). This makes sense because we already know the full - # response will not fit in an untruncated UDP packet. + protocols[candidate] = :tcp redo else yield(reply, reply_name) @@ -548,9 +545,8 @@ end } ensure - requester.close + requesters.each_value { |requester| requester.close } end - end def make_udp_requester # :nodoc: nameserver_port = @config.nameserver_port @@ -563,6 +559,11 @@ def make_tcp_requester(host, port) # :nodoc: return Requester::TCP.new(host, port) + rescue Errno::ECONNREFUSED + # Treat a refused TCP connection attempt to a nameserver like a timeout, + # as Resolv::DNS::Config#resolv considers ResolvTimeout exceptions as a + # hint to try the next nameserver: + raise ResolvTimeout end def extract_resources(msg, name, typeclass) # :nodoc: