From 1653b587778db0df201507115d19c0530096a5e3 Mon Sep 17 00:00:00 2001 From: ThibG Date: Thu, 5 Sep 2019 05:32:53 +0200 Subject: Attempt to concurrently connect to remote IP addresses (#11757) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Attempt to concurrently connect to remote IP addresses * Reduce code length to please CodeClimate 🤷 --- app/lib/request.rb | 52 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 17 deletions(-) (limited to 'app/lib') diff --git a/app/lib/request.rb b/app/lib/request.rb index 9d874fe2c..42ccc6513 100644 --- a/app/lib/request.rb +++ b/app/lib/request.rb @@ -191,6 +191,9 @@ class Request end end + socks = [] + addr_by_socket = {} + addresses.each do |address| begin check_private_address(address) @@ -200,30 +203,45 @@ class Request sock.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1) - begin - sock.connect_nonblock(sockaddr) - rescue IO::WaitWritable - if IO.select(nil, [sock], nil, Request::TIMEOUT[:connect]) - begin - sock.connect_nonblock(sockaddr) - rescue Errno::EISCONN - # Yippee! - rescue - sock.close - raise - end - else - sock.close - raise HTTP::TimeoutError, "Connect timed out after #{Request::TIMEOUT[:connect]} seconds" - end - end + sock.connect_nonblock(sockaddr) + # If that hasn't raised an exception, we somehow managed to connect + # immediately, close pending sockets and return immediately + socks.each(&:close) return sock + rescue IO::WaitWritable + socks << sock + addr_by_socket[sock] = sockaddr rescue => e outer_e = e end end + until socks.empty? + _, available_socks, = IO.select(nil, socks, nil, Request::TIMEOUT[:connect]) + + if available_socks.nil? + socks.each(&:close) + raise HTTP::TimeoutError, "Connect timed out after #{Request::TIMEOUT[:connect]} seconds" + end + + available_socks.each do |sock| + socks.delete(sock) + + begin + sock.connect_nonblock(addr_by_socket[sock]) + rescue Errno::EISCONN + rescue => e + sock.close + outer_e = e + next + end + + socks.each(&:close) + return sock + end + end + if outer_e raise outer_e else -- cgit