Project

General

Profile

Bug #8285 ยป ruby-trunk-8285-resolv-tcp-fallback-fix.diff

julian.mehnle (Julian Mehnle), 04/18/2013 07:36 AM

View differences:

lib/resolv.rb (working copy)
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)
......
end
}
ensure
requester.close
requesters.each_value { |requester| requester.close }
end
end
def make_udp_requester # :nodoc:
nameserver_port = @config.nameserver_port
......
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:
    (1-1/1)