1% HTTP/2 Campaign
2# Frames expressed as binary str were generated using the solicit and hpack-rs
3# Rust crates (https://github.com/mlalic/solicit, https://github.com/mlalic/hpack-rs)
4# except Continuation Frames, Priority Frames and Push Promise Frames that we generated
5# using Go x/net/http2 and x/net/http2/hpack modules.
6
7+ Syntax check
8= Configuring Scapy
9~ http2 frame hpack build dissect data headers priority settings rststream pushpromise ping goaway winupdate continuation hpackhdrtable helpers
10
11import scapy.config
12scapy.config.conf.debug_dissector=True
13import scapy.packet
14import scapy.fields
15import scapy.contrib.http2 as h2
16import re
17flags_bit_pattern = re.compile(r'''^\s+flags\s+=\s+\[.*['"]bit [0-9]+['"].*\]$''', re.M)
18def expect_exception(e, c):
19    try:
20        eval(c)
21        return False
22    except e:
23        return True
24
25+ HTTP/2 UVarIntField Test Suite
26
27= HTTP/2 UVarIntField.any2i
28~ http2 frame field uvarintfield
29
30f = h2.UVarIntField('value', 0, 5)
31expect_exception(AssertionError, 'f.any2i(None, None)')
32assert(f.any2i(None, 0) == 0)
33assert(f.any2i(None, 3) == 3)
34assert(f.any2i(None, 1<<5) == 1<<5)
35assert(f.any2i(None, 1<<16) == 1<<16)
36f = h2.UVarIntField('value', 0, 8)
37assert(f.any2i(None, b'\x1E') == 30)
38
39= HTTP/2 UVarIntField.m2i on full byte
40~ http2 frame field uvarintfield
41
42f = h2.UVarIntField('value', 0, 8)
43assert(f.m2i(None, b'\x00') == 0)
44assert(f.m2i(None, b'\x03') == 3)
45assert(f.m2i(None, b'\xFE') == 254)
46assert(f.m2i(None, b'\xFF\x00') == 255)
47assert(f.m2i(None, b'\xFF\xFF\x03') == 766) #0xFF + (0xFF ^ 0x80) + (3<<7)
48
49= HTTP/2 UVarIntField.m2i on partial byte
50~ http2 frame field uvarintfield
51
52f = h2.UVarIntField('value', 0, 5)
53assert(f.m2i(None, (b'\x00', 3)) == 0)
54assert(f.m2i(None, (b'\x03', 3)) == 3)
55assert(f.m2i(None, (b'\x1e', 3)) == 30)
56assert(f.m2i(None, (b'\x1f\x00', 3)) == 31)
57assert(f.m2i(None, (b'\x1f\xe1\xff\x03', 3)) == 65536)
58
59= HTTP/2 UVarIntField.getfield on full byte
60~ http2 frame field uvarintfield
61
62f = h2.UVarIntField('value', 0, 8)
63
64r = f.getfield(None, b'\x00\x00')
65assert(r[0] == b'\x00')
66assert(r[1] == 0)
67
68r = f.getfield(None, b'\x03\x00')
69assert(r[0] == b'\x00')
70assert(r[1] == 3)
71
72r = f.getfield(None, b'\xFE\x00')
73assert(r[0] == b'\x00')
74assert(r[1] == 254)
75
76r = f.getfield(None, b'\xFF\x00\x00')
77assert(r[0] == b'\x00')
78assert(r[1] == 255)
79
80r = f.getfield(None, b'\xFF\xFF\x03\x00')
81assert(r[0] == b'\x00')
82assert(r[1] == 766)
83
84= HTTP/2 UVarIntField.getfield on partial byte
85~ http2 frame field uvarintfield
86
87f = h2.UVarIntField('value', 0, 5)
88
89r = f.getfield(None, (b'\x00\x00', 3))
90assert(r[0] == b'\x00')
91assert(r[1] == 0)
92
93r = f.getfield(None, (b'\x03\x00', 3))
94assert(r[0] == b'\x00')
95assert(r[1] == 3)
96
97r = f.getfield(None, (b'\x1e\x00', 3))
98assert(r[0] == b'\x00')
99assert(r[1] == 30)
100
101r = f.getfield(None, (b'\x1f\x00\x00', 3))
102assert(r[0] == b'\x00')
103assert(r[1] == 31)
104
105r = f.getfield(None, (b'\x1f\xe1\xff\x03\x00', 3))
106assert(r[0] == b'\x00')
107assert(r[1] == 65536)
108
109= HTTP/2 UVarIntField.i2m on full byte
110~ http2 frame field uvarintfield
111
112f = h2.UVarIntField('value', 0, 8)
113assert(f.i2m(None, 0) == b'\x00')
114assert(f.i2m(None, 3) == b'\x03')
115assert(f.i2m(None, 254).lower() == b'\xfe')
116assert(f.i2m(None, 255).lower() == b'\xff\x00')
117assert(f.i2m(None, 766).lower() == b'\xff\xff\x03')
118
119= HTTP/2 UVarIntField.i2m on partial byte
120~ http2 frame field uvarintfield
121
122f = h2.UVarIntField('value', 0, 5)
123assert(f.i2m(None, 0) == b'\x00')
124assert(f.i2m(None, 3) == b'\x03')
125assert(f.i2m(None, 30).lower() == b'\x1e')
126assert(f.i2m(None, 31).lower() == b'\x1f\x00')
127assert(f.i2m(None, 65536).lower() == b'\x1f\xe1\xff\x03')
128
129= HTTP/2 UVarIntField.addfield on full byte
130~ http2 frame field uvarintfield
131
132f = h2.UVarIntField('value', 0, 8)
133
134assert(f.addfield(None, b'Toto', 0) == b'Toto\x00')
135assert(f.addfield(None, b'Toto', 3) == b'Toto\x03')
136assert(f.addfield(None, b'Toto', 254).lower() == b'toto\xfe')
137assert(f.addfield(None, b'Toto', 255).lower() == b'toto\xff\x00')
138assert(f.addfield(None, b'Toto', 766).lower() == b'toto\xff\xff\x03')
139
140= HTTP/2 UVarIntField.addfield on partial byte
141~ http2 frame field uvarintfield
142
143f = h2.UVarIntField('value', 0, 5)
144
145assert(f.addfield(None, (b'Toto', 3, 4), 0) == b'Toto\x80')
146assert(f.addfield(None, (b'Toto', 3, 4), 3) == b'Toto\x83')
147assert(f.addfield(None, (b'Toto', 3, 4), 30).lower() == b'toto\x9e')
148assert(f.addfield(None, (b'Toto', 3, 4), 31).lower() == b'toto\x9f\x00')
149assert(f.addfield(None, (b'Toto', 3, 4), 65536).lower() == b'toto\x9f\xe1\xff\x03')
150
151= HTTP/2 UVarIntField.i2len on full byte
152~ http2 frame field uvarintfield
153
154f = h2.UVarIntField('value', 0, 8)
155
156assert(f.i2len(None, 0) == 1)
157assert(f.i2len(None, 3) == 1)
158assert(f.i2len(None, 254) == 1)
159assert(f.i2len(None, 255) == 2)
160assert(f.i2len(None, 766) == 3)
161
162= HTTP/2 UVarIntField.i2len on partial byte
163~ http2 frame field uvarintfield
164
165f = h2.UVarIntField('value', 0, 5)
166
167assert(f.i2len(None, 0) == 1)
168assert(f.i2len(None, 3) == 1)
169assert(f.i2len(None, 30) == 1)
170assert(f.i2len(None, 31) == 2)
171assert(f.i2len(None, 65536) == 4)
172
173+ HTTP/2 FieldUVarLenField Test Suite
174
175= HTTP/2 FieldUVarLenField.i2m without adjustment
176~ http2 frame field fielduvarlenfield
177
178
179f = h2.FieldUVarLenField('len', None, 8, length_of='data')
180class TrivialPacket(Packet):
181    name = 'Trivial Packet'
182    fields_desc= [
183        f,
184        StrField('data', '')
185    ]
186
187assert(f.i2m(TrivialPacket(data='a'*5), None) == b'\x05')
188assert(f.i2m(TrivialPacket(data='a'*255), None).lower() == b'\xff\x00')
189assert(f.i2m(TrivialPacket(data='a'), 2) == b'\x02')
190assert(f.i2m(None, 2) == b'\x02')
191assert(f.i2m(None, 0) == b'\x00')
192
193= HTTP/2 FieldUVarLenField.i2m with adjustment
194~ http2 frame field fielduvarlenfield
195
196class TrivialPacket(Packet):
197    name = 'Trivial Packet'
198    fields_desc= [
199        f,
200        StrField('data', '')
201    ]
202
203f = h2.FieldUVarLenField('value', None, 8, length_of='data', adjust=lambda x: x-1)
204assert(f.i2m(TrivialPacket(data='a'*5), None) == b'\x04')
205assert(f.i2m(TrivialPacket(data='a'*255), None).lower() == b'\xfe')
206#Adjustement does not affect non-None value!
207assert(f.i2m(TrivialPacket(data='a'*3), 2) == b'\x02')
208
209+ HTTP/2 HPackZString Test Suite
210
211= HTTP/2 HPackZString Compression
212~ http2 hpack huffman
213
214string = 'Test'
215s = h2.HPackZString(string)
216assert(len(s) == 3)
217assert(raw(s) == b"\xdeT'")
218assert(s.origin() == string)
219
220string = 'a'*65535
221s = h2.HPackZString(string)
222assert(len(s) == 40960)
223assert(raw(s) == (b'\x18\xc61\x8cc' * 8191) + b'\x18\xc61\x8c\x7f')
224assert(s.origin() == string)
225
226= HTTP/2 HPackZString Decompression
227~ http2 hpack huffman
228
229s = b"\xdeT'"
230i, ibl = h2.HPackZString.huffman_conv2bitstring(s)
231assert(b'Test' == h2.HPackZString.huffman_decode(i, ibl))
232
233s = (b'\x18\xc61\x8cc' * 8191) + b'\x18\xc61\x8c\x7f'
234i, ibl = h2.HPackZString.huffman_conv2bitstring(s)
235assert(b'a'*65535 == h2.HPackZString.huffman_decode(i, ibl))
236
237assert(
238    expect_exception(h2.InvalidEncodingException,
239    'h2.HPackZString.huffman_decode(*h2.HPackZString.huffman_conv2bitstring(b"\\xdeT"))')
240)
241
242+ HTTP/2 HPackStrLenField Test Suite
243
244= HTTP/2 HPackStrLenField.m2i
245~ http2 hpack field hpackstrlenfield
246
247f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')
248class TrivialPacket(Packet):
249    name = 'Trivial Packet'
250    fields_desc = [
251        IntField('type', None),
252        IntField('len', None),
253        f
254    ]
255
256s = f.m2i(TrivialPacket(type=0, len=4), b'Test')
257assert(isinstance(s, h2.HPackLiteralString))
258assert(s.origin() == 'Test')
259
260s = f.m2i(TrivialPacket(type=1, len=3), b"\xdeT'")
261assert(isinstance(s, h2.HPackZString))
262assert(s.origin() == 'Test')
263
264= HTTP/2 HPackStrLenField.any2i
265~ http2 hpack field hpackstrlenfield
266
267f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')
268class TrivialPacket(Packet):
269    name = 'Trivial Packet'
270    fields_desc = [
271        IntField('type', None),
272        IntField('len', None),
273        f
274    ]
275
276s = f.any2i(TrivialPacket(type=0, len=4), b'Test')
277assert(isinstance(s, h2.HPackLiteralString))
278assert(s.origin() == 'Test')
279
280s = f.any2i(TrivialPacket(type=1, len=3), b"\xdeT'")
281assert(isinstance(s, h2.HPackZString))
282assert(s.origin() == 'Test')
283
284s = h2.HPackLiteralString('Test')
285s2 = f.any2i(TrivialPacket(type=0, len=4), s)
286assert(s.origin() == s2.origin())
287
288s = h2.HPackZString('Test')
289s2 = f.any2i(TrivialPacket(type=1, len=3), s)
290assert(s.origin() == s2.origin())
291
292s = h2.HPackLiteralString('Test')
293s2 = f.any2i(None, s)
294assert(s.origin() == s2.origin())
295
296s = h2.HPackZString('Test')
297s2 = f.any2i(None, s)
298assert(s.origin() == s2.origin())
299
300# Verifies that one can fuzz
301s = h2.HPackLiteralString('Test')
302s2 = f.any2i(TrivialPacket(type=1, len=1), s)
303assert(s.origin() == s2.origin())
304
305= HTTP/2 HPackStrLenField.i2m
306~ http2 hpack field hpackstrlenfield
307
308f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')
309
310s = b'Test'
311s2 = f.i2m(None, h2.HPackLiteralString(s))
312assert(s == s2)
313
314s = b'Test'
315s2 = f.i2m(None, h2.HPackZString(s))
316assert(s2 == b"\xdeT'")
317
318= HTTP/2 HPackStrLenField.addfield
319~ http2 hpack field hpackstrlenfield
320
321f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')
322
323s = b'Test'
324s2 = f.addfield(None, b'Toto', h2.HPackLiteralString(s))
325assert(b'Toto' + s == s2)
326
327s = b'Test'
328s2 = f.addfield(None, b'Toto', h2.HPackZString(s))
329assert(s2 == b"Toto\xdeT'")
330
331= HTTP/2 HPackStrLenField.getfield
332~ http2 hpack field hpackstrlenfield
333
334f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')
335class TrivialPacket(Packet):
336    name = 'Trivial Packet'
337    fields_desc = [
338        IntField('type', None),
339        IntField('len', None),
340        f
341    ]
342
343r = f.getfield(TrivialPacket(type=0, len=4), b'TestToto')
344assert(isinstance(r, tuple))
345assert(r[0] == b'Toto')
346assert(isinstance(r[1], h2.HPackLiteralString))
347assert(r[1].origin() == 'Test')
348
349r = f.getfield(TrivialPacket(type=1, len=3), b"\xdeT'Toto")
350assert(isinstance(r, tuple))
351assert(r[0] == b'Toto')
352assert(isinstance(r[1], h2.HPackZString))
353assert(r[1].origin() == 'Test')
354
355= HTTP/2 HPackStrLenField.i2h / i2repr
356~ http2 hpack field hpackstrlenfield
357
358f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')
359
360s = b'Test'
361assert(f.i2h(None, h2.HPackLiteralString(s)) == 'HPackLiteralString(Test)')
362assert(f.i2repr(None, h2.HPackLiteralString(s)) == repr('HPackLiteralString(Test)'))
363
364assert(f.i2h(None, h2.HPackZString(s)) == 'HPackZString(Test)')
365assert(f.i2repr(None, h2.HPackZString(s)) == repr('HPackZString(Test)'))
366
367= HTTP/2 HPackStrLenField.i2len
368~ http2 hpack field hpackstrlenfield
369
370f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')
371
372s = b'Test'
373assert(f.i2len(None, h2.HPackLiteralString(s)) == 4)
374assert(f.i2len(None, h2.HPackZString(s)) == 3)
375
376+ HTTP/2 HPackMagicBitField Test Suite
377# Magic bits are not supposed to be modified and if they are anyway, they must
378# be assigned the magic|default value only...
379
380= HTTP/2 HPackMagicBitField.addfield
381~ http2 hpack field hpackmagicbitfield
382
383f = h2.HPackMagicBitField('value', 3, 2)
384r = f.addfield(None, b'Toto', 3)
385assert(isinstance(r, tuple))
386assert(r[0] == b'Toto')
387assert(r[1] == 2)
388assert(r[2] == 3)
389
390r = f.addfield(None, (b'Toto', 2, 1) , 3)
391assert(isinstance(r, tuple))
392assert(r[0] == b'Toto')
393assert(r[1] == 4)
394assert(r[2] == 7)
395
396assert(expect_exception(AssertionError, 'f.addfield(None, "toto", 2)'))
397
398= HTTP/2 HPackMagicBitField.getfield
399~ http2 hpack field hpackmagicbitfield
400
401f = h2.HPackMagicBitField('value', 3, 2)
402
403r = f.getfield(None, b'\xc0')
404assert(isinstance(r, tuple))
405assert(len(r) == 2)
406assert(isinstance(r[0], tuple))
407assert(len(r[0]) == 2)
408assert(r[0][0] == b'\xc0')
409assert(r[0][1] == 2)
410assert(r[1] == 3)
411
412r = f.getfield(None, (b'\x03', 6))
413assert(isinstance(r, tuple))
414assert(len(r) == 2)
415assert(isinstance(r[0], bytes))
416assert(r[0] == b'')
417assert(r[1] == 3)
418
419expect_exception(AssertionError, 'f.getfield(None, b"\\x80")')
420
421= HTTP/2 HPackMagicBitField.h2i
422~ http2 hpack field hpackmagicbitfield
423
424f = h2.HPackMagicBitField('value', 3, 2)
425assert(f.h2i(None, 3) == 3)
426expect_exception(AssertionError, 'f.h2i(None, 2)')
427
428= HTTP/2 HPackMagicBitField.m2i
429~ http2 hpack field hpackmagicbitfield
430
431f = h2.HPackMagicBitField('value', 3, 2)
432assert(f.m2i(None, 3) == 3)
433expect_exception(AssertionError, 'f.m2i(None, 2)')
434
435= HTTP/2 HPackMagicBitField.i2m
436~ http2 hpack field hpackmagicbitfield
437
438f = h2.HPackMagicBitField('value', 3, 2)
439assert(f.i2m(None, 3) == 3)
440expect_exception(AssertionError, 'f.i2m(None, 2)')
441
442= HTTP/2 HPackMagicBitField.any2i
443~ http2 hpack field hpackmagicbitfield
444
445f = h2.HPackMagicBitField('value', 3, 2)
446assert(f.any2i(None, 3) == 3)
447expect_exception(AssertionError, 'f.any2i(None, 2)')
448
449+ HTTP/2 HPackHdrString Test Suite
450
451= HTTP/2 Dissect HPackHdrString
452~ http2 pack dissect hpackhdrstring
453
454p = h2.HPackHdrString(b'\x04Test')
455assert(p.type == 0)
456assert(p.len == 4)
457assert(isinstance(p.getfieldval('data'), h2.HPackLiteralString))
458assert(p.getfieldval('data').origin() == 'Test')
459
460p = h2.HPackHdrString(b"\x83\xdeT'")
461assert(p.type == 1)
462assert(p.len == 3)
463assert(isinstance(p.getfieldval('data'), h2.HPackZString))
464assert(p.getfieldval('data').origin() == 'Test')
465
466= HTTP/2 Build HPackHdrString
467~ http2 hpack build hpackhdrstring
468
469p = h2.HPackHdrString(data=h2.HPackLiteralString('Test'))
470assert(raw(p) == b'\x04Test')
471
472p = h2.HPackHdrString(data=h2.HPackZString('Test'))
473assert(raw(p) == b"\x83\xdeT'")
474
475#Fuzzing-able tests
476p = h2.HPackHdrString(type=1, len=3, data=h2.HPackLiteralString('Test'))
477assert(raw(p) == b'\x83Test')
478
479+ HTTP/2 HPackIndexedHdr Test Suite
480
481= HTTP/2 Dissect HPackIndexedHdr
482~ http2 hpack dissect hpackindexedhdr
483
484p = h2.HPackIndexedHdr(b'\x80')
485assert(p.magic == 1)
486assert(p.index == 0)
487
488p = h2.HPackIndexedHdr(b'\xFF\x00')
489assert(p.magic == 1)
490assert(p.index == 127)
491
492= HTTP/2 Build HPackIndexedHdr
493~ http2 hpack build hpackindexedhdr
494
495p = h2.HPackIndexedHdr(index=0)
496assert(raw(p) == b'\x80')
497
498p = h2.HPackIndexedHdr(index=127)
499assert(raw(p) == b'\xFF\x00')
500
501+ HTTP/2 HPackLitHdrFldWithIncrIndexing Test Suite
502
503= HTTP/2 Dissect HPackLitHdrFldWithIncrIndexing without indexed name
504~ http2 hpack dissect hpacklithdrfldwithincrindexing
505
506p = h2.HPackLitHdrFldWithIncrIndexing(b'\x40\x04Test\x04Toto')
507assert(p.magic == 1)
508assert(p.index == 0)
509assert(isinstance(p.hdr_name, h2.HPackHdrString))
510assert(p.hdr_name.type == 0)
511assert(p.hdr_name.len == 4)
512assert(p.hdr_name.getfieldval('data').origin() == 'Test')
513assert(isinstance(p.hdr_value, h2.HPackHdrString))
514assert(p.hdr_value.type == 0)
515assert(p.hdr_value.len == 4)
516assert(p.hdr_value.getfieldval('data').origin() == 'Toto')
517
518= HTTP/2 Dissect HPackLitHdrFldWithIncrIndexing with indexed name
519~ http2 hpack dissect hpacklithdrfldwithincrindexing
520
521p = h2.HPackLitHdrFldWithIncrIndexing(b'\x41\x04Toto')
522assert(p.magic == 1)
523assert(p.index == 1)
524assert(p.hdr_name is None)
525assert(isinstance(p.hdr_value, h2.HPackHdrString))
526assert(p.hdr_value.type == 0)
527assert(p.hdr_value.len == 4)
528assert(p.hdr_value.getfieldval('data').origin() == 'Toto')
529
530
531= HTTP/2 Build HPackLitHdrFldWithIncrIndexing without indexed name
532~ http2 hpack build hpacklithdrfldwithincrindexing
533
534p = h2.HPackLitHdrFldWithIncrIndexing(
535    hdr_name=h2.HPackHdrString(data=h2.HPackLiteralString('Test')),
536    hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto'))
537)
538assert(raw(p) == b'\x40\x04Test\x04Toto')
539
540= HTTP/2 Build HPackLitHdrFldWithIncrIndexing with indexed name
541~ http2 hpack build hpacklithdrfldwithincrindexing
542
543p = h2.HPackLitHdrFldWithIncrIndexing(
544    index=1,
545    hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto'))
546)
547assert(raw(p) == b'\x41\x04Toto')
548
549+ HTTP/2 HPackLitHdrFldWithoutIndexing Test Suite
550
551= HTTP/2 Dissect HPackLitHdrFldWithoutIndexing : don't index and no index
552~ http2 hpack dissect hpacklithdrfldwithoutindexing
553
554p = h2.HPackLitHdrFldWithoutIndexing(b'\x00\x04Test\x04Toto')
555assert(p.magic == 0)
556assert(p.never_index == 0)
557assert(p.index == 0)
558assert(isinstance(p.hdr_name, h2.HPackHdrString))
559assert(p.hdr_name.type == 0)
560assert(p.hdr_name.len == 4)
561assert(isinstance(p.hdr_name.getfieldval('data'), h2.HPackLiteralString))
562assert(p.hdr_name.getfieldval('data').origin() == 'Test')
563assert(isinstance(p.hdr_value, h2.HPackHdrString))
564assert(p.hdr_value.type == 0)
565assert(p.hdr_value.len == 4)
566assert(isinstance(p.hdr_value.getfieldval('data'), h2.HPackLiteralString))
567assert(p.hdr_value.getfieldval('data').origin() == 'Toto')
568
569= HTTP/2 Dissect HPackLitHdrFldWithoutIndexing : never index index and no index
570~ http2 hpack dissect hpacklithdrfldwithoutindexing
571
572p = h2.HPackLitHdrFldWithoutIndexing(b'\x10\x04Test\x04Toto')
573assert(p.magic == 0)
574assert(p.never_index == 1)
575assert(p.index == 0)
576assert(isinstance(p.hdr_name, h2.HPackHdrString))
577assert(p.hdr_name.type == 0)
578assert(p.hdr_name.len == 4)
579assert(isinstance(p.hdr_name.getfieldval('data'), h2.HPackLiteralString))
580assert(p.hdr_name.getfieldval('data').origin() == 'Test')
581assert(isinstance(p.hdr_value, h2.HPackHdrString))
582assert(p.hdr_value.type == 0)
583assert(p.hdr_value.len == 4)
584assert(isinstance(p.hdr_value.getfieldval('data'), h2.HPackLiteralString))
585assert(p.hdr_value.getfieldval('data').origin() == 'Toto')
586
587= HTTP/2 Dissect HPackLitHdrFldWithoutIndexing : never index and indexed name
588~ http2 hpack dissect hpacklithdrfldwithoutindexing
589
590p = h2.HPackLitHdrFldWithoutIndexing(b'\x11\x04Toto')
591assert(p.magic == 0)
592assert(p.never_index == 1)
593assert(p.index == 1)
594assert(p.hdr_name is None)
595assert(isinstance(p.hdr_value, h2.HPackHdrString))
596assert(p.hdr_value.type == 0)
597assert(p.hdr_value.len == 4)
598assert(isinstance(p.hdr_value.getfieldval('data'), h2.HPackLiteralString))
599assert(p.hdr_value.getfieldval('data').origin() == 'Toto')
600
601= HTTP/2 Build HPackLitHdrFldWithoutIndexing : don't index and no index
602~ http2 hpack build hpacklithdrfldwithoutindexing
603
604p = h2.HPackLitHdrFldWithoutIndexing(
605    hdr_name=h2.HPackHdrString(data=h2.HPackLiteralString('Test')),
606    hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto'))
607)
608assert(raw(p) == b'\x00\x04Test\x04Toto')
609
610= HTTP/2 Build HPackLitHdrFldWithoutIndexing : never index index and no index
611~ http2 hpack build hpacklithdrfldwithoutindexing
612
613p = h2.HPackLitHdrFldWithoutIndexing(
614    never_index=1,
615    hdr_name=h2.HPackHdrString(data=h2.HPackLiteralString('Test')),
616    hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto'))
617)
618assert(raw(p) == b'\x10\x04Test\x04Toto')
619
620= HTTP/2 Build HPackLitHdrFldWithoutIndexing : never index and indexed name
621~ http2 hpack build hpacklithdrfldwithoutindexing
622
623p = h2.HPackLitHdrFldWithoutIndexing(
624    never_index=1,
625    index=1,
626    hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto'))
627)
628assert(raw(p) == b'\x11\x04Toto')
629
630+ HTTP/2 HPackDynamicSizeUpdate Test Suite
631
632= HTTP/2 Dissect HPackDynamicSizeUpdate
633~ http2 hpack dissect hpackdynamicsizeupdate
634
635p = h2.HPackDynamicSizeUpdate(b'\x25')
636assert(p.magic == 1)
637assert(p.max_size == 5)
638p = h2.HPackDynamicSizeUpdate(b'\x3F\x00')
639assert(p.magic == 1)
640assert(p.max_size == 31)
641
642= HTTP/2 Build HPackDynamicSizeUpdate
643~ http2 hpack build hpackdynamicsizeupdate
644
645p = h2.HPackDynamicSizeUpdate(max_size=5)
646assert(raw(p) == b'\x25')
647p = h2.HPackDynamicSizeUpdate(max_size=31)
648assert(raw(p) == b'\x3F\x00')
649
650+ HTTP/2 Data Frame Test Suite
651
652= HTTP/2 Dissect Data Frame: Simple data frame
653~ http2 frame dissect data
654
655pkt = h2.H2Frame(b'\x00\x00\x04\x00\x00\x00\x00\x00\x01ABCD')
656assert(pkt.type == 0)
657assert(pkt.len == 4)
658assert(len(pkt.flags) == 0)
659assert(pkt.reserved == 0)
660assert(pkt.stream_id == 1)
661assert(isinstance(pkt.payload, h2.H2DataFrame))
662assert(pkt[h2.H2DataFrame])
663assert(pkt.payload.data == b'ABCD')
664assert(isinstance(pkt.payload.payload, scapy.packet.NoPayload))
665
666= HTTP/2 Build Data Frame: Simple data frame
667~ http2 frame build data
668
669pkt = h2.H2Frame(stream_id = 1)/h2.H2DataFrame(data='ABCD')
670assert(raw(pkt) == b'\x00\x00\x04\x00\x00\x00\x00\x00\x01ABCD')
671try:
672    pkt.show2(dump=True)
673    assert(True)
674except:
675    assert(False)
676
677= HTTP/2 Dissect Data Frame: Simple data frame with padding
678~ http2 frame dissect data
679
680pkt = h2.H2Frame(b'\x00\x00\r\x00\x08\x00\x00\x00\x01\x08ABCD\x00\x00\x00\x00\x00\x00\x00\x00') #Padded data frame
681assert(pkt.type == 0)
682assert(pkt.len == 13)
683assert(len(pkt.flags) ==  1)
684assert('P' in pkt.flags)
685assert(pkt.reserved == 0)
686assert(pkt.stream_id == 1)
687assert(isinstance(pkt.payload, h2.H2PaddedDataFrame))
688assert(pkt[h2.H2PaddedDataFrame])
689assert(pkt.payload.padlen == 8)
690assert(pkt.payload.data == b'ABCD')
691assert(pkt.payload.padding == b'\x00'*8)
692assert(flags_bit_pattern.search(pkt.show(dump=True)) is None)
693assert(isinstance(pkt.payload.payload, scapy.packet.NoPayload))
694
695= HTTP/2 Build Data Frame: Simple data frame with padding
696~ http2 frame build data
697
698pkt = h2.H2Frame(flags = {'P'}, stream_id = 1)/h2.H2PaddedDataFrame(data='ABCD', padding=b'\x00'*8)
699assert(raw(pkt) == b'\x00\x00\r\x00\x08\x00\x00\x00\x01\x08ABCD\x00\x00\x00\x00\x00\x00\x00\x00')
700try:
701    pkt.show2(dump=True)
702    assert(True)
703except:
704    assert(False)
705
706= HTTP/2 Dissect Data Frame: Simple data frame with padding and end stream flag
707~ http2 frame dissect data
708
709pkt = 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
710assert(pkt.type == 0)
711assert(pkt.len == 13)
712assert(len(pkt.flags) == 2)
713assert('P' in pkt.flags)
714assert('ES' in pkt.flags)
715assert(pkt.reserved == 0)
716assert(pkt.stream_id == 1)
717assert(isinstance(pkt.payload, h2.H2PaddedDataFrame))
718assert(pkt[h2.H2PaddedDataFrame])
719assert(pkt.payload.padlen == 8)
720assert(pkt.payload.data == b'ABCD')
721assert(pkt.payload.padding == b'\x00'*8)
722assert(flags_bit_pattern.search(pkt.show(dump=True)) is None)
723assert(isinstance(pkt.payload.payload, scapy.packet.NoPayload))
724
725= HTTP/2 Build Data Frame: Simple data frame with padding and end stream flag
726~ http2 frame build data
727
728pkt = h2.H2Frame(flags = {'P', 'ES'}, stream_id=1)/h2.H2PaddedDataFrame(data='ABCD', padding=b'\x00'*8)
729assert(raw(pkt) == b'\x00\x00\r\x00\t\x00\x00\x00\x01\x08ABCD\x00\x00\x00\x00\x00\x00\x00\x00')
730try:
731    pkt.show2(dump=True)
732    assert(True)
733except:
734    assert(False)
735
736+ HTTP/2 Headers Frame Test Suite
737
738= HTTP/2 Dissect Headers Frame: Simple header frame
739~ http2 frame dissect headers
740
741pkt = h2.H2Frame(b'\x00\x00\x0e\x01\x00\x00\x00\x00\x01\x88\x0f\x10\ntext/plain') #Header frame
742assert(pkt.type == 1)
743assert(pkt.len == 14)
744assert(len(pkt.flags) == 0)
745assert(pkt.reserved == 0)
746assert(pkt.stream_id == 1)
747assert(isinstance(pkt.payload, h2.H2HeadersFrame))
748assert(pkt[h2.H2HeadersFrame])
749hf = pkt[h2.H2HeadersFrame]
750assert(len(hf.hdrs) == 2)
751assert(isinstance(hf.hdrs[0], h2.HPackIndexedHdr))
752assert(hf.hdrs[0].magic == 1)
753assert(hf.hdrs[0].index == 8)
754assert(isinstance(hf.hdrs[1], h2.HPackLitHdrFldWithoutIndexing))
755assert(hf.hdrs[1].magic == 0)
756assert(hf.hdrs[1].never_index == 0)
757assert(hf.hdrs[1].index == 31)
758assert(hf.hdrs[1].hdr_name is None)
759assert(expect_exception(AttributeError, 'hf.hdrs[1].non_existant'))
760assert(isinstance(hf.hdrs[1].hdr_value, h2.HPackHdrString))
761s = hf.hdrs[1].hdr_value
762assert(s.type == 0)
763assert(s.len == 10)
764assert(s.getfieldval('data').origin() == 'text/plain')
765assert(isinstance(hf.payload, scapy.packet.NoPayload))
766
767= HTTP/2 Build Headers Frame: Simple header frame
768~ http2 frame build headers
769
770p = h2.H2Frame(stream_id=1)/h2.H2HeadersFrame(hdrs=[
771        h2.HPackIndexedHdr(index=8),
772        h2.HPackLitHdrFldWithoutIndexing(
773            index=31,
774            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('text/plain'))
775        )
776    ]
777)
778assert(raw(p) == b'\x00\x00\x0e\x01\x00\x00\x00\x00\x01\x88\x0f\x10\ntext/plain')
779
780= HTTP/2 Dissect Headers Frame: Header frame with padding
781~ http2 frame dissect headers
782
783pkt = 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
784assert(pkt.type == 1)
785assert(pkt.len == 23)
786assert(len(pkt.flags) == 1)
787assert('P' in pkt.flags)
788assert(pkt.reserved == 0)
789assert(pkt.stream_id == 1)
790assert(isinstance(pkt.payload, h2.H2PaddedHeadersFrame))
791assert(flags_bit_pattern.search(pkt.show(dump=True)) is None)
792assert(pkt[h2.H2PaddedHeadersFrame])
793hf = pkt[h2.H2PaddedHeadersFrame]
794assert(hf.padlen == 8)
795assert(hf.padding == b'\x00' * 8)
796assert(len(hf.hdrs) == 2)
797assert(isinstance(hf.hdrs[0], h2.HPackIndexedHdr))
798assert(hf.hdrs[0].magic == 1)
799assert(hf.hdrs[0].index == 8)
800assert(isinstance(hf.hdrs[1], h2.HPackLitHdrFldWithoutIndexing))
801assert(hf.hdrs[1].magic == 0)
802assert(hf.hdrs[1].never_index == 0)
803assert(hf.hdrs[1].index == 31)
804assert(hf.hdrs[1].hdr_name is None)
805assert(expect_exception(AttributeError, 'hf.hdrs[1].non_existant'))
806assert(isinstance(hf.hdrs[1].hdr_value, h2.HPackHdrString))
807s = hf.hdrs[1].hdr_value
808assert(s.type == 0)
809assert(s.len == 10)
810assert(s.getfieldval('data').origin() == 'text/plain')
811assert(isinstance(hf.payload, scapy.packet.NoPayload))
812
813= HTTP/2 Build Headers Frame: Header frame with padding
814~ http2 frame build headers
815
816p = h2.H2Frame(flags={'P'}, stream_id=1)/h2.H2PaddedHeadersFrame(
817    hdrs=[
818        h2.HPackIndexedHdr(index=8),
819        h2.HPackLitHdrFldWithoutIndexing(
820            index=31,
821            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('text/plain'))
822        )
823    ],
824    padding=b'\x00'*8,
825)
826assert(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')
827
828= HTTP/2 Dissect Headers Frame: Header frame with priority
829~ http2 frame dissect headers
830
831pkt = h2.H2Frame(b'\x00\x00\x13\x01 \x00\x00\x00\x01\x00\x00\x00\x02d\x88\x0f\x10\ntext/plain') #Header frame with priority
832assert(pkt.type == 1)
833assert(pkt.len == 19)
834assert(len(pkt.flags) == 1)
835assert('+' in pkt.flags)
836assert(pkt.reserved == 0)
837assert(pkt.stream_id == 1)
838assert(isinstance(pkt.payload, h2.H2PriorityHeadersFrame))
839assert(flags_bit_pattern.search(pkt.show(dump=True)) is None)
840assert(pkt[h2.H2PriorityHeadersFrame])
841hf = pkt[h2.H2PriorityHeadersFrame]
842assert(hf.exclusive == 0)
843assert(hf.stream_dependency == 2)
844assert(hf.weight == 100)
845assert(len(hf.hdrs) == 2)
846assert(isinstance(hf.hdrs[0], h2.HPackIndexedHdr))
847assert(hf.hdrs[0].magic == 1)
848assert(hf.hdrs[0].index == 8)
849assert(isinstance(hf.hdrs[1], h2.HPackLitHdrFldWithoutIndexing))
850assert(hf.hdrs[1].magic == 0)
851assert(hf.hdrs[1].never_index == 0)
852assert(hf.hdrs[1].index == 31)
853assert(hf.hdrs[1].hdr_name is None)
854assert(expect_exception(AttributeError, 'hf.hdrs[1].non_existant'))
855assert(isinstance(hf.hdrs[1].hdr_value, h2.HPackHdrString))
856s = hf.hdrs[1].hdr_value
857assert(s.type == 0)
858assert(s.len == 10)
859assert(s.getfieldval('data').origin() == 'text/plain')
860assert(isinstance(hf.payload, scapy.packet.NoPayload))
861
862= HTTP/2 Build Headers Frame: Header frame with priority
863~ http2 frame build headers
864
865p = h2.H2Frame(flags={'+'}, stream_id=1)/h2.H2PriorityHeadersFrame(
866    exclusive=0,
867    stream_dependency=2,
868    weight=100,
869    hdrs=[
870        h2.HPackIndexedHdr(index=8),
871        h2.HPackLitHdrFldWithoutIndexing(
872            index=31,
873            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('text/plain'))
874        )
875    ]
876)
877assert(raw(p) == b'\x00\x00\x13\x01 \x00\x00\x00\x01\x00\x00\x00\x02d\x88\x0f\x10\ntext/plain')
878
879= HTTP/2 Dissect Headers Frame: Header frame with priority and padding and flags
880~ http2 frame dissect headers
881
882pkt = 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
883assert(pkt.type == 1)
884assert(pkt.len == 28)
885assert(len(pkt.flags) == 4)
886assert('+' in pkt.flags)
887assert('P' in pkt.flags)
888assert('ES' in pkt.flags)
889assert('EH' in pkt.flags)
890assert(pkt.reserved == 0)
891assert(pkt.stream_id == 1)
892assert(isinstance(pkt.payload, h2.H2PaddedPriorityHeadersFrame))
893assert(flags_bit_pattern.search(pkt.show(dump=True)) is None)
894assert(pkt[h2.H2PaddedPriorityHeadersFrame])
895hf = pkt[h2.H2PaddedPriorityHeadersFrame]
896assert(hf.padlen == 8)
897assert(hf.padding == b'\x00' * 8)
898assert(hf.exclusive == 0)
899assert(hf.stream_dependency == 2)
900assert(hf.weight == 100)
901assert(len(hf.hdrs) == 2)
902assert(isinstance(hf.hdrs[0], h2.HPackIndexedHdr))
903assert(hf.hdrs[0].magic == 1)
904assert(hf.hdrs[0].index == 8)
905assert(isinstance(hf.hdrs[1], h2.HPackLitHdrFldWithoutIndexing))
906assert(hf.hdrs[1].magic == 0)
907assert(hf.hdrs[1].never_index == 0)
908assert(hf.hdrs[1].index == 31)
909assert(hf.hdrs[1].hdr_name is None)
910assert(expect_exception(AttributeError, 'hf.hdrs[1].non_existant'))
911assert(isinstance(hf.hdrs[1].hdr_value, h2.HPackHdrString))
912s = hf.hdrs[1].hdr_value
913assert(s.type == 0)
914assert(s.len == 10)
915assert(s.getfieldval('data').origin() == 'text/plain')
916assert(isinstance(hf.payload, scapy.packet.NoPayload))
917
918= HTTP/2 Build Headers Frame: Header frame with priority and padding and flags
919~ http2 frame build headers
920
921p = h2.H2Frame(flags={'P', '+', 'ES', 'EH'}, stream_id=1)/h2.H2PaddedPriorityHeadersFrame(
922    exclusive=0,
923    stream_dependency=2,
924    weight=100,
925    padding=b'\x00'*8,
926    hdrs=[
927        h2.HPackIndexedHdr(index=8),
928        h2.HPackLitHdrFldWithoutIndexing(
929            index=31,
930            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('text/plain'))
931        )
932    ]
933)
934
935+ HTTP/2 Priority Frame Test Suite
936
937= HTTP/2 Dissect Priority Frame
938~ http2 frame dissect priority
939
940pkt = h2.H2Frame(b'\x00\x00\x05\x02\x00\x00\x00\x00\x03\x80\x00\x00\x01d')
941assert(pkt.type == 2)
942assert(pkt.len == 5)
943assert(len(pkt.flags) == 0)
944assert(pkt.reserved == 0)
945assert(pkt.stream_id == 3)
946assert(isinstance(pkt.payload, h2.H2PriorityFrame))
947assert(pkt[h2.H2PriorityFrame])
948pp = pkt[h2.H2PriorityFrame]
949assert(pp.stream_dependency == 1)
950assert(pp.exclusive == 1)
951assert(pp.weight == 100)
952
953= HTTP/2 Build Priority Frame
954~ http2 frame build priority
955
956p = h2.H2Frame(stream_id=3)/h2.H2PriorityFrame(
957    exclusive=1,
958    stream_dependency=1,
959    weight=100
960)
961assert(raw(p) == b'\x00\x00\x05\x02\x00\x00\x00\x00\x03\x80\x00\x00\x01d')
962
963+ HTTP/2 Reset Stream Frame Test Suite
964
965= HTTP/2 Dissect Reset Stream Frame: Protocol Error
966~ http2 frame dissect rststream
967
968pkt = h2.H2Frame(b'\x00\x00\x04\x03\x00\x00\x00\x00\x01\x00\x00\x00\x01') #Reset stream with protocol error
969assert(pkt.type == 3)
970assert(pkt.len == 4)
971assert(len(pkt.flags) == 0)
972assert(pkt.reserved == 0)
973assert(pkt.stream_id == 1)
974assert(isinstance(pkt.payload, h2.H2ResetFrame))
975assert(pkt[h2.H2ResetFrame])
976rf = pkt[h2.H2ResetFrame]
977assert(rf.error == 1)
978assert(isinstance(rf.payload, scapy.packet.NoPayload))
979
980= HTTP/2 Build Reset Stream Frame: Protocol Error
981~ http2 frame build rststream
982
983p = h2.H2Frame(stream_id=1)/h2.H2ResetFrame(error='Protocol error')
984assert(raw(p) == b'\x00\x00\x04\x03\x00\x00\x00\x00\x01\x00\x00\x00\x01')
985
986p = h2.H2Frame(stream_id=1)/h2.H2ResetFrame(error=1)
987assert(raw(p) == b'\x00\x00\x04\x03\x00\x00\x00\x00\x01\x00\x00\x00\x01')
988
989= HTTP/2 Dissect Reset Stream Frame: Raw 123456 error
990~ http2 frame dissect rststream
991
992pkt = h2.H2Frame(b'\x00\x00\x04\x03\x00\x00\x00\x00\x01\x00\x01\xe2@') #Reset stream with raw error
993assert(pkt.type == 3)
994assert(pkt.len == 4)
995assert(len(pkt.flags) == 0)
996assert(pkt.reserved == 0)
997assert(pkt.stream_id == 1)
998assert(isinstance(pkt.payload, h2.H2ResetFrame))
999assert(pkt[h2.H2ResetFrame])
1000rf = pkt[h2.H2ResetFrame]
1001assert(rf.error == 123456)
1002assert(isinstance(rf.payload, scapy.packet.NoPayload))
1003
1004= HTTP/2 Dissect Reset Stream Frame: Raw 123456 error
1005~ http2 frame dissect rststream
1006
1007p = h2.H2Frame(stream_id=1)/h2.H2ResetFrame(error=123456)
1008assert(raw(p) == b'\x00\x00\x04\x03\x00\x00\x00\x00\x01\x00\x01\xe2@')
1009
1010+ HTTP/2 Settings Frame Test Suite
1011
1012= HTTP/2 Dissect Settings Frame: Settings Frame
1013~ http2 frame dissect settings
1014
1015pkt = 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
1016assert(pkt.type == 4)
1017assert(pkt.len == 36)
1018assert(len(pkt.flags) == 0)
1019assert(pkt.reserved == 0)
1020assert(pkt.stream_id == 0)
1021assert(isinstance(pkt.payload, h2.H2SettingsFrame))
1022assert(pkt[h2.H2SettingsFrame])
1023sf = pkt[h2.H2SettingsFrame]
1024assert(len(sf.settings) == 6)
1025assert(isinstance(sf.settings[0], h2.H2Setting))
1026assert(sf.settings[0].id == 1)
1027assert(sf.settings[0].value == 123456789)
1028assert(isinstance(sf.settings[1], h2.H2Setting))
1029assert(sf.settings[1].id == 2)
1030assert(sf.settings[1].value == 1)
1031assert(isinstance(sf.settings[2], h2.H2Setting))
1032assert(sf.settings[2].id == 3)
1033assert(sf.settings[2].value == 123)
1034assert(isinstance(sf.settings[3], h2.H2Setting))
1035assert(sf.settings[3].id == 4)
1036assert(sf.settings[3].value == 1234567)
1037assert(isinstance(sf.settings[4], h2.H2Setting))
1038assert(sf.settings[4].id == 5)
1039assert(sf.settings[4].value == 123456)
1040assert(isinstance(sf.settings[5], h2.H2Setting))
1041assert(sf.settings[5].id == 6)
1042assert(sf.settings[5].value == 123)
1043assert(isinstance(sf.payload, scapy.packet.NoPayload))
1044
1045= HTTP/2 Build Settings Frame: Settings Frame
1046~ http2 frame build settings
1047
1048p = h2.H2Frame()/h2.H2SettingsFrame(settings=[
1049        h2.H2Setting(id='Header table size',value=123456789),
1050        h2.H2Setting(id='Enable push', value=1),
1051        h2.H2Setting(id='Max concurrent streams', value=123),
1052        h2.H2Setting(id='Initial window size', value=1234567),
1053        h2.H2Setting(id='Max frame size', value=123456),
1054        h2.H2Setting(id='Max header list size', value=123)
1055    ]
1056)
1057assert(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{')
1058
1059= HTTP/2 Dissect Settings Frame: Incomplete Settings Frame
1060~ http2 frame dissect settings
1061
1062#We use here the decode('hex') method because null-bytes are rejected by eval()
1063assert(expect_exception(AssertionError, 'h2.H2Frame(bytes_hex("0000240400000000000001075bcd1500020000000100030000007b00040012d68700050001e2400006000000"))'))
1064
1065= HTTP/2 Dissect Settings Frame: Settings Frame acknowledgement
1066~ http2 frame dissect settings
1067
1068pkt = h2.H2Frame(b'\x00\x00\x00\x04\x01\x00\x00\x00\x00') #Settings frame w/ ack flag
1069assert(pkt.type == 4)
1070assert(pkt.len == 0)
1071assert(len(pkt.flags) == 1)
1072assert('A' in pkt.flags)
1073assert(pkt.reserved == 0)
1074assert(pkt.stream_id == 0)
1075assert(flags_bit_pattern.search(pkt.show(dump=True)) is None)
1076assert(isinstance(pkt.payload, scapy.packet.NoPayload))
1077
1078= HTTP/2 Build Settings Frame: Settings Frame acknowledgement
1079~ http2 frame build settings
1080
1081p = h2.H2Frame(type=h2.H2SettingsFrame.type_id, flags={'A'})
1082assert(raw(p) == b'\x00\x00\x00\x04\x01\x00\x00\x00\x00')
1083
1084+ HTTP/2 Push Promise Frame Test Suite
1085
1086= HTTP/2 Dissect Push Promise Frame: no flag & headers with compression and hdr_name
1087~ http2 frame dissect pushpromise
1088
1089pkt = 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')
1090assert(pkt.type == 5)
1091assert(pkt.len == 21)
1092assert(len(pkt.flags) == 0)
1093assert(pkt.reserved == 0)
1094assert(pkt.stream_id == 1)
1095assert(isinstance(pkt.payload, h2.H2PushPromiseFrame))
1096assert(pkt[h2.H2PushPromiseFrame])
1097pf = pkt[h2.H2PushPromiseFrame]
1098assert(pf.reserved == 0)
1099assert(pf.stream_id == 3)
1100assert(len(pf.hdrs) == 1)
1101assert(isinstance(pf.payload, scapy.packet.NoPayload))
1102hdr = pf.hdrs[0]
1103assert(isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing))
1104assert(hdr.magic == 1)
1105assert(hdr.index == 0)
1106assert(isinstance(hdr.hdr_name, h2.HPackHdrString))
1107assert(hdr.hdr_name.type == 1)
1108assert(hdr.hdr_name.len == 12)
1109assert(hdr.hdr_name.getfieldval('data').origin() == 'X-Requested-With')
1110assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
1111assert(hdr.hdr_value.type == 0)
1112assert(hdr.hdr_value.len == 2)
1113assert(hdr.hdr_value.getfieldval('data').origin() == 'Me')
1114
1115= HTTP/2 Build Push Promise Frame: no flag & headers with compression and hdr_name
1116~ http2 frame build pushpromise
1117
1118p = h2.H2Frame(stream_id=1)/h2.H2PushPromiseFrame(stream_id=3,hdrs=[
1119    h2.HPackLitHdrFldWithIncrIndexing(
1120        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Requested-With')),
1121        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me')),
1122    )
1123])
1124assert(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')
1125
1126= HTTP/2 Dissect Push Promise Frame: with padding, the flag END_Header & headers with compression and hdr_name
1127~ http2 frame dissect pushpromise
1128
1129pkt = 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')
1130assert(pkt.type == 5)
1131assert(pkt.len == 30)
1132assert(len(pkt.flags) == 2)
1133assert('P' in pkt.flags)
1134assert('EH' in pkt.flags)
1135assert(pkt.reserved == 0)
1136assert(pkt.stream_id == 1)
1137assert(flags_bit_pattern.search(pkt.show(dump=True)) is None)
1138assert(isinstance(pkt.payload, h2.H2PaddedPushPromiseFrame))
1139assert(pkt[h2.H2PaddedPushPromiseFrame])
1140pf = pkt[h2.H2PaddedPushPromiseFrame]
1141assert(pf.padlen == 8)
1142assert(pf.padding == b'\x00'*8)
1143assert(pf.stream_id == 3)
1144assert(len(pf.hdrs) == 1)
1145hdr = pf.hdrs[0]
1146assert(isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing))
1147assert(hdr.magic == 1)
1148assert(hdr.index == 0)
1149assert(isinstance(hdr.hdr_name, h2.HPackHdrString))
1150assert(hdr.hdr_name.type == 1)
1151assert(hdr.hdr_name.len == 12)
1152assert(hdr.hdr_name.getfieldval('data').origin() == 'X-Requested-With')
1153assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
1154assert(hdr.hdr_value.type == 0)
1155assert(hdr.hdr_value.len == 2)
1156assert(hdr.hdr_value.getfieldval('data').origin() == 'Me')
1157
1158= HTTP/2 Build Push Promise Frame: with padding, the flag END_Header & headers with compression and hdr_name
1159~ http2 frame build pushpromise
1160
1161p = h2.H2Frame(flags={'P', 'EH'}, stream_id=1)/h2.H2PaddedPushPromiseFrame(
1162    stream_id=3,
1163    hdrs=[
1164        h2.HPackLitHdrFldWithIncrIndexing(
1165            hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Requested-With')),
1166            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me'))
1167        )
1168    ],
1169    padding=b'\x00'*8
1170)
1171assert(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')
1172
1173+ HTTP/2 Ping Frame Test Suite
1174
1175= HTTP/2 Dissect Ping Frame: Ping frame
1176~ http2 frame dissect ping
1177
1178pkt = h2.H2Frame(b'\x00\x00\x08\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xe2@') #Ping frame with payload
1179assert(pkt.type == 6)
1180assert(pkt.len == 8)
1181assert(len(pkt.flags) == 0)
1182assert(pkt.reserved == 0)
1183assert(pkt.stream_id == 0)
1184assert(isinstance(pkt.payload, h2.H2PingFrame))
1185assert(pkt[h2.H2PingFrame])
1186pf = pkt[h2.H2PingFrame]
1187assert(pf.opaque == 123456)
1188assert(isinstance(pf.payload, scapy.packet.NoPayload))
1189
1190= HTTP/2 Build Ping Frame: Ping frame
1191~ http2 frame build ping
1192
1193p = h2.H2Frame()/h2.H2PingFrame(opaque=123456)
1194assert(raw(p) == b'\x00\x00\x08\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xe2@')
1195
1196= HTTP/2 Dissect Ping Frame: Pong frame
1197~ http2 frame dissect ping
1198
1199pkt = h2.H2Frame(b'\x00\x00\x08\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xe2@') #Pong frame
1200assert(pkt.type == 6)
1201assert(pkt.len == 8)
1202assert(len(pkt.flags) == 1)
1203assert('A' in pkt.flags)
1204assert(pkt.reserved == 0)
1205assert(pkt.stream_id == 0)
1206assert(isinstance(pkt.payload, h2.H2PingFrame))
1207assert(flags_bit_pattern.search(pkt.show(dump=True)) is None)
1208assert(pkt[h2.H2PingFrame])
1209pf = pkt[h2.H2PingFrame]
1210assert(pf.opaque == 123456)
1211assert(isinstance(pf.payload, scapy.packet.NoPayload))
1212
1213= HTTP/2 Dissect Ping Frame: Pong frame
1214~ http2 frame dissect ping
1215
1216p = h2.H2Frame(flags={'A'})/h2.H2PingFrame(opaque=123456)
1217assert(raw(p) == b'\x00\x00\x08\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xe2@')
1218
1219+ HTTP/2 Go Away Frame Test Suite
1220
1221= HTTP/2 Dissect Go Away Frame: No error
1222~ http2 frame dissect goaway
1223
1224pkt = 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 :)
1225assert(pkt.type == 7)
1226assert(pkt.len == 8)
1227assert(len(pkt.flags) == 0)
1228assert(pkt.reserved == 0)
1229assert(pkt.stream_id == 0)
1230assert(isinstance(pkt.payload, h2.H2GoAwayFrame))
1231assert(pkt[h2.H2GoAwayFrame])
1232gf = pkt[h2.H2GoAwayFrame]
1233assert(gf.reserved == 0)
1234assert(gf.last_stream_id == 1)
1235assert(gf.error == 0)
1236assert(len(gf.additional_data) == 0)
1237assert(isinstance(gf.payload, scapy.packet.NoPayload))
1238
1239= HTTP/2 Build Go Away Frame: No error
1240~ http2 frame build goaway
1241
1242p = h2.H2Frame()/h2.H2GoAwayFrame(last_stream_id=1, error='No error')
1243assert(raw(p) == b'\x00\x00\x08\x07\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00')
1244
1245= HTTP/2 Dissect Go Away Frame: Arbitrary error with additional data
1246~ http2 frame dissect goaway
1247
1248pkt = 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
1249assert(pkt.type == 7)
1250assert(pkt.len == 16)
1251assert(len(pkt.flags) == 0)
1252assert(pkt.reserved == 0)
1253assert(pkt.stream_id == 0)
1254assert(isinstance(pkt.payload, h2.H2GoAwayFrame))
1255assert(pkt[h2.H2GoAwayFrame])
1256gf = pkt[h2.H2GoAwayFrame]
1257assert(gf.reserved == 0)
1258assert(gf.last_stream_id == 2)
1259assert(gf.error == 123456)
1260assert(gf.additional_data == 8*b'\x00')
1261assert(isinstance(gf.payload, scapy.packet.NoPayload))
1262
1263= HTTP/2 Build Go Away Frame: Arbitrary error with additional data
1264~ http2 frame build goaway
1265
1266p = h2.H2Frame()/h2.H2GoAwayFrame(
1267    last_stream_id=2,
1268    error=123456,
1269    additional_data=b'\x00'*8
1270)
1271assert(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')
1272
1273+ HTTP/2 Window Update Frame Test Suite
1274
1275= HTTP/2 Dissect Window Update Frame: global
1276~ http2 frame dissect winupdate
1277
1278pkt = h2.H2Frame(b'\x00\x00\x04\x08\x00\x00\x00\x00\x00\x00\x01\xe2@') #Window update with increment for connection
1279assert(pkt.type == 8)
1280assert(pkt.len == 4)
1281assert(len(pkt.flags) == 0)
1282assert(pkt.reserved == 0)
1283assert(pkt.stream_id == 0)
1284assert(isinstance(pkt.payload, h2.H2WindowUpdateFrame))
1285assert(pkt[h2.H2WindowUpdateFrame])
1286wf = pkt[h2.H2WindowUpdateFrame]
1287assert(wf.reserved == 0)
1288assert(wf.win_size_incr == 123456)
1289assert(isinstance(wf.payload, scapy.packet.NoPayload))
1290
1291= HTTP/2 Build Window Update Frame: global
1292~ http2 frame build winupdate
1293
1294p = h2.H2Frame()/h2.H2WindowUpdateFrame(win_size_incr=123456)
1295assert(raw(p) == b'\x00\x00\x04\x08\x00\x00\x00\x00\x00\x00\x01\xe2@')
1296
1297= HTTP/2 Dissect Window Update Frame: a stream
1298~ http2 frame dissect winupdate
1299
1300pkt = h2.H2Frame(b'\x00\x00\x04\x08\x00\x00\x00\x00\x01\x00\x01\xe2@') #Window update with increment for a stream
1301assert(pkt.type == 8)
1302assert(pkt.len == 4)
1303assert(len(pkt.flags) == 0)
1304assert(pkt.reserved == 0)
1305assert(pkt.stream_id == 1)
1306assert(isinstance(pkt.payload, h2.H2WindowUpdateFrame))
1307assert(pkt[h2.H2WindowUpdateFrame])
1308wf = pkt[h2.H2WindowUpdateFrame]
1309assert(wf.reserved == 0)
1310assert(wf.win_size_incr == 123456)
1311assert(isinstance(wf.payload, scapy.packet.NoPayload))
1312
1313= HTTP/2 Build Window Update Frame: a stream
1314~ http2 frame build winupdate
1315
1316p = h2.H2Frame(stream_id=1)/h2.H2WindowUpdateFrame(win_size_incr=123456)
1317assert(raw(p) == b'\x00\x00\x04\x08\x00\x00\x00\x00\x01\x00\x01\xe2@')
1318
1319+ HTTP/2 Continuation Frame Test Suite
1320
1321= HTTP/2 Dissect Continuation Frame: no flag & headers with compression and hdr_name
1322~ http2 frame dissect continuation
1323
1324pkt = h2.H2Frame(b'\x00\x00\x11\t\x00\x00\x00\x00\x01@\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me')
1325assert(pkt.type == 9)
1326assert(pkt.len == 17)
1327assert(len(pkt.flags) == 0)
1328assert(pkt.reserved == 0)
1329assert(pkt.stream_id == 1)
1330assert(isinstance(pkt.payload, h2.H2ContinuationFrame))
1331assert(pkt[h2.H2ContinuationFrame])
1332hf = pkt[h2.H2ContinuationFrame]
1333assert(len(hf.hdrs) == 1)
1334assert(isinstance(hf.payload, scapy.packet.NoPayload))
1335hdr = hf.hdrs[0]
1336assert(isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing))
1337assert(hdr.magic == 1)
1338assert(hdr.index == 0)
1339assert(isinstance(hdr.hdr_name, h2.HPackHdrString))
1340assert(hdr.hdr_name.type == 1)
1341assert(hdr.hdr_name.len == 12)
1342assert(hdr.hdr_name.getfieldval('data').origin() == 'X-Requested-With')
1343assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
1344assert(hdr.hdr_value.type == 0)
1345assert(hdr.hdr_value.len == 2)
1346assert(hdr.hdr_value.getfieldval('data').origin() == 'Me')
1347
1348= HTTP/2 Build Continuation Frame: no flag & headers with compression and hdr_name
1349~ http2 frame build continuation
1350
1351p = h2.H2Frame(stream_id=1)/h2.H2ContinuationFrame(
1352    hdrs=[
1353        h2.HPackLitHdrFldWithIncrIndexing(
1354            hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Requested-With')),
1355            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me'))
1356        )
1357    ]
1358)
1359assert(raw(p) == b'\x00\x00\x11\t\x00\x00\x00\x00\x01@\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me')
1360
1361= HTTP/2 Dissect Continuation Frame: flag END_Header & headers with compression, sensitive flag and hdr_name
1362~ http2 frame dissect continuation
1363
1364pkt = h2.H2Frame(b'\x00\x00\x11\t\x04\x00\x00\x00\x01\x10\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me')
1365assert(pkt.type == 9)
1366assert(pkt.len == 17)
1367assert(len(pkt.flags) == 1)
1368assert('EH' in pkt.flags)
1369assert(pkt.reserved == 0)
1370assert(pkt.stream_id == 1)
1371assert(flags_bit_pattern.search(pkt.show(dump=True)) is None)
1372assert(isinstance(pkt.payload, h2.H2ContinuationFrame))
1373assert(pkt[h2.H2ContinuationFrame])
1374hf = pkt[h2.H2ContinuationFrame]
1375assert(len(hf.hdrs) == 1)
1376assert(isinstance(hf.payload, scapy.packet.NoPayload))
1377hdr = hf.hdrs[0]
1378assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
1379assert(hdr.magic == 0)
1380assert(hdr.never_index == 1)
1381assert(hdr.index == 0)
1382assert(isinstance(hdr.hdr_name, h2.HPackHdrString))
1383assert(hdr.hdr_name.type == 1)
1384assert(hdr.hdr_name.len == 12)
1385assert(hdr.hdr_name.getfieldval('data').origin() == 'X-Requested-With')
1386assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
1387assert(hdr.hdr_value.type == 0)
1388assert(hdr.hdr_value.len == 2)
1389assert(hdr.hdr_value.getfieldval('data').origin() == 'Me')
1390
1391= HTTP/2 Build Continuation Frame: flag END_Header & headers with compression, sensitive flag and hdr_name
1392~ http2 frame build continuation
1393
1394p = h2.H2Frame(flags={'EH'}, stream_id=1)/h2.H2ContinuationFrame(
1395    hdrs=[
1396        h2.HPackLitHdrFldWithoutIndexing(
1397            never_index=1,
1398            hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Requested-With')),
1399            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me'))
1400        )
1401    ]
1402)
1403assert(raw(p) == b'\x00\x00\x11\t\x04\x00\x00\x00\x01\x10\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me')
1404
1405+ HTTP/2 HPackHdrTable Test Suite
1406
1407= HTTP/2 HPackHdrEntry Tests
1408~ http2 hpack hpackhdrtable
1409
1410n = 'X-Requested-With'
1411v = 'Me'
1412h = h2.HPackHdrEntry(n, v)
1413assert(len(h) == 32 + len(n) + len(v))
1414assert(h.name() == n.lower())
1415assert(h.value() == v)
1416assert(str(h) == '{}: {}'.format(n.lower(), v))
1417
1418n = ':status'
1419v = '200'
1420h = h2.HPackHdrEntry(n, v)
1421assert(len(h) == 32 + len(n) + len(v))
1422assert(h.name() == n.lower())
1423assert(h.value() == v)
1424assert(str(h) == '{} {}'.format(n.lower(), v))
1425
1426= HTTP/2 HPackHdrTable : Querying Static Entries
1427~ http2 hpack hpackhdrtable
1428
1429# In RFC7541, the table is 1-based
1430assert(expect_exception(KeyError, 'h2.HPackHdrTable()[0]'))
1431
1432h = h2.HPackHdrTable()
1433assert(h[1].name() == ':authority')
1434assert(h[7].name() == ':scheme')
1435assert(h[7].value() == 'https')
1436assert(str(h[14]) == ':status 500')
1437assert(str(h[16]) == 'accept-encoding: gzip, deflate')
1438
1439assert(expect_exception(KeyError, 'h2.HPackHdrTable()[h2.HPackHdrTable._static_entries_last_idx+1]'))
1440
1441= HTTP/2 HPackHdrTable : Addind Dynamic Entries without overflowing the table
1442~ http2 hpack hpackhdrtable
1443
1444tbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32)
1445hdr = h2.HPackLitHdrFldWithIncrIndexing(
1446    index=32,
1447    hdr_value=h2.HPackHdrString(data=h2.HPackZString('PHPSESSID=abcdef0123456789'))
1448)
1449tbl.register(hdr)
1450
1451tbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32)
1452hdr2 = h2.HPackLitHdrFldWithIncrIndexing(
1453    index=32,
1454    hdr_value=h2.HPackHdrString(data=h2.HPackZString('JSESSID=abcdef0123456789'))
1455)
1456tbl.register([hdr,hdr2])
1457
1458tbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32)
1459hdr3 = h2.HPackLitHdrFldWithIncrIndexing(
1460    index=32,
1461    hdr_value=h2.HPackHdrString(data=h2.HPackZString('Test=abcdef0123456789'))
1462)
1463frm = h2.H2Frame(stream_id=1)/h2.H2HeadersFrame(hdrs=[hdr, hdr2, hdr3])
1464tbl.register(frm)
1465
1466
1467= HTTP/2 HPackHdrTable : Querying Dynamic Entries
1468~ http2 hpack hpackhdrtable
1469
1470tbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32)
1471hdrv = 'PHPSESSID=abcdef0123456789'
1472hdr = h2.HPackLitHdrFldWithIncrIndexing(
1473    index=32,
1474    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv))
1475)
1476tbl.register(hdr)
1477
1478hdrv2 = 'JSESSID=abcdef0123456789'
1479hdr2 = h2.HPackLitHdrFldWithIncrIndexing(
1480    index=32,
1481    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv2))
1482)
1483tbl.register(hdr2)
1484
1485hdr3 = h2.HPackLitHdrFldWithIncrIndexing(
1486    index=0,
1487    hdr_name=h2.HPackHdrString(data=h2.HPackLiteralString('x-requested-by')),
1488    hdr_value=h2.HPackHdrString(data=h2.HPackZString('me'))
1489)
1490tbl.register(hdr3)
1491
1492assert(tbl.get_idx_by_name('x-requested-by') == h2.HPackHdrTable._static_entries_last_idx+1)
1493assert(tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv2)
1494assert(tbl[h2.HPackHdrTable._static_entries_last_idx+3].value() == hdrv)
1495
1496= HTTP/2 HPackHdrTable : Addind already registered Dynamic Entries without overflowing the table
1497~ http2 hpack hpackhdrtable
1498
1499tbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32)
1500
1501assert(len(tbl) == 0)
1502
1503hdrv = 'PHPSESSID=abcdef0123456789'
1504hdr = h2.HPackLitHdrFldWithIncrIndexing(
1505    index=32,
1506    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv))
1507)
1508tbl.register(hdr)
1509assert(tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv)
1510
1511hdr2v = 'JSESSID=abcdef0123456789'
1512hdr2 = h2.HPackLitHdrFldWithIncrIndexing(
1513    index=32,
1514    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdr2v))
1515)
1516tbl.register(hdr2)
1517assert(tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdr2v)
1518
1519l = len(tbl)
1520tbl.register(hdr)
1521assert(tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv)
1522assert(tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdr2v)
1523assert(tbl[h2.HPackHdrTable._static_entries_last_idx+3].value() == hdrv)
1524
1525= HTTP/2 HPackHdrTable : Addind Dynamic Entries and overflowing the table
1526~ http2 hpack hpackhdrtable
1527
1528tbl = h2.HPackHdrTable(dynamic_table_max_size=80, dynamic_table_cap_size=80)
1529hdrv = 'PHPSESSID=abcdef0123456789'
1530hdr = h2.HPackLitHdrFldWithIncrIndexing(
1531    index=32,
1532    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv))
1533)
1534tbl.register(hdr)
1535assert(len(tbl) <= 80)
1536assert(tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv)
1537
1538hdrv2 = 'JSESSID=abcdef0123456789'
1539hdr2 = h2.HPackLitHdrFldWithIncrIndexing(
1540    index=32,
1541    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv2))
1542)
1543tbl.register(hdr2)
1544assert(len(tbl) <= 80)
1545assert(tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2)
1546try:
1547    tbl[h2.HPackHdrTable._static_entries_last_idx+2]
1548    ret = False
1549except:
1550    ret = True
1551
1552assert(ret)
1553
1554
1555= HTTP/2 HPackHdrTable : Resizing
1556~ http2 hpack hpackhdrtable
1557
1558tbl = h2.HPackHdrTable()
1559hdrv = 'PHPSESSID=abcdef0123456789'
1560hdr = h2.HPackLitHdrFldWithIncrIndexing(
1561    index=32,
1562    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv))
1563)
1564tbl.register(hdr)
1565assert(tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv)
1566
1567hdrv2 = 'JSESSID=abcdef0123456789'
1568hdr2 = h2.HPackLitHdrFldWithIncrIndexing(
1569    index=32,
1570    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv2))
1571)
1572tbl.register(hdr2)
1573assert(tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2)
1574assert(tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv)
1575
1576#Resizing to a value higher than cap (default:4096)
1577try:
1578    tbl.resize(8192)
1579    ret = False
1580except AssertionError:
1581    ret = True
1582
1583assert(ret)
1584#Resizing to a lower value by that is not small enough to cause eviction
1585tbl.resize(1024)
1586assert(tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2)
1587assert(tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv)
1588#Resizing to a higher value but thatt is lower than cap
1589tbl.resize(2048)
1590assert(tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2)
1591assert(tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv)
1592#Resizing to a lower value that causes eviction
1593tbl.resize(80)
1594assert(tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2)
1595try:
1596    tbl[h2.HPackHdrTable._static_entries_last_idx+2]
1597    ret = False
1598except:
1599    ret = True
1600
1601assert(ret)
1602
1603= HTTP/2 HPackHdrTable : Recapping
1604~ http2 hpack hpackhdrtable
1605
1606tbl = h2.HPackHdrTable()
1607hdrv = 'PHPSESSID=abcdef0123456789'
1608hdr = h2.HPackLitHdrFldWithIncrIndexing(
1609    index=32,
1610    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv))
1611)
1612tbl.register(hdr)
1613assert(tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv)
1614
1615hdrv2 = 'JSESSID=abcdef0123456789'
1616hdr2 = h2.HPackLitHdrFldWithIncrIndexing(
1617    index=32,
1618    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv2))
1619)
1620tbl.register(hdr2)
1621assert(tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2)
1622assert(tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv)
1623
1624#Recapping to a higher value
1625tbl.recap(8192)
1626assert(tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2)
1627assert(tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv)
1628
1629#Recapping to a low value but without causing eviction
1630tbl.recap(1024)
1631assert(tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2)
1632assert(tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv)
1633
1634#Recapping to a low value that causes evictiontbl.recap(1024)
1635tbl.recap(80)
1636assert(tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2)
1637try:
1638    tbl[h2.HPackHdrTable._static_entries_last_idx+2]
1639    ret = False
1640except:
1641    ret = True
1642
1643assert(ret)
1644
1645= HTTP/2 HPackHdrTable : Generating Textual Representation
1646~ http2 hpack hpackhdrtable helpers
1647
1648h = h2.HPackHdrTable()
1649h.register(h2.HPackLitHdrFldWithIncrIndexing(
1650        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),
1651        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))
1652))
1653
1654hdrs_lst = [
1655    h2.HPackIndexedHdr(index=2), #Method Get
1656    h2.HPackLitHdrFldWithIncrIndexing(
1657        index=h.get_idx_by_name(':path'),
1658        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('/index.php'))
1659    ),
1660    h2.HPackIndexedHdr(index=7), #Scheme HTTPS
1661    h2.HPackIndexedHdr(index=h2.HPackHdrTable._static_entries_last_idx+2),
1662    h2.HPackLitHdrFldWithIncrIndexing(
1663        index=58,
1664        hdr_value=h2.HPackHdrString(data=h2.HPackZString('Mozilla/5.0 Generated by hand'))
1665    ),
1666    h2.HPackLitHdrFldWithoutIndexing(
1667        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generated-By')),
1668        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me'))
1669    )
1670]
1671
1672p = h2.H2Frame(stream_id = 1)/h2.H2HeadersFrame(hdrs=hdrs_lst)
1673
1674expected_output = ''':method GET
1675:path /index.php
1676:scheme https
1677x-generation-date: 2016-08-11
1678user-agent: Mozilla/5.0 Generated by hand
1679X-Generated-By: Me'''
1680
1681assert(h.gen_txt_repr(p) == expected_output)
1682
1683= HTTP/2 HPackHdrTable : Parsing Textual Representation
1684~ http2 hpack hpackhdrtable helpers
1685
1686body = b'login=titi&passwd=toto'
1687hdrs = raw(''':method POST
1688:path /login.php
1689:scheme https
1690content-type: application/x-www-form-urlencoded
1691content-length: {}
1692user-agent: Mozilla/5.0 Generated by hand
1693x-generated-by: Me
1694x-generation-date: 2016-08-11
1695x-generation-software: scapy
1696'''.format(len(body)))
1697
1698h = h2.HPackHdrTable()
1699h.register(h2.HPackLitHdrFldWithIncrIndexing(
1700        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),
1701        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))
1702))
1703seq = h.parse_txt_hdrs(
1704    hdrs,
1705    stream_id=1,
1706    body=body,
1707    should_index=lambda name: name in ['user-agent', 'x-generation-software'],
1708    is_sensitive=lambda name, value: name in ['x-generated-by', ':path']
1709)
1710assert(isinstance(seq, h2.H2Seq))
1711assert(len(seq.frames) == 2)
1712p = seq.frames[0]
1713assert(isinstance(p, h2.H2Frame))
1714assert(p.type == 1)
1715assert(len(p.flags) == 1)
1716assert('EH' in p.flags)
1717assert(p.stream_id == 1)
1718assert(isinstance(p.payload, h2.H2HeadersFrame))
1719hdrs_frm = p[h2.H2HeadersFrame]
1720assert(len(p.hdrs) == 9)
1721hdr = p.hdrs[0]
1722assert(isinstance(hdr, h2.HPackIndexedHdr))
1723assert(hdr.magic == 1)
1724assert(hdr.index == 3)
1725hdr = p.hdrs[1]
1726assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
1727assert(hdr.magic == 0)
1728assert(hdr.never_index == 1)
1729assert(hdr.index in [4, 5])
1730assert(hdr.hdr_name is None)
1731assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
1732assert(hdr.hdr_value.data == 'HPackZString(/login.php)')
1733hdr = p.hdrs[2]
1734assert(isinstance(hdr, h2.HPackIndexedHdr))
1735assert(hdr.magic == 1)
1736assert(hdr.index == 7)
1737hdr = p.hdrs[3]
1738assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
1739assert(hdr.magic == 0)
1740assert(hdr.never_index == 0)
1741assert(hdr.index == 31)
1742assert(hdr.hdr_name is None)
1743assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
1744assert(hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)')
1745hdr = p.hdrs[4]
1746assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
1747assert(hdr.magic == 0)
1748assert(hdr.never_index == 0)
1749assert(hdr.index == 28)
1750assert(hdr.hdr_name is None)
1751assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
1752assert(hdr.hdr_value.data == 'HPackLiteralString(22)')
1753hdr = p.hdrs[5]
1754assert(isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing))
1755assert(hdr.magic == 1)
1756assert(hdr.index == 58)
1757assert(hdr.hdr_name is None)
1758assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
1759assert(hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)')
1760hdr = p.hdrs[6]
1761assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
1762assert(hdr.magic == 0)
1763assert(hdr.never_index == 1)
1764assert(hdr.index == 0)
1765assert(isinstance(hdr.hdr_name, h2.HPackHdrString))
1766assert(hdr.hdr_name.data == 'HPackZString(x-generated-by)')
1767assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
1768assert(hdr.hdr_value.data == 'HPackLiteralString(Me)')
1769hdr = p.hdrs[7]
1770assert(isinstance(hdr, h2.HPackIndexedHdr))
1771assert(hdr.magic == 1)
1772assert(hdr.index == 63)
1773hdr = p.hdrs[8]
1774assert(isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing))
1775assert(hdr.magic == 1)
1776assert(hdr.index == 0)
1777assert(isinstance(hdr.hdr_name, h2.HPackHdrString))
1778assert(hdr.hdr_name.data == 'HPackZString(x-generation-software)')
1779assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
1780assert(hdr.hdr_value.data == 'HPackZString(scapy)')
1781
1782p = seq.frames[1]
1783assert(isinstance(p, h2.H2Frame))
1784assert(p.type == 0)
1785assert(len(p.flags) == 1)
1786assert('ES' in p.flags)
1787assert(p.stream_id == 1)
1788assert(isinstance(p.payload, h2.H2DataFrame))
1789pay = p[h2.H2DataFrame]
1790assert(pay.data == body)
1791
1792= HTTP/2 HPackHdrTable : Parsing Textual Representation without body
1793~ http2 hpack hpackhdrtable helpers
1794
1795hdrs = b''':method POST
1796:path /login.php
1797:scheme https
1798user-agent: Mozilla/5.0 Generated by hand
1799x-generated-by: Me
1800x-generation-date: 2016-08-11
1801'''
1802
1803h = h2.HPackHdrTable()
1804h.register(h2.HPackLitHdrFldWithIncrIndexing(
1805        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),
1806        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))
1807))
1808
1809# Without body
1810seq = h.parse_txt_hdrs(hdrs, stream_id=1)
1811assert(isinstance(seq, h2.H2Seq))
1812#This is the first major difference with the first test
1813assert(len(seq.frames) == 1)
1814p = seq.frames[0]
1815assert(isinstance(p, h2.H2Frame))
1816assert(p.type == 1)
1817assert(len(p.flags) == 2)
1818assert('EH' in p.flags)
1819#This is the second major difference with the first test
1820assert('ES' in p.flags)
1821assert(p.stream_id == 1)
1822assert(isinstance(p.payload, h2.H2HeadersFrame))
1823hdrs_frm = p[h2.H2HeadersFrame]
1824assert(len(p.hdrs) == 6)
1825hdr = p.hdrs[0]
1826assert(isinstance(hdr, h2.HPackIndexedHdr))
1827assert(hdr.magic == 1)
1828assert(hdr.index == 3)
1829hdr = p.hdrs[1]
1830assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
1831assert(hdr.magic == 0)
1832assert(hdr.never_index == 0)
1833assert(hdr.index in [4, 5])
1834assert(hdr.hdr_name is None)
1835assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
1836assert(hdr.hdr_value.data == 'HPackZString(/login.php)')
1837hdr = p.hdrs[2]
1838assert(isinstance(hdr, h2.HPackIndexedHdr))
1839assert(hdr.magic == 1)
1840assert(hdr.index == 7)
1841hdr = p.hdrs[3]
1842assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
1843assert(hdr.magic == 0)
1844assert(hdr.never_index == 0)
1845assert(hdr.index == 58)
1846assert(hdr.hdr_name is None)
1847assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
1848assert(hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)')
1849hdr = p.hdrs[4]
1850assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
1851assert(hdr.magic == 0)
1852assert(hdr.never_index == 0)
1853assert(hdr.index == 0)
1854assert(isinstance(hdr.hdr_name, h2.HPackHdrString))
1855assert(hdr.hdr_name.data == 'HPackZString(x-generated-by)')
1856assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
1857assert(hdr.hdr_value.data == 'HPackLiteralString(Me)')
1858hdr = p.hdrs[5]
1859assert(isinstance(hdr, h2.HPackIndexedHdr))
1860assert(hdr.magic == 1)
1861assert(hdr.index == 62)
1862
1863
1864= HTTP/2 HPackHdrTable : Parsing Textual Representation with too small max frame
1865~ http2 hpack hpackhdrtable helpers
1866
1867body = b'login=titi&passwd=toto'
1868hdrs = raw(''':method POST
1869:path /login.php
1870:scheme https
1871content-type: application/x-www-form-urlencoded
1872content-length: {}
1873user-agent: Mozilla/5.0 Generated by hand
1874x-generated-by: Me
1875x-generation-date: 2016-08-11
1876x-long-header: {}
1877'''.format(len(body), 'a'*5000))
1878
1879h = h2.HPackHdrTable()
1880h.register(h2.HPackLitHdrFldWithIncrIndexing(
1881        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),
1882        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))
1883))
1884
1885#x-long-header is too long to fit in any frames (whose default max size is 4096)
1886expect_exception(Exception, "seq = h.parse_txt_hdrs('''{}''', stream_id=1".format(hdrs))
1887
1888= HTTP/2 HPackHdrTable : Parsing Textual Representation with very large header and a large authorized frame size
1889~ http2 hpack hpackhdrtable helpers
1890
1891body = b'login=titi&passwd=toto'
1892hdrs = raw(''':method POST
1893:path /login.php
1894:scheme https
1895content-type: application/x-www-form-urlencoded
1896content-length: {}
1897user-agent: Mozilla/5.0 Generated by hand
1898x-generated-by: Me
1899x-generation-date: 2016-08-11
1900x-long-header: {}
1901'''.format(len(body), 'a'*5000))
1902
1903h = h2.HPackHdrTable()
1904h.register(h2.HPackLitHdrFldWithIncrIndexing(
1905        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),
1906        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))
1907))
1908
1909# Now trying to parse it with a max frame size large enough for x-long-header to
1910# fit in a frame
1911seq = h.parse_txt_hdrs(hdrs, stream_id=1, max_frm_sz=8192)
1912assert(isinstance(seq, h2.H2Seq))
1913assert(len(seq.frames) == 1)
1914p = seq.frames[0]
1915assert(isinstance(p, h2.H2Frame))
1916assert(p.type == 1)
1917assert(len(p.flags) == 2)
1918assert('EH' in p.flags)
1919assert('ES' in p.flags)
1920assert(p.stream_id == 1)
1921assert(isinstance(p.payload, h2.H2HeadersFrame))
1922hdrs_frm = p[h2.H2HeadersFrame]
1923assert(len(p.hdrs) == 9)
1924hdr = p.hdrs[0]
1925assert(isinstance(hdr, h2.HPackIndexedHdr))
1926assert(hdr.magic == 1)
1927assert(hdr.index == 3)
1928hdr = p.hdrs[1]
1929assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
1930assert(hdr.magic == 0)
1931assert(hdr.never_index == 0)
1932assert(hdr.index in [4, 5])
1933assert(hdr.hdr_name is None)
1934assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
1935assert(hdr.hdr_value.data == 'HPackZString(/login.php)')
1936hdr = p.hdrs[2]
1937assert(isinstance(hdr, h2.HPackIndexedHdr))
1938assert(hdr.magic == 1)
1939assert(hdr.index == 7)
1940hdr = p.hdrs[3]
1941assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
1942assert(hdr.magic == 0)
1943assert(hdr.never_index == 0)
1944assert(hdr.index == 31)
1945assert(hdr.hdr_name is None)
1946assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
1947assert(hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)')
1948hdr = p.hdrs[4]
1949assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
1950assert(hdr.magic == 0)
1951assert(hdr.never_index == 0)
1952assert(hdr.index == 28)
1953assert(hdr.hdr_name is None)
1954assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
1955assert(hdr.hdr_value.data == 'HPackLiteralString(22)')
1956hdr = p.hdrs[5]
1957assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
1958assert(hdr.magic == 0)
1959assert(hdr.never_index == 0)
1960assert(hdr.index == 58)
1961assert(hdr.hdr_name is None)
1962assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
1963assert(hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)')
1964hdr = p.hdrs[6]
1965assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
1966assert(hdr.magic == 0)
1967assert(hdr.never_index == 0)
1968assert(hdr.index == 0)
1969assert(isinstance(hdr.hdr_name, h2.HPackHdrString))
1970assert(hdr.hdr_name.data == 'HPackZString(x-generated-by)')
1971assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
1972assert(hdr.hdr_value.data == 'HPackLiteralString(Me)')
1973hdr = p.hdrs[7]
1974assert(isinstance(hdr, h2.HPackIndexedHdr))
1975assert(hdr.magic == 1)
1976assert(hdr.index == 62)
1977hdr = p.hdrs[8]
1978assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
1979assert(hdr.magic == 0)
1980assert(hdr.never_index == 0)
1981assert(hdr.index == 0)
1982assert(isinstance(hdr.hdr_name, h2.HPackHdrString))
1983assert(hdr.hdr_name.data == 'HPackZString(x-long-header)')
1984assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
1985assert(hdr.hdr_value.data == 'HPackZString({})'.format('a'*5000))
1986
1987= HTTP/2 HPackHdrTable : Parsing Textual Representation with two very large headers and a large authorized frame size
1988~ http2 hpack hpackhdrtable helpers
1989
1990body = b'login=titi&passwd=toto'
1991hdrs = raw(''':method POST
1992:path /login.php
1993:scheme https
1994content-type: application/x-www-form-urlencoded
1995content-length: {}
1996user-agent: Mozilla/5.0 Generated by hand
1997x-generated-by: Me
1998x-generation-date: 2016-08-11
1999x-long-header: {}
2000x-long-header: {}
2001'''.format(len(body), 'a'*5000, 'b'*5000))
2002
2003h = h2.HPackHdrTable()
2004h.register(h2.HPackLitHdrFldWithIncrIndexing(
2005        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),
2006        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))
2007))
2008
2009# Now trying to parse it with a max frame size large enough for x-long-header to
2010# fit in a frame but a maximum header fragment size that is not large enough to
2011# store two x-long-header
2012seq = h.parse_txt_hdrs(hdrs, stream_id=1, max_frm_sz=8192)
2013assert(isinstance(seq, h2.H2Seq))
2014assert(len(seq.frames) == 2)
2015p = seq.frames[0]
2016assert(isinstance(p, h2.H2Frame))
2017assert(p.type == 1)
2018assert(len(p.flags) == 1)
2019assert('ES' in p.flags)
2020assert(p.stream_id == 1)
2021assert(isinstance(p.payload, h2.H2HeadersFrame))
2022hdrs_frm = p[h2.H2HeadersFrame]
2023assert(len(p.hdrs) == 9)
2024hdr = p.hdrs[0]
2025assert(isinstance(hdr, h2.HPackIndexedHdr))
2026assert(hdr.magic == 1)
2027assert(hdr.index == 3)
2028hdr = p.hdrs[1]
2029assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
2030assert(hdr.magic == 0)
2031assert(hdr.never_index == 0)
2032assert(hdr.index in [4, 5])
2033assert(hdr.hdr_name is None)
2034assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2035assert(hdr.hdr_value.data == 'HPackZString(/login.php)')
2036hdr = p.hdrs[2]
2037assert(isinstance(hdr, h2.HPackIndexedHdr))
2038assert(hdr.magic == 1)
2039assert(hdr.index == 7)
2040hdr = p.hdrs[3]
2041assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
2042assert(hdr.magic == 0)
2043assert(hdr.never_index == 0)
2044assert(hdr.index == 31)
2045assert(hdr.hdr_name is None)
2046assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2047assert(hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)')
2048hdr = p.hdrs[4]
2049assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
2050assert(hdr.magic == 0)
2051assert(hdr.never_index == 0)
2052assert(hdr.index == 28)
2053assert(hdr.hdr_name is None)
2054assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2055assert(hdr.hdr_value.data == 'HPackLiteralString(22)')
2056hdr = p.hdrs[5]
2057assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
2058assert(hdr.magic == 0)
2059assert(hdr.never_index == 0)
2060assert(hdr.index == 58)
2061assert(hdr.hdr_name is None)
2062assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2063assert(hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)')
2064hdr = p.hdrs[6]
2065assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
2066assert(hdr.magic == 0)
2067assert(hdr.never_index == 0)
2068assert(hdr.index == 0)
2069assert(isinstance(hdr.hdr_name, h2.HPackHdrString))
2070assert(hdr.hdr_name.data == 'HPackZString(x-generated-by)')
2071assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2072assert(hdr.hdr_value.data == 'HPackLiteralString(Me)')
2073hdr = p.hdrs[7]
2074assert(isinstance(hdr, h2.HPackIndexedHdr))
2075assert(hdr.magic == 1)
2076assert(hdr.index == 62)
2077hdr = p.hdrs[8]
2078assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
2079assert(hdr.magic == 0)
2080assert(hdr.never_index == 0)
2081assert(hdr.index == 0)
2082assert(isinstance(hdr.hdr_name, h2.HPackHdrString))
2083assert(hdr.hdr_name.data == 'HPackZString(x-long-header)')
2084assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2085assert(hdr.hdr_value.data == 'HPackZString({})'.format('a'*5000))
2086p = seq.frames[1]
2087assert(isinstance(p, h2.H2Frame))
2088assert(p.type == 9)
2089assert(len(p.flags) == 1)
2090assert('EH' in p.flags)
2091assert(p.stream_id == 1)
2092assert(isinstance(p.payload, h2.H2ContinuationFrame))
2093hdrs_frm = p[h2.H2ContinuationFrame]
2094assert(len(p.hdrs) == 1)
2095hdr = p.hdrs[0]
2096assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
2097assert(hdr.magic == 0)
2098assert(hdr.never_index == 0)
2099assert(hdr.index == 0)
2100assert(isinstance(hdr.hdr_name, h2.HPackHdrString))
2101assert(hdr.hdr_name.data == 'HPackZString(x-long-header)')
2102assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2103assert(hdr.hdr_value.data == 'HPackZString({})'.format('b'*5000))
2104
2105= HTTP/2 HPackHdrTable : Parsing Textual Representation with two very large headers, a large authorized frame size and a "small" max header list size
2106~ http2 hpack hpackhdrtable helpers
2107
2108body = b'login=titi&passwd=toto'
2109hdrs = raw(''':method POST
2110:path /login.php
2111:scheme https
2112content-type: application/x-www-form-urlencoded
2113content-length: {}
2114user-agent: Mozilla/5.0 Generated by hand
2115x-generated-by: Me
2116x-generation-date: 2016-08-11
2117x-long-header: {}
2118x-long-header: {}
2119'''.format(len(body), 'a'*5000, 'b'*5000))
2120
2121h = h2.HPackHdrTable()
2122h.register(h2.HPackLitHdrFldWithIncrIndexing(
2123        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),
2124        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))
2125))
2126
2127# Now trying to parse it with a max frame size large enough for x-long-header to
2128# fit in a frame but and a max header list size that is large enough to fit one
2129# but not two
2130seq = h.parse_txt_hdrs(hdrs, stream_id=1, max_frm_sz=8192, max_hdr_lst_sz=5050)
2131assert(isinstance(seq, h2.H2Seq))
2132assert(len(seq.frames) == 3)
2133p = seq.frames[0]
2134assert(isinstance(p, h2.H2Frame))
2135assert(p.type == 1)
2136assert(len(p.flags) == 1)
2137assert('ES' in p.flags)
2138assert(p.stream_id == 1)
2139assert(isinstance(p.payload, h2.H2HeadersFrame))
2140hdrs_frm = p[h2.H2HeadersFrame]
2141assert(len(p.hdrs) == 8)
2142hdr = p.hdrs[0]
2143assert(isinstance(hdr, h2.HPackIndexedHdr))
2144assert(hdr.magic == 1)
2145assert(hdr.index == 3)
2146hdr = p.hdrs[1]
2147assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
2148assert(hdr.magic == 0)
2149assert(hdr.never_index == 0)
2150assert(hdr.index in [4, 5])
2151assert(hdr.hdr_name is None)
2152assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2153assert(hdr.hdr_value.data == 'HPackZString(/login.php)')
2154hdr = p.hdrs[2]
2155assert(isinstance(hdr, h2.HPackIndexedHdr))
2156assert(hdr.magic == 1)
2157assert(hdr.index == 7)
2158hdr = p.hdrs[3]
2159assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
2160assert(hdr.magic == 0)
2161assert(hdr.never_index == 0)
2162assert(hdr.index == 31)
2163assert(hdr.hdr_name is None)
2164assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2165assert(hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)')
2166hdr = p.hdrs[4]
2167assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
2168assert(hdr.magic == 0)
2169assert(hdr.never_index == 0)
2170assert(hdr.index == 28)
2171assert(hdr.hdr_name is None)
2172assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2173assert(hdr.hdr_value.data == 'HPackLiteralString(22)')
2174hdr = p.hdrs[5]
2175assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
2176assert(hdr.magic == 0)
2177assert(hdr.never_index == 0)
2178assert(hdr.index == 58)
2179assert(hdr.hdr_name is None)
2180assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2181assert(hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)')
2182hdr = p.hdrs[6]
2183assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
2184assert(hdr.magic == 0)
2185assert(hdr.never_index == 0)
2186assert(hdr.index == 0)
2187assert(isinstance(hdr.hdr_name, h2.HPackHdrString))
2188assert(hdr.hdr_name.data == 'HPackZString(x-generated-by)')
2189assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2190assert(hdr.hdr_value.data == 'HPackLiteralString(Me)')
2191hdr = p.hdrs[7]
2192assert(isinstance(hdr, h2.HPackIndexedHdr))
2193assert(hdr.magic == 1)
2194assert(hdr.index == 62)
2195p = seq.frames[1]
2196assert(isinstance(p, h2.H2Frame))
2197assert(p.type == 9)
2198assert(len(p.flags) == 0)
2199assert(p.stream_id == 1)
2200assert(isinstance(p.payload, h2.H2ContinuationFrame))
2201hdrs_frm = p[h2.H2ContinuationFrame]
2202assert(len(p.hdrs) == 1)
2203hdr = p.hdrs[0]
2204assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
2205assert(hdr.magic == 0)
2206assert(hdr.never_index == 0)
2207assert(hdr.index == 0)
2208assert(isinstance(hdr.hdr_name, h2.HPackHdrString))
2209assert(hdr.hdr_name.data == 'HPackZString(x-long-header)')
2210assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2211assert(hdr.hdr_value.data == 'HPackZString({})'.format('a'*5000))
2212p = seq.frames[2]
2213assert(isinstance(p, h2.H2Frame))
2214assert(p.type == 9)
2215assert(len(p.flags) == 1)
2216assert('EH' in p.flags)
2217assert(p.stream_id == 1)
2218assert(isinstance(p.payload, h2.H2ContinuationFrame))
2219hdrs_frm = p[h2.H2ContinuationFrame]
2220assert(len(p.hdrs) == 1)
2221hdr = p.hdrs[0]
2222assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
2223assert(hdr.magic == 0)
2224assert(hdr.never_index == 0)
2225assert(hdr.index == 0)
2226assert(isinstance(hdr.hdr_name, h2.HPackHdrString))
2227assert(hdr.hdr_name.data == 'HPackZString(x-long-header)')
2228assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2229assert(hdr.hdr_value.data == 'HPackZString({})'.format('b'*5000))
2230
2231= HTTP/2 HPackHdrTable : Parsing Textual Representation with sensitive headers and non-indexable ones
2232~ http2 hpack hpackhdrtable helpers
2233
2234hdrs = raw(''':method POST
2235:path /login.php
2236:scheme https
2237content-type: application/x-www-form-urlencoded
2238content-length: {}
2239user-agent: Mozilla/5.0 Generated by hand
2240x-generated-by: Me
2241x-generation-date: 2016-08-11
2242'''.format(len(body)))
2243
2244h = h2.HPackHdrTable()
2245seq = 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')
2246assert(isinstance(seq, h2.H2Seq))
2247assert(len(seq.frames) == 2)
2248p = seq.frames[0]
2249assert(isinstance(p, h2.H2Frame))
2250assert(p.type == 1)
2251assert(len(p.flags) == 1)
2252assert('EH' in p.flags)
2253assert(p.stream_id == 1)
2254assert(isinstance(p.payload, h2.H2HeadersFrame))
2255hdrs_frm = p[h2.H2HeadersFrame]
2256assert(len(p.hdrs) == 8)
2257hdr = p.hdrs[0]
2258assert(isinstance(hdr, h2.HPackIndexedHdr))
2259assert(hdr.magic == 1)
2260assert(hdr.index == 3)
2261hdr = p.hdrs[1]
2262assert(isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing))
2263assert(hdr.magic == 1)
2264assert(hdr.index in [4, 5])
2265assert(hdr.hdr_name is None)
2266assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2267assert(hdr.hdr_value.data == 'HPackZString(/login.php)')
2268hdr = p.hdrs[2]
2269assert(isinstance(hdr, h2.HPackIndexedHdr))
2270assert(hdr.magic == 1)
2271assert(hdr.index == 7)
2272hdr = p.hdrs[3]
2273assert(isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing))
2274assert(hdr.magic == 1)
2275assert(hdr.index == 31)
2276assert(hdr.hdr_name is None)
2277assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2278assert(hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)')
2279hdr = p.hdrs[4]
2280assert(isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing))
2281assert(hdr.magic == 1)
2282assert(hdr.index == 28)
2283assert(hdr.hdr_name is None)
2284assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2285assert(hdr.hdr_value.data == 'HPackLiteralString(22)')
2286hdr = p.hdrs[5]
2287assert(isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing))
2288assert(hdr.magic == 1)
2289assert(hdr.index == 58)
2290assert(hdr.hdr_name is None)
2291assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2292assert(hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)')
2293hdr = p.hdrs[6]
2294assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
2295assert(hdr.magic == 0)
2296assert(hdr.never_index == 0)
2297assert(hdr.index == 0)
2298assert(isinstance(hdr.hdr_name, h2.HPackHdrString))
2299assert(hdr.hdr_name.data == 'HPackZString(x-generated-by)')
2300assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2301assert(hdr.hdr_value.data == 'HPackLiteralString(Me)')
2302hdr = p.hdrs[7]
2303assert(isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing))
2304assert(hdr.magic == 0)
2305assert(hdr.never_index == 1)
2306assert(hdr.index == 0)
2307assert(isinstance(hdr.hdr_name, h2.HPackHdrString))
2308assert(hdr.hdr_name.data == 'HPackZString(x-generation-date)')
2309assert(isinstance(hdr.hdr_value, h2.HPackHdrString))
2310assert(hdr.hdr_value.data == 'HPackZString(2016-08-11)')
2311p = seq.frames[1]
2312assert(isinstance(p, h2.H2Frame))
2313assert(p.type == 0)
2314assert(len(p.flags) == 1)
2315assert('ES' in p.flags)
2316assert(p.stream_id == 1)
2317assert(isinstance(p.payload, h2.H2DataFrame))
2318pay = p[h2.H2DataFrame]
2319assert(pay.data == body)
2320