Skip to content

Commit 39ec88d

Browse files
Merge pull request #185 from zarqman/allow-multiple-goaway
Allow multiple GOAWAY frames
2 parents 99cdf08 + 14fbf81 commit 39ec88d

11 files changed

Lines changed: 35 additions & 24 deletions

File tree

lib/http/2/connection.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,8 @@ def connection_management(frame)
525525
when :closed
526526
case frame_type
527527
when :goaway
528-
connection_error
528+
# 6.8. GOAWAY
529+
# An endpoint MAY send multiple GOAWAY frames if circumstances change.
529530
when :ping
530531
ping_management(frame)
531532
else

lib/http/2/extensions.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def append_str(str, data)
2525
def read_str(str, n)
2626
return "".b if n == 0
2727

28-
chunk = str.byteslice(0..n - 1)
28+
chunk = str.byteslice(0..(n - 1))
2929
remaining = str.byteslice(n..-1)
3030
remaining ? str.replace(remaining) : str.clear
3131
chunk

lib/http/2/framer.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ def read_common_header(buf)
185185
{
186186
type: type,
187187
flags: FRAME_FLAGS[type].filter_map do |name, pos|
188-
name if flags.anybits?((1 << pos))
188+
name if flags.anybits?(1 << pos)
189189
end,
190190
length: length,
191191
stream: stream & RBIT
@@ -359,7 +359,7 @@ def generate(frame)
359359
# Padding: Padding octets that contain no application semantic value.
360360
# Padding octets MUST be set to zero when sending and ignored when
361361
# receiving.
362-
append_str(bytes, ("\0" * padlen))
362+
append_str(bytes, "\0" * padlen)
363363
end
364364

365365
frame[:length] = length

lib/http/2/header/encoding_context.rb

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ def process(cmd)
211211
emit = [name, value]
212212

213213
# add to table
214-
if type == :incremental && size_check(name.bytesize + value.bytesize + 32)
214+
if type == :incremental && size_check?(name.bytesize + value.bytesize + 32)
215215
@table.unshift(emit)
216216
@current_table_size += name.bytesize + value.bytesize + 32
217217
@_table_updated = true
@@ -302,7 +302,7 @@ def addcmd(field, value)
302302
# When the size is reduced, some headers might be evicted.
303303
def table_size=(size)
304304
@limit = size
305-
size_check(0)
305+
resize_table(0)
306306
end
307307

308308
def listen_on_table
@@ -313,22 +313,25 @@ def listen_on_table
313313

314314
private
315315

316+
def resize_table(cmdsize)
317+
return if @table.empty?
318+
319+
while @current_table_size + cmdsize > @limit
320+
321+
name, value = @table.pop
322+
@current_table_size -= name.bytesize + value.bytesize + 32
323+
break if @table.empty?
324+
325+
end
326+
end
327+
316328
# To keep the dynamic table size lower than or equal to @limit,
317329
# remove one or more entries at the end of the dynamic table.
318330
#
319331
# @param cmdsize [Integer]
320332
# @return [Boolean] whether +cmd+ fits in the dynamic table.
321-
def size_check(cmdsize)
322-
unless @table.empty?
323-
while @current_table_size + cmdsize > @limit
324-
325-
name, value = @table.pop
326-
@current_table_size -= name.bytesize + value.bytesize + 32
327-
break if @table.empty?
328-
329-
end
330-
end
331-
333+
def size_check?(cmdsize)
334+
resize_table(cmdsize)
332335
cmdsize <= @limit
333336
end
334337
end

lib/http/2/header/huffman.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ module Huffman
2929
def encode(str, buffer = "".b)
3030
bitstring = String.new("", encoding: Encoding::BINARY, capacity: (str.bytesize * 30) + ((8 - str.size) % 8))
3131
str.each_byte { |chr| append_str(bitstring, ENCODE_TABLE[chr]) }
32-
append_str(bitstring, ("1" * ((8 - bitstring.size) % 8)))
32+
append_str(bitstring, "1" * ((8 - bitstring.size) % 8))
3333
pack([bitstring], "B*", buffer: buffer)
3434
end
3535

sig/header/encoding_context.rbs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ module HTTP2
4646

4747
def add_to_table: (string name, string value) -> void
4848

49-
def size_check: (Integer cmdsize) -> bool
49+
def resize_table: (Integer cmdsize) -> void
50+
51+
def size_check?: (Integer cmdsize) -> bool
5052
end
5153
end
5254
end

spec/connection_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
RSpec.describe HTTP2::Connection do
66
include FrameHelpers
7+
78
let(:conn) { Client.new }
89
let(:f) { Framer.new }
910

spec/emitter_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
RSpec.describe HTTP2::Emitter do
66
class Worker
77
include Emitter
8+
89
def initialize
910
@listeners = Hash.new { |hash, key| hash[key] = [] }
1011
end

spec/shared_examples/connection.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,11 +173,13 @@
173173
expect { conn << f.generate(ping_frame) }.not_to raise_error(ProtocolError)
174174
end
175175

176-
it "should respond with protocol error when receiving goaway" do
176+
it "should ignore additional goaway" do
177+
expect { conn << f.generate(settings_frame) }.not_to raise_error(ProtocolError)
178+
177179
conn.goaway
178180
expect(conn).to be_closed
179181

180-
expect { conn << f.generate(goaway_frame) }.to raise_error(ProtocolError)
182+
expect { conn << f.generate(goaway_frame) }.not_to raise_error(ProtocolError)
181183
end
182184

183185
it "should raise error on frame for invalid stream ID" do

spec/stream_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
RSpec.describe HTTP2::Stream do
66
include FrameHelpers
7+
78
let(:f) { Framer.new }
89
let(:client) { Client.new }
910
let(:stream) { client.new_stream }

0 commit comments

Comments
 (0)