class Excon::Socket
def connect
def connect @socket = nil exception = nil if @data[:proxy] family = @data[:proxy][:family] || ::Socket::Constants::AF_UNSPEC args = [@data[:proxy][:host], @data[:proxy][:port], family, ::Socket::Constants::SOCK_STREAM] else family = @data[:family] || ::Socket::Constants::AF_UNSPEC args = [@data[:host], @data[:port], family, ::Socket::Constants::SOCK_STREAM] end if RUBY_VERSION >= '1.9.2' && defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ruby' args << nil << nil << false # no reverse lookup end addrinfo = ::Socket.getaddrinfo(*args) addrinfo.each do |_, port, _, ip, a_family, s_type| @remote_ip = ip # nonblocking connect begin sockaddr = ::Socket.sockaddr_in(port, ip) socket = ::Socket.new(a_family, s_type, 0) if @data[:reuseaddr] socket.setsockopt(::Socket::Constants::SOL_SOCKET, ::Socket::Constants::SO_REUSEADDR, true) if defined?(::Socket::Constants::SO_REUSEPORT) socket.setsockopt(::Socket::Constants::SOL_SOCKET, ::Socket::Constants::SO_REUSEPORT, true) end end begin Timeout.timeout(@data[:connect_timeout]) do if @nonblock socket.connect_nonblock(sockaddr) else socket.connect(sockaddr) end end rescue Timeout::Error raise Excon::Errors::Timeout.new('connect timeout reached') end @socket = socket break rescue Errno::EINPROGRESS unless IO.select(nil, [socket], nil, @data[:connect_timeout]) raise(Excon::Errors::Timeout.new("connect timeout reached")) end begin socket.connect_nonblock(sockaddr) @socket = socket break rescue Errno::EISCONN @socket = socket break rescue SystemCallError => exception socket.close rescue nil next end rescue SystemCallError => exception socket.close rescue nil if socket next end end unless @socket # this will be our last encountered exception raise exception end if @data[:tcp_nodelay] @socket.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, true) end end