class HTTPX::TCP

  1. lib/httpx/io/tcp.rb
Superclass: Object

Included modules

  1. Loggable

Attributes

addresses [R]
host [R]
interests [R]
ip [R]
port [R]
state [R]

Public Class methods

new(origin, addresses, options)
[show source]
   # File lib/httpx/io/tcp.rb
16 def initialize(origin, addresses, options)
17   @state = :idle
18   @addresses = []
19   @hostname = origin.host
20   @options = options
21   @fallback_protocol = @options.fallback_protocol
22   @port = origin.port
23   @interests = :w
24   if @options.io
25     @io = case @options.io
26           when Hash
27             @options.io[origin.authority]
28           else
29             @options.io
30     end
31     raise Error, "Given IO objects do not match the request authority" unless @io
32 
33     _, _, _, @ip = @io.addr
34     @addresses << @ip
35     @keep_open = true
36     @state = :connected
37   else
38     add_addresses(addresses)
39   end
40   @ip_index = @addresses.size - 1
41 end

Public Instance methods

add_addresses(addrs)
[show source]
   # File lib/httpx/io/tcp.rb
47 def add_addresses(addrs)
48   return if addrs.empty?
49 
50   addrs = addrs.map { |addr| addr.is_a?(IPAddr) ? addr : IPAddr.new(addr) }
51 
52   ip_index = @ip_index || (@addresses.size - 1)
53   if addrs.first.ipv6?
54     # should be the next in line
55     @addresses = [*@addresses[0, ip_index], *addrs, *@addresses[ip_index..-1]]
56   else
57     @addresses.unshift(*addrs)
58     @ip_index += addrs.size if @ip_index
59   end
60 end
close()
[show source]
    # File lib/httpx/io/tcp.rb
148 def close
149   return if @keep_open || closed?
150 
151   begin
152     @io.close
153   ensure
154     transition(:closed)
155   end
156 end
closed?()
[show source]
    # File lib/httpx/io/tcp.rb
162 def closed?
163   @state == :idle || @state == :closed
164 end
connect()
[show source]
    # File lib/httpx/io/tcp.rb
 70 def connect
 71   return unless closed?
 72 
 73   if !@io || @io.closed?
 74     transition(:idle)
 75     @io = build_socket
 76   end
 77   try_connect
 78 rescue Errno::EHOSTUNREACH,
 79        Errno::ENETUNREACH => e
 80   raise e if @ip_index <= 0
 81 
 82   log { "failed connecting to #{@ip} (#{e.message}), evict from cache and trying next..." }
 83   Resolver.cached_lookup_evict(@hostname, @ip)
 84 
 85   @ip_index -= 1
 86   @io = build_socket
 87   retry
 88 rescue Errno::ECONNREFUSED,
 89        Errno::EADDRNOTAVAIL,
 90        SocketError,
 91        IOError => e
 92   raise e if @ip_index <= 0
 93 
 94   log { "failed connecting to #{@ip} (#{e.message}), trying next..." }
 95   @ip_index -= 1
 96   @io = build_socket
 97   retry
 98 rescue Errno::ETIMEDOUT => e
 99   raise ConnectTimeoutError.new(@options.timeout[:connect_timeout], e.message) if @ip_index <= 0
100 
101   log { "failed connecting to #{@ip} (#{e.message}), trying next..." }
102   @ip_index -= 1
103   @io = build_socket
104   retry
105 end
connected?()
[show source]
    # File lib/httpx/io/tcp.rb
158 def connected?
159   @state == :connected
160 end
expired?()
[show source]
    # File lib/httpx/io/tcp.rb
166 def expired?
167   # do not mess with external sockets
168   return false if @options.io
169 
170   return true unless @addresses
171 
172   resolver_addresses = Resolver.nolookup_resolve(@hostname)
173 
174   (Array(resolver_addresses) & @addresses).empty?
175 end
inspect()

:nocov:

[show source]
    # File lib/httpx/io/tcp.rb
178 def inspect
179   "#<#{self.class}:#{object_id} " \
180     "#{@ip}:#{@port} " \
181     "@state=#{@state} " \
182     "@hostname=#{@hostname} " \
183     "@addresses=#{@addresses} " \
184     "@state=#{@state}>"
185 end
protocol()
[show source]
   # File lib/httpx/io/tcp.rb
66 def protocol
67   @fallback_protocol
68 end
read(size, buffer)
[show source]
    # File lib/httpx/io/tcp.rb
125 def read(size, buffer)
126   ret = @io.read_nonblock(size, buffer, exception: false)
127   if ret == :wait_readable
128     buffer.clear
129     return 0
130   end
131   return if ret.nil?
132 
133   log { "READ: #{buffer.bytesize} bytes..." }
134   buffer.bytesize
135 end
socket()
[show source]
   # File lib/httpx/io/tcp.rb
43 def socket
44   @io
45 end
to_io()
[show source]
   # File lib/httpx/io/tcp.rb
62 def to_io
63   @io.to_io
64 end
write(buffer)
[show source]
    # File lib/httpx/io/tcp.rb
137 def write(buffer)
138   siz = @io.write_nonblock(buffer, exception: false)
139   return 0 if siz == :wait_writable
140   return if siz.nil?
141 
142   log { "WRITE: #{siz} bytes..." }
143 
144   buffer.shift!(siz)
145   siz
146 end