spdy3 的名称/值块有时无法用 python 解压缩
Posted
技术标签:
【中文标题】spdy3 的名称/值块有时无法用 python 解压缩【英文标题】:spdy3's name/value block can't be decompressed SOMETIMES with python 【发布时间】:2014-01-23 09:10:15 【问题描述】:我正在为 chrome 构建一个 spdy 代理服务器。
当从 chrome 发送代理请求时,通常我会收到 3 帧:
-
一个 SETTINGS 框架(正确解析)
https 的 CONNECT 请求的 SYN_STREAM 帧(也已正确解析)
另一个无法解压缩名称/值块的 SYN_STREAM 帧(解压缩数据时出现错误 -3:标头检查不正确)
最后一帧很奇怪,因为我可以解析第一个 SYN_STREAM,它也有名称/值块。
我整整2天都在尝试解决这个问题,甚至将spdy版本从2切换到3,但仍然无法解决。
这是我的解压缩函数(Python 3.3):
def decompress(buf):
decompressor = zlib.decompressobj(zdict=DICT3)
# DICT3 is the dictionary of spdy3 to decompress NV block
return decompressor.decompress(buf)
这是日志的完整示例:
(1)2014-01-06 14:44:55,070 proxy DEBUG: [49036176] on_read b'\x80\x03\x00\x04\x00\x00\x00\x14\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x03\xe8\x00\x00\x00\x07\x00\xa0\x00\x00\x80\x03\x00\x01\x00\x00\x00\xbf\x00\x00\x00\x01\x00\x00\x00\x00\x00\x008\xea\xe3\xc6\xa7\xc2\x02e%\x10\xb6\x82\x16\x08\\\xc0\xd4U\x90X\xa9\x97\x0c.&\xd8\xad\xe0\x89\x99\xdd\xd9\xdf\xcf\xcf\xd59\x04\xac\xb8 \x11\\l\xf1\x01\x04PbNfAb\xa5^r~\xae\x95\x89\x891@\x00\x81\x12\xb3\x15\xf6\x84\x8d\x9a\xa1r|\xf3\xab2sr\x12\xf5M\xf5\x0c\x144\xc23\xf3R\xf2\xcb\x8b\x15\xfcB\x14\xcc\xf4\x0c\xad\x15\xc2\xfd\xc3\xcdL4\x811\x06\x8c\xdf\xf0\xd4$\xef\xcc\x12Scs=c3\x05\ro\x8f\x10_\x1f\x1d\x85\x9c\xcc\xecT\x05\xf7\xd4\xe4\xec|M\x05\xe7\x0c`\x89\x96\xaaol\xa8g\xa0ghfj\xa0g\x06L\x0b\x89i\x89E\x99P]\x00\x00\x00\x00\xff\xff\x80\x03\x00\x01\x00\x00\x00)\x00\x00\x00\x03\x00\x00\x00\x00`\x00\xa2\xcc\x87\x00\x01\x94\x98\x93Y\x90X\xa9\x97\x9c\x9fkebb\x0c\x10@\x83\xd3\x87\x00\x00\x00\x00\xff\xff'
(2)2014-01-06 14:44:55,071 proxy DEBUG: [49036176] >-- <SETTINGS SETTINGS_MAX_CONCURRENT_STREAMS=1000 SETTINGS_INITIAL_WINDOW_SIZE=10485760 [20]>
(3)2014-01-06 14:44:55,073 proxy DEBUG: [49036176] >-- <SYN_STREAM #1->#0 [191]:host: alipay.com :method: CONNECT :version: HTTP/1.1 :path: alipay.com:443 user-agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/31.0.1650.63 Safari/537.36 >
(4)2014-01-06 14:44:55,074 proxy DEBUG: [49036176] error Error -3 while decompressing data: incorrect header check
(5)2014-01-06 14:44:55,074 proxy DEBUG: [49036176] zlib.e b'\x80\x03\x00\x01\x00\x00\x00)\x00\x00\x00\x03\x00\x00\x00\x00`\x00\xa2\xcc\x87\x00\x01\x94\x98\x93Y\x90X\xa9\x97\x9c\x9fkebb\x0c\x10@\x83\xd3\x87\x00\x00\x00\x00\xff\xff'
(6)2014-01-06 14:45:25,070 proxy DEBUG: [49036176] on_read b'\x80\x03\x00\x03\x00\x00\x00\x08\x00\x00\x00\x01\x00\x00\x00\x05\x80\x03\x00\x01\x00\x00\x00)\x00\x00\x00\x05\x00\x00\x00\x00`\x00\xa2\xcc\x87\x00\x01\x94\x98\x93Y\x90X\xa9\x97\x9c\x9fkebb\x0c\x10@\x83\xd3\x87\x00\x00\x00\x00\xff\xff\x80\x03\x00\x03\x00\x00\x00\x08\x00\x00\x00\x03\x00\x00\x00\x05'
(7)2014-01-06 14:45:25,072 proxy DEBUG: [49036176] >-- <RST_STREAM #1 [8]CANCEL>
让我解释一下:
(1) 代理从套接字接收到原始字节,其中包含 3 个 spdy 帧
(2) 从 (1) 的字节中解析出一个 SETTINGS 帧
b'\x80\x03\x00\x04\x00\x00\x00\x14\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x03\xe8\x00\x00\x00\x07\x00\xa0\x00\x00
(3) 还解析了一个 SYN_STREAM 帧
b'\x80\x03\x00\x01\x00\x00\x00\xbf\x00\x00\x00\x01\x00\x00\x00\x00\x00\x008\xea\xe3\xc6\xa7\xc2\x02e%\x10\xb6\x82\x16\x08\\\xc0\xd4U\x90X\xa9\x97\x0c.&\xd8\xad\xe0\x89\x99\xdd\xd9\xdf\xcf\xcf\xd59\x04\xac\xb8 \x11\\l\xf1\x01\x04PbNfAb\xa5^r~\xae\x95\x89\x891@\x00\x81\x12\xb3\x15\xf6\x84\x8d\x9a\xa1r|\xf3\xab2sr\x12\xf5M\xf5\x0c\x144\xc23\xf3R\xf2\xcb\x8b\x15\xfcB\x14\xcc\xf4\x0c\xad\x15\xc2\xfd\xc3\xcdL4\x811\x06\x8c\xdf\xf0\xd4$\xef\xcc\x12Scs=c3\x05\ro\x8f\x10_\x1f\x1d\x85\x9c\xcc\xecT\x05\xf7\xd4\xe4\xec|M\x05\xe7\x0c`\x89\x96\xaaol\xa8g\xa0ghfj\xa0g\x06L\x0b\x89i\x89E\x99P]\x00\x00\x00\x00\xff\xff'
(4) 继续解析时,遇到另一个SYN_STREAM
b'\x80\x03\x00\x01\x00\x00\x00)\x00\x00\x00\x03\x00\x00\x00\x00`\x00\xa2\xcc\x87\x00\x01\x94\x98\x93Y\x90X\xa9\x97\x9c\x9fkebb\x0c\x10@\x83\xd3\x87\x00\x00\x00\x00\xff\xff'
但是名称/值块部分无法解压
这6-8个字节告诉剩余数据的长度(长度:'\x00\x00'=41),尾部是'\x00\x00\xff\xff',所以我应该把帧正确。
在“长度字节”之后,压缩后的名称/值块之前还有 10 个其他字节。
(5) 捕获到错误,列出了故障帧的字节,实际压缩的名称/值块的字节为:
b'\xa2\xcc\x87\x00\x01\x94\x98\x93Y\x90X\xa9\x97\x9c\x9fkebb\x0c\x10@\x83\xd3\x87\x00\x00\x00\x00\xff\xff'
(6/7) chrome有一阵子没回复了,所以它发送了一个RST_STREAM帧来取消之前的(3)的SYN_STREAM请求(这样就OK了)
解压功能有什么问题?
或者有谁知道如何解压第二个 SYN_STREAM 的 NV 块?
谢谢!
编辑:
我添加了一个完整的日志示例。
感谢@Mark,我看到 .flush() 没有被调用,但主要错误是“不正确的标题”)
【问题讨论】:
【参考方案1】:您需要冲洗。例如:
temp = decompressor.decompress(buf)
return temp + decompressor.flush()
即便如此,您提供的数据也不是有效的 zlib 流。会不会是上一个流的延续?
【讨论】:
感谢您的回答。我最近才意识到“冲洗”步骤。但主要问题是“不正确的标题”错误,让我在我的问题中添加更多详细信息。 请提供前面压缩的数据。以上是关于spdy3 的名称/值块有时无法用 python 解压缩的主要内容,如果未能解决你的问题,请参考以下文章