Repository navigation
Fix header table size assignment #209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,9 +15,11 @@ def initialize(settings = Settings.new) | |
| @cc = EncodingContext.new(settings) | ||
| end | ||
|
|
||
| # Set dynamic table +size+ in EncodingContext | ||
| # Set the maximum dynamic table +size+ allowed by our acknowledged | ||
| # SETTINGS_HEADER_TABLE_SIZE. When the current table is larger, the | ||
| # next header block has to start with a dynamic table size update. | ||
| def table_size=(size) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same |
||
| @cc.table_size = size | ||
| @cc.max_table_size = size | ||
| end | ||
|
|
||
| # Decodes integer value from provided +buffer+. | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -101,12 +101,20 @@ class EncodingContext | |||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Initializes compression context with appropriate client/server | ||||||||||||||||||||||
| # +settings+ and maximum size of the dynamic table. | ||||||||||||||||||||||
| # | ||||||||||||||||||||||
| # The dynamic table starts at +settings.table_size+ octets. The same | ||||||||||||||||||||||
| # value is the initial maximum size allowed for the table. | ||||||||||||||||||||||
| def initialize(settings = Settings.new) | ||||||||||||||||||||||
| @table = [] | ||||||||||||||||||||||
| @table_by_field = Hash.new { |hs, k| hs[k] = [] } | ||||||||||||||||||||||
| @unshifts = 0 | ||||||||||||||||||||||
| @settings = settings | ||||||||||||||||||||||
| # Current dynamic table size, as known to both encoder and decoder. | ||||||||||||||||||||||
| @limit = settings.table_size | ||||||||||||||||||||||
| # Maximum dynamic table size allowed by SETTINGS_HEADER_TABLE_SIZE. | ||||||||||||||||||||||
| @max_limit = @limit | ||||||||||||||||||||||
| # Smallest maximum size set since the last dynamic table size update. | ||||||||||||||||||||||
| @lowest_max_limit = @limit | ||||||||||||||||||||||
|
Comment on lines
113
to
+117
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
(reads slightly better) |
||||||||||||||||||||||
| @_table_updated = false | ||||||||||||||||||||||
| @current_table_size = 0 | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
|
|
@@ -118,11 +126,15 @@ def dup | |||||||||||||||||||||
| tbf = @table_by_field.transform_values(&:dup) | ||||||||||||||||||||||
| unshifts = @unshifts | ||||||||||||||||||||||
| l = @limit | ||||||||||||||||||||||
| ml = @max_limit | ||||||||||||||||||||||
| lml = @lowest_max_limit | ||||||||||||||||||||||
| other.instance_eval do | ||||||||||||||||||||||
| @table = t.dup # shallow copy | ||||||||||||||||||||||
| @table_by_field = tbf | ||||||||||||||||||||||
| @unshifts = unshifts | ||||||||||||||||||||||
| @limit = l | ||||||||||||||||||||||
| @max_limit = ml | ||||||||||||||||||||||
| @lowest_max_limit = lml | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
| other | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
|
|
@@ -152,16 +164,21 @@ def process(cmd) | |||||||||||||||||||||
| name = cmd[:name] | ||||||||||||||||||||||
| value = cmd[:value] | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # The maximum size was reduced below the current table size and the | ||||||||||||||||||||||
| # encoder has not signalled a size that fits into it. | ||||||||||||||||||||||
| raise CompressionError, "dynamic table size update required" if type != :changetablesize && @lowest_max_limit < @limit | ||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this clause can be moved below L163 |
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| case type | ||||||||||||||||||||||
| when :changetablesize | ||||||||||||||||||||||
| raise CompressionError, "tried to change table size after adding elements to table" if @_table_updated | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # we can receive multiple table size change commands inside a header frame. However, | ||||||||||||||||||||||
| # we should blow up if we receive another frame where the new table size is bigger. | ||||||||||||||||||||||
| table_size_updated = @limit != @settings.table_size | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| raise CompressionError, "dynamic table size update exceed limit" if !table_size_updated && value > @limit | ||||||||||||||||||||||
| # The new maximum size MUST be lower than or equal to the limit set | ||||||||||||||||||||||
| # by SETTINGS_HEADER_TABLE_SIZE. | ||||||||||||||||||||||
| # - https://www.rfc-editor.org/rfc/rfc7541#section-6.3 | ||||||||||||||||||||||
| raise CompressionError, "dynamic table size update exceed limit" if value > @max_limit | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # The smallest maximum size set since the last update is signalled. | ||||||||||||||||||||||
| @lowest_max_limit = @max_limit if value <= @lowest_max_limit | ||||||||||||||||||||||
| self.table_size = value | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| nil | ||||||||||||||||||||||
|
|
@@ -210,10 +227,26 @@ def process(cmd) | |||||||||||||||||||||
| end | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Plan +headers+ compression. | ||||||||||||||||||||||
| # | ||||||||||||||||||||||
| # Emits dynamic table size updates first when the table size has to | ||||||||||||||||||||||
| # change. See #max_table_size=. | ||||||||||||||||||||||
| def encode(headers) | ||||||||||||||||||||||
| # Literals commands are marked with :noindex when index is not used | ||||||||||||||||||||||
| noindex = STATIC_NEVER.include?(@settings.index) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| if @lowest_max_limit < @limit | ||||||||||||||||||||||
| self.table_size = @lowest_max_limit | ||||||||||||||||||||||
| yield({ type: :changetablesize, value: @limit }) | ||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I know that ultimately it's the same, but it is easier to read. |
||||||||||||||||||||||
| end | ||||||||||||||||||||||
| @lowest_max_limit = @max_limit | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| size = @settings.table_size | ||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💅 renaming var to |
||||||||||||||||||||||
| size = @max_limit if @max_limit < size | ||||||||||||||||||||||
|
Comment on lines
+241
to
+244
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
| if size != @limit | ||||||||||||||||||||||
| self.table_size = size | ||||||||||||||||||||||
| yield({ type: :changetablesize, value: size }) | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| headers.each do |field, value| | ||||||||||||||||||||||
| # Literal header names MUST be translated to lowercase before | ||||||||||||||||||||||
| # encoding and transmission. | ||||||||||||||||||||||
|
|
@@ -276,6 +309,24 @@ def table_size=(size) | |||||||||||||||||||||
| resize_table(0) | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Set the maximum dynamic table +size+ allowed by | ||||||||||||||||||||||
| # SETTINGS_HEADER_TABLE_SIZE. | ||||||||||||||||||||||
| # | ||||||||||||||||||||||
| # The current table size does not change here. It changes only with a | ||||||||||||||||||||||
| # dynamic table size update at the beginning of a header block: | ||||||||||||||||||||||
| # - an encoder emits the update in the next #encode call. It uses | ||||||||||||||||||||||
| # +settings.table_size+, capped by this maximum. | ||||||||||||||||||||||
| # - a decoder requires the update in the next header block when the | ||||||||||||||||||||||
| # current table size exceeds this maximum. | ||||||||||||||||||||||
| # | ||||||||||||||||||||||
| # When the maximum is reduced and then increased again before the next | ||||||||||||||||||||||
| # header block, the smallest maximum has to be signalled first. | ||||||||||||||||||||||
| # - https://www.rfc-editor.org/rfc/rfc7541#section-4.2 | ||||||||||||||||||||||
| def max_table_size=(size) | ||||||||||||||||||||||
| @max_limit = size | ||||||||||||||||||||||
| @lowest_max_limit = size if size < @lowest_max_limit | ||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there should be a boolean variable set to true here, i.e. |
||||||||||||||||||||||
| end | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def listen_on_table | ||||||||||||||||||||||
| yield | ||||||||||||||||||||||
| ensure | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that this method should be rename to
max_table_size, wdyt?