diff --git a/example/server.rb b/example/server.rb index cb97d83..555326a 100644 --- a/example/server.rb +++ b/example/server.rb @@ -62,10 +62,7 @@ end conn.on(:goaway) do - Thread.start do - sleep(1) - sock.close - end + sock.close end conn.on(:stream) do |stream| diff --git a/lib/http/2/connection.rb b/lib/http/2/connection.rb index d3cf180..1b97d3e 100644 --- a/lib/http/2/connection.rb +++ b/lib/http/2/connection.rb @@ -527,8 +527,6 @@ def connection_management(frame) when :goaway # 6.8. GOAWAY # An endpoint MAY send multiple GOAWAY frames if circumstances change. - when :ping - ping_management(frame) else connection_error if (Process.clock_gettime(Process::CLOCK_MONOTONIC) - @closed_since) > 15 end diff --git a/lib/http/2/framer.rb b/lib/http/2/framer.rb index b09c118..6ab0c11 100644 --- a/lib/http/2/framer.rb +++ b/lib/http/2/framer.rb @@ -119,6 +119,7 @@ def initialize(local_max_frame_size = DEFAULT_MAX_FRAME_SIZE, remote_max_frame_size = DEFAULT_MAX_FRAME_SIZE) @local_max_frame_size = local_max_frame_size @remote_max_frame_size = remote_max_frame_size + @frames = [] end # Generates common 9-byte frame header. @@ -371,6 +372,21 @@ def generate(frame) # # @param buf [Buffer] def parse(buf) + while (frame = decode_frame(buf)) + if frame[:type] == :ping + # PING responses SHOULD be given higher priority than any other frame. + @frames.unshift(frame) + else + @frames << frame + end + end + + @frames.shift + end + + private + + def decode_frame(buf) return if buf.size < 9 frame = read_common_header(buf) @@ -491,8 +507,6 @@ def parse(buf) frame end - private - def pack_error(error, buffer:) unless error.is_a? Integer error = DEFINED_ERRORS[error] diff --git a/sig/framer.rbs b/sig/framer.rbs index 5205990..ffc66b2 100644 --- a/sig/framer.rbs +++ b/sig/framer.rbs @@ -34,6 +34,7 @@ module HTTP2 @local_max_frame_size: Integer @remote_max_frame_size: Integer + @streams: Hash[Integer, Stream] attr_accessor local_max_frame_size: Integer @@ -47,12 +48,14 @@ module HTTP2 def generate: (frame) -> String - def parse: (String) -> frame? + def parse: (String buf) -> frame? private def initialize: (?Integer local_max_frame_size, ?Integer remote_max_frame_size) -> untyped + def decode_frame: (String buf) -> frame? + def pack_error: (Integer | Symbol error, buffer: String) -> String def unpack_error: (Integer) -> (Symbol | Integer) diff --git a/spec/shared_examples/connection.rb b/spec/shared_examples/connection.rb index a2e9f20..b43683f 100644 --- a/spec/shared_examples/connection.rb +++ b/spec/shared_examples/connection.rb @@ -135,6 +135,16 @@ expect(pong).to eq "12345678" end + it "should not fire callback on PONG if connection is closed" do + conn << f.generate(settings_frame) + conn << f.generate(goaway_frame) + + pong = nil + conn.ping("12345678") { |d| pong = d } + conn << f.generate(pong_frame) + expect(pong).to be_nil + end + it "should fire callback on receipt of GOAWAY" do last_stream, payload, error = nil conn << f.generate(settings_frame)