summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKasumi Hanazuki <[email protected]>2024-06-01 10:07:46 +0000
committergit <[email protected]>2024-08-13 21:09:08 +0000
commit094e53360d3e2537339997606eaa45f37a375f18 (patch)
tree75e87174c766e2000e017521eff8d469fcedd04f
parent4be9b72fbb44e7754337f4957f2c7bfe3cd41891 (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.rb29
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