http/2动态table解码出错

http/2 dynamic table decoding goes wrong

我尝试执行 http/2 代码,我正在尝试向 google 发送请求。我在 wireshark 中查看了 Mozilla Firefox 是如何做到的。这是一个例子:

这是对 google 的第一个请求,在第一个 SETTINGS

之后
Header Block Fragment: 8205a563fc9a52c5649012cf829a03f1f3372e66f78c9eb6...
[Header Length: 590]
[Header Count: 11]
Header: :method: GET
    Representation: Indexed Header Field

Header: :path: /?gfe_rd=cr&ei=oVxgWYizHcyRZK-lqKgG&gws_rd=ssl
    Representation: Literal Header Field without Indexing - Indexed Name

Header: :authority: www.google.ru
    Representation: Literal Header Field with Incremental Indexing - Indexed Name

Header: :scheme: https
    Representation: Indexed Header Field

Header: user-agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0
    Representation: Literal Header Field with Incremental Indexing - Indexed Name

Header: accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Representation: Literal Header Field with Incremental Indexing - Indexed Name

Header: accept-language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
    Representation: Literal Header Field with Incremental Indexing - Indexed Name

Header: accept-encoding: gzip, deflate, br
    Representation: Literal Header Field with Incremental Indexing - Indexed Name

Header: cookie: NID=107=L67kU0sEsfzwpItJcUZyRfjKENJ1xa2N8_m4xqnVLCj9dW289EDyzg7ZvXZCt9kEII0nd5BA2Tns95vlkCGlGP850ULPoOKFeMJoaQT_0o7Cl3skG4PDdQgUW2hlRh7Z
    Representation: Literal Header Field with Incremental Indexing - Indexed Name

Header: dnt: 1
    Representation: Literal Header Field with Incremental Indexing - New Name

Header: upgrade-insecure-requests: 1
    Representation: Literal Header Field with Incremental Indexing - New Name
Padding: <MISSING>

因此客户端的动态 table 将如下所示,假设我理解正确:

1 ->upgrade-insecure-requests: 1
2 ->dnt :1
3 ->cookie: NID=107=kjxoLmF8StT6CO8a8T-z68DAIJB6cyzAwqWOjjmXGubtu2pmJSfGPCjUAo9D-OTzuk03u34YLxLMjH236FBDzKVYayleievvTkamyhrLuOz4AYT_7KiuVIS5JA_BuVEa
4 ->accept-encoding: gzip, deflate, br
5 ->accept-language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
6 ->accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
7 ->user-agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0
8 ->:authority: www.google.ru

所有标记为Representation: Literal Header Field with Incremental Indexing的header都插入到动态table中,先插入的,移动到更高的索引,新条目在最前面.

但是这个 table 不起作用,因为当浏览器执行第二个请求时,要下载一些图像(google 徽标或其他),一些混乱正在发生,

第二个请求已解码:

[Header Length: 535]
[Header Count: 11]
Header: :method: GET
    Representation: Indexed Header Field

Header: :path: /images/hpp/ic_wahlberg_product_core_48.png8.png
    Representation: Literal Header Field without Indexing - Indexed Name

Header: :authority: www.google.ru
    Representation: Indexed Header Field

Header: :scheme: https
    Representation: Indexed Header Field

Header: user-agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0
    Representation: Indexed Header Field

Header: accept: */*
    Representation: Literal Header Field with Incremental Indexing - Indexed Name

Header: accept-language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
    Representation: Indexed Header Field

Header: accept-encoding: gzip, deflate, br
    Representation: Indexed Header Field

Header: referer: https://www.google.ru/
    Representation: Literal Header Field with Incremental Indexing - Indexed Name

Header: cookie: NID=107=j8x_CchswQznRlhYWeTtf7rDE7QaxZBxbGeQevst16TVFJ3qOJjlsVwxEobdZaVAeUFboCuuUhu0VdJwujroT_u5hoGttx5Mcu4xnMZQIfK7OSMhqtSbO135AL8GlZWU
    Representation: Literal Header Field with Incremental Indexing - Indexed Name

Header: dnt: 1
    Representation: Indexed Header Field

Padding: <MISSING>

这是编码的第二个请求:

82 = :method: GET ( index 2 in the static table is "method: GET" )
05 a3 60 d4 8e 62 a1 89 eb ad 83 12 2f 03 9e 88
cb 64 d1 57 61 e4 b4 89 88 87 b0 b1 34 f2 f5 d5
33 cb d7 54 df  = :path: /images/hpp/ic_wahlberg_product_core_48.png8.png (05 is the index of "path:" in static table, rest is huffman encoded literal )
c5 = :authority: www.google.ru ( index 8 at the dynamic table, 0xc5 & 0x7f = 69 (dec) static table length (61)? is this correct?
87 = scheme: https - static table
c4 = user-agent: Mozilla/5.0... ( index 7 at the dynamic table, 0xc5 & 0x7f = 68 (dec) static table length (61)? is this correct?

这里是我无法理解的地方:

7f 04 83 f9 63 e7 - 这假设根据 wireshark 表示 accept: */* 并且它被标记为 Literal Header Field with Incremental Indexing - Indexed Name,所以 0x7f 应该是 [=51= 的索引].文字增量索引的掩码是 0x40,所以我们用 0x3f0x7f 上做布尔值 AND,我们得到 ‭63‬ 十进制,也就是 dnt: 1 header 来自我们的动态 table,这是完全不正确的。 有人可以帮忙,这是如何正确解码的? http/2 是否使用相同的动态 table 进行响应解码? (也许这就是为什么我的解码搞砸了?)

您仅通过查看单个字节(0x7f0x3f 剥离索引字段信息后计算索引号是错误的。但是,您还需要查看整数(以及 header 字段索引)在 HPACK 中的表示方式。这包含在 HPACK 规范的 5.1 Integer Representation 部分。

你可以在那里看到,如果第一个字节中用于数字的所有位都设置为零,你也需要考虑下一个字节。在这种情况下会发生这种情况,因为 0x3f 意味着所有使用的 6 位都设置为 1。因此实际索引号被编码为 0x7f 0x04。我认为这应该导致 63+4 = 67,这是动态 table 的第 6 个条目。在第一次请求后,这将与您预期的动态 table 布局相匹配。

顺便说一句:有趣的是它没有 select 索引 19,它是来自静态 table 的 accept。从我的角度来看,这里没有额外的价值来引用动态 table ,当只有字段名称(并且没有取值)时,在静态 table 中查找东西可能会减少开销对于某些实现。

并澄清这个问题:

Does http/2 uses the same dynamic table for response decoding?

不,所有发送的headers(客户端请求headers)有一个动态table实例,所有接收的header有一个实例]s(在客户端响应 headers)。