diff options
author | Kasumi Hanazuki <[email protected]> | 2024-06-01 10:07:46 +0000 |
---|---|---|
committer | git <[email protected]> | 2024-08-13 21:09:08 +0000 |
commit | 094e53360d3e2537339997606eaa45f37a375f18 (patch) | |
tree | 75e87174c766e2000e017521eff8d469fcedd04f | |
parent | 4be9b72fbb44e7754337f4957f2c7bfe3cd41891 (diff) |
[ruby/resolv] Reuse open TCP connection
[RFC7766] Section 5 recommends stub resolvers to reuse open TCP
connections to a nameserver.
[RFC7766]: https://datatracker.ietf.org/doc/html/rfc7766
https://github.com/ruby/resolv/commit/9bf1b08f5c
-rw-r--r-- | lib/resolv.rb | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/lib/resolv.rb b/lib/resolv.rb index 2aee310feb..0574ce622b 100644 --- a/lib/resolv.rb +++ b/lib/resolv.rb @@ -513,27 +513,28 @@ class Resolv def fetch_resource(name, typeclass) lazy_initialize - protocols = {} + truncated = {} requesters = {} + udp_requester = begin + make_udp_requester + rescue Errno::EACCES + # fall back to TCP + end senders = {} + begin @config.resolv(name) do |candidate, tout, nameserver, port| msg = Message.new msg.rd = 1 msg.add_question(candidate, typeclass) - protocol = protocols[candidate] ||= :udp - requester = requesters[[protocol, nameserver]] ||= - case protocol - when :udp - begin - make_udp_requester - rescue Errno::EACCES - make_tcp_requester(nameserver, port) - end - when :tcp - make_tcp_requester(nameserver, port) + requester = requesters.fetch([nameserver, port]) do + if !truncated[candidate] && udp_requester + udp_requester + else + requesters[[nameserver, port]] = make_tcp_requester(nameserver, port) end + end unless sender = senders[[candidate, requester, nameserver, port]] sender = requester.sender(msg, candidate, nameserver, port) @@ -544,9 +545,8 @@ class Resolv case reply.rcode when RCode::NoError if reply.tc == 1 and not Requester::TCP === requester - requester.close # Retry via TCP: - protocols[candidate] = :tcp + truncated[candidate] = true redo else yield(reply, reply_name) @@ -559,6 +559,7 @@ class Resolv end end ensure + udp_requester&.close requesters.each_value { |requester| requester&.close } end end |