% 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)).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')) )) 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) = 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)