Блок имени/значения spdy3 не может быть распакован ИНОГДА с помощью python

Я собирал прокси-сервер spdy для chrome.

Когда прокси-запросы отправлялись из хрома, обычно я получал 3 кадра:

  1. кадр НАСТРОЙКИ (правильно проанализирован)
  2. кадр SYN_STREAM запроса HTTPS CONNECT (тоже проанализирован правильно)
  3. другой кадр 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\x12}Scs=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) Кадр SETTINGS был проанализирован из байтов (1)

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\x12}Scs=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) Я некоторое время не отвечал на хром, поэтому он отправил кадр RST_STREAM, чтобы отменить предыдущий запрос SYN_STREAM (3) (это нормально)

В чем проблема с функцией распаковки?

или кто-нибудь знает, как распаковать NV-блок второго SYN_STREAM?

Спасибо!

изменить:

Добавляю полный пример логов.

Благодаря @Mark я вижу, что .flush() не вызывался, но основной ошибкой был «неправильный заголовок»)


person Vergil Lu    schedule 06.01.2014    source источник


Ответы (1)


Вам нужно смывать. Например.:

temp = decompressor.decompress(buf)
return temp + decompressor.flush()

Тем не менее, предоставленные вами данные не являются действительным потоком zlib. Возможно, это продолжение предыдущего стрима?

person Mark Adler    schedule 06.01.2014
comment
Спасибо за ответ. Я только недавно понял шаг «флеш». но основная проблема заключается в ошибке «неправильный заголовок», позвольте мне добавить больше деталей в мой вопрос. - person Vergil Lu; 06.01.2014
comment
Предоставьте непосредственно предшествующие сжатые данные. - person Mark Adler; 06.01.2014