From 81b83590fb7ee7b316595dd1e405c3c4882c15d1 Mon Sep 17 00:00:00 2001 From: HoneyryderChuck Date: Mon, 22 Jul 2024 15:19:54 +0100 Subject: [PATCH] allow RST_STREAM to be received when a stream has been recently closed as per spec. fixed other tests wrongly using closed streams. --- .rubocop.yml | 3 +++ lib/http/2/connection.rb | 7 +++++++ spec/client_spec.rb | 3 --- spec/server_spec.rb | 12 ++++++++++++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index c151f92..0e1981b 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -21,6 +21,9 @@ Layout/HeredocIndentation: Metrics/BlockLength: Enabled: false +Metrics/PerceivedComplexity: + Enabled: false + Lint/EmptyWhen: Enabled: false diff --git a/lib/http/2/connection.rb b/lib/http/2/connection.rb index 8e3aecc..a13ef74 100644 --- a/lib/http/2/connection.rb +++ b/lib/http/2/connection.rb @@ -391,6 +391,13 @@ def receive(data) stream = @streams_recently_closed[frame[:stream]] connection_error(:protocol_error, msg: "sent window update on idle stream") unless stream process_window_update(frame: frame, encode: true) + # Endpoints MUST ignore + # WINDOW_UPDATE or RST_STREAM frames received in this state (closed), though + # endpoints MAY choose to treat frames that arrive a significant + # time after sending END_STREAM as a connection error. + when :rst_stream + stream = @streams_recently_closed[frame[:stream]] + connection_error(:protocol_error, msg: "sent window update on idle stream") unless stream else # An endpoint that receives an unexpected stream identifier # MUST respond with a connection error of type PROTOCOL_ERROR. diff --git a/spec/client_spec.rb b/spec/client_spec.rb index 640ecd0..2198c72 100644 --- a/spec/client_spec.rb +++ b/spec/client_spec.rb @@ -205,7 +205,6 @@ it "should emit :altsvc" do s = client.new_stream s.send headers_frame - s.close frame = nil s.on(:altsvc) { |f| frame = f } @@ -217,7 +216,6 @@ it "should not emit :alt_svc when the frame when contains a origin" do s = client.new_stream s.send headers_frame - s.close frame = nil s.on(:altsvc) { |f| frame = f } @@ -270,7 +268,6 @@ it "should be ignored" do s = client.new_stream s.send headers_frame - s.close expect do client << set_stream_id(f.generate(orig_frame), s.id) diff --git a/spec/server_spec.rb b/spec/server_spec.rb index 83a6f43..8617714 100644 --- a/spec/server_spec.rb +++ b/spec/server_spec.rb @@ -118,9 +118,21 @@ stream.send data_frame stream.close + # WINDOW_UPDATE or RST_STREAM frames can be received in this state + # for a short period expect do srv << f.generate(rst_stream_frame.merge(stream: stream.id)) end.to_not raise_error + + expect do + srv << f.generate(window_update_frame.merge(stream: stream.id)) + end.to_not raise_error + + # PRIORITY frames can be sent on closed streams to prioritize + # streams that are dependent on the closed stream. + expect do + srv << f.generate(priority_frame.merge(stream: stream.id)) + end.to_not raise_error end end