% HTTP/2 Campaign # Frames expressed as binary str were generated using the solicit and hpack-rs # Rust crates (https://github.com/mlalic/solicit, https://github.com/mlalic/hpack-rs) # except Continuation Frames, Priority Frames and Push Promise Frames that we generated # using Go x/net/http2 and x/net/http2/hpack modules. + Syntax check = Configuring Scapy ~ http2 frame hpack build dissect data headers priority settings rststream pushpromise ping goaway winupdate continuation hpackhdrtable helpers import scapy.config scapy.config.conf.debug_dissector=True import scapy.packet import scapy.fields import scapy.contrib.http2 as h2 import re flags_bit_pattern = re.compile(r'''^\s+flags\s+=\s+\[.*['"]bit [0-9]+['"].*\]$''', re.M) def expect_exception(e, c): try: eval(c) return False except e: return True + HTTP/2 UVarIntField Test Suite = HTTP/2 UVarIntField.any2i ~ http2 frame field uvarintfield f = h2.UVarIntField('value', 0, 5) expect_exception(AssertionError, 'f.any2i(None, None)') assert f.any2i(None, 0) == 0 assert f.any2i(None, 3) == 3 assert f.any2i(None, 1<<5) == 1<<5 assert f.any2i(None, 1<<16) == 1<<16 f = h2.UVarIntField('value', 0, 8) assert f.any2i(None, b'\x1E') == 30 = HTTP/2 UVarIntField.m2i on full byte ~ http2 frame field uvarintfield f = h2.UVarIntField('value', 0, 8) assert f.m2i(None, b'\x00') == 0 assert f.m2i(None, b'\x03') == 3 assert f.m2i(None, b'\xFE') == 254 assert f.m2i(None, b'\xFF\x00') == 255 assert f.m2i(None, b'\xFF\xFF\x03') == 766 #0xFF + (0xFF ^ 0x80) + (3<<7 = HTTP/2 UVarIntField.m2i on partial byte ~ http2 frame field uvarintfield f = h2.UVarIntField('value', 0, 5) assert f.m2i(None, (b'\x00', 3)) == 0 assert f.m2i(None, (b'\x03', 3)) == 3 assert f.m2i(None, (b'\x1e', 3)) == 30 assert f.m2i(None, (b'\x1f\x00', 3)) == 31 assert f.m2i(None, (b'\x1f\xe1\xff\x03', 3)) == 65536 = HTTP/2 UVarIntField.getfield on full byte ~ http2 frame field uvarintfield f = h2.UVarIntField('value', 0, 8) r = f.getfield(None, b'\x00\x00') assert r[0] == b'\x00' assert r[1] == 0 r = f.getfield(None, b'\x03\x00') assert r[0] == b'\x00' assert r[1] == 3 r = f.getfield(None, b'\xFE\x00') assert r[0] == b'\x00' assert r[1] == 254 r = f.getfield(None, b'\xFF\x00\x00') assert r[0] == b'\x00' assert r[1] == 255 r = f.getfield(None, b'\xFF\xFF\x03\x00') assert r[0] == b'\x00' assert r[1] == 766 = HTTP/2 UVarIntField.getfield on partial byte ~ http2 frame field uvarintfield f = h2.UVarIntField('value', 0, 5) r = f.getfield(None, (b'\x00\x00', 3)) assert r[0] == b'\x00' assert r[1] == 0 r = f.getfield(None, (b'\x03\x00', 3)) assert r[0] == b'\x00' assert r[1] == 3 r = f.getfield(None, (b'\x1e\x00', 3)) assert r[0] == b'\x00' assert r[1] == 30 r = f.getfield(None, (b'\x1f\x00\x00', 3)) assert r[0] == b'\x00' assert r[1] == 31 r = f.getfield(None, (b'\x1f\xe1\xff\x03\x00', 3)) assert r[0] == b'\x00' assert r[1] == 65536 = HTTP/2 UVarIntField.i2m on full byte ~ http2 frame field uvarintfield f = h2.UVarIntField('value', 0, 8) assert f.i2m(None, 0) == b'\x00' assert f.i2m(None, 3) == b'\x03' assert f.i2m(None, 254).lower() == b'\xfe' assert f.i2m(None, 255).lower() == b'\xff\x00' assert f.i2m(None, 766).lower() == b'\xff\xff\x03' = HTTP/2 UVarIntField.i2m on partial byte ~ http2 frame field uvarintfield f = h2.UVarIntField('value', 0, 5) assert f.i2m(None, 0) == b'\x00' assert f.i2m(None, 3) == b'\x03' assert f.i2m(None, 30).lower() == b'\x1e' assert f.i2m(None, 31).lower() == b'\x1f\x00' assert f.i2m(None, 65536).lower() == b'\x1f\xe1\xff\x03' = HTTP/2 UVarIntField.addfield on full byte ~ http2 frame field uvarintfield f = h2.UVarIntField('value', 0, 8) assert f.addfield(None, b'Toto', 0) == b'Toto\x00' assert f.addfield(None, b'Toto', 3) == b'Toto\x03' assert f.addfield(None, b'Toto', 254).lower() == b'toto\xfe' assert f.addfield(None, b'Toto', 255).lower() == b'toto\xff\x00' assert f.addfield(None, b'Toto', 766).lower() == b'toto\xff\xff\x03' = HTTP/2 UVarIntField.addfield on partial byte ~ http2 frame field uvarintfield f = h2.UVarIntField('value', 0, 5) assert f.addfield(None, (b'Toto', 3, 4), 0) == b'Toto\x80' assert f.addfield(None, (b'Toto', 3, 4), 3) == b'Toto\x83' assert f.addfield(None, (b'Toto', 3, 4), 30).lower() == b'toto\x9e' assert f.addfield(None, (b'Toto', 3, 4), 31).lower() == b'toto\x9f\x00' assert f.addfield(None, (b'Toto', 3, 4), 65536).lower() == b'toto\x9f\xe1\xff\x03' = HTTP/2 UVarIntField.i2len on full byte ~ http2 frame field uvarintfield f = h2.UVarIntField('value', 0, 8) assert f.i2len(None, 0) == 1 assert f.i2len(None, 3) == 1 assert f.i2len(None, 254) == 1 assert f.i2len(None, 255) == 2 assert f.i2len(None, 766) == 3 = HTTP/2 UVarIntField.i2len on partial byte ~ http2 frame field uvarintfield f = h2.UVarIntField('value', 0, 5) assert f.i2len(None, 0) == 1 assert f.i2len(None, 3) == 1 assert f.i2len(None, 30) == 1 assert f.i2len(None, 31) == 2 assert f.i2len(None, 65536) == 4 + HTTP/2 FieldUVarLenField Test Suite = HTTP/2 FieldUVarLenField.i2m without adjustment ~ http2 frame field fielduvarlenfield f = h2.FieldUVarLenField('len', None, 8, length_of='data') class TrivialPacket(Packet): name = 'Trivial Packet' fields_desc= [ f, StrField('data', '') ] assert f.i2m(TrivialPacket(data='a'*5), None) == b'\x05' assert f.i2m(TrivialPacket(data='a'*255), None).lower() == b'\xff\x00' assert f.i2m(TrivialPacket(data='a'), 2) == b'\x02' assert f.i2m(None, 2) == b'\x02' assert f.i2m(None, 0) == b'\x00' = HTTP/2 FieldUVarLenField.i2m with adjustment ~ http2 frame field fielduvarlenfield class TrivialPacket(Packet): name = 'Trivial Packet' fields_desc= [ f, StrField('data', '') ] f = h2.FieldUVarLenField('value', None, 8, length_of='data', adjust=lambda x: x-1) assert f.i2m(TrivialPacket(data='a'*5), None) == b'\x04' assert f.i2m(TrivialPacket(data='a'*255), None).lower() == b'\xfe' #Adjustment does not affect non-None value! assert f.i2m(TrivialPacket(data='a'*3), 2) == b'\x02' + HTTP/2 HPackZString Test Suite = HTTP/2 HPackZString Compression ~ http2 hpack huffman string = 'Test' s = h2.HPackZString(string) assert len(s) == 3 assert raw(s) == b"\xdeT'" assert s.origin() == string string = 'a'*65535 s = h2.HPackZString(string) assert len(s) == 40960 assert raw(s) == (b'\x18\xc61\x8cc' * 8191) + b'\x18\xc61\x8c\x7f' assert s.origin() == string = HTTP/2 HPackZString Decompression ~ http2 hpack huffman s = b"\xdeT'" i, ibl = h2.HPackZString.huffman_conv2bitstring(s) assert b'Test' == h2.HPackZString.huffman_decode(i, ibl) s = (b'\x18\xc61\x8cc' * 8191) + b'\x18\xc61\x8c\x7f' i, ibl = h2.HPackZString.huffman_conv2bitstring(s) assert b'a'*65535 == h2.HPackZString.huffman_decode(i, ibl) assert( expect_exception(h2.InvalidEncodingException, 'h2.HPackZString.huffman_decode(*h2.HPackZString.huffman_conv2bitstring(b"\\xdeT"))') ) + HTTP/2 HPackStrLenField Test Suite = HTTP/2 HPackStrLenField.m2i ~ http2 hpack field hpackstrlenfield f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type') class TrivialPacket(Packet): name = 'Trivial Packet' fields_desc = [ IntField('type', None), IntField('len', None), f ] s = f.m2i(TrivialPacket(type=0, len=4), b'Test') assert isinstance(s, h2.HPackLiteralString) assert s.origin() == 'Test' s = f.m2i(TrivialPacket(type=1, len=3), b"\xdeT'") assert isinstance(s, h2.HPackZString) assert s.origin() == 'Test' = HTTP/2 HPackStrLenField.any2i ~ http2 hpack field hpackstrlenfield f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type') class TrivialPacket(Packet): name = 'Trivial Packet' fields_desc = [ IntField('type', None), IntField('len', None), f ] s = f.any2i(TrivialPacket(type=0, len=4), b'Test') assert isinstance(s, h2.HPackLiteralString) assert s.origin() == 'Test' s = f.any2i(TrivialPacket(type=1, len=3), b"\xdeT'") assert isinstance(s, h2.HPackZString) assert s.origin() == 'Test' s = h2.HPackLiteralString('Test') s2 = f.any2i(TrivialPacket(type=0, len=4), s) assert s.origin() == s2.origin() s = h2.HPackZString('Test') s2 = f.any2i(TrivialPacket(type=1, len=3), s) assert s.origin() == s2.origin() s = h2.HPackLiteralString('Test') s2 = f.any2i(None, s) assert s.origin() == s2.origin() s = h2.HPackZString('Test') s2 = f.any2i(None, s) assert s.origin() == s2.origin() # Verifies that one can fuzz s = h2.HPackLiteralString('Test') s2 = f.any2i(TrivialPacket(type=1, len=1), s) assert s.origin() == s2.origin() = HTTP/2 HPackStrLenField.i2m ~ http2 hpack field hpackstrlenfield f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type') s = b'Test' s2 = f.i2m(None, h2.HPackLiteralString(s)) assert s == s2 s = b'Test' s2 = f.i2m(None, h2.HPackZString(s)) assert s2 == b"\xdeT'" = HTTP/2 HPackStrLenField.addfield ~ http2 hpack field hpackstrlenfield f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type') s = b'Test' s2 = f.addfield(None, b'Toto', h2.HPackLiteralString(s)) assert b'Toto' + s == s2 s = b'Test' s2 = f.addfield(None, b'Toto', h2.HPackZString(s)) assert s2 == b"Toto\xdeT'" = HTTP/2 HPackStrLenField.getfield ~ http2 hpack field hpackstrlenfield f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type') class TrivialPacket(Packet): name = 'Trivial Packet' fields_desc = [ IntField('type', None), IntField('len', None), f ] r = f.getfield(TrivialPacket(type=0, len=4), b'TestToto') assert isinstance(r, tuple) assert r[0] == b'Toto' assert isinstance(r[1], h2.HPackLiteralString) assert r[1].origin() == 'Test' r = f.getfield(TrivialPacket(type=1, len=3), b"\xdeT'Toto") assert isinstance(r, tuple) assert r[0] == b'Toto' assert isinstance(r[1], h2.HPackZString) assert r[1].origin() == 'Test' = HTTP/2 HPackStrLenField.i2h / i2repr ~ http2 hpack field hpackstrlenfield f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type') s = b'Test' assert f.i2h(None, h2.HPackLiteralString(s)) == 'HPackLiteralString(Test)' assert f.i2repr(None, h2.HPackLiteralString(s)) == repr('HPackLiteralString(Test)') assert f.i2h(None, h2.HPackZString(s)) == 'HPackZString(Test)' assert f.i2repr(None, h2.HPackZString(s)) == repr('HPackZString(Test)') = HTTP/2 HPackStrLenField.i2len ~ http2 hpack field hpackstrlenfield f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type') s = b'Test' assert f.i2len(None, h2.HPackLiteralString(s)) == 4 assert f.i2len(None, h2.HPackZString(s)) == 3 + HTTP/2 HPackMagicBitField Test Suite # Magic bits are not supposed to be modified and if they are anyway, they must # be assigned the magic|default value only... = HTTP/2 HPackMagicBitField.addfield ~ http2 hpack field hpackmagicbitfield f = h2.HPackMagicBitField('value', 3, 2) r = f.addfield(None, b'Toto', 3) assert isinstance(r, tuple) assert r[0] == b'Toto' assert r[1] == 2 assert r[2] == 3 r = f.addfield(None, (b'Toto', 2, 1) , 3) assert isinstance(r, tuple) assert r[0] == b'Toto' assert r[1] == 4 assert r[2] == 7 assert expect_exception(AssertionError, 'f.addfield(None, "toto", 2)') = HTTP/2 HPackMagicBitField.getfield ~ http2 hpack field hpackmagicbitfield f = h2.HPackMagicBitField('value', 3, 2) r = f.getfield(None, b'\xc0') assert isinstance(r, tuple) assert len(r) == 2 assert isinstance(r[0], tuple) assert len(r[0]) == 2 assert r[0][0] == b'\xc0' assert r[0][1] == 2 assert r[1] == 3 r = f.getfield(None, (b'\x03', 6)) assert isinstance(r, tuple) assert len(r) == 2 assert isinstance(r[0], bytes) assert r[0] == b'' assert r[1] == 3 expect_exception(AssertionError, 'f.getfield(None, b"\\x80")') = HTTP/2 HPackMagicBitField.h2i ~ http2 hpack field hpackmagicbitfield f = h2.HPackMagicBitField('value', 3, 2) assert f.h2i(None, 3) == 3 expect_exception(AssertionError, 'f.h2i(None, 2)') = HTTP/2 HPackMagicBitField.m2i ~ http2 hpack field hpackmagicbitfield f = h2.HPackMagicBitField('value', 3, 2) assert f.m2i(None, 3) == 3 expect_exception(AssertionError, 'f.m2i(None, 2)') = HTTP/2 HPackMagicBitField.i2m ~ http2 hpack field hpackmagicbitfield f = h2.HPackMagicBitField('value', 3, 2) assert f.i2m(None, 3) == 3 expect_exception(AssertionError, 'f.i2m(None, 2)') = HTTP/2 HPackMagicBitField.any2i ~ http2 hpack field hpackmagicbitfield f = h2.HPackMagicBitField('value', 3, 2) assert f.any2i(None, 3) == 3 expect_exception(AssertionError, 'f.any2i(None, 2)') + HTTP/2 HPackHdrString Test Suite = HTTP/2 Dissect HPackHdrString ~ http2 pack dissect hpackhdrstring p = h2.HPackHdrString(b'\x04Test') assert p.type == 0 assert p.len == 4 assert isinstance(p.getfieldval('data'), h2.HPackLiteralString) assert p.getfieldval('data').origin() == 'Test' p = h2.HPackHdrString(b"\x83\xdeT'") assert p.type == 1 assert p.len == 3 assert isinstance(p.getfieldval('data'), h2.HPackZString) assert p.getfieldval('data').origin() == 'Test' = HTTP/2 Build HPackHdrString ~ http2 hpack build hpackhdrstring p = h2.HPackHdrString(data=h2.HPackLiteralString('Test')) assert raw(p) == b'\x04Test' p = h2.HPackHdrString(data=h2.HPackZString('Test')) assert raw(p) == b"\x83\xdeT'" #Fuzzing-able tests p = h2.HPackHdrString(type=1, len=3, data=h2.HPackLiteralString('Test')) assert raw(p) == b'\x83Test' + HTTP/2 HPackIndexedHdr Test Suite = HTTP/2 Dissect HPackIndexedHdr ~ http2 hpack dissect hpackindexedhdr p = h2.HPackIndexedHdr(b'\x80') assert p.magic == 1 assert p.index == 0 p = h2.HPackIndexedHdr(b'\xFF\x00') assert p.magic == 1 assert p.index == 127 = HTTP/2 Build HPackIndexedHdr ~ http2 hpack build hpackindexedhdr p = h2.HPackIndexedHdr(index=0) assert raw(p) == b'\x80' p = h2.HPackIndexedHdr(index=127) assert raw(p) == b'\xFF\x00' + HTTP/2 HPackLitHdrFldWithIncrIndexing Test Suite = HTTP/2 Dissect HPackLitHdrFldWithIncrIndexing without indexed name ~ http2 hpack dissect hpacklithdrfldwithincrindexing p = h2.HPackLitHdrFldWithIncrIndexing(b'\x40\x04Test\x04Toto') assert p.magic == 1 assert p.index == 0 assert isinstance(p.hdr_name, h2.HPackHdrString) assert p.hdr_name.type == 0 assert p.hdr_name.len == 4 assert p.hdr_name.getfieldval('data').origin() == 'Test' assert isinstance(p.hdr_value, h2.HPackHdrString) assert p.hdr_value.type == 0 assert p.hdr_value.len == 4 assert p.hdr_value.getfieldval('data').origin() == 'Toto' = HTTP/2 Dissect HPackLitHdrFldWithIncrIndexing with indexed name ~ http2 hpack dissect hpacklithdrfldwithincrindexing p = h2.HPackLitHdrFldWithIncrIndexing(b'\x41\x04Toto') assert p.magic == 1 assert p.index == 1 assert p.hdr_name is None assert isinstance(p.hdr_value, h2.HPackHdrString) assert p.hdr_value.type == 0 assert p.hdr_value.len == 4 assert p.hdr_value.getfieldval('data').origin() == 'Toto' = HTTP/2 Build HPackLitHdrFldWithIncrIndexing without indexed name ~ http2 hpack build hpacklithdrfldwithincrindexing p = h2.HPackLitHdrFldWithIncrIndexing( hdr_name=h2.HPackHdrString(data=h2.HPackLiteralString('Test')), hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto')) ) assert raw(p) == b'\x40\x04Test\x04Toto' = HTTP/2 Build HPackLitHdrFldWithIncrIndexing with indexed name ~ http2 hpack build hpacklithdrfldwithincrindexing p = h2.HPackLitHdrFldWithIncrIndexing( index=1, hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto')) ) assert raw(p) == b'\x41\x04Toto' + HTTP/2 HPackLitHdrFldWithoutIndexing Test Suite = HTTP/2 Dissect HPackLitHdrFldWithoutIndexing : don't index and no index ~ http2 hpack dissect hpacklithdrfldwithoutindexing p = h2.HPackLitHdrFldWithoutIndexing(b'\x00\x04Test\x04Toto') assert p.magic == 0 assert p.never_index == 0 assert p.index == 0 assert isinstance(p.hdr_name, h2.HPackHdrString) assert p.hdr_name.type == 0 assert p.hdr_name.len == 4 assert isinstance(p.hdr_name.getfieldval('data'), h2.HPackLiteralString) assert p.hdr_name.getfieldval('data').origin() == 'Test' assert isinstance(p.hdr_value, h2.HPackHdrString) assert p.hdr_value.type == 0 assert p.hdr_value.len == 4 assert isinstance(p.hdr_value.getfieldval('data'), h2.HPackLiteralString) assert p.hdr_value.getfieldval('data').origin() == 'Toto' = HTTP/2 Dissect HPackLitHdrFldWithoutIndexing : never index index and no index ~ http2 hpack dissect hpacklithdrfldwithoutindexing p = h2.HPackLitHdrFldWithoutIndexing(b'\x10\x04Test\x04Toto') assert p.magic == 0 assert p.never_index == 1 assert p.index == 0 assert isinstance(p.hdr_name, h2.HPackHdrString) assert p.hdr_name.type == 0 assert p.hdr_name.len == 4 assert isinstance(p.hdr_name.getfieldval('data'), h2.HPackLiteralString) assert p.hdr_name.getfieldval('data').origin() == 'Test' assert isinstance(p.hdr_value, h2.HPackHdrString) assert p.hdr_value.type == 0 assert p.hdr_value.len == 4 assert isinstance(p.hdr_value.getfieldval('data'), h2.HPackLiteralString) assert p.hdr_value.getfieldval('data').origin() == 'Toto' = HTTP/2 Dissect HPackLitHdrFldWithoutIndexing : never index and indexed name ~ http2 hpack dissect hpacklithdrfldwithoutindexing p = h2.HPackLitHdrFldWithoutIndexing(b'\x11\x04Toto') assert p.magic == 0 assert p.never_index == 1 assert p.index == 1 assert p.hdr_name is None assert isinstance(p.hdr_value, h2.HPackHdrString) assert p.hdr_value.type == 0 assert p.hdr_value.len == 4 assert isinstance(p.hdr_value.getfieldval('data'), h2.HPackLiteralString) assert p.hdr_value.getfieldval('data').origin() == 'Toto' = HTTP/2 Build HPackLitHdrFldWithoutIndexing : don't index and no index ~ http2 hpack build hpacklithdrfldwithoutindexing p = h2.HPackLitHdrFldWithoutIndexing( hdr_name=h2.HPackHdrString(data=h2.HPackLiteralString('Test')), hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto')) ) assert raw(p) == b'\x00\x04Test\x04Toto' = HTTP/2 Build HPackLitHdrFldWithoutIndexing : never index index and no index ~ http2 hpack build hpacklithdrfldwithoutindexing p = h2.HPackLitHdrFldWithoutIndexing( never_index=1, hdr_name=h2.HPackHdrString(data=h2.HPackLiteralString('Test')), hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto')) ) assert raw(p) == b'\x10\x04Test\x04Toto' = HTTP/2 Build HPackLitHdrFldWithoutIndexing : never index and indexed name ~ http2 hpack build hpacklithdrfldwithoutindexing p = h2.HPackLitHdrFldWithoutIndexing( never_index=1, index=1, hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto')) ) assert raw(p) == b'\x11\x04Toto' + HTTP/2 HPackDynamicSizeUpdate Test Suite = HTTP/2 Dissect HPackDynamicSizeUpdate ~ http2 hpack dissect hpackdynamicsizeupdate p = h2.HPackDynamicSizeUpdate(b'\x25') assert p.magic == 1 assert p.max_size == 5 p = h2.HPackDynamicSizeUpdate(b'\x3F\x00') assert p.magic == 1 assert p.max_size == 31 = HTTP/2 Build HPackDynamicSizeUpdate ~ http2 hpack build hpackdynamicsizeupdate p = h2.HPackDynamicSizeUpdate(max_size=5) assert raw(p) == b'\x25' p = h2.HPackDynamicSizeUpdate(max_size=31) assert raw(p) == b'\x3F\x00' + HTTP/2 Data Frame Test Suite = HTTP/2 Dissect Data Frame: Simple data frame ~ http2 frame dissect data pkt = h2.H2Frame(b'\x00\x00\x04\x00\x00\x00\x00\x00\x01ABCD') assert pkt.type == 0 assert pkt.len == 4 assert len(pkt.flags) == 0 assert pkt.reserved == 0 assert pkt.stream_id == 1 assert isinstance(pkt.payload, h2.H2DataFrame) assert pkt[h2.H2DataFrame] assert pkt.payload.data == b'ABCD' assert isinstance(pkt.payload.payload, scapy.packet.NoPayload) = HTTP/2 Build Data Frame: Simple data frame ~ http2 frame build data pkt = h2.H2Frame(stream_id = 1)/h2.H2DataFrame(data='ABCD') assert raw(pkt) == b'\x00\x00\x04\x00\x00\x00\x00\x00\x01ABCD' try: pkt.show2(dump=True) assert True except Exception: assert False = HTTP/2 Dissect Data Frame: Simple data frame with padding ~ http2 frame dissect data pkt = h2.H2Frame(b'\x00\x00\r\x00\x08\x00\x00\x00\x01\x08ABCD\x00\x00\x00\x00\x00\x00\x00\x00') #Padded data frame assert pkt.type == 0 assert pkt.len == 13 assert len(pkt.flags) == 1 assert 'P' in pkt.flags assert pkt.reserved == 0 assert pkt.stream_id == 1 assert isinstance(pkt.payload, h2.H2PaddedDataFrame) assert pkt[h2.H2PaddedDataFrame] assert pkt.payload.padlen == 8 assert pkt.payload.data == b'ABCD' assert pkt.payload.padding == b'\x00'*8 assert flags_bit_pattern.search(pkt.show(dump=True)) is None assert isinstance(pkt.payload.payload, scapy.packet.NoPayload) = HTTP/2 Build Data Frame: Simple data frame with padding ~ http2 frame build data pkt = h2.H2Frame(flags = {'P'}, stream_id = 1)/h2.H2PaddedDataFrame(data='ABCD', padding=b'\x00'*8) assert raw(pkt) == b'\x00\x00\r\x00\x08\x00\x00\x00\x01\x08ABCD\x00\x00\x00\x00\x00\x00\x00\x00' try: pkt.show2(dump=True) assert True except Exception: assert False = HTTP/2 Dissect Data Frame: Simple data frame with padding and end stream flag ~ http2 frame dissect data pkt = h2.H2Frame(b'\x00\x00\r\x00\t\x00\x00\x00\x01\x08ABCD\x00\x00\x00\x00\x00\x00\x00\x00') #Padded data frame with end stream flag assert pkt.type == 0 assert pkt.len == 13 assert len(pkt.flags) == 2 assert 'P' in pkt.flags assert 'ES' in pkt.flags assert pkt.reserved == 0 assert pkt.stream_id == 1 assert isinstance(pkt.payload, h2.H2PaddedDataFrame) assert pkt[h2.H2PaddedDataFrame] assert pkt.payload.padlen == 8 assert pkt.payload.data == b'ABCD' assert pkt.payload.padding == b'\x00'*8 assert flags_bit_pattern.search(pkt.show(dump=True)) is None assert isinstance(pkt.payload.payload, scapy.packet.NoPayload) = HTTP/2 Build Data Frame: Simple data frame with padding and end stream flag ~ http2 frame build data pkt = h2.H2Frame(flags = {'P', 'ES'}, stream_id=1)/h2.H2PaddedDataFrame(data='ABCD', padding=b'\x00'*8) assert raw(pkt) == b'\x00\x00\r\x00\t\x00\x00\x00\x01\x08ABCD\x00\x00\x00\x00\x00\x00\x00\x00' try: pkt.show2(dump=True) assert True except Exception: assert False + HTTP/2 Headers Frame Test Suite = HTTP/2 Dissect Headers Frame: Simple header frame ~ http2 frame dissect headers pkt = h2.H2Frame(b'\x00\x00\x0e\x01\x00\x00\x00\x00\x01\x88\x0f\x10\ntext/plain') #Header frame assert pkt.type == 1 assert pkt.len == 14 assert len(pkt.flags) == 0 assert pkt.reserved == 0 assert pkt.stream_id == 1 assert isinstance(pkt.payload, h2.H2HeadersFrame) assert pkt[h2.H2HeadersFrame] hf = pkt[h2.H2HeadersFrame] assert len(hf.hdrs) == 2 assert isinstance(hf.hdrs[0], h2.HPackIndexedHdr) assert hf.hdrs[0].magic == 1 assert hf.hdrs[0].index == 8 assert isinstance(hf.hdrs[1], h2.HPackLitHdrFldWithoutIndexing) assert hf.hdrs[1].magic == 0 assert hf.hdrs[1].never_index == 0 assert hf.hdrs[1].index == 31 assert hf.hdrs[1].hdr_name is None assert expect_exception(AttributeError, 'hf.hdrs[1].non_existant') assert isinstance(hf.hdrs[1].hdr_value, h2.HPackHdrString) s = hf.hdrs[1].hdr_value assert s.type == 0 assert s.len == 10 assert s.getfieldval('data').origin() == 'text/plain' assert isinstance(hf.payload, scapy.packet.NoPayload) = HTTP/2 Build Headers Frame: Simple header frame ~ http2 frame build headers p = h2.H2Frame(stream_id=1)/h2.H2HeadersFrame(hdrs=[ h2.HPackIndexedHdr(index=8), h2.HPackLitHdrFldWithoutIndexing( index=31, hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('text/plain')) ) ] ) assert raw(p) == b'\x00\x00\x0e\x01\x00\x00\x00\x00\x01\x88\x0f\x10\ntext/plain' = HTTP/2 Dissect Headers Frame: Header frame with padding ~ http2 frame dissect headers pkt = h2.H2Frame(b'\x00\x00\x17\x01\x08\x00\x00\x00\x01\x08\x88\x0f\x10\ntext/plain\x00\x00\x00\x00\x00\x00\x00\x00') #Header frame with padding assert pkt.type == 1 assert pkt.len == 23 assert len(pkt.flags) == 1 assert 'P' in pkt.flags assert pkt.reserved == 0 assert pkt.stream_id == 1 assert isinstance(pkt.payload, h2.H2PaddedHeadersFrame) assert flags_bit_pattern.search(pkt.show(dump=True)) is None assert pkt[h2.H2PaddedHeadersFrame] hf = pkt[h2.H2PaddedHeadersFrame] assert hf.padlen == 8 assert hf.padding == b'\x00' * 8 assert len(hf.hdrs) == 2 assert isinstance(hf.hdrs[0], h2.HPackIndexedHdr) assert hf.hdrs[0].magic == 1 assert hf.hdrs[0].index == 8 assert isinstance(hf.hdrs[1], h2.HPackLitHdrFldWithoutIndexing) assert hf.hdrs[1].magic == 0 assert hf.hdrs[1].never_index == 0 assert hf.hdrs[1].index == 31 assert hf.hdrs[1].hdr_name is None assert expect_exception(AttributeError, 'hf.hdrs[1].non_existant') assert isinstance(hf.hdrs[1].hdr_value, h2.HPackHdrString) s = hf.hdrs[1].hdr_value assert s.type == 0 assert s.len == 10 assert s.getfieldval('data').origin() == 'text/plain' assert isinstance(hf.payload, scapy.packet.NoPayload) = HTTP/2 Build Headers Frame: Header frame with padding ~ http2 frame build headers p = h2.H2Frame(flags={'P'}, stream_id=1)/h2.H2PaddedHeadersFrame( hdrs=[ h2.HPackIndexedHdr(index=8), h2.HPackLitHdrFldWithoutIndexing( index=31, hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('text/plain')) ) ], padding=b'\x00'*8, ) assert raw(p) == b'\x00\x00\x17\x01\x08\x00\x00\x00\x01\x08\x88\x0f\x10\ntext/plain\x00\x00\x00\x00\x00\x00\x00\x00' = HTTP/2 Dissect Headers Frame: Header frame with priority ~ http2 frame dissect headers pkt = h2.H2Frame(b'\x00\x00\x13\x01 \x00\x00\x00\x01\x00\x00\x00\x02d\x88\x0f\x10\ntext/plain') #Header frame with priority assert pkt.type == 1 assert pkt.len == 19 assert len(pkt.flags) == 1 assert '+' in pkt.flags assert pkt.reserved == 0 assert pkt.stream_id == 1 assert isinstance(pkt.payload, h2.H2PriorityHeadersFrame) assert flags_bit_pattern.search(pkt.show(dump=True)) is None assert pkt[h2.H2PriorityHeadersFrame] hf = pkt[h2.H2PriorityHeadersFrame] assert hf.exclusive == 0 assert hf.stream_dependency == 2 assert hf.weight == 100 assert len(hf.hdrs) == 2 assert isinstance(hf.hdrs[0], h2.HPackIndexedHdr) assert hf.hdrs[0].magic == 1 assert hf.hdrs[0].index == 8 assert isinstance(hf.hdrs[1], h2.HPackLitHdrFldWithoutIndexing) assert hf.hdrs[1].magic == 0 assert hf.hdrs[1].never_index == 0 assert hf.hdrs[1].index == 31 assert hf.hdrs[1].hdr_name is None assert expect_exception(AttributeError, 'hf.hdrs[1].non_existant') assert isinstance(hf.hdrs[1].hdr_value, h2.HPackHdrString) s = hf.hdrs[1].hdr_value assert s.type == 0 assert s.len == 10 assert s.getfieldval('data').origin() == 'text/plain' assert isinstance(hf.payload, scapy.packet.NoPayload) = HTTP/2 Build Headers Frame: Header frame with priority ~ http2 frame build headers p = h2.H2Frame(flags={'+'}, stream_id=1)/h2.H2PriorityHeadersFrame( exclusive=0, stream_dependency=2, weight=100, hdrs=[ h2.HPackIndexedHdr(index=8), h2.HPackLitHdrFldWithoutIndexing( index=31, hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('text/plain')) ) ] ) assert raw(p) == b'\x00\x00\x13\x01 \x00\x00\x00\x01\x00\x00\x00\x02d\x88\x0f\x10\ntext/plain' = HTTP/2 Dissect Headers Frame: Header frame with priority and padding and flags ~ http2 frame dissect headers pkt = h2.H2Frame(b'\x00\x00\x1c\x01-\x00\x00\x00\x01\x08\x00\x00\x00\x02d\x88\x0f\x10\ntext/plain\x00\x00\x00\x00\x00\x00\x00\x00') #Header frame with priority and padding and flags ES|EH assert pkt.type == 1 assert pkt.len == 28 assert len(pkt.flags) == 4 assert '+' in pkt.flags assert 'P' in pkt.flags assert 'ES' in pkt.flags assert 'EH' in pkt.flags assert pkt.reserved == 0 assert pkt.stream_id == 1 assert isinstance(pkt.payload, h2.H2PaddedPriorityHeadersFrame) assert flags_bit_pattern.search(pkt.show(dump=True)) is None assert pkt[h2.H2PaddedPriorityHeadersFrame] hf = pkt[h2.H2PaddedPriorityHeadersFrame] assert hf.padlen == 8 assert hf.padding == b'\x00' * 8 assert hf.exclusive == 0 assert hf.stream_dependency == 2 assert hf.weight == 100 assert len(hf.hdrs) == 2 assert isinstance(hf.hdrs[0], h2.HPackIndexedHdr) assert hf.hdrs[0].magic == 1 assert hf.hdrs[0].index == 8 assert isinstance(hf.hdrs[1], h2.HPackLitHdrFldWithoutIndexing) assert hf.hdrs[1].magic == 0 assert hf.hdrs[1].never_index == 0 assert hf.hdrs[1].index == 31 assert hf.hdrs[1].hdr_name is None assert expect_exception(AttributeError, 'hf.hdrs[1].non_existant') assert isinstance(hf.hdrs[1].hdr_value, h2.HPackHdrString) s = hf.hdrs[1].hdr_value assert s.type == 0 assert s.len == 10 assert s.getfieldval('data').origin() == 'text/plain' assert isinstance(hf.payload, scapy.packet.NoPayload) = HTTP/2 Build Headers Frame: Header frame with priority and padding and flags ~ http2 frame build headers p = h2.H2Frame(flags={'P', '+', 'ES', 'EH'}, stream_id=1)/h2.H2PaddedPriorityHeadersFrame( exclusive=0, stream_dependency=2, weight=100, padding=b'\x00'*8, hdrs=[ h2.HPackIndexedHdr(index=8), h2.HPackLitHdrFldWithoutIndexing( index=31, hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('text/plain')) ) ] ) + HTTP/2 Priority Frame Test Suite = HTTP/2 Dissect Priority Frame ~ http2 frame dissect priority pkt = h2.H2Frame(b'\x00\x00\x05\x02\x00\x00\x00\x00\x03\x80\x00\x00\x01d') assert pkt.type == 2 assert pkt.len == 5 assert len(pkt.flags) == 0 assert pkt.reserved == 0 assert pkt.stream_id == 3 assert isinstance(pkt.payload, h2.H2PriorityFrame) assert pkt[h2.H2PriorityFrame] pp = pkt[h2.H2PriorityFrame] assert pp.stream_dependency == 1 assert pp.exclusive == 1 assert pp.weight == 100 = HTTP/2 Build Priority Frame ~ http2 frame build priority p = h2.H2Frame(stream_id=3)/h2.H2PriorityFrame( exclusive=1, stream_dependency=1, weight=100 ) assert raw(p) == b'\x00\x00\x05\x02\x00\x00\x00\x00\x03\x80\x00\x00\x01d' + HTTP/2 Reset Stream Frame Test Suite = HTTP/2 Dissect Reset Stream Frame: Protocol Error ~ http2 frame dissect rststream pkt = h2.H2Frame(b'\x00\x00\x04\x03\x00\x00\x00\x00\x01\x00\x00\x00\x01') #Reset stream with protocol error assert pkt.type == 3 assert pkt.len == 4 assert len(pkt.flags) == 0 assert pkt.reserved == 0 assert pkt.stream_id == 1 assert isinstance(pkt.payload, h2.H2ResetFrame) assert pkt[h2.H2ResetFrame] rf = pkt[h2.H2ResetFrame] assert rf.error == 1 assert isinstance(rf.payload, scapy.packet.NoPayload) = HTTP/2 Build Reset Stream Frame: Protocol Error ~ http2 frame build rststream p = h2.H2Frame(stream_id=1)/h2.H2ResetFrame(error='Protocol error') assert raw(p) == b'\x00\x00\x04\x03\x00\x00\x00\x00\x01\x00\x00\x00\x01' p = h2.H2Frame(stream_id=1)/h2.H2ResetFrame(error=1) assert raw(p) == b'\x00\x00\x04\x03\x00\x00\x00\x00\x01\x00\x00\x00\x01' = HTTP/2 Dissect Reset Stream Frame: Raw 123456 error ~ http2 frame dissect rststream pkt = h2.H2Frame(b'\x00\x00\x04\x03\x00\x00\x00\x00\x01\x00\x01\xe2@') #Reset stream with raw error assert pkt.type == 3 assert pkt.len == 4 assert len(pkt.flags) == 0 assert pkt.reserved == 0 assert pkt.stream_id == 1 assert isinstance(pkt.payload, h2.H2ResetFrame) assert pkt[h2.H2ResetFrame] rf = pkt[h2.H2ResetFrame] assert rf.error == 123456 assert isinstance(rf.payload, scapy.packet.NoPayload) = HTTP/2 Dissect Reset Stream Frame: Raw 123456 error ~ http2 frame dissect rststream p = h2.H2Frame(stream_id=1)/h2.H2ResetFrame(error=123456) assert raw(p) == b'\x00\x00\x04\x03\x00\x00\x00\x00\x01\x00\x01\xe2@' + HTTP/2 Settings Frame Test Suite = HTTP/2 Dissect Settings Frame: Settings Frame ~ http2 frame dissect settings pkt = h2.H2Frame(b'\x00\x00$\x04\x00\x00\x00\x00\x00\x00\x01\x07[\xcd\x15\x00\x02\x00\x00\x00\x01\x00\x03\x00\x00\x00{\x00\x04\x00\x12\xd6\x87\x00\x05\x00\x01\xe2@\x00\x06\x00\x00\x00{') #Settings frame assert pkt.type == 4 assert pkt.len == 36 assert len(pkt.flags) == 0 assert pkt.reserved == 0 assert pkt.stream_id == 0 assert isinstance(pkt.payload, h2.H2SettingsFrame) assert pkt[h2.H2SettingsFrame] sf = pkt[h2.H2SettingsFrame] assert len(sf.settings) == 6 assert isinstance(sf.settings[0], h2.H2Setting) assert sf.settings[0].id == 1 assert sf.settings[0].value == 123456789 assert isinstance(sf.settings[1], h2.H2Setting) assert sf.settings[1].id == 2 assert sf.settings[1].value == 1 assert isinstance(sf.settings[2], h2.H2Setting) assert sf.settings[2].id == 3 assert sf.settings[2].value == 123 assert isinstance(sf.settings[3], h2.H2Setting) assert sf.settings[3].id == 4 assert sf.settings[3].value == 1234567 assert isinstance(sf.settings[4], h2.H2Setting) assert sf.settings[4].id == 5 assert sf.settings[4].value == 123456 assert isinstance(sf.settings[5], h2.H2Setting) assert sf.settings[5].id == 6 assert sf.settings[5].value == 123 assert isinstance(sf.payload, scapy.packet.NoPayload) = HTTP/2 Build Settings Frame: Settings Frame ~ http2 frame build settings p = h2.H2Frame()/h2.H2SettingsFrame(settings=[ h2.H2Setting(id='Header table size',value=123456789), h2.H2Setting(id='Enable push', value=1), h2.H2Setting(id='Max concurrent streams', value=123), h2.H2Setting(id='Initial window size', value=1234567), h2.H2Setting(id='Max frame size', value=123456), h2.H2Setting(id='Max header list size', value=123) ] ) assert raw(p) == b'\x00\x00$\x04\x00\x00\x00\x00\x00\x00\x01\x07[\xcd\x15\x00\x02\x00\x00\x00\x01\x00\x03\x00\x00\x00{\x00\x04\x00\x12\xd6\x87\x00\x05\x00\x01\xe2@\x00\x06\x00\x00\x00{' = HTTP/2 Dissect Settings Frame: Incomplete Settings Frame ~ http2 frame dissect settings #We use here the decode('hex') method because null-bytes are rejected by eval() assert expect_exception(AssertionError, 'h2.H2Frame(bytes_hex("0000240400000000000001075bcd1500020000000100030000007b00040012d68700050001e2400006000000"))') = HTTP/2 Dissect Settings Frame: Settings Frame acknowledgement ~ http2 frame dissect settings pkt = h2.H2Frame(b'\x00\x00\x00\x04\x01\x00\x00\x00\x00') #Settings frame w/ ack flag assert pkt.type == 4 assert pkt.len == 0 assert len(pkt.flags) == 1 assert 'A' in pkt.flags assert pkt.reserved == 0 assert pkt.stream_id == 0 assert flags_bit_pattern.search(pkt.show(dump=True)) is None assert isinstance(pkt.payload, scapy.packet.NoPayload) = HTTP/2 Build Settings Frame: Settings Frame acknowledgement ~ http2 frame build settings p = h2.H2Frame(type=h2.H2SettingsFrame.type_id, flags={'A'}) assert raw(p) == b'\x00\x00\x00\x04\x01\x00\x00\x00\x00' + HTTP/2 Push Promise Frame Test Suite = HTTP/2 Dissect Push Promise Frame: no flag & headers with compression and hdr_name ~ http2 frame dissect pushpromise pkt = h2.H2Frame(b'\x00\x00\x15\x05\x00\x00\x00\x00\x01\x00\x00\x00\x03@\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me') assert pkt.type == 5 assert pkt.len == 21 assert len(pkt.flags) == 0 assert pkt.reserved == 0 assert pkt.stream_id == 1 assert isinstance(pkt.payload, h2.H2PushPromiseFrame) assert pkt[h2.H2PushPromiseFrame] pf = pkt[h2.H2PushPromiseFrame] assert pf.reserved == 0 assert pf.stream_id == 3 assert len(pf.hdrs) == 1 assert isinstance(pf.payload, scapy.packet.NoPayload) hdr = pf.hdrs[0] assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing) assert hdr.magic == 1 assert hdr.index == 0 assert isinstance(hdr.hdr_name, h2.HPackHdrString) assert hdr.hdr_name.type == 1 assert hdr.hdr_name.len == 12 assert hdr.hdr_name.getfieldval('data').origin() == 'X-Requested-With' assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.type == 0 assert hdr.hdr_value.len == 2 assert hdr.hdr_value.getfieldval('data').origin() == 'Me' = HTTP/2 Build Push Promise Frame: no flag & headers with compression and hdr_name ~ http2 frame build pushpromise p = h2.H2Frame(stream_id=1)/h2.H2PushPromiseFrame(stream_id=3,hdrs=[ h2.HPackLitHdrFldWithIncrIndexing( hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Requested-With')), hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me')), ) ]) assert raw(p) == b'\x00\x00\x15\x05\x00\x00\x00\x00\x01\x00\x00\x00\x03@\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me' = HTTP/2 Dissect Push Promise Frame: with padding, the flag END_Header & headers with compression and hdr_name ~ http2 frame dissect pushpromise pkt = h2.H2Frame(b'\x00\x00\x1e\x05\x0c\x00\x00\x00\x01\x08\x00\x00\x00\x03@\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me\x00\x00\x00\x00\x00\x00\x00\x00') assert pkt.type == 5 assert pkt.len == 30 assert len(pkt.flags) == 2 assert 'P' in pkt.flags assert 'EH' in pkt.flags assert pkt.reserved == 0 assert pkt.stream_id == 1 assert flags_bit_pattern.search(pkt.show(dump=True)) is None assert isinstance(pkt.payload, h2.H2PaddedPushPromiseFrame) assert pkt[h2.H2PaddedPushPromiseFrame] pf = pkt[h2.H2PaddedPushPromiseFrame] assert pf.padlen == 8 assert pf.padding == b'\x00'*8 assert pf.stream_id == 3 assert len(pf.hdrs) == 1 hdr = pf.hdrs[0] assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing) assert hdr.magic == 1 assert hdr.index == 0 assert isinstance(hdr.hdr_name, h2.HPackHdrString) assert hdr.hdr_name.type == 1 assert hdr.hdr_name.len == 12 assert hdr.hdr_name.getfieldval('data').origin() == 'X-Requested-With' assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.type == 0 assert hdr.hdr_value.len == 2 assert hdr.hdr_value.getfieldval('data').origin() == 'Me' = HTTP/2 Build Push Promise Frame: with padding, the flag END_Header & headers with compression and hdr_name ~ http2 frame build pushpromise p = h2.H2Frame(flags={'P', 'EH'}, stream_id=1)/h2.H2PaddedPushPromiseFrame( stream_id=3, hdrs=[ h2.HPackLitHdrFldWithIncrIndexing( hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Requested-With')), hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me')) ) ], padding=b'\x00'*8 ) assert raw(p) == b'\x00\x00\x1e\x05\x0c\x00\x00\x00\x01\x08\x00\x00\x00\x03@\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me\x00\x00\x00\x00\x00\x00\x00\x00' + HTTP/2 Ping Frame Test Suite = HTTP/2 Dissect Ping Frame: Ping frame ~ http2 frame dissect ping pkt = h2.H2Frame(b'\x00\x00\x08\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xe2@') #Ping frame with payload assert pkt.type == 6 assert pkt.len == 8 assert len(pkt.flags) == 0 assert pkt.reserved == 0 assert pkt.stream_id == 0 assert isinstance(pkt.payload, h2.H2PingFrame) assert pkt[h2.H2PingFrame] pf = pkt[h2.H2PingFrame] assert pf.opaque == 123456 assert isinstance(pf.payload, scapy.packet.NoPayload) = HTTP/2 Build Ping Frame: Ping frame ~ http2 frame build ping p = h2.H2Frame()/h2.H2PingFrame(opaque=123456) assert raw(p) == b'\x00\x00\x08\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xe2@' = HTTP/2 Dissect Ping Frame: Pong frame ~ http2 frame dissect ping pkt = h2.H2Frame(b'\x00\x00\x08\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xe2@') #Pong frame assert pkt.type == 6 assert pkt.len == 8 assert len(pkt.flags) == 1 assert 'A' in pkt.flags assert pkt.reserved == 0 assert pkt.stream_id == 0 assert isinstance(pkt.payload, h2.H2PingFrame) assert flags_bit_pattern.search(pkt.show(dump=True)) is None assert pkt[h2.H2PingFrame] pf = pkt[h2.H2PingFrame] assert pf.opaque == 123456 assert isinstance(pf.payload, scapy.packet.NoPayload) = HTTP/2 Dissect Ping Frame: Pong frame ~ http2 frame dissect ping p = h2.H2Frame(flags={'A'})/h2.H2PingFrame(opaque=123456) assert raw(p) == b'\x00\x00\x08\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xe2@' + HTTP/2 Go Away Frame Test Suite = HTTP/2 Dissect Go Away Frame: No error ~ http2 frame dissect goaway pkt = h2.H2Frame(b'\x00\x00\x08\x07\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00') #Go Away for no particular reason :) assert pkt.type == 7 assert pkt.len == 8 assert len(pkt.flags) == 0 assert pkt.reserved == 0 assert pkt.stream_id == 0 assert isinstance(pkt.payload, h2.H2GoAwayFrame) assert pkt[h2.H2GoAwayFrame] gf = pkt[h2.H2GoAwayFrame] assert gf.reserved == 0 assert gf.last_stream_id == 1 assert gf.error == 0 assert len(gf.additional_data) == 0 assert isinstance(gf.payload, scapy.packet.NoPayload) = HTTP/2 Build Go Away Frame: No error ~ http2 frame build goaway p = h2.H2Frame()/h2.H2GoAwayFrame(last_stream_id=1, error='No error') assert raw(p) == b'\x00\x00\x08\x07\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00' = HTTP/2 Dissect Go Away Frame: Arbitrary error with additional data ~ http2 frame dissect goaway pkt = h2.H2Frame(b'\x00\x00\x10\x07\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\xe2@\x00\x00\x00\x00\x00\x00\x00\x00') #Go Away with debug data assert pkt.type == 7 assert pkt.len == 16 assert len(pkt.flags) == 0 assert pkt.reserved == 0 assert pkt.stream_id == 0 assert isinstance(pkt.payload, h2.H2GoAwayFrame) assert pkt[h2.H2GoAwayFrame] gf = pkt[h2.H2GoAwayFrame] assert gf.reserved == 0 assert gf.last_stream_id == 2 assert gf.error == 123456 assert gf.additional_data == 8*b'\x00' assert isinstance(gf.payload, scapy.packet.NoPayload) = HTTP/2 Build Go Away Frame: Arbitrary error with additional data ~ http2 frame build goaway p = h2.H2Frame()/h2.H2GoAwayFrame( last_stream_id=2, error=123456, additional_data=b'\x00'*8 ) assert raw(p) == b'\x00\x00\x10\x07\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\xe2@\x00\x00\x00\x00\x00\x00\x00\x00' + HTTP/2 Window Update Frame Test Suite = HTTP/2 Dissect Window Update Frame: global ~ http2 frame dissect winupdate pkt = h2.H2Frame(b'\x00\x00\x04\x08\x00\x00\x00\x00\x00\x00\x01\xe2@') #Window update with increment for connection assert pkt.type == 8 assert pkt.len == 4 assert len(pkt.flags) == 0 assert pkt.reserved == 0 assert pkt.stream_id == 0 assert isinstance(pkt.payload, h2.H2WindowUpdateFrame) assert pkt[h2.H2WindowUpdateFrame] wf = pkt[h2.H2WindowUpdateFrame] assert wf.reserved == 0 assert wf.win_size_incr == 123456 assert isinstance(wf.payload, scapy.packet.NoPayload) = HTTP/2 Build Window Update Frame: global ~ http2 frame build winupdate p = h2.H2Frame()/h2.H2WindowUpdateFrame(win_size_incr=123456) assert raw(p) == b'\x00\x00\x04\x08\x00\x00\x00\x00\x00\x00\x01\xe2@' = HTTP/2 Dissect Window Update Frame: a stream ~ http2 frame dissect winupdate pkt = h2.H2Frame(b'\x00\x00\x04\x08\x00\x00\x00\x00\x01\x00\x01\xe2@') #Window update with increment for a stream assert pkt.type == 8 assert pkt.len == 4 assert len(pkt.flags) == 0 assert pkt.reserved == 0 assert pkt.stream_id == 1 assert isinstance(pkt.payload, h2.H2WindowUpdateFrame) assert pkt[h2.H2WindowUpdateFrame] wf = pkt[h2.H2WindowUpdateFrame] assert wf.reserved == 0 assert wf.win_size_incr == 123456 assert isinstance(wf.payload, scapy.packet.NoPayload) = HTTP/2 Build Window Update Frame: a stream ~ http2 frame build winupdate p = h2.H2Frame(stream_id=1)/h2.H2WindowUpdateFrame(win_size_incr=123456) assert raw(p) == b'\x00\x00\x04\x08\x00\x00\x00\x00\x01\x00\x01\xe2@' + HTTP/2 Continuation Frame Test Suite = HTTP/2 Dissect Continuation Frame: no flag & headers with compression and hdr_name ~ http2 frame dissect continuation pkt = h2.H2Frame(b'\x00\x00\x11\t\x00\x00\x00\x00\x01@\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me') assert pkt.type == 9 assert pkt.len == 17 assert len(pkt.flags) == 0 assert pkt.reserved == 0 assert pkt.stream_id == 1 assert isinstance(pkt.payload, h2.H2ContinuationFrame) assert pkt[h2.H2ContinuationFrame] hf = pkt[h2.H2ContinuationFrame] assert len(hf.hdrs) == 1 assert isinstance(hf.payload, scapy.packet.NoPayload) hdr = hf.hdrs[0] assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing) assert hdr.magic == 1 assert hdr.index == 0 assert isinstance(hdr.hdr_name, h2.HPackHdrString) assert hdr.hdr_name.type == 1 assert hdr.hdr_name.len == 12 assert hdr.hdr_name.getfieldval('data').origin() == 'X-Requested-With' assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.type == 0 assert hdr.hdr_value.len == 2 assert hdr.hdr_value.getfieldval('data').origin() == 'Me' = HTTP/2 Build Continuation Frame: no flag & headers with compression and hdr_name ~ http2 frame build continuation p = h2.H2Frame(stream_id=1)/h2.H2ContinuationFrame( hdrs=[ h2.HPackLitHdrFldWithIncrIndexing( hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Requested-With')), hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me')) ) ] ) assert raw(p) == b'\x00\x00\x11\t\x00\x00\x00\x00\x01@\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me' = HTTP/2 Dissect Continuation Frame: flag END_Header & headers with compression, sensitive flag and hdr_name ~ http2 frame dissect continuation pkt = h2.H2Frame(b'\x00\x00\x11\t\x04\x00\x00\x00\x01\x10\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me') assert pkt.type == 9 assert pkt.len == 17 assert len(pkt.flags) == 1 assert 'EH' in pkt.flags assert pkt.reserved == 0 assert pkt.stream_id == 1 assert flags_bit_pattern.search(pkt.show(dump=True)) is None assert isinstance(pkt.payload, h2.H2ContinuationFrame) assert pkt[h2.H2ContinuationFrame] hf = pkt[h2.H2ContinuationFrame] assert len(hf.hdrs) == 1 assert isinstance(hf.payload, scapy.packet.NoPayload) hdr = hf.hdrs[0] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 1 assert hdr.index == 0 assert isinstance(hdr.hdr_name, h2.HPackHdrString) assert hdr.hdr_name.type == 1 assert hdr.hdr_name.len == 12 assert hdr.hdr_name.getfieldval('data').origin() == 'X-Requested-With' assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.type == 0 assert hdr.hdr_value.len == 2 assert hdr.hdr_value.getfieldval('data').origin() == 'Me' = HTTP/2 Build Continuation Frame: flag END_Header & headers with compression, sensitive flag and hdr_name ~ http2 frame build continuation p = h2.H2Frame(flags={'EH'}, stream_id=1)/h2.H2ContinuationFrame( hdrs=[ h2.HPackLitHdrFldWithoutIndexing( never_index=1, hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Requested-With')), hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me')) ) ] ) assert raw(p) == b'\x00\x00\x11\t\x04\x00\x00\x00\x01\x10\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me' + HTTP/2 HPackHdrTable Test Suite = HTTP/2 HPackHdrEntry Tests ~ http2 hpack hpackhdrtable n = 'X-Requested-With' v = 'Me' h = h2.HPackHdrEntry(n, v) assert len(h) == 32 + len(n) + len(v) assert h.name() == n.lower() assert h.value() == v assert str(h) == '{}: {}'.format(n.lower(), v) n = ':status' v = '200' h = h2.HPackHdrEntry(n, v) assert len(h) == 32 + len(n) + len(v) assert h.name() == n.lower() assert h.value() == v assert str(h) == '{} {}'.format(n.lower(), v) = HTTP/2 HPackHdrTable : Querying Static Entries ~ http2 hpack hpackhdrtable # In RFC7541, the table is 1-based assert expect_exception(KeyError, 'h2.HPackHdrTable()[0]') h = h2.HPackHdrTable() assert h[1].name() == ':authority' assert h[7].name() == ':scheme' assert h[7].value() == 'https' assert str(h[14]) == ':status 500' assert str(h[16]) == 'accept-encoding: gzip, deflate' assert expect_exception(KeyError, 'h2.HPackHdrTable()[h2.HPackHdrTable._static_entries_last_idx+1]') = HTTP/2 HPackHdrTable : Addind Dynamic Entries without overflowing the table ~ http2 hpack hpackhdrtable tbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32) hdr = h2.HPackLitHdrFldWithIncrIndexing( index=32, hdr_value=h2.HPackHdrString(data=h2.HPackZString('PHPSESSID=abcdef0123456789')) ) tbl.register(hdr) tbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32) hdr2 = h2.HPackLitHdrFldWithIncrIndexing( index=32, hdr_value=h2.HPackHdrString(data=h2.HPackZString('JSESSID=abcdef0123456789')) ) tbl.register([hdr,hdr2]) tbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32) hdr3 = h2.HPackLitHdrFldWithIncrIndexing( index=32, hdr_value=h2.HPackHdrString(data=h2.HPackZString('Test=abcdef0123456789')) ) frm = h2.H2Frame(stream_id=1)/h2.H2HeadersFrame(hdrs=[hdr, hdr2, hdr3]) tbl.register(frm) = HTTP/2 HPackHdrTable : Querying Dynamic Entries ~ http2 hpack hpackhdrtable tbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32) hdrv = 'PHPSESSID=abcdef0123456789' hdr = h2.HPackLitHdrFldWithIncrIndexing( index=32, hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv)) ) tbl.register(hdr) hdrv2 = 'JSESSID=abcdef0123456789' hdr2 = h2.HPackLitHdrFldWithIncrIndexing( index=32, hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv2)) ) tbl.register(hdr2) hdr3 = h2.HPackLitHdrFldWithIncrIndexing( index=0, hdr_name=h2.HPackHdrString(data=h2.HPackLiteralString('x-requested-by')), hdr_value=h2.HPackHdrString(data=h2.HPackZString('me')) ) tbl.register(hdr3) assert tbl.get_idx_by_name('x-requested-by') == h2.HPackHdrTable._static_entries_last_idx+1 assert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv2 assert tbl[h2.HPackHdrTable._static_entries_last_idx+3].value() == hdrv = HTTP/2 HPackHdrTable : Addind already registered Dynamic Entries without overflowing the table ~ http2 hpack hpackhdrtable tbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32) assert len(tbl) == 0 hdrv = 'PHPSESSID=abcdef0123456789' hdr = h2.HPackLitHdrFldWithIncrIndexing( index=32, hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv)) ) tbl.register(hdr) assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv hdr2v = 'JSESSID=abcdef0123456789' hdr2 = h2.HPackLitHdrFldWithIncrIndexing( index=32, hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdr2v)) ) tbl.register(hdr2) assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdr2v l = len(tbl) tbl.register(hdr) assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv assert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdr2v assert tbl[h2.HPackHdrTable._static_entries_last_idx+3].value() == hdrv = HTTP/2 HPackHdrTable : Addind Dynamic Entries and overflowing the table ~ http2 hpack hpackhdrtable tbl = h2.HPackHdrTable(dynamic_table_max_size=80, dynamic_table_cap_size=80) hdrv = 'PHPSESSID=abcdef0123456789' hdr = h2.HPackLitHdrFldWithIncrIndexing( index=32, hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv)) ) tbl.register(hdr) assert len(tbl) <= 80 assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv hdrv2 = 'JSESSID=abcdef0123456789' hdr2 = h2.HPackLitHdrFldWithIncrIndexing( index=32, hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv2)) ) tbl.register(hdr2) assert len(tbl) <= 80 assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2 try: tbl[h2.HPackHdrTable._static_entries_last_idx+2] ret = False except Exception: ret = True assert ret = HTTP/2 HPackHdrTable : Resizing ~ http2 hpack hpackhdrtable tbl = h2.HPackHdrTable() hdrv = 'PHPSESSID=abcdef0123456789' hdr = h2.HPackLitHdrFldWithIncrIndexing( index=32, hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv)) ) tbl.register(hdr) assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv hdrv2 = 'JSESSID=abcdef0123456789' hdr2 = h2.HPackLitHdrFldWithIncrIndexing( index=32, hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv2)) ) tbl.register(hdr2) assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2 assert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv #Resizing to a value higher than cap (default:4096) try: tbl.resize(8192) ret = False except AssertionError: ret = True assert ret #Resizing to a lower value by that is not small enough to cause eviction tbl.resize(1024) assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2 assert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv #Resizing to a higher value but thatt is lower than cap tbl.resize(2048) assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2 assert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv #Resizing to a lower value that causes eviction tbl.resize(80) assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2 try: tbl[h2.HPackHdrTable._static_entries_last_idx+2] ret = False except Exception: ret = True assert ret = HTTP/2 HPackHdrTable : Recapping ~ http2 hpack hpackhdrtable tbl = h2.HPackHdrTable() hdrv = 'PHPSESSID=abcdef0123456789' hdr = h2.HPackLitHdrFldWithIncrIndexing( index=32, hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv)) ) tbl.register(hdr) assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv hdrv2 = 'JSESSID=abcdef0123456789' hdr2 = h2.HPackLitHdrFldWithIncrIndexing( index=32, hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv2)) ) tbl.register(hdr2) assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2 assert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv #Recapping to a higher value tbl.recap(8192) assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2 assert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv #Recapping to a low value but without causing eviction tbl.recap(1024) assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2 assert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv #Recapping to a low value that causes evictiontbl.recap(1024) tbl.recap(80) assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2 try: tbl[h2.HPackHdrTable._static_entries_last_idx+2] ret = False except Exception: ret = True assert ret = HTTP/2 HPackHdrTable : Generating Textual Representation ~ http2 hpack hpackhdrtable helpers h = h2.HPackHdrTable() h.register(h2.HPackLitHdrFldWithIncrIndexing( hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')), hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11')) )) hdrs_lst = [ h2.HPackIndexedHdr(index=2), #Method Get h2.HPackLitHdrFldWithIncrIndexing( index=h.get_idx_by_name(':path'), hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('/index.php')) ), h2.HPackIndexedHdr(index=7), #Scheme HTTPS h2.HPackIndexedHdr(index=h2.HPackHdrTable._static_entries_last_idx+2), h2.HPackLitHdrFldWithIncrIndexing( index=58, hdr_value=h2.HPackHdrString(data=h2.HPackZString('Mozilla/5.0 Generated by hand')) ), h2.HPackLitHdrFldWithoutIndexing( hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generated-By')), hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me')) ) ] p = h2.H2Frame(stream_id = 1)/h2.H2HeadersFrame(hdrs=hdrs_lst) expected_output = ''':method GET :path /index.php :scheme https x-generation-date: 2016-08-11 user-agent: Mozilla/5.0 Generated by hand X-Generated-By: Me''' assert h.gen_txt_repr(p) == expected_output = HTTP/2 HPackHdrTable : Parsing Textual Representation ~ http2 hpack hpackhdrtable helpers body = b'login=titi&passwd=toto' hdrs = ''':method POST :path /login.php :scheme https content-type: application/x-www-form-urlencoded content-length: {} user-agent: Mozilla/5.0 Generated by hand x-generated-by: Me x-generation-date: 2016-08-11 x-generation-software: scapy '''.format(len(body)) h = h2.HPackHdrTable() h.register(h2.HPackLitHdrFldWithIncrIndexing( hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')), hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11')) )) seq = h.parse_txt_hdrs( hdrs, stream_id=1, body=body, should_index=lambda name: name in ['user-agent', 'x-generation-software'], is_sensitive=lambda name, value: name in ['x-generated-by', ':path'] ) assert isinstance(seq, h2.H2Seq) assert len(seq.frames) == 2 p = seq.frames[0] assert isinstance(p, h2.H2Frame) assert p.type == 1 assert len(p.flags) == 1 assert 'EH' in p.flags assert p.stream_id == 1 assert isinstance(p.payload, h2.H2HeadersFrame) hdrs_frm = p[h2.H2HeadersFrame] assert len(p.hdrs) == 9 hdr = p.hdrs[0] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 3 hdr = p.hdrs[1] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 1 assert hdr.index in [4, 5] assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(/login.php)' hdr = p.hdrs[2] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 7 hdr = p.hdrs[3] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 31 assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)' hdr = p.hdrs[4] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 28 assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackLiteralString(22)' hdr = p.hdrs[5] assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing) assert hdr.magic == 1 assert hdr.index == 58 assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)' hdr = p.hdrs[6] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 1 assert hdr.index == 0 assert isinstance(hdr.hdr_name, h2.HPackHdrString) assert hdr.hdr_name.data == 'HPackZString(x-generated-by)' assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackLiteralString(Me)' hdr = p.hdrs[7] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 63 hdr = p.hdrs[8] assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing) assert hdr.magic == 1 assert hdr.index == 0 assert isinstance(hdr.hdr_name, h2.HPackHdrString) assert hdr.hdr_name.data == 'HPackZString(x-generation-software)' assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(scapy)' p = seq.frames[1] assert isinstance(p, h2.H2Frame) assert p.type == 0 assert len(p.flags) == 1 assert 'ES' in p.flags assert p.stream_id == 1 assert isinstance(p.payload, h2.H2DataFrame) pay = p[h2.H2DataFrame] assert pay.data == body # now with bytes h = h2.HPackHdrTable() h.register(h2.HPackLitHdrFldWithIncrIndexing( hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')), hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11')) )) seq = h.parse_txt_hdrs( hdrs.encode(), stream_id=1, body=body, should_index=lambda name: name in ['user-agent', 'x-generation-software'], is_sensitive=lambda name, value: name in ['x-generated-by', ':path'] ) assert isinstance(seq, h2.H2Seq) assert len(seq.frames) == 2 p = seq.frames[0] assert isinstance(p, h2.H2Frame) assert p.type == 1 assert len(p.flags) == 1 assert 'EH' in p.flags assert p.stream_id == 1 assert isinstance(p.payload, h2.H2HeadersFrame) hdrs_frm = p[h2.H2HeadersFrame] assert len(p.hdrs) == 9 hdr = p.hdrs[0] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 3 hdr = p.hdrs[1] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 1 assert hdr.index in [4, 5] assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(/login.php)' hdr = p.hdrs[2] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 7 hdr = p.hdrs[3] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 31 assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)' hdr = p.hdrs[4] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 28 assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackLiteralString(22)' hdr = p.hdrs[5] assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing) assert hdr.magic == 1 assert hdr.index == 58 assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)' hdr = p.hdrs[6] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 1 assert hdr.index == 0 assert isinstance(hdr.hdr_name, h2.HPackHdrString) assert hdr.hdr_name.data == 'HPackZString(x-generated-by)' assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackLiteralString(Me)' hdr = p.hdrs[7] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 63 hdr = p.hdrs[8] assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing) assert hdr.magic == 1 assert hdr.index == 0 assert isinstance(hdr.hdr_name, h2.HPackHdrString) assert hdr.hdr_name.data == 'HPackZString(x-generation-software)' assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(scapy)' p = seq.frames[1] assert isinstance(p, h2.H2Frame) assert p.type == 0 assert len(p.flags) == 1 assert 'ES' in p.flags assert p.stream_id == 1 assert isinstance(p.payload, h2.H2DataFrame) pay = p[h2.H2DataFrame] assert pay.data == body = HTTP/2 HPackHdrTable : Parsing Textual Representation without body ~ http2 hpack hpackhdrtable helpers hdrs = b''':method POST :path /login.php :scheme https user-agent: Mozilla/5.0 Generated by hand x-generated-by: Me x-generation-date: 2016-08-11 ''' h = h2.HPackHdrTable() h.register(h2.HPackLitHdrFldWithIncrIndexing( hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')), hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11')) )) # Without body seq = h.parse_txt_hdrs(hdrs, stream_id=1) assert isinstance(seq, h2.H2Seq) #This is the first major difference with the first test assert len(seq.frames) == 1 p = seq.frames[0] assert isinstance(p, h2.H2Frame) assert p.type == 1 assert len(p.flags) == 2 assert 'EH' in p.flags #This is the second major difference with the first test assert 'ES' in p.flags assert p.stream_id == 1 assert isinstance(p.payload, h2.H2HeadersFrame) hdrs_frm = p[h2.H2HeadersFrame] assert len(p.hdrs) == 6 hdr = p.hdrs[0] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 3 hdr = p.hdrs[1] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index in [4, 5] assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(/login.php)' hdr = p.hdrs[2] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 7 hdr = p.hdrs[3] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 58 assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)' hdr = p.hdrs[4] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 0 assert isinstance(hdr.hdr_name, h2.HPackHdrString) assert hdr.hdr_name.data == 'HPackZString(x-generated-by)' assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackLiteralString(Me)' hdr = p.hdrs[5] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 62 = HTTP/2 HPackHdrTable : Parsing Textual Representation with too small max frame ~ http2 hpack hpackhdrtable helpers body = b'login=titi&passwd=toto' hdrs = ''':method POST :path /login.php :scheme https content-type: application/x-www-form-urlencoded content-length: {} user-agent: Mozilla/5.0 Generated by hand x-generated-by: Me x-generation-date: 2016-08-11 x-long-header: {} '''.format(len(body), 'a'*5000).encode() h = h2.HPackHdrTable() h.register(h2.HPackLitHdrFldWithIncrIndexing( hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')), hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11')) )) #x-long-header is too long to fit in any frames (whose default max size is 4096) expect_exception(Exception, "seq = h.parse_txt_hdrs('''{}''', stream_id=1".format(hdrs)) = HTTP/2 HPackHdrTable : Parsing Textual Representation with very large header and a large authorized frame size ~ http2 hpack hpackhdrtable helpers body = b'login=titi&passwd=toto' hdrs = ''':method POST :path /login.php :scheme https content-type: application/x-www-form-urlencoded content-length: {} user-agent: Mozilla/5.0 Generated by hand x-generated-by: Me x-generation-date: 2016-08-11 x-long-header: {} '''.format(len(body), 'a'*5000).encode() h = h2.HPackHdrTable() h.register(h2.HPackLitHdrFldWithIncrIndexing( hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')), hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11')) )) # Now trying to parse it with a max frame size large enough for x-long-header to # fit in a frame seq = h.parse_txt_hdrs(hdrs, stream_id=1, max_frm_sz=8192) assert isinstance(seq, h2.H2Seq) assert len(seq.frames) == 1 p = seq.frames[0] assert isinstance(p, h2.H2Frame) assert p.type == 1 assert len(p.flags) == 2 assert 'EH' in p.flags assert 'ES' in p.flags assert p.stream_id == 1 assert isinstance(p.payload, h2.H2HeadersFrame) hdrs_frm = p[h2.H2HeadersFrame] assert len(p.hdrs) == 9 hdr = p.hdrs[0] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 3 hdr = p.hdrs[1] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index in [4, 5] assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(/login.php)' hdr = p.hdrs[2] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 7 hdr = p.hdrs[3] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 31 assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)' hdr = p.hdrs[4] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 28 assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackLiteralString(22)' hdr = p.hdrs[5] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 58 assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)' hdr = p.hdrs[6] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 0 assert isinstance(hdr.hdr_name, h2.HPackHdrString) assert hdr.hdr_name.data == 'HPackZString(x-generated-by)' assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackLiteralString(Me)' hdr = p.hdrs[7] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 62 hdr = p.hdrs[8] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 0 assert isinstance(hdr.hdr_name, h2.HPackHdrString) assert hdr.hdr_name.data == 'HPackZString(x-long-header)' assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString({})'.format('a'*5000) = HTTP/2 HPackHdrTable : Parsing Textual Representation with two very large headers and a large authorized frame size ~ http2 hpack hpackhdrtable helpers body = b'login=titi&passwd=toto' hdrs = ''':method POST :path /login.php :scheme https content-type: application/x-www-form-urlencoded content-length: {} user-agent: Mozilla/5.0 Generated by hand x-generated-by: Me x-generation-date: 2016-08-11 x-long-header: {} x-long-header: {} '''.format(len(body), 'a'*5000, 'b'*5000).encode() h = h2.HPackHdrTable() h.register(h2.HPackLitHdrFldWithIncrIndexing( hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')), hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11')) )) # Now trying to parse it with a max frame size large enough for x-long-header to # fit in a frame but a maximum header fragment size that is not large enough to # store two x-long-header seq = h.parse_txt_hdrs(hdrs, stream_id=1, max_frm_sz=8192) assert isinstance(seq, h2.H2Seq) assert len(seq.frames) == 2 p = seq.frames[0] assert isinstance(p, h2.H2Frame) assert p.type == 1 assert len(p.flags) == 1 assert 'ES' in p.flags assert p.stream_id == 1 assert isinstance(p.payload, h2.H2HeadersFrame) hdrs_frm = p[h2.H2HeadersFrame] assert len(p.hdrs) == 9 hdr = p.hdrs[0] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 3 hdr = p.hdrs[1] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index in [4, 5] assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(/login.php)' hdr = p.hdrs[2] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 7 hdr = p.hdrs[3] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 31 assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)' hdr = p.hdrs[4] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 28 assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackLiteralString(22)' hdr = p.hdrs[5] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 58 assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)' hdr = p.hdrs[6] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 0 assert isinstance(hdr.hdr_name, h2.HPackHdrString) assert hdr.hdr_name.data == 'HPackZString(x-generated-by)' assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackLiteralString(Me)' hdr = p.hdrs[7] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 62 hdr = p.hdrs[8] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 0 assert isinstance(hdr.hdr_name, h2.HPackHdrString) assert hdr.hdr_name.data == 'HPackZString(x-long-header)' assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString({})'.format('a'*5000) p = seq.frames[1] assert isinstance(p, h2.H2Frame) assert p.type == 9 assert len(p.flags) == 1 assert 'EH' in p.flags assert p.stream_id == 1 assert isinstance(p.payload, h2.H2ContinuationFrame) hdrs_frm = p[h2.H2ContinuationFrame] assert len(p.hdrs) == 1 hdr = p.hdrs[0] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 0 assert isinstance(hdr.hdr_name, h2.HPackHdrString) assert hdr.hdr_name.data == 'HPackZString(x-long-header)' assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString({})'.format('b'*5000) = HTTP/2 HPackHdrTable : Parsing Textual Representation with two very large headers, a large authorized frame size and a "small" max header list size ~ http2 hpack hpackhdrtable helpers body = b'login=titi&passwd=toto' hdrs = ''':method POST :path /login.php :scheme https content-type: application/x-www-form-urlencoded content-length: {} user-agent: Mozilla/5.0 Generated by hand x-generated-by: Me x-generation-date: 2016-08-11 x-long-header: {} x-long-header: {} '''.format(len(body), 'a'*5000, 'b'*5000).encode() h = h2.HPackHdrTable() h.register(h2.HPackLitHdrFldWithIncrIndexing( hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')), hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11')) )) # Now trying to parse it with a max frame size large enough for x-long-header to # fit in a frame but and a max header list size that is large enough to fit one # but not two seq = h.parse_txt_hdrs(hdrs, stream_id=1, max_frm_sz=8192, max_hdr_lst_sz=5050) assert isinstance(seq, h2.H2Seq) assert len(seq.frames) == 3 p = seq.frames[0] assert isinstance(p, h2.H2Frame) assert p.type == 1 assert len(p.flags) == 1 assert 'ES' in p.flags assert p.stream_id == 1 assert isinstance(p.payload, h2.H2HeadersFrame) hdrs_frm = p[h2.H2HeadersFrame] assert len(p.hdrs) == 8 hdr = p.hdrs[0] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 3 hdr = p.hdrs[1] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index in [4, 5] assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(/login.php)' hdr = p.hdrs[2] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 7 hdr = p.hdrs[3] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 31 assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)' hdr = p.hdrs[4] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 28 assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackLiteralString(22)' hdr = p.hdrs[5] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 58 assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)' hdr = p.hdrs[6] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 0 assert isinstance(hdr.hdr_name, h2.HPackHdrString) assert hdr.hdr_name.data == 'HPackZString(x-generated-by)' assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackLiteralString(Me)' hdr = p.hdrs[7] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 62 p = seq.frames[1] assert isinstance(p, h2.H2Frame) assert p.type == 9 assert len(p.flags) == 0 assert p.stream_id == 1 assert isinstance(p.payload, h2.H2ContinuationFrame) hdrs_frm = p[h2.H2ContinuationFrame] assert len(p.hdrs) == 1 hdr = p.hdrs[0] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 0 assert isinstance(hdr.hdr_name, h2.HPackHdrString) assert hdr.hdr_name.data == 'HPackZString(x-long-header)' assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString({})'.format('a'*5000) p = seq.frames[2] assert isinstance(p, h2.H2Frame) assert p.type == 9 assert len(p.flags) == 1 assert 'EH' in p.flags assert p.stream_id == 1 assert isinstance(p.payload, h2.H2ContinuationFrame) hdrs_frm = p[h2.H2ContinuationFrame] assert len(p.hdrs) == 1 hdr = p.hdrs[0] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 0 assert isinstance(hdr.hdr_name, h2.HPackHdrString) assert hdr.hdr_name.data == 'HPackZString(x-long-header)' assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString({})'.format('b'*5000) = HTTP/2 HPackHdrTable : Parsing Textual Representation with sensitive headers and non-indexable ones ~ http2 hpack hpackhdrtable helpers hdrs = ''':method POST :path /login.php :scheme https content-type: application/x-www-form-urlencoded content-length: {} user-agent: Mozilla/5.0 Generated by hand x-generated-by: Me x-generation-date: 2016-08-11 '''.format(len(body)).encode() h = h2.HPackHdrTable() seq = h.parse_txt_hdrs(hdrs, stream_id=1, body=body, is_sensitive=lambda n,v: n in ['x-generation-date'], should_index=lambda x: x != 'x-generated-by') assert isinstance(seq, h2.H2Seq) assert len(seq.frames) == 2 p = seq.frames[0] assert isinstance(p, h2.H2Frame) assert p.type == 1 assert len(p.flags) == 1 assert 'EH' in p.flags assert p.stream_id == 1 assert isinstance(p.payload, h2.H2HeadersFrame) hdrs_frm = p[h2.H2HeadersFrame] assert len(p.hdrs) == 8 hdr = p.hdrs[0] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 3 hdr = p.hdrs[1] assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing) assert hdr.magic == 1 assert hdr.index in [4, 5] assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(/login.php)' hdr = p.hdrs[2] assert isinstance(hdr, h2.HPackIndexedHdr) assert hdr.magic == 1 assert hdr.index == 7 hdr = p.hdrs[3] assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing) assert hdr.magic == 1 assert hdr.index == 31 assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)' hdr = p.hdrs[4] assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing) assert hdr.magic == 1 assert hdr.index == 28 assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackLiteralString(22)' hdr = p.hdrs[5] assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing) assert hdr.magic == 1 assert hdr.index == 58 assert hdr.hdr_name is None assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)' hdr = p.hdrs[6] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 0 assert hdr.index == 0 assert isinstance(hdr.hdr_name, h2.HPackHdrString) assert hdr.hdr_name.data == 'HPackZString(x-generated-by)' assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackLiteralString(Me)' hdr = p.hdrs[7] assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing) assert hdr.magic == 0 assert hdr.never_index == 1 assert hdr.index == 0 assert isinstance(hdr.hdr_name, h2.HPackHdrString) assert hdr.hdr_name.data == 'HPackZString(x-generation-date)' assert isinstance(hdr.hdr_value, h2.HPackHdrString) assert hdr.hdr_value.data == 'HPackZString(2016-08-11)' p = seq.frames[1] assert isinstance(p, h2.H2Frame) assert p.type == 0 assert len(p.flags) == 1 assert 'ES' in p.flags assert p.stream_id == 1 assert isinstance(p.payload, h2.H2DataFrame) pay = p[h2.H2DataFrame] assert pay.data == body