Project

General

Profile

socket-tcp-connect-timeout.patch

akr (Akira Tanaka), 08/03/2011 12:42 PM

View differences:

lib/net/http.rb (working copy)
763 763

  
764 764
    def connect
765 765
      D "opening connection to #{conn_address()}..."
766
      s = timeout(@open_timeout) { TCPSocket.open(conn_address(), conn_port()) }
766
      s = timeout(@open_timeout) { Socket.tcp(conn_address(), conn_port()) }
767 767
      D "opened"
768 768
      if use_ssl?
769 769
        ssl_parameters = Hash.new
ext/socket/lib/socket.rb (working copy)
35 35
  #
36 36
  # If a block is given the created socket is yielded for each address.
37 37
  #
38
  def connect_internal(local_addrinfo) # :yields: socket
38
  def connect_internal(local_addrinfo, timeout=nil) # :yields: socket
39 39
    sock = Socket.new(self.pfamily, self.socktype, self.protocol)
40 40
    begin
41 41
      sock.ipv6only! if self.ipv6?
42 42
      sock.bind local_addrinfo if local_addrinfo
43
      sock.connect(self)
43
      if timeout
44
        begin
45
          sock.connect_nonblock(self)
46
        rescue IO::WaitWritable
47
          if !IO.select(nil, [sock], nil, timeout)
48
            raise Errno::ETIMEDOUT, 'user specified timeout'
49
          end
50
          begin
51
            sock.connect_nonblock(self) # check connection failure
52
          rescue Errno::EISCONN
53
          end
54
        end
55
      else
56
        sock.connect(self)
57
      end
44 58
      if block_given?
45 59
        yield sock
46 60
      else
......
74 88
  #     puts s.read
75 89
  #   }
76 90
  #
77
  def connect_from(*local_addr_args, &block)
78
    connect_internal(family_addrinfo(*local_addr_args), &block)
91
  def connect_from(*args, &block)
92
    opts = Hash === args.last ? args.pop : {}
93
    local_addr_args = args
94
    connect_internal(family_addrinfo(*local_addr_args), opts[:timeout], &block)
79 95
  end
80 96

  
81 97
  # creates a socket connected to the address of self.
......
88 104
  #     puts s.read
89 105
  #   }
90 106
  #
91
  def connect(&block)
92
    connect_internal(nil, &block)
107
  def connect(opts={}, &block)
108
    connect_internal(nil, opts[:timeout], &block)
93 109
  end
94 110

  
95 111
  # creates a socket connected to _remote_addr_args_ and bound to self.
......
102 118
  #     puts s.read
103 119
  #   }
104 120
  #
105
  def connect_to(*remote_addr_args, &block)
121
  def connect_to(*args, &block)
122
    opts = Hash === args.last ? args.pop : {}
123
    remote_addr_args = args
106 124
    remote_addrinfo = family_addrinfo(*remote_addr_args)
107
    remote_addrinfo.send(:connect_internal, self, &block)
125
    remote_addrinfo.send(:connect_internal, self, opts[:timeout], &block)
108 126
  end
109 127

  
110 128
  # creates a socket bound to self.
......
233 251
  #     puts sock.read
234 252
  #   }
235 253
  #
236
  def self.tcp(host, port, local_host=nil, local_port=nil) # :yield: socket
254
  def self.tcp(host, port, *rest) # :yield: socket
255
    opts = Hash === rest.last ? rest.pop : {}
256
    local_host, local_port = rest
237 257
    last_error = nil
238 258
    ret = nil
239 259

  
260
    connect_timeout = opts[:connect_timeout]
261

  
240 262
    local_addr_list = nil
241 263
    if local_host != nil || local_port != nil
242 264
      local_addr_list = Addrinfo.getaddrinfo(local_host, local_port, nil, :STREAM, nil)
......
250 272
        local_addr = nil
251 273
      end
252 274
      begin
253
        sock = local_addr ? ai.connect_from(local_addr) : ai.connect
275
        sock = local_addr ?
276
          ai.connect_from(local_addr, :timeout => connect_timeout) :
277
          ai.connect(:timeout => connect_timeout)
254 278
      rescue SystemCallError
255 279
        last_error = $!
256 280
        next