Skip to content

Commit

Permalink
Ensure we *always* send a dynamic table resize command
Browse files Browse the repository at this point in the history
Closer reading of RFC9113§4.3.1para¶4 (https://www.rfc-editor.org/rfc/rfc9113.html#section-4.3.1)
suggests that we should always send a dynamic resize

Fixes elixir-mint#20
  • Loading branch information
mtrudel committed Dec 19, 2024
1 parent 6d034a1 commit e82d8e1
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 14 deletions.
18 changes: 8 additions & 10 deletions lib/hpax/table.ex
Original file line number Diff line number Diff line change
Expand Up @@ -264,24 +264,22 @@ defmodule HPAX.Table do
In all cases, the table's `:protocol_max_table_size` is updated accordingly
"""
@spec resize(t(), non_neg_integer()) :: t()
def resize(%__MODULE__{max_table_size: max_table_size} = table, new_protocol_max_table_size)
when new_protocol_max_table_size >= max_table_size do
%__MODULE__{
table
| protocol_max_table_size: new_protocol_max_table_size,
max_table_size: new_protocol_max_table_size
}
end

def resize(%__MODULE__{} = table, new_protocol_max_table_size) do
pending_minimum_resize =
case table.pending_minimum_resize do
nil -> new_protocol_max_table_size
current -> min(current, new_protocol_max_table_size)
end

table =
if new_protocol_max_table_size < table.size do
evict_to_size(table, new_protocol_max_table_size)
else
table
end

%__MODULE__{
evict_to_size(table, new_protocol_max_table_size)
table
| protocol_max_table_size: new_protocol_max_table_size,
max_table_size: new_protocol_max_table_size,
pending_minimum_resize: pending_minimum_resize
Expand Down
38 changes: 34 additions & 4 deletions test/hpax_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ defmodule HPAXTest do

property "encode/3 prepends dynamic resizes at the start of a block" do
enc_table = HPAX.new(20_000)
# Start with a non-empty decode table
dec_table = HPAX.new(20_000)

# Put a record in both to prime the pump. The table sizes should match
Expand All @@ -120,14 +119,45 @@ defmodule HPAXTest do
assert enc_table.max_table_size == 20_000
assert dec_table.max_table_size == 20_000

# Encode a record after resizing the table. We expect a dynamic resize to be
# encoded and the for two table sizes to be identical after decoding
# Scenario 1: Simulate the decoder growing the table via settings

# First, the decoder resizes its table to some maximum size
dec_table = HPAX.resize(dec_table, 40_000)

# It then communicates that size to the encoder, who chooses a smaller size
enc_table = HPAX.resize(enc_table, 30_000)

# Now, encode a header
{encoded, enc_table} = HPAX.encode([{:store, "lame", "LAME"}], enc_table)
encoded = IO.iodata_to_binary(encoded)

# Ensure that we encoded a resize on the wire
assert <<0b001::3, rest::bitstring>> = encoded
assert {:ok, 30_000, _rest} = HPAX.Types.decode_integer(rest, 5)

# Finally, ensure that the decoder makes proper sense of this encoding and that it resizes
# back down to the size chosen by the encoder
assert {:ok, _decoded, dec_table} = HPAX.decode(encoded, dec_table)
assert dec_table.size == enc_table.size
assert enc_table.max_table_size == 30_000
assert dec_table.max_table_size == 30_000

# Scenario 2: Simulate the decoder shrinking the table ia settings

# First, the decoder resizes its table to some maximum size
dec_table = HPAX.resize(dec_table, 10_000)

# It then communicates that size to the encoder, who chooses a smaller size
enc_table = HPAX.resize(enc_table, 0)

# It then changes its mind and goes back up to a size still smaller than the decoder's choice
enc_table = HPAX.resize(enc_table, 1234)

# Now, encode a header
{encoded, enc_table} = HPAX.encode([{:store, "lame", "LAME"}], enc_table)
encoded = IO.iodata_to_binary(encoded)

# Ensure that we see two resizes in order
# Ensure that we encoded two resizes in order on the wire
assert <<0b001::3, rest::bitstring>> = encoded
assert {:ok, 0, rest} = HPAX.Types.decode_integer(rest, 5)
assert <<0b001::3, rest::bitstring>> = rest
Expand Down

0 comments on commit e82d8e1

Please sign in to comment.