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:
parent
529856a608
commit
1653b58777
1 changed files with 35 additions and 17 deletions
|
@ -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,30 +203,45 @@ 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)
|
|
||||||
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
|
|
||||||
|
|
||||||
|
# If that hasn't raised an exception, we somehow managed to connect
|
||||||
|
# immediately, close pending sockets and return immediately
|
||||||
|
socks.each(&:close)
|
||||||
return sock
|
return sock
|
||||||
|
rescue IO::WaitWritable
|
||||||
|
socks << sock
|
||||||
|
addr_by_socket[sock] = sockaddr
|
||||||
rescue => e
|
rescue => e
|
||||||
outer_e = e
|
outer_e = e
|
||||||
end
|
end
|
||||||
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
|
if outer_e
|
||||||
raise outer_e
|
raise outer_e
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in a new issue