Class: HTTPX::TCP
Constant Summary
Constants included from Loggable
Loggable::COLORS, Loggable::USE_DEBUG_LOG
Instance Attribute Summary collapse
-
#addresses ⇒ Object
readonly
Returns the value of attribute addresses.
-
#interests ⇒ Object
readonly
Returns the value of attribute interests.
-
#ip ⇒ Object
(also: #host)
readonly
Returns the value of attribute ip.
-
#port ⇒ Object
readonly
Returns the value of attribute port.
-
#state ⇒ Object
readonly
Returns the value of attribute state.
Instance Method Summary collapse
- #add_addresses(addrs) ⇒ Object
-
#addresses? ⇒ Boolean
eliminates expired entries and returns whether there are still any left.
- #close ⇒ Object
- #closed? ⇒ Boolean
- #connect ⇒ Object
- #connected? ⇒ Boolean
-
#initialize(origin, addresses, options) ⇒ TCP
constructor
A new instance of TCP.
-
#inspect ⇒ Object
:nocov:.
- #protocol ⇒ Object
- #read(size, buffer) ⇒ Object
- #socket ⇒ Object
- #to_io ⇒ Object
- #write(buffer) ⇒ Object
Methods included from Loggable
#log, #log_exception, #log_redact
Constructor Details
#initialize(origin, addresses, options) ⇒ TCP
Returns a new instance of TCP.
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/httpx/io/tcp.rb', line 15 def initialize(origin, addresses, ) @state = :idle @addresses = [] @hostname = origin.host @options = @fallback_protocol = @options.fallback_protocol @port = origin.port @interests = :w if @options.io @io = case @options.io when Hash @options.io[origin.] else @options.io end raise Error, "Given IO objects do not match the request authority" unless @io _, _, _, ip = @io.addr @ip = Resolver::Entry.new(ip) @addresses << @ip @keep_open = true @state = :connected else add_addresses(addresses) end @ip_index = @addresses.size - 1 end |
Instance Attribute Details
#addresses ⇒ Object (readonly)
Returns the value of attribute addresses.
11 12 13 |
# File 'lib/httpx/io/tcp.rb', line 11 def addresses @addresses end |
#interests ⇒ Object (readonly)
Returns the value of attribute interests.
11 12 13 |
# File 'lib/httpx/io/tcp.rb', line 11 def interests @interests end |
#ip ⇒ Object (readonly) Also known as: host
Returns the value of attribute ip.
11 12 13 |
# File 'lib/httpx/io/tcp.rb', line 11 def ip @ip end |
#port ⇒ Object (readonly)
Returns the value of attribute port.
11 12 13 |
# File 'lib/httpx/io/tcp.rb', line 11 def port @port end |
#state ⇒ Object (readonly)
Returns the value of attribute state.
11 12 13 |
# File 'lib/httpx/io/tcp.rb', line 11 def state @state end |
Instance Method Details
#add_addresses(addrs) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/httpx/io/tcp.rb', line 47 def add_addresses(addrs) return if addrs.empty? ip_index = @ip_index || (@addresses.size - 1) if addrs.first.ipv6? # should be the next in line @addresses = [*@addresses[0, ip_index], *addrs, *@addresses[ip_index..-1]] else @addresses.unshift(*addrs) @ip_index += addrs.size if @ip_index end end |
#addresses? ⇒ Boolean
eliminates expired entries and returns whether there are still any left.
61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/httpx/io/tcp.rb', line 61 def addresses? prev_addr_size = @addresses.size @addresses.delete_if(&:expired?) unless (decr = prev_addr_size - @addresses.size).zero? @ip_index = @addresses.size - decr end @addresses.any? end |
#close ⇒ Object
159 160 161 162 163 164 165 166 167 |
# File 'lib/httpx/io/tcp.rb', line 159 def close return if @keep_open || closed? begin @io.close ensure transition(:closed) end end |
#closed? ⇒ Boolean
173 174 175 |
# File 'lib/httpx/io/tcp.rb', line 173 def closed? @state == :idle || @state == :closed end |
#connect ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/httpx/io/tcp.rb', line 81 def connect return unless closed? if !@io || @io.closed? transition(:idle) @io = build_socket end try_connect rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH => e raise e if @ip_index <= 0 log { "failed connecting to #{@ip} (#{e.}), evict from cache and trying next..." } Resolver.cached_lookup_evict(@hostname, @ip) @ip_index -= 1 @io = build_socket retry rescue Errno::ECONNREFUSED, Errno::EADDRNOTAVAIL, SocketError, IOError => e raise e if @ip_index <= 0 log { "failed connecting to #{@ip} (#{e.}), trying next..." } @ip_index -= 1 @io = build_socket retry rescue Errno::ETIMEDOUT => e raise ConnectTimeoutError.new(@options.timeout[:connect_timeout], e.) if @ip_index <= 0 log { "failed connecting to #{@ip} (#{e.}), trying next..." } @ip_index -= 1 @io = build_socket retry end |
#connected? ⇒ Boolean
169 170 171 |
# File 'lib/httpx/io/tcp.rb', line 169 def connected? @state == :connected end |
#inspect ⇒ Object
:nocov:
178 179 180 181 182 183 184 185 |
# File 'lib/httpx/io/tcp.rb', line 178 def inspect "#<#{self.class}:#{object_id} " \ "#{@ip}:#{@port} " \ "@state=#{@state} " \ "@hostname=#{@hostname} " \ "@addresses=#{@addresses} " \ "@state=#{@state}>" end |
#protocol ⇒ Object
77 78 79 |
# File 'lib/httpx/io/tcp.rb', line 77 def protocol @fallback_protocol end |
#read(size, buffer) ⇒ Object
136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/httpx/io/tcp.rb', line 136 def read(size, buffer) ret = @io.read_nonblock(size, buffer, exception: false) if ret == :wait_readable buffer.clear return 0 end return if ret.nil? log { "READ: #{buffer.bytesize} bytes..." } buffer.bytesize end |
#socket ⇒ Object
43 44 45 |
# File 'lib/httpx/io/tcp.rb', line 43 def socket @io end |
#to_io ⇒ Object
73 74 75 |
# File 'lib/httpx/io/tcp.rb', line 73 def to_io @io.to_io end |
#write(buffer) ⇒ Object
148 149 150 151 152 153 154 155 156 157 |
# File 'lib/httpx/io/tcp.rb', line 148 def write(buffer) siz = @io.write_nonblock(buffer, exception: false) return 0 if siz == :wait_writable return if siz.nil? log { "WRITE: #{siz} bytes..." } buffer.shift!(siz) siz end |