lib/httpx/connection/http2.rb in httpx-0.8.1 vs lib/httpx/connection/http2.rb in httpx-0.8.2

- old
+ new

@@ -1,7 +1,8 @@ # frozen_string_literal: true +require "securerandom" require "io/wait" require "http/2/next" module HTTPX class Connection::HTTP2 @@ -23,10 +24,11 @@ @max_concurrent_requests = @options.max_concurrent_requests || MAX_CONCURRENT_REQUESTS @max_requests = @options.max_requests || 0 @pending = [] @streams = {} @drains = {} + @pings = [] @buffer = buffer @handshake_completed = false init_connection end @@ -51,12 +53,12 @@ def reset init_connection end - def close - @connection.goaway unless @connection.state == :closed + def close(*args) + @connection.goaway(*args) unless @connection.state == :closed emit(:close) end def empty? @connection.state == :closed || @streams.empty? @@ -107,10 +109,17 @@ @pending.each do |request| emit(:error, request, ex) end end + def ping + ping = SecureRandom.gen_random(8) + @connection.ping(ping) + ensure + @pings << ping + end + private def send_pending while (request = @pending.shift) break unless send(request) @@ -141,10 +150,11 @@ @connection.on(:frame_received, &method(:on_frame_received)) @connection.on(:origin, &method(:on_origin)) @connection.on(:promise, &method(:on_promise)) @connection.on(:altsvc) { |frame| on_altsvc(frame[:origin], frame) } @connection.on(:settings_ack, &method(:on_settings)) + @connection.on(:ack, &method(:on_pong)) @connection.on(:goaway, &method(:on_close)) # # Some servers initiate HTTP/2 negotiation right away, some don't. # As such, we have to check the socket buffer. If there is something # to read, the server initiated the negotiation. If not, we have to @@ -302,9 +312,17 @@ emit(:promise, @streams.key(stream.parent), stream) end def on_origin(origin) emit(:origin, origin) + end + + def on_pong(ping) + if !@pings.delete(ping) + close(:protocol_error, "ping payload did not match") + else + emit(:pong) + end end def respond_to_missing?(meth, *args) @connection.respond_to?(meth, *args) || super end