http / 2动态表解码出错

时间:2017-07-08 05:13:03

标签: protocols wireshark capture network-protocols http2

我尝试实施http / 2代码,我试图向谷歌发送请求。我查看了Wirehark Mozilla Firefox是如何做到的。这是一个例子:

这是第一个SETTINGS框架之后第一个google请求

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>

所以客户端的动态表看起来像这样,假设我明白这一点:

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 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应该是标头的索引。文字增量索引的掩码为0x40,因此我们使用AND0x7f进行布尔0x3f,得到‭63‬十进制,即dnt: 1我们的动态表中的标头,这是完全错误的。 有人可以帮忙,这怎么解码正确? http / 2是否使用相同的动态表进行响应解码? (也许那就是为什么我的解码搞砸了?)

1 个答案:

答案 0 :(得分:1)

通过仅在查找索引字段信息后查看单个字节(0x7f0x3f),计算错误的索引号。但是,您还需要另外查看HPACK中如何表示整数(以及头字段索引)。 HPACK规范中的5.1 Integer Representation部分对此进行了介绍。

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

顺便说一句:有趣的是它没有从静态表中选择索引19,即accept。从我的角度来看,这里没有额外的值来引用动态表,只有字段名称(并且没有采用任何值),并且在静态表中查找可能会减少某些实现的开销。

澄清这些问题:

  

http / 2是否使用相同的动态表进行响应解码?

不,所有已发送标头的动态表都有一个实例(客户端请求标头),所有收到的标头都有一个实例(客户端的响应标头)。