From bd67d3d74537a97f07c91a58e5c1cf5f8da36cf2 Mon Sep 17 00:00:00 2001 From: HoneyryderChuck Date: Wed, 29 Nov 2017 21:26:47 +0000 Subject: [PATCH] added nonblocking connection, which makes timeouts now much more acurate; force renovation of timeout, as per_operation's first is the connection one (after connection, pass to operation) --- lib/httpx/channel/ssl.rb | 3 ++- lib/httpx/channel/tcp.rb | 23 ++++++++++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/lib/httpx/channel/ssl.rb b/lib/httpx/channel/ssl.rb index c24751a6..b46af7e4 100644 --- a/lib/httpx/channel/ssl.rb +++ b/lib/httpx/channel/ssl.rb @@ -37,12 +37,13 @@ module HTTPX::Channel ctx.alpn_select_cb = lambda do |pr| pr.first unless pr.nil? || pr.empty? end if ctx.respond_to?(:alpn_select_cb=) - super + return if @closed @io = OpenSSL::SSL::SSLSocket.new(@io, ctx) @io.hostname = uri.host @io.sync_close = true @io.connect # TODO: non-block variant missing + rescue IO::WaitWritable end def perform_io diff --git a/lib/httpx/channel/tcp.rb b/lib/httpx/channel/tcp.rb index 2301bab7..906f1662 100644 --- a/lib/httpx/channel/tcp.rb +++ b/lib/httpx/channel/tcp.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require "ipaddr" require "forwardable" module HTTPX::Channel @@ -17,9 +18,10 @@ module HTTPX::Channel attr_reader :uri, :remote_ip, :remote_port def to_io - return @io.to_io if defined?(@io) - connect - set_processor + if @closed + connect + set_processor unless @closed + end @io.to_io end @@ -32,6 +34,8 @@ module HTTPX::Channel @pending = [] @on_response = on_response set_remote_info + addr = IPAddr.new(@remote_ip) + @io = Socket.new(addr.family, :STREAM, 0) end def protocol @@ -68,7 +72,8 @@ module HTTPX::Channel end end - def call + def call + return if @closed dread dwrite nil @@ -135,10 +140,18 @@ module HTTPX::Channel end def connect - @io = TCPSocket.new(@remote_ip, @remote_port) + return unless @closed + begin + @io.connect_nonblock(Socket.sockaddr_in(@remote_port, @remote_ip)) + rescue Errno::EISCONN + end + @options.timeout # force renovation @read_buffer.clear @write_buffer.clear @closed = false + rescue Errno::EINPROGRESS, + Errno::EALREADY, + IO::WaitReadable end def set_processor