Attempt to concurrently connect to remote IP addresses (#11757)

* Attempt to concurrently connect to remote IP addresses

* Reduce code length to please CodeClimate 🤷
This commit is contained in:
ThibG 2019-09-05 05:32:53 +02:00 committed by Eugen Rochko
parent 529856a608
commit 1653b58777

View file

@ -191,6 +191,9 @@ class Request
end end
end end
socks = []
addr_by_socket = {}
addresses.each do |address| addresses.each do |address|
begin begin
check_private_address(address) check_private_address(address)
@ -200,27 +203,42 @@ class Request
sock.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1) sock.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1)
begin
sock.connect_nonblock(sockaddr) 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 rescue IO::WaitWritable
if IO.select(nil, [sock], nil, Request::TIMEOUT[:connect]) socks << sock
begin addr_by_socket[sock] = sockaddr
sock.connect_nonblock(sockaddr) rescue => e
rescue Errno::EISCONN outer_e = e
# Yippee!
rescue
sock.close
raise
end
else
sock.close
raise HTTP::TimeoutError, "Connect timed out after #{Request::TIMEOUT[:connect]} seconds"
end end
end end
return sock 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 rescue => e
sock.close
outer_e = e outer_e = e
next
end
socks.each(&:close)
return sock
end end
end end